Public/New-PstModuleManifest.ps1

function New-PstModuleManifest {
    <#
.SYNOPSIS
    Generates a PowerShell module manifest by enumerating all function files in the Public folder and updating the module version.
.DESCRIPTION
    This function automates the process of creating a PowerShell module manifest by scanning the specified Public folder for all .ps1 files, extracting the function names, updating the module version by incrementing the build number, and including them in the manifest.
.PARAMETER PublicFolderPath
    The path to the Public folder containing the function files.
.PARAMETER ManifestPath
    The path where the module manifest will be created.
.PARAMETER RootModule
    The name of the root module file.
.EXAMPLE
    New-PstModuleManifest -PublicFolderPath "C:\MyModule\Public" -ManifestPath "C:\MyModule\MyModule.psd1" -RootModule "MyModule.psm1"
#>

    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory = $false, Position = 0, HelpMessage = "The path to the Public folder containing the function files.")]
        [string]$PublicFolderPath = "$(Get-PublicPath)",
        [Parameter(Mandatory = $false, Position = 1, HelpMessage = "The path where the module manifest will be created.")]
        [string]$ManifestPath = "$(Get-ModulePSScriptRoot)",
        [Parameter(Mandatory = $false, Position = 2, HelpMessage = "The name of the root module file.")]
        [string]$RootModule = "$([System.IO.Path]::GetFileNameWithoutExtension($(Get-ModuleRootFileName)))"
    )
    begin {
        Write-Debug -Message "Begin '$($MyInvocation.MyCommand.Name)' at '$(Get-Date)'"
        if (-not (Test-Path $PublicFolderPath)) {
            throw "PublicFolderPath not found: $PublicFolderPath"
        } else {
            Write-Verbose "PublicFolderPath found: $PublicFolderPath"
        }
        if (-not (Test-Path $ManifestPath)) {
            throw "ManifestPath not found: $ManifestPath"
        } else {
            Write-Verbose "ManifestPath found: $ManifestPath"
        }
        $RootModuleFileName = "$($RootModule).psm1"
        $RootModulePath = Join-Path -Path $ManifestPath -ChildPath $RootModuleFileName
        if (-not (Test-Path $RootModulePath)) {
            throw "RootModulePath file not found: $RootModulePath"
        } else {
            Write-Verbose "RootModulePath file found: $RootModulePath"
        }
        $RootManifestFileName = "$($RootModule).psd1"
        $ManifestFilePath = Join-Path -Path $ManifestPath -ChildPath $RootManifestFileName
    }
    process {
        try {
            Write-Verbose -Message "Get all the .ps1 files in the Public folder '$($PublicFolderPath)'"
            $FunctionFiles = Get-ChildItem -Path $PublicFolderPath -Filter *.ps1
            Write-Verbose -Message "Extract the function names from the files"
            $FunctionNames = foreach ($File in $FunctionFiles) {
                [System.IO.Path]::GetFileNameWithoutExtension($($File.FullName))
            }
            Write-Verbose -Message "Ensure the FunctionNames array is not empty or null"
            if (-not $FunctionNames) {
                Write-Error "No functions found in the Public folder."
                return
            }
            Write-Verbose -Message "Read the module version from the root module file"
            if (-not (Test-Path -Path $RootModulePath)) {
                Write-Error "Root module file '$RootModulePath' not found."
                return
            }
            $RootModuleContent = Get-Content -Path $RootModulePath
            $UpdatedContent = New-Object System.Collections.ArrayList
            $versionFound = $false
            $regionDeclarationsFound = $false
            $ModuleVersion = $null
            foreach ($Line in $RootModuleContent) {
                if ($Line -match '\[version\]\$Script:PstModuleVersion\s*=') {
                    # Extract the current version and increment the revision by 1
                    $currentVersion = [version]($Line -replace '.*?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', '$1')
                    $ModuleVersion = [version]::new($currentVersion.Major, $currentVersion.Minor, $currentVersion.Build, $currentVersion.Revision + 1)
                    # Replace the existing version line with the new version
                    $UpdatedContent.Add('[version]$Script:PstModuleVersion = "' + $ModuleVersion.ToString() + '"') > $null
                    $versionFound = $true
                } else {
                    $UpdatedContent.Add($Line) > $null
                }
                if ($Line -match '#region Declarations') {
                    $regionDeclarationsFound = $true
                }
            }
            # If the version line was not found, initialize $ModuleVersion and insert it after #region Declarations with version 0.0.0.1
            if (-not $versionFound -and $regionDeclarationsFound) {
                $ModuleVersion = [version]"0.0.0.1"
                for ($i = 0; $i -lt $UpdatedContent.Count; $i++) {
                    if ($UpdatedContent[$i] -match '#region Declarations') {
                        $UpdatedContent.Insert($i + 1, '[version]$Script:PstModuleVersion = "' + $ModuleVersion.ToString() + '"') > $null
                        break
                    }
                }
            }
            # Write the updated content back to the file
            $UpdatedContent | Set-Content -Path $RootModulePath
            New-ModuleManifest  -Path $ManifestFilePath `
                -RootModule $RootModuleFileName `
                -FunctionsToExport $FunctionNames `
                -ModuleVersion $ModuleVersion `
                -CmdletsToExport @() `
                -VariablesToExport @() `
                -AliasesToExport @()
            Write-Output "New Module manifest created '$($ManifestFilePath)' for RootModuleFileName '$($RootModuleFileName)', ModuleVersion '$($ModuleVersion)"
        }
        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)'"
        }
    }
}