< Summary - Kestrun — Combined Coverage

Information
Class: Public.Service.New-KrServiceDescriptor
Assembly: Kestrun.PowerShell.Public
File(s): /home/runner/work/Kestrun/Kestrun/src/PowerShell/Kestrun/Public/Service/New-KrServiceDescriptor.ps1
Tag: Kestrun/Kestrun@6135d944f8787fb570e4dfbacac6e80312799a86
Line coverage
92%
Covered lines: 47
Uncovered lines: 4
Coverable lines: 51
Total lines: 158
Line coverage: 92.1%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 03/26/2026 - 03:54:59 Line coverage: 90.9% (40/44) Total lines: 139 Tag: Kestrun/Kestrun@844b5179fb0492dc6b1182bae3ff65fa7365521d04/19/2026 - 15:52:57 Line coverage: 92.1% (47/51) Total lines: 158 Tag: Kestrun/Kestrun@765a8f13c573c01494250a29d6392b6037f087c9

Coverage delta

Coverage delta 2 -2

Metrics

File(s)

/home/runner/work/Kestrun/Kestrun/src/PowerShell/Kestrun/Public/Service/New-KrServiceDescriptor.ps1

#LineLine coverage
 1<#
 2.SYNOPSIS
 3    Creates a Service.psd1 descriptor file.
 4.DESCRIPTION
 5    Creates a Service.psd1 descriptor file used by Kestrun.Tool content-root service install flow.
 6    Required keys are FormatVersion, Name, Description, Version, and EntryPoint.
 7    Optional keys are ServiceLogPath, PreservePaths, and ApplicationDataFolders.
 8.PARAMETER Path
 9    Target descriptor path. Accepts either a descriptor file path or a directory path.
 10    When a directory path is provided, Service.psd1 is appended automatically.
 11.PARAMETER Name
 12    Immutable service name value written to the descriptor.
 13.PARAMETER Description
 14    Service description value.
 15.PARAMETER Version
 16    Service version. Must be compatible with System.Version.
 17.PARAMETER EntryPoint
 18    Optional entry point path relative to the content root. Defaults to Service.ps1.
 19.PARAMETER ServiceLogPath
 20    Optional default service log path.
 21.PARAMETER PreservePaths
 22    Optional list of relative file/folder paths that must be preserved during service update.
 23.PARAMETER ApplicationDataFolders
 24    Optional list of relative application-data folders that must be preserved during service update.
 25.PARAMETER Force
 26    Overwrite an existing descriptor file.
 27.PARAMETER WhatIf
 28    Shows what would happen if the cmdlet runs. The cmdlet is not executed.
 29.PARAMETER Confirm
 30    Prompts for confirmation before running the cmdlet.
 31.EXAMPLE
 32    New-KrServiceDescriptor -Name demo -Description 'Demo service' -Version 1.2.0
 33#>
 34function New-KrServiceDescriptor {
 35    [KestrunRuntimeApi('Everywhere')]
 36    [CmdletBinding(SupportsShouldProcess)]
 37    [OutputType([pscustomobject])]
 38    param(
 39        [Parameter()]
 40        [ValidateNotNullOrEmpty()]
 41        [string]$Path = 'Service.psd1',
 42
 43        [Parameter(Mandatory)]
 44        [ValidateNotNullOrEmpty()]
 45        [string]$Name,
 46
 47        [Parameter(Mandatory)]
 48        [ValidateNotNullOrEmpty()]
 49        [string]$Description,
 50
 51        [Parameter(Mandatory)]
 52        [ValidateNotNullOrEmpty()]
 53        [version]$Version,
 54
 55        [Parameter()]
 56        [string]$EntryPoint,
 57
 58        [Parameter()]
 59        [string]$ServiceLogPath,
 60
 61        [Parameter()]
 62        [string[]]$PreservePaths,
 63
 64        [Parameter()]
 65        [string[]]$ApplicationDataFolders,
 66
 67        [Parameter()]
 68        [switch]$Force
 69    )
 70
 171    $fullPath = [System.IO.Path]::GetFullPath($Path)
 172    if (Test-Path -LiteralPath $fullPath -PathType Container) {
 173        $fullPath = Join-Path -Path $fullPath -ChildPath 'Service.psd1'
 74    }
 75
 176    if ([System.IO.Path]::GetExtension($fullPath) -ne '.psd1') {
 077        throw "Path must target a .psd1 descriptor file or an existing directory: $fullPath"
 78    }
 79
 280    if ((Test-Path -LiteralPath $fullPath) -and -not $Force) {
 081        throw "Descriptor file already exists: $fullPath. Use -Force to overwrite."
 82    }
 83
 184    $directory = [System.IO.Path]::GetDirectoryName($fullPath)
 285    if (-not [string]::IsNullOrWhiteSpace($directory) -and -not (Test-Path -LiteralPath $directory)) {
 086        $null = New-Item -ItemType Directory -Path $directory -Force
 87    }
 88
 189    $escapedName = $Name.Replace("'", "''")
 190    $escapedDescription = $Description.Replace("'", "''")
 191    $escapedVersion = $Version.ToString().Replace("'", "''")
 392    $resolvedEntryPoint = if ([string]::IsNullOrWhiteSpace($EntryPoint)) { 'Service.ps1' } else { $EntryPoint }
 93
 194    if ([System.IO.Path]::IsPathRooted($resolvedEntryPoint)) {
 095        throw "EntryPoint must be a relative path under the descriptor directory: $resolvedEntryPoint"
 96    }
 97
 298    $entryPointPath = [System.IO.Path]::GetFullPath((Join-Path -Path $directory -ChildPath $resolvedEntryPoint))
 299    $descriptorRootWithSeparator = if ($directory.EndsWith([System.IO.Path]::DirectorySeparatorChar)) { $directory } els
 1100    if (-not $entryPointPath.StartsWith($descriptorRootWithSeparator, [System.StringComparison]::OrdinalIgnoreCase)) {
 1101        throw "EntryPoint must resolve to a file under descriptor path: $resolvedEntryPoint"
 102    }
 103
 2104    if (-not (Test-Path -LiteralPath $entryPointPath -PathType Leaf)) {
 1105        throw "EntryPoint file not found under descriptor path: $resolvedEntryPoint"
 106    }
 107
 1108    $escapedEntryPoint = $resolvedEntryPoint.Replace("'", "''")
 109
 1110    $contentLines = [System.Collections.Generic.List[string]]::new()
 1111    $contentLines.Add('@{')
 1112    $contentLines.Add("    FormatVersion = '1.0'")
 1113    $contentLines.Add("    Name = '$escapedName'")
 1114    $contentLines.Add("    Description = '$escapedDescription'")
 1115    $contentLines.Add("    Version = '$escapedVersion'")
 1116    $contentLines.Add("    EntryPoint = '$escapedEntryPoint'")
 117
 1118    if (-not [string]::IsNullOrWhiteSpace($ServiceLogPath)) {
 1119        $escapedServiceLogPath = $ServiceLogPath.Replace("'", "''")
 1120        $contentLines.Add("    ServiceLogPath = '$escapedServiceLogPath'")
 121    }
 122
 1123    if ($null -ne $PreservePaths -and $PreservePaths.Count -gt 0) {
 1124        $contentLines.Add('    PreservePaths = @(')
 1125        foreach ($preservePath in $PreservePaths) {
 1126            if ([string]::IsNullOrWhiteSpace($preservePath)) {
 127                continue
 128            }
 129
 1130            $escapedPreservePath = $preservePath.Replace("'", "''")
 1131            $contentLines.Add("        '$escapedPreservePath'")
 132        }
 133
 1134        $contentLines.Add('    )')
 135    }
 136
 1137    if ($null -ne $ApplicationDataFolders -and $ApplicationDataFolders.Count -gt 0) {
 1138        $contentLines.Add('    ApplicationDataFolders = @(')
 1139        foreach ($applicationDataFolder in $ApplicationDataFolders) {
 1140            if ([string]::IsNullOrWhiteSpace($applicationDataFolder)) {
 141                continue
 142            }
 143
 1144            $escapedApplicationDataFolder = $applicationDataFolder.Replace("'", "''")
 1145            $contentLines.Add("        '$escapedApplicationDataFolder'")
 146        }
 147
 1148        $contentLines.Add('    )')
 149    }
 150
 1151    $contentLines.Add('}')
 152
 1153    if ($PSCmdlet.ShouldProcess($fullPath, 'Create Service.psd1 descriptor')) {
 2154        Set-Content -LiteralPath $fullPath -Value ($contentLines -join [Environment]::NewLine) -Encoding utf8NoBOM
 155    }
 156
 1157    Get-KrServiceDescriptor -Path $fullPath
 158}

Methods/Properties

New-KrServiceDescriptor()