Public/New-PstFunction.ps1
|
function New-PstFunction { <# .SYNOPSIS Creates a new PowerShell function from a template with configurable complexity levels. .DESCRIPTION This function takes an approved verb and noun, copies a function template based on the specified complexity level, and renames the file and function block to the specified verb-noun combination. Complexity Levels: - Basic: Simple function with minimal structure (no error handling, basic parameters) - Moderate: Function with parameter validation, basic error handling, and help documentation - Complex: Full cmdlet features including begin/process/end blocks, pipeline support, ShouldProcess .PARAMETER Verb (Required) The approved verb for the function name. .PARAMETER Noun (Required) The noun for the function name. .PARAMETER ComplexityLevel (Optional) The complexity level of the function template. Valid values: Basic, Moderate, Complex. Defaults to Complex for backward compatibility. .PARAMETER Force (Optional) Forces creation even if file exists, useful in automation scenarios. .EXAMPLE New-PstFunction -Verb Get -Noun Item Creates a new complex function file named Get-Item.ps1 with full cmdlet features. .EXAMPLE New-PstFunction -Verb Get -Noun Item -ComplexityLevel Basic Creates a simple function with minimal structure for basic automation tasks. .EXAMPLE New-PstFunction -Verb Set -Noun Configuration -ComplexityLevel Moderate Creates a moderately complex function with parameter validation and error handling. .NOTES Ensure that the appropriate template files exist in the Resources/Samples directory. Template files: Function-Basic.ps1, Function-Moderate.ps1, Function-Complex.ps1 .LINK For more information on approved verbs, visit: https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true, Position = 0, HelpMessage = "The approved verb for the function name.")] [ValidateSet("Add", "Approve", "Assert", "Backup", "Block", "Checkpoint", "Clear", "Close", "Compare", "Complete", "Compress", "Confirm", "Connect", "Convert", "ConvertFrom", "ConvertTo", "Copy", "Debug", "Deny", "Disable", "Disconnect", "Dismount", "Edit", "Enable", "Enter", "Exit", "Expand", "Export", "Find", "Format", "Get", "Grant", "Group", "Hide", "Import", "Initialize", "Install", "Invoke", "Join", "Limit", "Lock", "Measure", "Merge", "Mount", "Move", "New", "Open", "Optimize", "Out", "Ping", "Pop", "Protect", "Publish", "Push", "Read", "Receive", "Redo", "Register", "Remove", "Rename", "Repair", "Request", "Reset", "Resize", "Resolve", "Restart", "Restore", "Resume", "Revoke", "Save", "Search", "Select", "Send", "Set", "Show", "Skip", "Split", "Start", "Step", "Stop", "Submit", "Suspend", "Switch", "Sync", "Test", "Trace", "Unblock", "Undo", "Uninstall", "Unlock", "Unprotect", "Unpublish", "Unregister", "Update", "Use", "Wait", "Watch", "Write")] [string]$Verb, [Parameter(Mandatory = $true, Position = 1, HelpMessage = "The noun for the function name.")] [ValidatePattern('^[A-Za-z][A-Za-z0-9]*$')] [string]$Noun, [Parameter(Mandatory = $false)] [ValidateSet("Basic", "Moderate", "Complex")] [string]$ComplexityLevel = "Complex", [Parameter(Mandatory = $false)] [switch]$Force ) begin { Write-Debug -Message "Begin '$($MyInvocation.MyCommand.Name)' at '$(Get-Date)'" # Select template based on complexity level $templateFileName = switch ($ComplexityLevel) { "Basic" { "Function-Basic.ps1" } "Moderate" { "Function-Moderate.ps1" } "Complex" { "Function-Complex.ps1" } default { "Function-Complex.ps1" } # Fallback to Complex } $templatePath = $Samples[$templateFileName] $newFunctionName = "$Verb-$Noun" $newFilePath = "$newFunctionName.ps1" Write-Verbose "Using complexity level: $ComplexityLevel" Write-Verbose "Selected template: $templateFileName" if (-not $templatePath) { throw "Template '$templateFileName' not found in Samples hashtable. Available templates: $($Samples.Keys -join ', ')" } if (-not (Test-Path $templatePath)) { throw "Template file not found: $templatePath" } else { Write-Verbose "Template file found: $templatePath" } } process { try { # Check if we're in automation mode - inline check to avoid scope issues $isAutomationMode = $Force -or ($Global:PstAutomationMode -eq $true) -or ($env:CI -eq 'true') -or ($env:GITHUB_ACTIONS -eq 'true') -or ($Host.Name -eq 'ServerRemoteHost') -or (-not [Environment]::UserInteractive) -or ($global:ConfirmPreference -eq 'None') # Check if file already exists if ((Test-Path $newFilePath) -and -not $isAutomationMode) { if (-not $PSCmdlet.ShouldProcess($newFilePath, "Overwrite existing function file")) { Write-Warning "Operation cancelled by user." return } } elseif ((Test-Path $newFilePath) -and $isAutomationMode -and -not $Force) { Write-Warning "File '$newFilePath' already exists. Use -Force to overwrite in automation mode." return } # Proceed with file creation - skip ShouldProcess in automation mode if ($isAutomationMode -or $PSCmdlet.ShouldProcess($newFilePath, "Create new function file")) { Write-Verbose "Getting file content from '$($templatePath)'" $templateContent = (Get-Content -Path $templatePath) -join "`n" Write-Verbose "Replacing '""Function Verb-Noun"" with ""Function $($newFunctionName)""' " $newContent = $templateContent -replace "Function Verb-Noun", "Function $newFunctionName" Write-Verbose "Set-Content to path '$($newFilePath)'" $newContent | Set-Content -Path $newFilePath Write-Output "New function file created: $newFilePath" } else { Write-Verbose "Operation cancelled or skipped." } } catch { if ($_.Exception -and $_.Exception.Message) { Write-Error "An error occurred: $($_.Exception.Message)" } else { Write-Error "An error occurred, but no additional information is available." } } } end { if ($?) { Write-Debug -Message "End '$($MyInvocation.MyCommand.Name)' at '$(Get-Date)'" } } } |