Skip to content

Commit 17da0ba

Browse files
psjamespHeyItsGilbert
authored andcommitted
Updated json support
1 parent a7a54f4 commit 17da0ba

5 files changed

Lines changed: 171 additions & 24 deletions

File tree

Plaster/JsonManifestHandler.ps1

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,85 @@ function New-JsonManifestStructure {
922922

923923
return $manifest
924924
}
925+
function Get-PlasterManifestType {
926+
[CmdletBinding()]
927+
[OutputType([string])]
928+
param(
929+
[Parameter(Mandatory)]
930+
[string]$ManifestPath
931+
)
932+
933+
if (-not (Test-Path -LiteralPath $ManifestPath)) {
934+
throw "Manifest file not found: $ManifestPath"
935+
}
936+
937+
try {
938+
$content = Get-Content -LiteralPath $ManifestPath -Raw -ErrorAction Stop
939+
940+
# Check file extension first
941+
$extension = [System.IO.Path]::GetExtension($ManifestPath).ToLower()
942+
if ($extension -eq '.json') {
943+
# Validate it's actually JSON
944+
try {
945+
$jsonObject = $content | ConvertFrom-Json -ErrorAction Stop
946+
# Check for Plaster 2.0 JSON schema
947+
if ($jsonObject.schemaVersion -eq '2.0') {
948+
return 'JSON'
949+
}
950+
# Also accept older JSON formats without strict version check
951+
if ($jsonObject.PSObject.Properties['metadata'] -and $jsonObject.PSObject.Properties['content']) {
952+
return 'JSON'
953+
}
954+
} catch {
955+
throw "File has .json extension but contains invalid JSON: $($_.Exception.Message)"
956+
}
957+
} elseif ($extension -eq '.xml') {
958+
# Validate it's actually XML
959+
try {
960+
$xmlDoc = New-Object System.Xml.XmlDocument
961+
$xmlDoc.LoadXml($content)
962+
if ($xmlDoc.DocumentElement.LocalName -eq 'plasterManifest') {
963+
return 'XML'
964+
}
965+
} catch {
966+
throw "File has .xml extension but contains invalid XML: $($_.Exception.Message)"
967+
}
968+
}
969+
970+
# If no extension or ambiguous, try to detect by content
971+
$trimmedContent = $content.TrimStart()
972+
973+
# Check for JSON format (starts with { or [)
974+
if ($trimmedContent -match '^[\s]*[\{\[]') {
975+
try {
976+
$jsonObject = $content | ConvertFrom-Json -ErrorAction Stop
977+
# Validate it's a Plaster JSON manifest
978+
if ($jsonObject.PSObject.Properties['metadata'] -and $jsonObject.PSObject.Properties['content']) {
979+
return 'JSON'
980+
}
981+
} catch {
982+
# Not valid JSON, continue to XML check
983+
}
984+
}
985+
986+
# Check for XML format
987+
if ($trimmedContent -match '^[\s]*<\?xml' -or $trimmedContent -match '<plasterManifest') {
988+
try {
989+
$xmlDoc = New-Object System.Xml.XmlDocument
990+
$xmlDoc.LoadXml($content)
991+
if ($xmlDoc.DocumentElement.LocalName -eq 'plasterManifest') {
992+
return 'XML'
993+
}
994+
} catch {
995+
# Not valid XML
996+
}
997+
}
998+
999+
throw "Unable to determine manifest format. File must be valid XML or JSON."
1000+
} catch {
1001+
throw "Error determining manifest type for '$ManifestPath': $($_.Exception.Message)"
1002+
}
1003+
}
9251004

