Public/New-TaskDefinition.ps1

function New-TaskDefinition {
    <#
    .SYNOPSIS
        Creates a new task definition scaffolding.
     
    .DESCRIPTION
        Generates a new task definition with Task.json metadata and Task.ps1
        implementation template in the user task directory.
     
    .PARAMETER TaskName
        Name of the task in Category.TaskName format (e.g., "Custom.MyTask").
     
    .PARAMETER Description
        Task description.
     
    .PARAMETER Author
        Task author name. Defaults to current user.
     
    .PARAMETER Parameters
        Array of parameter definitions. Each should be a hashtable with Name, Type,
        Mandatory, and Description keys.
     
    .PARAMETER RequiresElevation
        Indicates if the task requires elevated privileges.
     
    .PARAMETER OutputPath
        Custom output path for the task. If not specified, creates in user task directory.
     
    .PARAMETER Force
        Overwrite existing task if it exists.
     
    .EXAMPLE
        New-TaskDefinition -TaskName "Custom.MyTask" -Description "My custom task"
        Creates a basic task template.
     
    .EXAMPLE
        $params = @(
            @{ Name = "Path"; Type = "string"; Mandatory = $true; Description = "File path" }
            @{ Name = "Recurse"; Type = "bool"; Mandatory = $false; Description = "Recurse subdirectories" }
        )
        New-TaskDefinition -TaskName "Custom.FileProcessor" -Description "Process files" -Parameters $params
        Creates a task with custom parameters.
     
    .EXAMPLE
        New-TaskDefinition -TaskName "Security.AuditUsers" -Description "Audit user accounts" -RequiresElevation
        Creates a task that requires administrator privileges.
     
    .EXAMPLE
        New-TaskDefinition -TaskName "Custom.BackupCheck" -Description "Verify backups" -OutputPath "C:\Scripts\Tasks"
        Creates a task in a custom location instead of user task directory.
     
    .OUTPUTS
        PSCustomObject containing the created task definition paths.
     
    .NOTES
        Tasks are created in %APPDATA%\Toolbox\Tasks by default.
        Task names must follow Category.TaskName format with proper PowerShell Verb-Noun naming.
        Generated files include proper comment-based help and parameter definitions.
        Edit the generated .ps1 file to implement your task logic.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, Position = 0)]
        [ValidatePattern("^[A-Za-z]+\.[A-Za-z0-9]+$")]
        [string]$TaskName,
        
        [Parameter(Mandatory, Position = 1)]
        [string]$Description,
        
        [Parameter()]
        [string]$Author = $env:USERNAME,
        
        [Parameter()]
        [hashtable[]]$Parameters,
        
        [Parameter()]
        [switch]$RequiresElevation,
        
        [Parameter()]
        [string]$OutputPath,
        
        [Parameter()]
        [switch]$Force
    )
    
    try {
        # Parse category from task name
        $parts = $TaskName -split '\.'
        if ($parts.Count -ne 2) {
            Write-Error 'TaskName must be in Category.TaskName format (e.g., Custom.MyTask)'
            return
        }
        
        $category = $parts[0]
        $taskSimpleName = $parts[1]
        
        # Convert task name to PowerShell verb-noun format
        $fileName = $taskSimpleName -creplace '([a-z])([A-Z])', '$1-$2'
        if ($fileName -notmatch '^[A-Z][a-z]+-') {
            $fileName = $taskSimpleName
        }
        $fileName = "$fileName.ps1"
        
        # Determine output directory
        if ($OutputPath) {
            $categoryDir = Join-Path $OutputPath $category
        }
        else {
            $config = Get-TbConfig -Section Tasks
            $categoryDir = Join-Path $config.UserTaskPath $category
        }
        
        $taskScriptPath = Join-Path $categoryDir $fileName
        
        # Check if task already exists
        if ((Test-Path $taskScriptPath) -and -not $Force) {
            Write-Error "Task file already exists: $taskScriptPath. Use -Force to overwrite."
            return
        }
        
        if ($PSCmdlet.ShouldProcess($taskScriptPath, 'Create task definition')) {
            # Create category directory
            New-Item -ItemType Directory -Path $categoryDir -Force | Out-Null
            Write-Verbose "Created category directory: $categoryDir"
            
            # Get template file
            $templatePath = Join-Path $PSScriptRoot '..\Templates\TaskTemplate.ps1'
            if (-not (Test-Path $templatePath)) {
                Write-Error "Template file not found: $templatePath"
                return
            }
            
            # Copy template
            Copy-Item -Path $templatePath -Destination $taskScriptPath -Force
            
            # Update template with task-specific values
            $content = Get-Content -Path $taskScriptPath -Raw
            $content = $content -replace 'Task description goes here', $Description
            $content = $content -replace 'Detailed description of what this task does\.', "Detailed task implementation for $TaskName."
            $content = $content -replace 'CategoryName\.TaskName', $TaskName
            $content = $content -replace 'Your Name', $Author
            $content = $content -replace 'Tags: category', "Tags: $category"
            $content = $content -replace 'RequiresElevation: False', "RequiresElevation: $([bool]$RequiresElevation)"
            
            # Save updated content
            Set-Content -Path $taskScriptPath -Value $content -Force
            Write-Verbose "Created task script: $taskScriptPath"
            
            # Clear task cache
            $script:TaskCache = $null
            
            Write-Host "? Task created successfully: $TaskName" -ForegroundColor Green
            Write-Host " Location: $taskScriptPath" -ForegroundColor Cyan
            Write-Host " Edit the script to implement your task logic" -ForegroundColor Yellow
            
            return [PSCustomObject]@{
                TaskName = $TaskName
                Category = $category
                FileName = $fileName
                TaskScriptPath = $taskScriptPath
            }
        }
    }
    catch {
        throw
    }
}