PsKrane.psm1
Enum ProjectType { Module Script } Class KraneFile { #CraneFile is a class that represents the .Krane.json file that is used to store the configuration of the Krane project. [System.IO.FileInfo]$Path [System.Collections.Hashtable]$Data = @{} [Bool]$IsPresent KraneFile([String]$Path) { #Handeling case when Path doesn't exists yet (For creation scenarios) $Root = "" if((Test-Path -Path $Path) -eq $False){ if($Path.EndsWith(".krane.json")){ [System.Io.DirectoryInfo]$Root = ([System.Io.FileInfo]$Path).Directory } else { [System.Io.DirectoryInfo]$Root = $Path } }else{ #Path exists. We need to determine if it is a file or a folder. $Item = Get-Item -Path $Path if($Item.PSIsContainer){ $Root = $Item }else{ $Root = $Item.Directory } } $this.Path = Join-Path -Path $Root.FullName -ChildPath ".krane.json" $this.IsPresent = $this.Path.Exists if (!$this.Path.Exists) { #Krane file doesn't exists. No point in importing data from a file that doesn't exists. $this.Data = @{} return } $Raw = Get-Content -Path $This.Path.FullName -Raw | ConvertFrom-Json #Convert the JSON to a hashtable as it is easier to manipulate. foreach ($key in $Raw.PsObject.Properties) { $this.Data.$($key.Name) = $key.Value } } [String]Get([String]$Key) { return $this.Data.$Key } [Void]Set([String]$Key, [String]$Value) { $this.Data.$Key = $Value } [Void]Save() { if (!($this.Path.Exists)){ $Null = [System.Io.Directory]::CreateDirectory($this.Path.Directory.FullName) | Out-Null } $this.Data | ConvertTo-Json | Out-File -Path $this.Path.FullName -Encoding utf8 -Force $this.Path.Refresh() $this.IsPresent = $this.File.Exists } [void]Fetch() { $Raw = Get-Content -Path $This.Path.FullName -Raw | ConvertFrom-Json #Convert the JSON to a hashtable as it is easier to manipulate. foreach ($key in $Raw.PsObject.Properties) { $this.Data.$($key.Name) = $key.Value } $this.Path.Refresh() $this.IsPresent = $this.Path.Exists } [String]ToString() { return "ProjectName:{0} ProjectType:{1}" -f $this.Get("Name"), $this.Get("ProjectType") } static [KraneFile] Create([System.IO.DirectoryInfo]$Path, [String]$Name, [ProjectType]$Type) { $KraneFile = [KraneFile]::New($Path) if ($KraneFile.Path.Exists) { Throw ".Krane File $($KraneFile.Path.FullName) already exists" } $KraneFile.Set("Name", $Name) $KraneFile.Set("ProjectType", $Type) $KraneFile.Set("ProjectVersion", "0.0.1") $KraneFile.Save() Return $KraneFile } } Class KraneProject { [KraneFile]$KraneFile [ProjectType]$ProjectType [System.IO.DirectoryInfo]$Root KraneProject() {} KraneProject([System.IO.DirectoryInfo]$Root) { $this.KraneFile = [KraneFile]::New($Root) } } Class KraneModule : KraneProject { [String]$ModuleName [System.IO.FileInfo]$ModuleFile [System.IO.FileInfo]$ModuleDataFile [System.IO.DirectoryInfo]$Build [System.IO.DirectoryInfo]$Sources [System.IO.DirectoryInfo]$Tests [System.IO.DirectoryInfo]$Outputs [String[]] $Tags = @( 'PSEdition_Core', 'PSEdition_Desktop' ) [String]$Description [String]$ProjectUri Hidden [System.Collections.Hashtable]$ModuleData = @{} #Add option Overwrite KraneModule([System.IO.DirectoryInfo]$Root){ #When the module Name is Not passed, we assume that a .Krane.json file is already present. $this.KraneFile = [KraneFile]::New($Root) $this.ProjectType = [ProjectType]::Module $this.Root = $Root $this.Build = "$($Root.FullName)\Build" $this.Sources = "$($Root.FullName)\Sources" $this.Tests = "$($Root.FullName)\Tests" $this.Outputs = "$($Root.FullName)\Outputs" #get the module name from the krane file $mName = $this.KraneFile.Get("Name") $this.SetModuleName($mName) $this.ProjectType = $this.KraneFile.Get("ProjectType") $this.FetchModuleInfo() } KraneModule([System.IO.DirectoryInfo]$Root, [String]$ModuleName) { #When the module Name is passed, we assume that the module is being created, and that there is not a .Krane.json file present. yet. #$this.KraneFile = [KraneFile]::New($Root) $This.KraneFile = [KraneFile]::Create($Root, $ModuleName, [ProjectType]::Module) $this.ProjectType = [ProjectType]::Module $this.Root = $Root $this.Build = "$Root\Build" $this.Sources = "$Root\Sources" $this.Tests = "$Root\Tests" $this.Outputs = "$Root\Outputs" $this.ModuleName = $ModuleName <# if (($this.Build.Exists -eq $false) -or ($this.Sources.Exists -eq $false) -or ($this.Tests.Exists -eq $false)) { Throw "No Build, Sources or Tests folder found in $($This.Root)" } #> $this.FetchModuleInfo() } hidden [void] FetchModuleInfo() { if (($null -eq $this.ModuleName)) { Throw "Module Name not provided." } $this.SetModuleName($this.ModuleName) if ($this.ModuleDataFile.Exists) { $this.ModuleData = Import-PowerShellDataFile -Path $this.ModuleDataFile.FullName $this.Description = $this.ModuleData.Description $this.ProjectUri = $this.ModuleData.PrivateData.PsData.ProjectUri $this.Tags = $this.ModuleData.PrivateData.PsData.Tags } } [void] BuildModule() { Write-Verbose "[KraneModule][BuildModule] Start" Write-Verbose "[KraneModule][BuildModule][PSM1] Starting PSM1 Operations $($this.ModuleName)" if ($this.ModuleFile.Exists) { Write-Verbose "[KraneModule][BuildModule][PSM1] Module file already exists. Deleting." $this.ModuleFile.Delete() $this.ModuleFile.Refresh() } Write-Verbose "[KraneModule][BuildModule][PSM1] (Re)creating file $($this.ModuleFile.FullName)" $Null = New-Item -Path $this.ModuleFile.FullName -ItemType "file" -Force $MainPSM1Contents = @() Write-Verbose "[KraneModule][BuildModule][PSM1] Searching for classes and functions" [System.IO.FileInfo]$PreContentPath = Join-Path -Path $this.Sources.FullName -ChildPath "PreContent.ps1" If ($PrecontentPath.Exists) { Write-Verbose "[KraneModule][BuildModule][PSM1] Precontent.ps1 file found. Adding to module file." $MainPSM1Contents += $PreContentPath } else { Write-Verbose "[KraneModule][BuildModule][PSM1] No Precontent detected." } [System.IO.DirectoryInfo]$ClassFolderPath = Join-Path -Path $this.Sources.FullName -ChildPath "Classes" If ($ClassFolderPath.Exists) { $PublicClasses = Get-ChildItem -Path $ClassFolderPath.FullName -Filter *.ps1 | sort-object Name if($PublicClasses){ write-Verbose "[KraneModule][BuildModule][PSM1] Classes Found. Importing..." $MainPSM1Contents += $PublicClasses } } [System.IO.DirectoryInfo]$PrivateFunctionsFolderPath = Join-Path -Path $this.Sources.FullName -ChildPath "Functions/Private" If ($PrivateFunctionsFolderPath.Exists) { $Privatefunctions = Get-ChildItem -Path $PrivateFunctionsFolderPath.FullName -Filter *.ps1 | sort-object Name if ($Privatefunctions) { write-Verbose "[KraneModule][BuildModule][PSM1] Private functions Found. Importing..." $MainPSM1Contents += $Privatefunctions } } $Publicfunctions = $null [System.IO.DirectoryInfo]$PublicFunctionsFolderPath = Join-Path -Path $this.Sources.FullName -ChildPath "Functions/Public" If ($PublicFunctionsFolderPath.Exists) { $Publicfunctions = Get-ChildItem -Path $PublicFunctionsFolderPath.FullName -Filter *.ps1 | sort-object Name if ($Publicfunctions) { write-Verbose "[KraneModule][BuildModule][PSM1] Public functions Found. Importing..." $MainPSM1Contents += $Publicfunctions } } [System.IO.FileInfo]$PostContentPath = Join-Path -Path $this.Sources.FullName -ChildPath "postContent.ps1" If ($PostContentPath.Exists) { write-Verbose "[KraneModule][BuildModule][PSM1] Postcontent Found. Importing..." $MainPSM1Contents += $PostContentPath } #Creating PSM1 write-Verbose "[KraneModule][BuildModule][PSM1] Building PSM1 content" Foreach ($file in $MainPSM1Contents) { write-Verbose "[KraneModule][BuildModule][PSM1] Adding -> $($File.FullName)" Get-Content $File.FullName | out-File -FilePath $this.ModuleFile.FullName -Encoding utf8 -Append } Write-verbose "[KraneModule][BuildModule][PSD1] Starding PSD1 actions. Adding functions to export" if (!$this.ModuleDataFile.Exists) { Write-verbose "[KraneModule][BuildModule][PSD1] Module Manifest not found. Creating one." New-ModuleManifest -Path $this.ModuleDataFile.FullName } $ManifestParams = @{} $ManifestParams.Path = $this.ModuleDataFile.FullName $ManifestParams.FunctionsToExport = $Publicfunctions.BaseName $ManifestParams.Tags = $This.Tags $ManifestParams.RootModule = $this.ModuleFile.Name $ManifestParams.Description = $this.Description $ManifestParams.ProjectUri = $this.ProjectUri Write-verbose "[KraneModule][BuildModule][PSD1] Writing Manifest settings:" foreach ($ManifestSetting in $ManifestParams.GetEnumerator()) { Write-Verbose "[KraneModule][BuildModule][PSD1][Setting] $($ManifestSetting.Key) -> $($ManifestSetting.Value)" } try{ Update-ModuleManifest @ManifestParams }Catch{ Write-Error "[KraneModule][BuildModule][PSD1] Error updating module manifest. $_" } Write-Verbose "[KraneModule][BuildModule] End" } [void] SetModuleName([String]$ModuleName) { $this.ModuleName = $ModuleName $this.ModuleFile = Join-Path -Path $this.Outputs.FullName -ChildPath "Module\$($ModuleName).psm1" $this.ModuleDataFile = Join-Path -Path $this.Outputs.FullName -ChildPath "Module\$($ModuleName).psd1" } [void] CreateBaseStructure(){ if($this.Outputs.Exists -eq $false){ $Null = New-Item -Path $this.Outputs.FullName -ItemType "directory" } if($this.Build.Exists -eq $false){ $Null = New-Item -Path $this.Build.FullName -ItemType "directory" } if($this.Sources.Exists -eq $false){ $Null = New-Item -Path $this.Sources.FullName -ItemType "directory" } [System.IO.DirectoryInfo] $PrivateFunctions = Join-Path -Path $this.Sources.FullName -ChildPath "Functions/Private" if ($PrivateFunctions.Exists -eq $false) { $Null = New-Item -Path $PrivateFunctions.FullName -ItemType "directory" } [System.IO.DirectoryInfo] $PublicFunctions = Join-Path -Path $this.Sources.FullName -ChildPath "Functions/Public" if ($PublicFunctions.Exists -eq $false) { $Null = New-Item -Path $PublicFunctions.FullName -ItemType "directory" } if($this.Tests.Exists -eq $false){ $Null = New-Item -Path $this.Tests.FullName -ItemType "directory" } } [void]ReverseBuild(){ #ReverseBuild will take the module file and extract the content to the sources folder. #It will also update the module manifest with the new functions. Throw "Not implemented yet" } } Class ModuleObfuscator { [String]$ModuleName [KraneModule]$Module [System.IO.DirectoryInfo]$Bin [System.IO.FileInfo]$BinaryModuleFile [System.IO.FileInfo]$ModuleDataFile Obfuscator() {} SetKraneModule([KraneModule]$Module) { $Module.ModuleDataFile.Refresh() if (!$Module.ModuleDataFile.Exists) { Write-Verbose "[BUILD][OBFUSCATE] Module data file Not found. Building module" $this.Module.BuildModule() } $this.Module = $Module $this.Bin = $Module.Outputs.FullName + "\Bin" $this.BinaryModuleFile = Join-Path -Path $this.Bin.FullName -ChildPath ($this.Module.ModuleFile.BaseName + ".dll") $this.ModuleDataFile = $this.Bin.FullName + "\" + $this.Module.ModuleName + ".psd1" } Obfuscate() { Write-Verbose "[BUILD][OBFUSCATE] Obfuscating module" Write-Verbose "[BUILD][OBFUSCATE] Starting psd1 operations" if (!$this.ModuleDataFile.Exists) { $this.Module.ModuleDataFile.CopyTo($this.ModuleDataFile.FullName) $this.ModuleDataFile.Refresh() } #Does seem to work. #Update-ModuleManifest -Path $this.ModuleDataFile.FullName -RootModule $this.BinaryModuleFile.Name $MdfContent = Get-Content -Path $this.ModuleDataFile.FullName $MdfContent.Replace($this.Module.ModuleFile.Name, $this.BinaryModuleFile.Name) | Set-Content -Path $this.ModuleDataFile.FullName #We obfuscate #Create the DLL in the Artifacts folder } } Class KraneFactory { static [KraneProject]GetProject([System.IO.FileInfo]$KraneFile) { $KraneDocument = [KraneFile]::New($KraneFile) $ProjectType = $KraneDocument.Get("ProjectType") $Root = $KraneFile.Directory switch ($ProjectType) { "Module" { write-verbose "[KraneFactory][GetProject] Returning root project of type Module $($Root.FullName)" return [KraneModule]::New($Root) } default { Throw "Project type $ProjectType not supported" } } Throw "Project type $ProjectType not supported" #For some strange reason, having the throw in the switch statement does no suffice for the compiler... } } Class NuSpecFile { [KraneModule]$KraneModule [String]$Version [System.IO.DirectoryInfo]$ExportFolderPath [System.IO.FileInfo]$NuSpecFilePath hidden [String]$RawContent NuspecFile([KraneModule]$KraneModule) { $this.SetKraneModule($KraneModule) $this.ExportFolderPath = Join-Path -Path $this.KraneModule.Outputs -ChildPath "Nuget" } SetKraneModule([KraneModule]$KraneModule) { $this.KraneModule = $KraneModule } hidden [Void]Generate() { $psd1Data = Import-PowerShellDataFile -Path $this.KraneModule.ModuleDataFile.FullName $NuSpecString = @" <?xml version="1.0" encoding="utf-8"?> <package> <metadata> <id>{0}</id> <version>{1}</version> <authors>{2}</authors> <requireLicenseAcceptance>false</requireLicenseAcceptance> <license type="expression">MIT</license> <!-- <icon>icon.png</icon> --> <projectUrl>{3}</projectUrl> <description>{4}</description> <releaseNotes>{5}</releaseNotes> <copyright>Copyright All rights reserved</copyright> <tags>{6}</tags> <dependencies> </dependencies> </metadata> </package> "@ $Id = $this.KraneModule.ModuleName #0 $this.Version = $psd1Data.ModuleVersion #1 $Authors = $psd1Data.Author #2 $ProjectUri = $psd1Data.PrivateData.PsData.ProjectUri #3 $Description = $psd1Data.Description #4 $ReleaseNotes = $psd1Data.releaseNotes #4 $Tags = $psd1Data.PrivateData.PsData.tags -join "," #5 $Final = $NuSpecString -f $Id, $this.Version, $Authors, $ProjectUri, $Description, $ReleaseNotes, $Tags $this.RawContent = $Final } [System.IO.FileInfo] CreateNuSpecFile() { $this.Generate() $Modulefolder = Join-Path -Path $this.KraneModule.Outputs.FullName -ChildPath "Module" $this.NuSpecFilePath = Join-Path -Path $Modulefolder -ChildPath ($this.KraneModule.ModuleName + ".nuspec") $this.RawContent | Out-File -FilePath $this.NuspecFilePath -Encoding utf8 -Force Return $this.NuspecFilePath } CreateNugetFile() { & nuget pack $this.NuSpecFilePath.FullName -OutputDirectory $this.ExportFolderPath } } Class PsScriptFile { [System.Io.FileInfo]$Path } Class BuildScript : PsScriptFile { #Creates the build script that will be used to build the module and create the nuspec file BuildScript([KraneModule]$KraneModule) { $this.Path = Join-Path -Path $KraneModule.Build.FullName -ChildPath "Build.Krane.ps1" } BuildScript([System.Io.DirectoryInfo]$Path) { $this.Path = Join-Path -Path $Path.FullName -ChildPath "Build.Krane.ps1" } [void] CreateBuildScript() { $Content = @' # This script is used to invoke PsKrane and to build the module and create the nuspec file install-Module PsKrane -Repository PSGallery -Force import-Module PsKrane -Force $psr = $PSScriptRoot $Root = split-Path -Path $psr -Parent $KraneModule = Get-KraneProject -Root $Root $KraneModule.Description = "This module is a test module" $KraneModule.ProjectUri = "http://link.com" $KraneModule.BuildModule() New-KraneNugetFile -KraneModule $KraneModule -Force '@ $Content | Out-File -FilePath $this.Path.FullName -Encoding utf8 -Force } } Class TestScript : PsScriptFile { #Creates the test script that will be used to test the module TestScript([KraneModule]$KraneModule,[String]$TestName) { if(!($TestName.Contains(".Tests.ps1"))){ $TestName = $TestName + ".Tests.ps1" } $this.Path = Join-Path -Path $KraneModule.Tests.FullName -ChildPath $TestName } [void] CreateTestScript() { if(Test-Path $this.Path.FullName){ Write-Verbose "[Krane][TestScript][CreateTestScript]Test script $($this.Path.FullName) already exists" return } #Create the test script $Content = @' # Generated with love using PsKrane Import-Module PsKrane [System.IO.DirectoryInfo]$psroot = $PSScriptRoot $KraneProject = Get-KraneProject -Root $PsRoot.Parent Import-Module $($KraneProject.ModuleDataFile.FullName) -Force InModuleScope -ModuleName $KraneProject.ModuleName -ScriptBlock { Describe "Should return Plop" { it "Should return Plop" { $result = Write-Plop $result | Should -Be "Plop" } } } '@ Write-Verbose "[Krane][TestScript][CreateTestScript]Creating Test script at -> $($this.Path.FullName)" $Content | Out-File -FilePath $this.Path.FullName -Encoding utf8 -Force } } # Public functions Function New-KraneProject { <# .SYNOPSIS Creates a new Krane project .DESCRIPTION Will create a base .krane.json project file. The project can be either a module or a script. Use -Force to create the base structure of the project. .NOTES Author: Stéphane vg .LINK https://github.com/Stephanevg/PsKrane .EXAMPLE New-KraneProject -Type Module -Path C:\Users\Stephane\Code\KraneTest\wip -Name "wip" -verbose ModuleName : wip ModuleFile : C:\Users\Stephane\Code\KraneTest\wip\Outputs\Module\wip.psm1 ModuleDataFile : C:\Users\Stephane\Code\KraneTest\wip\Outputs\Module\wip.psd1 Build : C:\Users\Stephane\Code\KraneTest\wip\Build Sources : C:\Users\Stephane\Code\KraneTest\wip\Sources Tests : C:\Users\Stephane\Code\KraneTest\wip\Tests Outputs : C:\Users\Stephane\Code\KraneTest\wip\Outputs Tags : {PSEdition_Core, PSEdition_Desktop} Description : ProjectUri : KraneFile : ProjectName:wip ProjectType:Module ProjectType : Module Root : C:\Users\Stephane\Code\KraneTest\wip .EXAMPLE New-KraneProject -Type Module -Path C:\Users\Stephane\Code\KraneTest\plop -Name "Plop" -Force When using force, it will create the base structure of the project. C:\USERS\STEPHANE\CODE\KRANETEST\PLOP │ .krane.json ├───Build │ └───Build.Krane.ps1 ├───Outputs ├───Sources │ └───Functions │ ├───Private │ └───Public └───Tests #> [cmdletBinding()] [OutputType([KraneProject])] Param( [Parameter(Mandatory = $True, HelpMessage = "Type of project to create. Can be either 'Module' or 'Script'")] [ProjectType]$Type, [Parameter(Mandatory = $True, HelpMessage = "Name of the project")] [String]$Name, [Parameter(Mandatory = $True, HelpMessage = "Root folder of the project")] [System.IO.DirectoryInfo]$Path, [Switch]$Force ) switch($Type) { "Module" { $KraneProject = [KraneModule]::New($Path, $Name) } default { Throw "Project type $Type not supported" } } if($Force){ $KraneProject.CreateBaseStructure() Add-KraneBuildScript -KraneModule $KraneProject } Return $KraneProject } Function New-KraneNuspecFile { <# .SYNOPSIS Creates a new NuSpec file .DESCRIPTION Creates a new Nuspec File based on a PsKrane project. .LINK https://github.com/Stephanevg/PsKrane .EXAMPLE $KraneProject = Get-KraneProject -Root C:\Plop\ New-KraneNuspecFile -KraneProject $KraneProject Generates a .nuspec file in .\Outputs\Module\ folder of the KraneProject #> Param( [Parameter(Mandatory = $True)] [KraneModule]$KraneModule ) $NuSpec = [NuSpecFile]::New($KraneModule) $NuSpec.CreateNuSpecFile() } Function Get-KraneProject { [CmdletBinding()] [OutputType([KraneProject])] Param( [Parameter(Mandatory = $False, HelpMessage = "Root folder of the project. If not specified, it assumes it is located in a folder called 'Build' in the root of the project.")] [System.IO.DirectoryInfo]$Root ) # Retrieve parent folder if (!$Root) { #Stole this part from PSHTML $EC = Get-Variable ExecutionContext -ValueOnly $Root = $ec.SessionState.Path.CurrentLocation.Path write-Verbose "[Get-KraneProject] Root parameter was omitted. Using Current location: $Root" } ElseIf($Root.Exists -eq $false) { Throw "Root $($Root.FullName) folder not found" } [System.IO.FileInfo]$KraneFile = Join-Path -Path $Root.FullName -ChildPath ".krane.json" If (!($KraneFile.Exists)){ Throw "No .Krane file found in $($Root.FullName). Verify the path, or create a new project using New-KraneProject" } write-Verbose "[Get-KraneProject] Fetching Krane project from path: $Root" Return [KraneFactory]::GetProject($KraneFile) } Function Add-KraneBuildScript { <# .SYNOPSIS Adds the build script to the project .DESCRIPTION Adds the build script to the project. The build script is used to invoke PsKrane and to build the module and create the nuspec file .NOTES Author: Stephane van Gulick version: 0.1 .LINK http://github.com/stephanevg/PsKrane .EXAMPLE Add-BuildScript -Root C:\Users\Stephane\Code\KraneTest\wip #> [CmdletBinding()] Param( [Parameter(Mandatory = $False, ParameterSetName="Path")] [System.IO.DirectoryInfo]$Path, [Parameter(Mandatory = $False, ParameterSetName = "KraneModule")] [KraneModule]$KraneModule ) Switch($PSCmdlet.ParameterSetName){ "Path" { $BuildScript = [BuildScript]::New($Path) $BuildScript.CreateBuildScript() } "KraneModule" { $BuildScript = [BuildScript]::New($KraneModule.Build) $BuildScript.CreateBuildScript() } } } Function New-KraneTestScript { <# .SYNOPSIS Creates a new test script .DESCRIPTION Creates a new test script in the Tests folder of the project .NOTES .PARAMETER KraneModule The KraneModule object that represents the project .PARAMETER TestName The name of the test script .EXAMPLE New-KraneTestScript -KraneModule $KraneModule -TestName "Plop" Creates a new test script called Plop.Tests.ps1 in the Tests folder of the project #> [CmdletBinding()] Param( [Parameter(Mandatory = $True)] [KraneModule]$KraneModule, [Parameter(Mandatory = $True)] [String]$TestName ) $TestScript = [TestScript]::New($KraneModule, $TestName) $TestScript.CreateTestScript() } Function Invoke-KraneBuild { [CmdletBinding()] Param( [KraneProject]$KraneProject ) $BuildFile = Join-Path -Path $KraneProject.Build.FullName -ChildPath "Build.Krane.ps1" if (!(Test-Path -Path $BuildFile)){ Throw "BuildFile $($BuildFile) not found. Please make sure it is there, and try again" } & $BuildFile } Function New-KraneNugetFile { <# .SYNOPSIS Creates a new nuget package .DESCRIPTION Create a new nuget package based for a specific kraneproject (Nuspec must already have been generated) .NOTES Information or caveats about the function e.g. 'This function is not supported in Linux' .LINK https://github.com/Stephanevg/PsKrane .EXAMPLE $KraneProject = Get-KraneProject -Root C:\Plop\ New-KraneNugetFile -KraneProject $KraneProject -Force Generates a .nupkg file in .\Outputs\Nuget\ folder of the KraneProject. -Force will create the nuspec file .PARAMETER KraneModule The KraneModule object that represents the project .PARAMETER Force Creates the nuspec file first #> Param( [Parameter(Mandatory = $True)] [KraneModule]$KraneModule, [Switch]$Force ) $NuSpec = [NuSpecFile]::New($KraneModule) if($Force){ $NuSpec.CreateNuSpecFile() } $NuSpec.CreateNugetFile() } |