11function Invoke-PSMDTemplate {
2- <#
2+ <#
33 . SYNOPSIS
44 Creates a project/file from a template.
55
4949 By default, all parameters will be replaced during invocation.
5050 In Raw mode, this is skipped, reproducing mostly the original template input (dynamic scriptblocks will now be named scriptblocks)).
5151
52+ . PARAMETER GenerateObjects
53+ By default, Invoke-PSMDTemplate generates files.
54+ In GenerateObjects mode, no file but objects are created.
55+
5256 . PARAMETER Force
5357 If the target path the template should be written to (filename or folder name within $OutPath), then overwrite it.
5458 By default, this function will fail if an overwrite is required.
7882#>
7983 [Diagnostics.CodeAnalysis.SuppressMessageAttribute (" PSPossibleIncorrectUsageOfAssignmentOperator" , " " )]
8084 [Diagnostics.CodeAnalysis.SuppressMessageAttribute (' PSReviewUnusedParameter' , ' ' )]
81- [Alias (' imt' )]
85+ [OutputType ([PSModuleDevelopment.Template.TemplateResult ])]
86+ [Alias (' imt' )]
8287 [CmdletBinding (SupportsShouldProcess = $true )]
8388 param (
8489 [Parameter (Mandatory = $true , Position = 0 , ParameterSetName = ' NameStore' )]
119124 [switch ]
120125 $Raw ,
121126
127+ [switch ]
128+ $GenerateObjects ,
129+
122130 [switch ]
123131 $Force ,
124132
175183 [bool ]
176184 $Raw ,
177185
186+ [switch ]
187+ $GenerateObjects ,
188+
178189 [bool ]
179190 $Silent
180191 )
212223 }
213224 }
214225 # endregion Scripts
215-
216- switch ($templateData.Type.ToString ()) {
226+ $createdTemplateItems = switch ($templateData.Type.ToString ()) {
217227 # region File
218- " File"
219- {
228+ " File" {
220229 foreach ($child in $templateData.Children ) {
221- Write -TemplateItem - Item $child - Path $OutPath - Encoding $Encoding - ParameterFlat $Parameters - ParameterScript $scriptParameters - Raw $Raw
230+ New -TemplateItem - Item $child - Path $OutPath - ParameterFlat $Parameters - ParameterScript $scriptParameters - Raw $Raw
222231 }
223232 if ($Raw -and $templateData.Scripts.Values ) {
224233 $templateData.Scripts.Values | Export-Clixml - Path (Join-Path $OutPath " _PSMD_ParameterScripts.xml" )
227236 # endregion File
228237
229238 # region Project
230- " Project"
231- {
239+ " Project" {
232240 # region Resolve output folder
233241 if (-not $NoFolder ) {
234242 if ($Parameters [" Name" ]) {
247255 # endregion Resolve output folder
248256
249257 foreach ($child in $templateData.Children ) {
250- Write -TemplateItem - Item $child - Path $newFolder.FullName - Encoding $Encoding - ParameterFlat $Parameters - ParameterScript $scriptParameters - Raw $Raw
258+ New -TemplateItem - Item $child - Path $newFolder.FullName - ParameterFlat $Parameters - ParameterScript $scriptParameters - Raw $Raw
251259 }
252260
253261 # region Write Config File (Raw)
278286 $optionsTemplate = $optionsTemplate -replace " þþþPLACEHOLDER-$ ( $guid ) þþþ" , " "
279287 }
280288
281- $configFile = Join-Path $newFolder.FullName " PSMDTemplate.ps1"
282- Set-Content - Path $configFile - Value $optionsTemplate - Encoding ([PSFEncoding ]' utf-8' ).Encoding
289+ [PSModuleDevelopment.Template.TemplateResult ]@ {
290+ Name = " PSMDTemplate.ps1"
291+ Path = $newFolder.FullName
292+ FullPath = (Join-Path $newFolder.FullName " PSMDTemplate.ps1" )
293+ Content = $optionsTemplate
294+ }
283295 }
284296 # endregion Write Config File (Raw)
285297 }
286298 # endregion Project
287299 }
300+ If ($GenerateObjects ) {
301+ return $createdTemplateItems
302+ }
303+ Write-TemplateResult - TemplateResult $createdTemplateItems - Encoding $Encoding
288304 }
289305
290- function Write -TemplateItem {
306+ function New -TemplateItem {
291307 [Diagnostics.CodeAnalysis.SuppressMessageAttribute (" PSUseShouldProcessForStateChangingFunctions" , " " )]
308+ [OutputType ([PSModuleDevelopment.Template.TemplateResult ])]
292309 [CmdletBinding ()]
293310 param (
294311 [PSModuleDevelopment.Template.TemplateItemBase ]
297314 [string ]
298315 $Path ,
299316
300- [PSFEncoding ]
301- $Encoding ,
302-
303317 [hashtable ]
304318 $ParameterFlat ,
305319
309323 [bool ]
310324 $Raw
311325 )
312-
313- Write-PSFMessage - Level Verbose - Message " Creating file: $ ( $Item.Name ) ($ ( $Item.RelativePath ) )" - FunctionName Invoke-PSMDTemplate - ModuleName PSModuleDevelopment - Tag ' create' , ' template'
326+ Write-PSFMessage - Level Verbose - Message " Creating Template-Item: $ ( $Item.Name ) ($ ( $Item.RelativePath ) )" - FunctionName Invoke-PSMDTemplate - ModuleName PSModuleDevelopment - Tag ' create' , ' template'
314327
315328 $identifier = $Item.Identifier
316329 $isFile = $Item.GetType ().Name -eq ' TemplateItemFile'
320333 $fileName = $Item.Name
321334 if (-not $Raw ) {
322335 foreach ($param in $Item.FileSystemParameterFlat ) {
323- $fileName = [PSModuleDevelopment.Utility.UtilityHost ]::Replace($fileName , " $ ( $identifier ) $ ( $param ) $ ( $identifier ) " , $ParameterFlat [$param ], $false )
336+ $fileName = [PSModuleDevelopment.Utility.UtilityHost ]::Replace($fileName , " $ ( $identifier ) $ ( $param ) $ ( $identifier ) " , $ParameterFlat [$param ], $false )
324337 }
325338 foreach ($param in $Item.FileSystemParameterScript ) {
326339 $fileName = [PSModuleDevelopment.Utility.UtilityHost ]::Replace($fileName , " $ ( $identifier ) $ ( $param ) $ ( $identifier ) " , $ParameterScript [$param ], $false )
338351 $text = [PSModuleDevelopment.Utility.UtilityHost ]::Replace($text , " $ ( $identifier ) !$ ( $param ) !$ ( $identifier ) " , $ParameterScript [$param ], $false )
339352 }
340353 }
341- [System.IO.File ]::WriteAllText($destPath , $text , $Encoding )
354+ return [PSModuleDevelopment.Template.TemplateResult ]@ {
355+ Name = $fileName
356+ Path = $Path
357+ FullPath = $destPath
358+ Content = $text
359+ }
342360 }
343361 else {
344362 $bytes = [System.Convert ]::FromBase64String($Item.Value )
345- [System.IO.File ]::WriteAllBytes($destPath , $bytes )
363+ return [PSModuleDevelopment.Template.TemplateResult ]@ {
364+ Name = $fileName
365+ Path = $Path
366+ FullPath = $destPath
367+ Content = $bytes
368+ IsText = $false
369+ }
346370 }
347371 }
348372 # endregion File
358382 $folderName = $folderName -replace " $ ( $identifier ) !$ ( [regex ]::Escape($param )) !$ ( $identifier ) " , $ParameterScript [$param ]
359383 }
360384 }
361- $folder = New-Item - Path $Path - Name $folderName - ItemType Directory
385+ $folder = Join-Path - Path $Path - ChildPath $folderName
386+
387+ # Return a folder object to make sure empty folders are not excluded
388+ [PSModuleDevelopment.Template.TemplateResult ]@ {
389+ Name = $folderName
390+ Path = $Path
391+ FullPath = $folder
392+ IsFolder = $true
393+ IsText = $false
394+ }
362395
363396 foreach ($child in $Item.Children ) {
364- Write -TemplateItem - Item $child - Path $folder.FullName - Encoding $Encoding - ParameterFlat $ParameterFlat - ParameterScript $ParameterScript - Raw $Raw
397+ New -TemplateItem - Item $child - Path $folder - ParameterFlat $ParameterFlat - ParameterScript $ParameterScript - Raw $Raw
365398 }
366399 }
367400 # endregion Folder
368401 }
402+
403+ function Write-TemplateResult {
404+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute (" PSUseShouldProcessForStateChangingFunctions" , " " )]
405+ [CmdletBinding ()]
406+ param (
407+ [PSModuleDevelopment.Template.TemplateResult []]
408+ $TemplateResult ,
409+
410+ [PSFEncoding ]
411+ $Encoding
412+ )
413+ $msgParam = @ { Level = ' Verbose' ; FunctionName = ' Invoke-PSMDTemplate' }
414+ foreach ($item in $TemplateResult | Sort-Object { $_.FullPath.Length }) {
415+ Write-PSFMessage @msgParam - Message " Creating file: $ ( $item.FullPath ) " - FunctionName Invoke-PSMDTemplate - ModuleName PSModuleDevelopment - Tag ' create' , ' template'
416+ if (-not (Test-Path $item.Path )) {
417+ Write-PSFMessage - Level Verbose - Message " Creating Folder $ ( $item.Path ) "
418+ $null = New-Item - Path $item.Path - ItemType Directory
419+ }
420+ if ($item.IsFolder ) {
421+ if (-not (Test-Path $item.FullPath )) {
422+ Write-PSFMessage @msgParam - Message " Creating Folder $ ( $item.FullPath ) "
423+ $null = New-Item - Path $item.FullPath - ItemType Directory
424+ }
425+ continue
426+ }
427+ if ($item.IsText ) {
428+ Write-PSFMessage @msgParam - Message " Creating as a Text-File"
429+ [System.IO.File ]::WriteAllText($item.FullPath , $item.Content , $Encoding )
430+ }
431+ else {
432+ Write-PSFMessage @msgParam - Message " Creating as a Binary-File"
433+ [System.IO.File ]::WriteAllBytes($item.FullPath , $item.Content )
434+ }
435+ }
436+ }
369437 # endregion Helper function
370438 }
371439 process {
372440 if (Test-PSFFunctionInterrupt ) { return }
373441
374442 $invokeParam = @ {
375- Parameters = $Parameters.Clone ()
376- OutPath = Resolve-PSFPath - Path $OutPath
377- NoFolder = $NoFolder
378- Encoding = $Encoding
379- Raw = $Raw
380- Silent = $Silent
443+ Parameters = $Parameters.Clone ()
444+ OutPath = Resolve-PSFPath - Path $OutPath
445+ NoFolder = $NoFolder
446+ Encoding = $Encoding
447+ Raw = $Raw
448+ Silent = $Silent
449+ GenerateObjects = $GenerateObjects
381450 }
382451
383452 foreach ($item in $Template ) {
391460 } - EnableException $EnableException - PSCmdlet $PSCmdlet - Continue
392461 }
393462 }
394- }
463+ }
0 commit comments