Public/New-PowerShellProject.ps1
|
function New-PowerShellProject { <# .SYNOPSIS Creates a PowerShell module project. .DESCRIPTION Creates a conventional PowerShell module layout with a valid manifest, module root, README, gitignore, and Pester import test. .PARAMETER Name Project directory name. .PARAMETER Path Parent directory in which the project is created. .PARAMETER ModuleName PowerShell module name. Defaults to Name. .PARAMETER Description Module description used in the manifest and README.md. .PARAMETER Force Allows an existing project directory and overwrites generated files. .EXAMPLE mkpsproj ExampleTools #> [CmdletBinding(SupportsShouldProcess = $true)] [Alias('mkpsproj')] [OutputType([System.IO.DirectoryInfo])] param( [Parameter(Mandatory = $true, Position = 0)] [ValidatePattern('^[A-Za-z0-9][A-Za-z0-9._-]*$')] [string]$Name, [Parameter()] [string]$Path = (Get-Location).Path, [Parameter()] [string]$ModuleName, [Parameter()] [string]$Description = 'PowerShell module generated by DevXToolkit.', [switch]$Force ) if ([string]::IsNullOrWhiteSpace($ModuleName)) { $ModuleName = $Name } if ($ModuleName -notmatch '^[A-Za-z][A-Za-z0-9._-]*$') { throw "ModuleName '$ModuleName' must start with a letter and contain only letters, numbers, dots, underscores, or hyphens." } $projectRoot = Resolve-DtContainedPath -BasePath $Path -ChildName $Name if ((Test-Path -LiteralPath $projectRoot) -and -not $Force) { throw "Project already exists. Use -Force to update generated files: $projectRoot" } if (-not $PSCmdlet.ShouldProcess($projectRoot, 'Create PowerShell module project')) { return } $moduleRoot = Join-Path -Path $projectRoot -ChildPath "src/$ModuleName" $testsRoot = Join-Path -Path $projectRoot -ChildPath 'tests' New-DtDirectory -Path $projectRoot -Confirm:$false | Out-Null New-DtDirectory -Path $moduleRoot -Confirm:$false | Out-Null New-DtDirectory -Path $testsRoot -Confirm:$false | Out-Null $safeTitle = ConvertTo-DtSafeMarkdownText -Text $Name $safeDescription = ConvertTo-DtSafeMarkdownText -Text $Description $manifestDescription = $safeDescription.Replace("'", "''") $moduleGuid = [guid]::NewGuid().ToString() $manifest = @" @{ RootModule = '$ModuleName.psm1' ModuleVersion = '0.1.0' GUID = '$moduleGuid' Author = 'Generated by DevXToolkit' Description = '$manifestDescription' PowerShellVersion = '5.1' FunctionsToExport = @() CmdletsToExport = @() VariablesToExport = @() AliasesToExport = @() } "@ $moduleContent = @" # $ModuleName Set-StrictMode -Version Latest "@ $testContent = @" BeforeAll { Import-Module (Join-Path `$PSScriptRoot '../src/$ModuleName/$ModuleName.psd1') -Force } Describe '$ModuleName' { It 'imports successfully' { Get-Module '$ModuleName' | Should -Not -BeNullOrEmpty } } "@ $readme = @" # $safeTitle $safeDescription ## Test ``````powershell Invoke-Pester ./tests `````` "@ $gitignore = @" artifacts/ TestResults/ *.nupkg "@ Set-DtFileContent -Path (Join-Path $moduleRoot "$ModuleName.psd1") -Content $manifest -Force:$Force -Confirm:$false | Out-Null Set-DtFileContent -Path (Join-Path $moduleRoot "$ModuleName.psm1") -Content $moduleContent -Force:$Force -Confirm:$false | Out-Null Set-DtFileContent -Path (Join-Path $testsRoot "$ModuleName.Tests.ps1") -Content $testContent -Force:$Force -Confirm:$false | Out-Null Set-DtFileContent -Path (Join-Path $projectRoot 'README.md') -Content $readme -Force:$Force -Confirm:$false | Out-Null Set-DtFileContent -Path (Join-Path $projectRoot '.gitignore') -Content $gitignore -Force:$Force -Confirm:$false | Out-Null Get-Item -LiteralPath $projectRoot } |