Public/New-FunctionTemplate.ps1
|
function New-FunctionTemplate { <# .SYNOPSIS Creates new function script files from the module's function template. .DESCRIPTION New-FunctionTemplate creates one <Name>.ps1 file per function name from the templates shipped in the module's Templates folder. The generated function has comment-based help, CmdletBinding, a begin/process/end structure and, unless -ExcludeTelemetryCollection is used, the tcs.core telemetry pattern (Start in begin, End on success and End -Failed on error). Functions with a state-changing verb (New, Set, Remove, Start, Stop, Restart, Reset, Update) get SupportsShouldProcess and a ShouldProcess check. .PARAMETER Name The name of each function to create, for example Get-Widget. Accepts pipeline input. .PARAMETER Path Directory where the new function file(s) will be created. Must be an existing directory. Defaults to the current location. .PARAMETER ExcludeTelemetryCollection Do not include the tcs.core telemetry calls in the generated function. .PARAMETER Force Overwrite an existing function file of the same name without asking. .PARAMETER PassThru Return the created file (System.IO.FileInfo) for each function generated. .EXAMPLE New-FunctionTemplate -Name 'Get-MyFunction' -Path './MyModule/Public' Creates Get-MyFunction.ps1 in ./MyModule/Public with the telemetry pattern. .EXAMPLE 'Get-Widget', 'Set-Widget' | New-FunctionTemplate -Path './MyModule/Public' -ExcludeTelemetryCollection -Force -PassThru Creates or overwrites two function files without telemetry and returns the created files. .INPUTS System.String. Function names (Name) can be passed by pipeline. .OUTPUTS None by default. System.IO.FileInfo for each created file when -PassThru is used. .NOTES Author: TheCodeSaiyan #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([System.IO.FileInfo])] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [string[]] $Name, [ValidateScript({ Test-Path -Path $_ -PathType Container })] [string] $Path = $PWD.Path, [switch] $ExcludeTelemetryCollection, [switch] $Force, [switch] $PassThru ) begin { $TelemetryArgs = @{ ModuleName = $MyInvocation.MyCommand.Module.Name ModuleVersion = [string]$MyInvocation.MyCommand.Module.Version CommandName = $MyInvocation.MyCommand.Name ExecutionID = [guid]::NewGuid().ToString() } Invoke-TelemetryCollection @TelemetryArgs -Stage Start -ClearTimer $TemplateName = if ($ExcludeTelemetryCollection) { 'Function_Template.template' } else { 'Function_Template_Telemetry.template' } $TemplatePath = Join-Path -Path (Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath 'Templates') -ChildPath $TemplateName try { $Template = Get-Content -Path $TemplatePath -Raw -ErrorAction Stop } catch { Invoke-TelemetryCollection @TelemetryArgs -Stage End -Failed $true -Exception $_ throw } $StateChangingVerbs = @('New', 'Set', 'Remove', 'Start', 'Stop', 'Restart', 'Reset', 'Update') $Requested = 0 $Created = 0 $Failures = 0 } process { foreach ($FunctionName in $Name) { $Requested++ $FunctionPath = Join-Path -Path $Path -ChildPath "$FunctionName.ps1" $Content = $Template.Replace('###TEMPLATE_FUNCTION_NAME', $FunctionName) $Verb = ($FunctionName -split '-', 2)[0] if ($Verb -in $StateChangingVerbs) { # Functions that change state must support -WhatIf and -Confirm $Content = $Content.Replace('[CmdletBinding()]', '[CmdletBinding(SupportsShouldProcess = $true)]') $Content = $Content -replace '(?m)^([ \t]*)(Write-Verbose "Processing ''\$Name''\.")', ('$1if ($PSCmdlet.ShouldProcess($Name, ''' + $Verb + ''')) {' + "`n" + '$1 $2' + "`n" + '$1}') } if ((Test-Path -Path $FunctionPath) -and -not $Force) { if (-not $PSCmdlet.ShouldContinue("The file '$FunctionPath' already exists. Do you want to overwrite it?", 'Confirm overwrite')) { Write-Warning "The function '$FunctionPath' was skipped." continue } } if (-not $PSCmdlet.ShouldProcess($FunctionPath, 'Create function file')) { continue } try { Set-Content -Path $FunctionPath -Value $Content -NoNewline -Force -ErrorAction Stop $Created++ if ($PassThru) { Get-Item -Path $FunctionPath } } catch { $Failures++ Write-Error "The function '$FunctionPath' was not created. Error: $($_.Exception.Message)" } } } end { Write-Verbose "Created $Created out of $Requested function(s)." Invoke-TelemetryCollection @TelemetryArgs -Stage End -Failed ($Failures -gt 0) } } |