Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $script:LoaderRoot = Split-Path -Parent $MyInvocation.MyCommand.Path $script:ConfigPath = Join-Path -Path $script:LoaderRoot -ChildPath 'config.json' $script:ConfigCache = $null function Get-ProjectStructureConfig { if ($null -ne $script:ConfigCache) { return $script:ConfigCache } if (Test-Path -LiteralPath $script:ConfigPath) { try { $raw = Get-Content -LiteralPath $script:ConfigPath -Raw -ErrorAction Stop if ($raw.Trim().Length -gt 0) { $script:ConfigCache = $raw | ConvertFrom-Json return $script:ConfigCache } } catch { Write-Warning "Failed to parse config.json: $($_.Exception.Message)" } } $script:ConfigCache = [pscustomobject]@{} return $script:ConfigCache } function Get-ConfigValue { param( [Parameter(Mandatory)] [string]$Name, $Default = $null ) $config = Get-ProjectStructureConfig if ($config.PSObject.Properties.Name -contains $Name) { $value = $config.$Name if ($null -ne $value -and ($value -isnot [string] -or $value.Trim().Length -gt 0)) { return $value } } return $Default } function Get-StructDirectory { $value = Get-ConfigValue -Name 'structDir' if ($null -eq $value -or [string]::IsNullOrWhiteSpace($value)) { return $script:LoaderRoot } if ([System.IO.Path]::IsPathRooted($value)) { $resolved = Resolve-Path -LiteralPath $value -ErrorAction SilentlyContinue if ($null -ne $resolved) { return $resolved.Path } return $value } $candidate = Join-Path -Path $script:LoaderRoot -ChildPath $value $resolvedCandidate = Resolve-Path -LiteralPath $candidate -ErrorAction SilentlyContinue if ($null -ne $resolvedCandidate) { return $resolvedCandidate.Path } return $candidate } function Get-ProjectsRoot { $value = Get-ConfigValue -Name 'projectsRoot' if ($null -eq $value -or [string]::IsNullOrWhiteSpace($value)) { $structDir = Get-StructDirectory $parent = Split-Path -Parent $structDir if ($null -eq $parent -or $parent.Length -eq 0 -or $parent -eq $structDir) { return $structDir } return $parent } if ([System.IO.Path]::IsPathRooted($value)) { $resolved = Resolve-Path -LiteralPath $value -ErrorAction SilentlyContinue if ($null -ne $resolved) { return $resolved.Path } return $value } $candidate = Join-Path -Path $script:LoaderRoot -ChildPath $value $resolvedCandidate = Resolve-Path -LiteralPath $candidate -ErrorAction SilentlyContinue if ($null -ne $resolvedCandidate) { return $resolvedCandidate.Path } return $candidate } function Use-IsoDailyFormat { $dailyFormat = Get-ConfigValue -Name 'dailyFormat' -Default $true return [bool]$dailyFormat } function Use-7Zip { $zipper = Get-ConfigValue -Name 'zipper' -Default $true return [bool]$zipper } function Get-ZipCompressionLevel { $value = Get-ConfigValue -Name 'compression' -Default 9 if ($value -is [string]) { $parsed = 0 if ([int]::TryParse($value, [ref]$parsed)) { $value = $parsed } } if ($value -isnot [int]) { return 9 } return [Math]::Min(9, [Math]::Max(0, $value)) }