KnowIT.Builder.psm1
#region === Source functions === ### Source file: 'Build-KnowITModule.ps1' ### function Build-KnowITModule { [CmdletBinding()] param( [switch]$MergePSM ) $ErrorActionPreference = 'Stop' try { BuildPSM -Merge:$MergePSM BuildManifest } catch { Write-Error $_ } } ### Source file: 'Get-ModuleInfo.ps1' ### function Get-ModuleInfo { param( [string]$Path = '.' ) try { $rootFolder = Convert-Path $Path $buildModuleFile = Join-Path $rootFolder 'module.psd1' if(!(Test-Path $buildModuleFile -PathType Leaf)) { throw "Not found 'module.psd1' file in project folder [$rootFolder]" } $data = Import-PowerShellDataFile $buildModuleFile -ErrorAction Stop $data.ProjectFolder = $rootFolder $data.PSSourceFiles = $data.PSSourceFiles.ForEach({ Join-Path $rootFolder 'src' $_ }) $outDir = $data.OutputFolder ?? 'out' $data.OutputFolder = Join-Path $rootFolder $outDir $data.ModuleName $data } catch { Write-Error $_ } } ### Source file: 'BuildPSM.ps1' ### function BuildPSM ([switch]$Merge) { $ErrorActionPreference = 'Stop' $moduleData = Get-ModuleInfo $moduleName = $moduleData.ModuleName $output = $moduleData.OutputFolder Write-Build Blue "Module output location: [$output]" $null = New-Item $output -ItemType Directory -Force try { Write-Build Magenta " Building module file: '$moduleName.psm1'..." Push-Location (Join-Path $moduleData.ProjectFolder 'src') $sourceBuilder = [Text.StringBuilder]::new() $usings = [Collections.Generic.SortedSet[string]]::new([StringComparer]::OrdinalIgnoreCase) $requires = [Collections.Generic.SortedSet[string]]::new([StringComparer]::OrdinalIgnoreCase) $sourceFiles = Get-ChildItem $moduleData.PSSourceFiles -Include '*.ps1' -Recurse [void]$sourceBuilder.AppendLine("`n#region === Source functions ===") foreach($source in $sourceFiles) { [void]$sourceBuilder.AppendLine("`n### Source file: '$($source.Name)' ###") Get-Content $source | ParseSource $sourceBuilder $usings $requires } [void]$sourceBuilder.AppendLine("`n#endregion") $currentPSM = "$moduleName.psm1" if($Merge -and (Test-Path $currentPSM)) { Write-Build Magenta ' Merging current PSM file...' [void]$sourceBuilder.AppendLine("`n#region === Source .psm1 file ===") Get-Content $currentPSM | ParseSource $sourceBuilder $usings $requires -SkipRegion '=== .Source files ===' [void]$sourceBuilder.AppendLine("`n#endregion") } # Header for PSM file (using directives must be at the top followed by #requires) if($requires.Count -gt 0) { [void]$sourceBuilder.Insert(0, "#requires -Modules $($requires -join ', ')`n") Write-Build Magenta ' Writing ''requires.txt'' file...' $requires | Set-Content "$output/requires.txt" -Encoding utf8BOM } if($usings.Count -gt 0) { [void]$sourceBuilder.Insert(0, "$($usings -join "`n")`n") } $sourceCode = $sourceBuilder.ToString() #TODO:External help if($script:HelpFile) { $helpPattern = "(?ms)(\<#.*?\.SYNOPSIS.*?#>)" $externalHelp = "# .ExternalHelp $ModuleName-help.xml`n" $sourceCode = $sourceCode -replace $helpPattern, $externalHelp } $sourceCode | Set-Content "$output/$moduleName.psm1" -Encoding utf8BOM if($additional = $moduleData.AdditionalFiles) { Write-Build Magenta " Copying additional files '$additional'..." Copy-Item $additional -Destination $output -Recurse -Force } } finally { Pop-Location } } filter ParseSource { param($Builder, $Usings, $Requires, $SkipRegion) begin { $skipPattern = [string]::IsNullOrWhiteSpace($SkipRegion) ? '^#region\ SKIP_BUILD' : "^#region\ (SKIP_BUILD|$([regex]::Escape($SkipRegion)))" $skipping = $false $lineNumber = 0 } process { $lineNumber++ switch -Regex ($_) { '^\s*using' { [void]$Usings.Add($_.Trim()) break } '^\s*#requires -Modules\s*(.*)' { $Matches[1].Split(','). ForEach({ [void]$Requires.Add($_.Trim()) }) break } $skipPattern { if($skipping) { throw "Nested skipped regions are not supported. Line: $lineNumber" } $skipping = $true break } '^#endregion' { if(!$skipping) { [void]$SourceBuilder.AppendLine($_) } else { $skipping = $false } } default { if(!$skipping) { [void]$SourceBuilder.AppendLine($_) } } } } } ### Source file: 'Common.ps1' ### function Write-Build { param( $Color, $Message ) Write-Verbose $Message -Verbose } ### Source file: 'Manifest.ps1' ### function BuildManifest { $moduleData = Get-ModuleInfo $moduleName = $moduleData.ModuleName Write-Build Magenta " Actualizando archivo Manifest: '$moduleName.psd1'..." $manifest = $moduleData.Manifest $allowedParams = (Get-Command New-ModuleManifest).Parameters.Keys $invalidKeys = $manifest.Keys.Where({ $_ -notin $allowedParams }) if($invalidKeys.Count -gt 0) { Write-Warning "Found invalid keys in Manifest: ($($invalidKeys -join ', '))" $invalidKeys.ForEach({ $manifest.Remove($_) }) } $manifest.PrivateData ??= @{} $version, $prerelease = $moduleData.Version.Split('-', 2) $manifest.ModuleVersion = $version if($prerelease) { $manifest.PreRelease = $prerelease } $manifest.PrivateData.FullVersion = $moduleData.Version $manifest.RootModule = "$moduleName.psm1" $manifest.Description = $moduleData.Description $manifest.FunctionsToExport = GetPublicFunctions if($moduleData.ExternalModules) { $manifest.RequiredModules = $moduleData.ExternalModules $manifest.ExternalModuleDependencies = $moduleData.ExternalModules } # $manifest.NestedModules = $NestedModules # $manifest.RequiredAssemblies = $Assemblies.ForEach({"bin/$_.dll"}) $manifest.Path = Join-Path $moduleData.OutputFolder "$moduleName.psd1" Write-Debug 'Module Manifest Parameters:' Write-Debug ($manifest | Out-String) New-ModuleManifest @manifest } function GetPublicFunctions { $publicFolder = $moduleData.PSSourceFiles.Where({ (Split-Path $_ -Leaf) -eq 'Public' }) (Get-ChildItem $publicFolder -Include '*.ps1' -Recurse).BaseName } #endregion |