Advanced Template Module Generator Tool
<# .SYNOPSIS Advanced Template Module Generator Tool .DESCRIPTION This script provides an interactive tool to generate a comprehensive structure for a PowerShell module, including advanced features like dependency management, script analyzer settings, and extensive testing setup. .NOTES File Name : AdvancedTemplateModuleGenerator.ps1 Author : [Your Name] Prerequisite : PowerShell V5.1 or later Version : 1.0 Date : [Current Date] .EXAMPLE .\AdvancedTemplateModuleGenerator.ps1 #> function Show-Menu { Clear-Host Write-Host "=== Advanced Template Module Generator Tool ===" -ForegroundColor Cyan Write-Host "1. Set Module Details" Write-Host "2. Add Public Function" Write-Host "3. Add Private Function" Write-Host "4. Add Module Dependencies" Write-Host "5. Configure Build Settings" Write-Host "6. Configure Test Settings" Write-Host "7. Generate Module Files" Write-Host "8. Exit" } function Set-ModuleDetails { $script:moduleName = Read-Host "Enter the name of the module" $script:moduleDescription = Read-Host "Enter a brief description of the module" $script:moduleAuthor = Read-Host "Enter the author's name" $script:moduleVersion = Read-Host "Enter the module version (e.g., 1.0.0)" $script:moduleLicense = Read-Host "Enter the module license (e.g., MIT)" $script:moduleProjectUri = Read-Host "Enter the project URI (optional)" Write-Host "Module details set successfully." -ForegroundColor Green } function Add-PublicFunction { $functionName = Read-Host "Enter the name of the public function" $script:publicFunctions += $functionName Write-Host "Public function '$functionName' added." -ForegroundColor Green } function Add-PrivateFunction { $functionName = Read-Host "Enter the name of the private function" $script:privateFunctions += $functionName Write-Host "Private function '$functionName' added." -ForegroundColor Green } function Add-ModuleDependencies { do { $dependencyName = Read-Host "Enter the name of the module dependency (or press Enter to finish)" if ($dependencyName -ne "") { $dependencyVersion = Read-Host "Enter the required version (leave blank for any version)" $script:moduleDependencies += [PSCustomObject]@{ Name = $dependencyName Version = $dependencyVersion } Write-Host "Dependency added: $dependencyName $dependencyVersion" -ForegroundColor Green } } while ($dependencyName -ne "") } function Set-BuildSettings { $script:usePSScriptAnalyzer = (Read-Host "Use PSScriptAnalyzer for code analysis? (Y/N)") -eq 'Y' $script:useplatyPS = (Read-Host "Use platyPS for documentation generation? (Y/N)") -eq 'Y' Write-Host "Build settings configured." -ForegroundColor Green } function Set-TestSettings { $script:usePester = (Read-Host "Use Pester for testing? (Y/N)") -eq 'Y' $script:useCodeCoverage = (Read-Host "Include code coverage in tests? (Y/N)") -eq 'Y' Write-Host "Test settings configured." -ForegroundColor Green } function Generate-ModuleFiles { if ([string]::IsNullOrWhiteSpace($script:moduleName)) { Write-Host "Please set module details first." -ForegroundColor Yellow return } $modulePath = Join-Path -Path $PWD -ChildPath $script:moduleName New-Item -Path $modulePath -ItemType Directory -Force | Out-Null # Create module manifest $manifestPath = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psd1" $manifestParams = @{ Path = $manifestPath RootModule = "$($script:moduleName).psm1" ModuleVersion = $script:moduleVersion Author = $script:moduleAuthor Description = $script:moduleDescription FunctionsToExport = $script:publicFunctions PowerShellVersion = '5.1' } if ($script:moduleLicense) { $manifestParams['LicenseUri'] = $script:moduleLicense } if ($script:moduleProjectUri) { $manifestParams['ProjectUri'] = $script:moduleProjectUri } if ($script:moduleDependencies) { $manifestParams['RequiredModules'] = $script:moduleDependencies | ForEach-Object { if ($_.Version) { @{ModuleName = $_.Name; ModuleVersion = $_.Version} } else { $_.Name } } } New-ModuleManifest @manifestParams # Create module script file $modulePSM1Path = Join-Path -Path $modulePath -ChildPath "$($script:moduleName).psm1" $modulePSM1Content = @" # Dot source public/private functions `$public = @(Get-ChildItem -Path `$PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue) `$private = @(Get-ChildItem -Path `$PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue) foreach (`$import in @(`$public + `$private)) { try { . `$import.FullName } catch { Write-Error -Message "Failed to import function `$(`$import.FullName): `$_" } } # Export public functions Export-ModuleMember -Function `$public.BaseName "@ Set-Content -Path $modulePSM1Path -Value $modulePSM1Content # Create Public and Private folders New-Item -Path (Join-Path -Path $modulePath -ChildPath "Public") -ItemType Directory -Force | Out-Null New-Item -Path (Join-Path -Path $modulePath -ChildPath "Private") -ItemType Directory -Force | Out-Null # Create function files foreach ($function in $script:publicFunctions) { $functionPath = Join-Path -Path $modulePath -ChildPath "Public\$function.ps1" $functionContent = @" function $function { <# .SYNOPSIS Brief description of $function .DESCRIPTION Detailed description of $function .PARAMETER Param1 Description of Param1 .EXAMPLE $function -Param1 Value Explanation of the example .NOTES Additional notes about the function #> [CmdletBinding()] param ( [Parameter(Mandatory=`$true)] [string]`$Param1 ) begin { # Initialize any prerequisites } process { # Main function logic } end { # Cleanup or final actions } } "@ Set-Content -Path $functionPath -Value $functionContent } foreach ($function in $script:privateFunctions) { $functionPath = Join-Path -Path $modulePath -ChildPath "Private\$function.ps1" $functionContent = @" function $function { [CmdletBinding()] param ( [Parameter(Mandatory=`$true)] [string]`$Param1 ) # Function logic here } "@ Set-Content -Path $functionPath -Value $functionContent } # Create tests folder and files $testsFolderPath = Join-Path -Path $modulePath -ChildPath "Tests" New-Item -Path $testsFolderPath -ItemType Directory -Force | Out-Null if ($script:usePester) { $testFilePath = Join-Path -Path $testsFolderPath -ChildPath "$($script:moduleName).Tests.ps1" $testFileContent = @" `$ModuleName = '$($script:moduleName)' `$ModuleManifestPath = "`$PSScriptRoot\..\`$ModuleName.psd1" Describe "`$ModuleName Module Tests" { BeforeAll { `$Module = Import-Module `$ModuleManifestPath -PassThru -Force } It "Module manifest is valid" { Test-ModuleManifest -Path `$ModuleManifestPath | Should -Not -BeNullOrEmpty `$? | Should -Be `$true } It "Module can be imported" { `$Module | Should -Not -BeNullOrEmpty } Context "Function Tests" { # Add tests for each function $(foreach ($function in $script:publicFunctions) { @" It "$function exists" { Get-Command $function -Module `$ModuleName | Should -Not -BeNullOrEmpty } "@ }) } } "@ Set-Content -Path $testFilePath -Value $testFileContent } # Create build configuration $buildFolderPath = Join-Path -Path $modulePath -ChildPath "Build" New-Item -Path $buildFolderPath -ItemType Directory -Force | Out-Null $buildFilePath = Join-Path -Path $buildFolderPath -ChildPath "build.ps1" $buildFileContent = @" param ( [switch]`$Test, [switch]`$Analyze, [switch]`$Documentation ) `$ModuleName = '$($script:moduleName)' `$ModuleRoot = "`$PSScriptRoot\.." `$OutputPath = "`$ModuleRoot\Output" # Clean and create output directory if (Test-Path -Path `$OutputPath) { Remove-Item -Path `$OutputPath -Recurse -Force } New-Item -Path `$OutputPath -ItemType Directory -Force | Out-Null # Copy module files to output directory Copy-Item -Path "`$ModuleRoot\`$ModuleName.psd1" -Destination `$OutputPath Copy-Item -Path "`$ModuleRoot\`$ModuleName.psm1" -Destination `$OutputPath Copy-Item -Path "`$ModuleRoot\Public" -Destination `$OutputPath -Recurse Copy-Item -Path "`$ModuleRoot\Private" -Destination `$OutputPath -Recurse if (`$Test) { # Run Pester tests `$testResults = Invoke-Pester -Path "`$ModuleRoot\Tests" -PassThru if (`$testResults.FailedCount -gt 0) { throw "One or more tests failed." } } if (`$Analyze) { # Run PSScriptAnalyzer `$analysisResults = Invoke-ScriptAnalyzer -Path `$OutputPath -Recurse if (`$analysisResults) { `$analysisResults | Format-Table throw "PSScriptAnalyzer found one or more issues." } } if (`$Documentation) { # Generate documentation using platyPS Import-Module platyPS New-MarkdownHelp -Module `$ModuleName -OutputFolder "`$OutputPath\docs" -Force } Write-Host "Build completed successfully." -ForegroundColor Green "@ Set-Content -Path $buildFilePath -Value $buildFileContent # Create PSScriptAnalyzer settings file if ($script:usePSScriptAnalyzer) { $analyzerSettingsPath = Join-Path -Path $modulePath -ChildPath "PSScriptAnalyzerSettings.psd1" $analyzerSettingsContent = @" @{ Severity = @('Error', 'Warning') ExcludeRules = @('PSUseShouldProcessForStateChangingFunctions') Rules = @{ PSAvoidUsingCmdletAliases = @{ Whitelist = @('Where', 'Select') } } } "@ Set-Content -Path $analyzerSettingsPath -Value $analyzerSettingsContent } Write-Host "Module files generated successfully at: $modulePath" -ForegroundColor Green } # Initialize variables $script:moduleName = "" $script:moduleDescription = "" $script:moduleAuthor = "" $script:moduleVersion = "" $script:moduleLicense = "" $script:moduleProjectUri = "" $script:publicFunctions = @() $script:privateFunctions = @() $script:moduleDependencies = @() $script:usePSScriptAnalyzer = $false $script:useplatyPS = $false $script:usePester = $false $script:useCodeCoverage = $false # Main program loop do { Show-Menu $choice = Read-Host "`nEnter your choice (1-8)" switch ($choice) { "1" { Set-ModuleDetails } "2" { Add-PublicFunction } "3" { Add-PrivateFunction } "4" { Add-ModuleDependencies } "5" { Set-BuildSettings } "6" { Set-TestSettings } "7" { Generate-ModuleFiles } "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break } default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red } } if ($choice -ne "8") { Read-Host "`nPress Enter to continue..." } } while ($choice -ne "8")
This Advanced Template Module Generator Tool includes:
- A menu-driven interface for easy navigation.
- Enhanced functions to:
- Set detailed module information (including license and project URI)
- Add public and private functions
- Specify module dependencies
- Configure build and test settings
Key features:
- Advanced Module Manifest Generation:
- Includes more detailed module information
- Supports specifying module dependencies
- Comprehensive Module Structure:
- Creates a more robust folder structure including build and test directories
- Enhanced Function File Generation:
- Generates more detailed function templates
- Build Script Generation:
- Creates a build.ps1 script for module building, testing, and documentation generation
- Test Configuration:
- Sets up Pester tests with placeholders for each public function
- Optionally includes code coverage settings
- PSScriptAnalyzer Integration:
- Generates a PSScriptAnalyzer settings file
- Includes PSScriptAnalyzer in the build process
- Documentation Support:
- Optionally sets up platyPS for documentation generation
- Dependency Management:
- Allows specifying module dependencies with version requirements
This tool is particularly useful for:
- Experienced PowerShell module developers
- Teams working on larger PowerShell projects
- Developers who want to follow best practices in module development
To use this script effectively:
- Run the script in PowerShell
- Use the menu options to:
- Set detailed module information
- Add public and private functions
- Specify dependencies and configure build/test settings
- Generate the module files
- Review the generated module structure and customize as needed
This advanced script provides a more comprehensive starting point for PowerShell module development, incorporating best practices and tools commonly used in professional PowerShell module projects.