9261005
# Export functions
9271006
Export-ModuleMember -Function @(

Plaster/PlasterVariables.ps1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Requires -Version 5.1
2+
3+
# Global variables and constants for Plaster 2.0
4+
5+
# Enhanced $TargetNamespace definition with proper scoping
6+
if (-not (Get-Variable -Name 'TargetNamespace' -Scope Script -ErrorAction SilentlyContinue)) {
7+
Set-Variable -Name 'TargetNamespace' -Value 'http://www.microsoft.com/schemas/PowerShell/Plaster/v1' -Scope Script -Option ReadOnly
8+
}
9+
10+
# Enhanced $DefaultEncoding definition
11+
if (-not (Get-Variable -Name 'DefaultEncoding' -Scope Script -ErrorAction SilentlyContinue)) {
12+
Set-Variable -Name 'DefaultEncoding' -Value 'UTF8-NoBOM' -Scope Script -Option ReadOnly
13+
}
14+
15+
# JSON Schema version for new manifests
16+
if (-not (Get-Variable -Name 'JsonSchemaVersion' -Scope Script -ErrorAction SilentlyContinue)) {
17+
Set-Variable -Name 'JsonSchemaVersion' -Value '2.0' -Scope Script -Option ReadOnly
18+
}
19+
20+
# Export the variables that need to be available globally
21+
Export-ModuleMember -Variable @('TargetNamespace', 'DefaultEncoding', 'JsonSchemaVersion')

Plaster/Private/Invoke-PlasterOperation.ps1

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@ function Invoke-PlasterOperation {
4242
[switch]
4343
$PassThru
4444
)
45-
4645
try {
4746
Write-PlasterLog -Level Debug -Message "Starting operation: $OperationName"
4847
$result = & $ScriptBlock
4948
Write-PlasterLog -Level Debug -Message "Completed operation: $OperationName"
5049

51-
if ($PassThru.IsPresent) {
50+
if ($PassThru) {
5251
return $result
5352
}
5453
} catch {

Plaster/Private/Write-PlasterLog.ps1

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ function Write-PlasterLog {
2828
consistent logging across various operations.
2929
It is not intended for direct use outside of the Plaster context.
3030
#>
31-
[CmdletBinding()]
3231
param(
3332
[Parameter(Mandatory)]
3433
[ValidateSet('Error', 'Warning', 'Information', 'Verbose', 'Debug')]
@@ -37,17 +36,56 @@ function Write-PlasterLog {
3736
[Parameter(Mandatory)]
3837
[string]$Message,
3938

39+
[Parameter()]
4040
[string]$Source = 'Plaster'
4141
)
4242

43+
# Check if we should log at this level
44+
$logLevels = @{
45+
'Error' = 0
46+
'Warning' = 1
47+
'Information' = 2
48+
'Verbose' = 3
49+
'Debug' = 4
50+
}
51+
52+
$currentLogLevel = $script:LogLevel ?? 'Information'
53+
$currentLevelValue = $logLevels[$currentLogLevel] ?? 2
54+
$messageLevelValue = $logLevels[$Level] ?? 2
55+
56+
if ($messageLevelValue -gt $currentLevelValue) {
57+
return
58+
}
59+
4360
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
4461
$logMessage = "[$timestamp] [$Level] [$Source] $Message"
4562

63+
# Handle different log levels appropriately
4664
switch ($Level) {
47-
'Error' { Write-Error $logMessage }
48-
'Warning' { Write-Warning $logMessage }
49-
'Information' { Write-Information $logMessage }
50-
'Verbose' { Write-Verbose $logMessage }
51-
'Debug' { Write-Debug $logMessage }
65+
'Error' {
66+
Write-Error $logMessage -ErrorAction Continue
67+
}
68+
'Warning' {
69+
Write-Warning $logMessage
70+
}
71+
'Information' {
72+
Write-Information $logMessage -InformationAction Continue
73+
}
74+
'Verbose' {
75+
Write-Verbose $logMessage
76+
}
77+
'Debug' {
78+
Write-Debug $logMessage
79+
}
80+
}
81+
82+
# Also write to host for immediate feedback during interactive sessions
83+
if ($Level -in @('Error', 'Warning') -and $Host.Name -ne 'ServerRemoteHost') {
84+
$color = switch ($Level) {
85+
'Error' { 'Red' }
86+
'Warning' { 'Yellow' }
87+
default { 'White' }
88+
}
89+
Write-Host $logMessage -ForegroundColor $color
5290
}
5391
}

Plaster/Public/Invoke-Plaster.ps1

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,20 @@ function Invoke-Plaster {
7272
# since we are only evaluating the parameters in the manifest - no need for Test-ConditionAttribute as we
7373
# are not building up multiple parametersets. And no need for EvaluateAttributeValue since we are only
7474
# grabbing the parameter's value which is static.
75-
$templateAbsolutePath = $ExecutionConteut # Load manifest file using culture lookup
75+
# Load manifest file using culture lookup - try both JSON and XML formats
76+
$manifestPath = GetPlasterManifestPathForCulture $templateAbsolutePath $PSCulture
77+
78+
# If XML not found, try JSON
79+
if (($null -eq $manifestPath) -or (!(Test-Path $manifestPath))) {
80+
$jsonManifestPath = Join-Path $templateAbsolutePath 'plasterManifest.json'
81+
if (Test-Path $jsonManifestPath) {
82+
$manifestPath = $jsonManifestPath
83+
}
84+
}
85+
86+
if (($null -eq $manifestPath) -or (!(Test-Path $manifestPath))) {
87+
return
88+
}
7689
# Determine manifest type and process accordingly
7790
try {
7891
$manifestType = Get-PlasterManifestType -ManifestPath $manifestPath
@@ -242,8 +255,7 @@ function Invoke-Plaster {
242255

243256
} else {
244257
# Load XML manifest
245-
246-
if (Test-Path -LiteralPath $manifestPath -PathType Leaf) {
258+
if ($manifestPath -and (Test-Path -LiteralPath $manifestPath -PathType Leaf)) {
247259
$manifest = Test-PlasterManifest -Path $manifestPath -ErrorAction Stop 3>$null
248260
$PSCmdlet.WriteDebug("Loading XML manifest file '$manifestPath'")
249261
} else {
@@ -262,16 +274,16 @@ function Invoke-Plaster {
262274
# Prepare output object if user has specified the -PassThru parameter.
263275
if ($PassThru) {
264276
$InvokePlasterInfo = [PSCustomObject]@{
265-
TemplatePath = if ($templateAbsolutePath) { $templateAbsolutePath } else { 'Inline Definition' }
277+
TemplatePath = if ($templateAbsolutePath) { $templateAbsolutePath } else { 'Inline Definition' }
266278
DestinationPath = $destinationAbsolutePath
267-
ManifestType = $manifestType
268-
Success = $false
269-
TemplateType = if ($manifest.plasterManifest.templateType) { $manifest.plasterManifest.templateType } else { 'Unspecified' }
270-
CreatedFiles = [string[]]@()
271-
UpdatedFiles = [string[]]@()
272-
MissingModules = [string[]]@()
273-
OpenFiles = [string[]]@()
274-
ProcessingTime = $null
279+
ManifestType = $manifestType
280+
Success = $false
281+
TemplateType = if ($manifest.plasterManifest.templateType) { $manifest.plasterManifest.templateType } else { 'Unspecified' }
282+
CreatedFiles = [string[]]@()
283+
UpdatedFiles = [string[]]@()
284+
MissingModules = [string[]]@()
285+
OpenFiles = [string[]]@()
286+
ProcessingTime = $null
275287
}
276288
}
277289

@@ -357,8 +369,7 @@ function Invoke-Plaster {
357369
} else {
358370
Write-PlasterLog -Level Information -Message "Template processing completed successfully in $($stopwatch.Elapsed.TotalSeconds) seconds"
359371
}
360-
}
361-
catch {
372+
} catch {
362373
$stopwatch.Stop()
363374
$errorMessage = "Template processing failed after $($stopwatch.Elapsed.TotalSeconds) seconds: $($_.Exception.Message)"
364375
Write-PlasterLog -Level Error -Message $errorMessage
@@ -370,8 +381,7 @@ function Invoke-Plaster {
370381
}
371382

372383
throw $_
373-
}
374-
finally {
384+
} finally {
375385
# Enhanced cleanup
376386
if ($script:constrainedRunspace) {
377387
$script:constrainedRunspace.Dispose()

0 commit comments

Comments
 (0)