Skip to content

Commit

Permalink
Console improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mdaneri committed Dec 12, 2024
1 parent caf1992 commit 41ab522
Show file tree
Hide file tree
Showing 9 changed files with 297 additions and 90 deletions.
2 changes: 1 addition & 1 deletion examples/Suspend-Resume.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ Start-PodeServer -Threads 4 -EnablePool Tasks -ScriptBlock {
Get-PodeSchedule -Name 'predefined'
Write-Verbose "Last: $($Event.Sender.LastTriggerTime)"
Write-Verbose "Next: $($Event.Sender.NextTriggerTime)"
Write-Verbose "Message1: $($Message1)"
Write-Verbose "Message1: $($Message1)"
Write-Verbose "Message2: $($Message2)"
}

Expand Down
20 changes: 13 additions & 7 deletions examples/server.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,19 @@
ShowEndpoints = $true
ShowHelp = $false
Colors = @{
Header = 'Cyan'
Help = 'Cyan'
EndpointsHeader = 'Green'
Endpoints = 'Yellow'
OpenApiUrls = 'White'
OpenApiHeaders = 'Green'
OpenApiTitles = 'Yellow'
Header = 'White'
Help = 'Cyan'
EndpointsHeader = 'Yellow'
Endpoints = 'Cyan'
OpenApiUrls = 'Cyan'
OpenApiHeaders = 'Yellow'
OpenApiTitles = 'White'
OpenApiSubtitles = 'Yellow'
HelpHeader = 'Yellow'
HelpKey = 'Green'
HelpDescription = 'White'
HelpDivider = 'Gray'
Divider = 'DarkGray'
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Locales/en-us/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
noLogicPassedForRouteExceptionMessage = 'No logic passed for Route: {0}'
scriptPathDoesNotExistExceptionMessage = 'The script path does not exist: {0}'
mutexAlreadyExistsExceptionMessage = 'A mutex with the following name already exists: {0}'
listeningOnEndpointsMessage = 'Listening on the following {0} endpoint(s) [{1} thread(s)]:'
listeningOnEndpointsMessage = 'Listening on {0} endpoint(s) [{1} thread(s)]:'
unsupportedFunctionInServerlessContextExceptionMessage = 'The {0} function is not supported in a serverless context.'
expectedNoJwtSignatureSuppliedExceptionMessage = 'Expected no JWT signature to be supplied.'
secretAlreadyMountedExceptionMessage = "A Secret with the name '{0}' has already been mounted."
Expand Down Expand Up @@ -277,7 +277,7 @@
discriminatorIncompatibleWithAllOfExceptionMessage = "The parameter 'Discriminator' is incompatible with 'allOf'."
noNameForWebSocketSendMessageExceptionMessage = 'No Name for a WebSocket to send message to supplied.'
hashtableMiddlewareNoLogicExceptionMessage = 'A Hashtable Middleware supplied has no Logic defined.'
openApiInfoMessage = 'OpenAPI Info:'
openApiInfoMessage = 'OpenAPI Information:'
invalidSchemeForAuthValidatorExceptionMessage = "The supplied '{0}' Scheme for the '{1}' authentication validator requires a valid ScriptBlock."
sseFailedToBroadcastExceptionMessage = 'SSE failed to broadcast due to defined SSE broadcast level for {0}: {1}'
adModuleWindowsOnlyExceptionMessage = 'Active Directory module only available on Windows OS.'
Expand Down
4 changes: 2 additions & 2 deletions src/Locales/en/Pode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
noLogicPassedForRouteExceptionMessage = 'No logic passed for Route: {0}'
scriptPathDoesNotExistExceptionMessage = 'The script path does not exist: {0}'
mutexAlreadyExistsExceptionMessage = 'A mutex with the following name already exists: {0}'
listeningOnEndpointsMessage = 'Listening on the following {0} endpoint(s) [{1} thread(s)]:'
listeningOnEndpointsMessage = 'Listening on {0} endpoint(s) [{1} thread(s)]:'
unsupportedFunctionInServerlessContextExceptionMessage = 'The {0} function is not supported in a serverless context.'
expectedNoJwtSignatureSuppliedExceptionMessage = 'Expected no JWT signature to be supplied.'
secretAlreadyMountedExceptionMessage = "A Secret with the name '{0}' has already been mounted."
Expand Down Expand Up @@ -277,7 +277,7 @@
discriminatorIncompatibleWithAllOfExceptionMessage = "The parameter 'Discriminator' is incompatible with 'allOf'."
noNameForWebSocketSendMessageExceptionMessage = 'No Name for a WebSocket to send message to supplied.'
hashtableMiddlewareNoLogicExceptionMessage = 'A Hashtable Middleware supplied has no Logic defined.'
openApiInfoMessage = 'OpenAPI Info:'
openApiInfoMessage = 'OpenAPI Information:'
invalidSchemeForAuthValidatorExceptionMessage = "The supplied '{0}' Scheme for the '{1}' authentication validator requires a valid ScriptBlock."
sseFailedToBroadcastExceptionMessage = 'SSE failed to broadcast due to defined SSE broadcast level for {0}: {1}'
adModuleWindowsOnlyExceptionMessage = 'Active Directory module only available on Windows OS.'
Expand Down
15 changes: 13 additions & 2 deletions src/Private/Context.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -944,16 +944,27 @@ function Set-PodeServerConfiguration {
ShowEndpoints = [bool](Protect-PodeValue -Value $Configuration.Console.ShowEndpoints -Default $Context.Server.Console.ShowEndpoints)
ShowHelp = [bool](Protect-PodeValue -Value $Configuration.Console.ShowHelp -Default $Context.Server.Console.ShowHelp)

Colors = @{

}

try {
$Context.Server.Console.Colors = @{
Header = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.Header -Default $Context.Server.Console.Colors.Header), $true)
Help = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.Help -Default $Context.Server.Console.Colors.Help), $true)
EndpointsHeader = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.EndpointsHeader -Default $Context.Server.Console.Colors.EndpointsHeader), $true)
Endpoints = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.Endpoints -Default $Context.Server.Console.Colors.Endpoints), $true)
OpenApiUrls = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.OpenApiUrls -Default $Context.Server.Console.Colors.OpenApiUrls), $true)
OpenApiHeaders = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.OpenApiHeaders -Default $Context.Server.Console.Colors.OpenApiHeaders), $true)
OpenApiTitles = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.OpenApiTitles -Default $Context.Server.Console.Colors.OpenApiTitles), $true)
HelpHeader = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.HelpHeader -Default $Context.Server.Console.Colors.HelpHeader), $true)
HelpKey = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.HelpKey -Default $Context.Server.Console.Colors.HelpKey), $true)
HelpDescription = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.HelpDescription -Default $Context.Server.Console.Colors.HelpDescription), $true)
HelpDivider = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.HelpDivider -Default $Context.Server.Console.Colors.HelpDivider), $true)
Divider = [System.ConsoleColor]::parse([System.ConsoleColor], (Protect-PodeValue -Value $Configuration.Console.Colors.Divider -Default $Context.Server.Console.Colors.Divider), $true)
}
}
catch {
$_ | Write-PodeErrorLog
}
}

function Set-PodeWebConfiguration {
Expand Down
68 changes: 55 additions & 13 deletions src/Private/Endpoints.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,6 @@ function Get-PodeEndpointByName {
return $null
}


<#
.SYNOPSIS
Displays information about the endpoints the Pode server is listening on.
Expand All @@ -409,33 +408,76 @@ function Get-PodeEndpointByName {
.NOTES
This function uses `Write-PodeHost` to display messages, with the `Yellow` foreground
color for clarity. It ensures each endpoint is displayed with its associated flags,
enhancing visibility of specific configurations like `DualMode`.
color for the summary and other appropriate colors for URLs and flags.
#>
function Show-PodeEndPointConsoleInfo {
param(
[switch]
$Force
)

# Default colors if not set
if ($null -ne $PodeContext.Server.Console.Colors.EndpointsHeader) {
$headerColor = $PodeContext.Server.Console.Colors.EndpointsHeader
}
else {
$headerColor = [System.ConsoleColor]::Yellow
}

if ($null -ne $PodeContext.Server.Console.Colors.Endpoints) {
$endpointsColor = $PodeContext.Server.Console.Colors.Endpoints
}
else {
$endpointsColor = [System.ConsoleColor]::Cyan
}

if ($null -ne $PodeContext.Server.Console.Colors.Divider) {
$dividerColor = $PodeContext.Server.Console.Colors.Divider
}
else {
$dividerColor = [System.ConsoleColor]::Yellow
}


# Return early if no endpoints are available
if ($PodeContext.Server.EndpointsInfo.Length -eq 0) {
return
}

# Listening on the following $endpoints.Length endpoint(s) [$PodeContext.Threads.General thread(s)]
Write-PodeHost ($PodeLocale.listeningOnEndpointsMessage -f $PodeContext.Server.EndpointsInfo.Length, $PodeContext.Threads.General) -ForegroundColor Yellow -Force:$Force
# Display header
Write-PodeHost ($PodeLocale.listeningOnEndpointsMessage -f $PodeContext.Server.EndpointsInfo.Length, $PodeContext.Threads.General) -ForegroundColor $headerColor -Force:$Force
Write-PodeHost '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' -ForegroundColor $dividerColor -Force:$Force

# Display each endpoint with extracted protocol
$PodeContext.Server.EndpointsInfo | ForEach-Object {
# Extract protocol from the URL
$protocol = ($_.Url -split ':')[0].ToUpper()

# Determine protocol label
$protocolLabel = switch ($protocol) {
'HTTP' { 'HTTP ' }
'HTTPS' { 'HTTPS ' }
'WS' { 'WebSocket ' }
'SMTP' { 'SMTP ' }
'SMTPS' { 'SMTPS ' }
'TCP' { 'TCP ' }
'TCPS' { 'TCPS ' }
default { 'UNKNOWN ' }
}

# Handle flags like DualMode
$flags = @()
if ($_.DualMode) {
$flags += 'DualMode'
}

if ($flags.Length -eq 0) {
$flags = [string]::Empty
}
else {
$flags = "[$($flags -join ',')]"
}
$flagString = if ($flags.Length -gt 0) { "[$($flags -join ',')]" } else { [string]::Empty }

Write-PodeHost "`t- $($_.Url) $($flags)" -ForegroundColor Yellow -Force:$Force
# Display endpoint details
Write-PodeHost " - $protocolLabel : $($_.Url) $flagString" -ForegroundColor $endpointsColor -Force:$Force
}
}

# Footer
Write-PodeHost
Write-PodeHost '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' -ForegroundColor $dividerColor -Force:$Force
}
98 changes: 74 additions & 24 deletions src/Private/OpenApi.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2401,53 +2401,103 @@ function Show-PodeOAConsoleInfo {
[switch]
$Force
)
# state the OpenAPI endpoints for each definition
foreach ($key in $PodeContext.Server.OpenAPI.Definitions.keys) {

# Default header initialization
$openAPIHeader = $false

# Fallback colors

if ($null -ne $PodeContext.Server.Console.Colors.Divider) {
$dividerColor = $PodeContext.Server.Console.Colors.Divider
}
else {
$dividerColor = [System.ConsoleColor]::Yellow
}

$headerColor = if ($null -ne $PodeContext.Server.Console.Colors.OpenApiHeaders) {
$PodeContext.Server.Console.Colors.OpenApiHeaders
}
else {
[System.ConsoleColor]::Yellow
}

$titleColor = if ($null -ne $PodeContext.Server.Console.Colors.OpenApiTitles) {
$PodeContext.Server.Console.Colors.OpenApiTitles
}
else {
[System.ConsoleColor]::White
}

$subtitleColor = if ($null -ne $PodeContext.Server.Console.Colors.OpenApiSubtitles) {
$PodeContext.Server.Console.Colors.OpenApiSubtitles
}
else {
[System.ConsoleColor]::Yellow
}

$urlColor = if ($null -ne $PodeContext.Server.Console.Colors.OpenApiUrls) {
$PodeContext.Server.Console.Colors.OpenApiUrls
}
else {
[System.ConsoleColor]::Cyan
}

# Iterate through OpenAPI definitions
foreach ($key in $PodeContext.Server.OpenAPI.Definitions.Keys) {
$bookmarks = $PodeContext.Server.OpenAPI.Definitions[$key].hiddenComponents.bookmarks
if ( !$bookmarks) {
if (!$bookmarks) {
continue
}

Write-PodeHost -Force:$Force
if (!$OpenAPIHeader) {
# OpenAPI Info
Write-PodeHost $PodeLocale.openApiInfoMessage -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiHeaders -Force:$Force
$OpenAPIHeader = $true
# Print the header only once
# Write-PodeHost -Force:$Force
if (!$openAPIHeader) {
Write-PodeHost $PodeLocale.openApiInfoMessage -ForegroundColor $headerColor -Force:$Force
Write-PodeHost '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' -ForegroundColor $dividerColor -Force:$Force
$openAPIHeader = $true
}
Write-PodeHost " '$key':" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiTitles -Force:$Force

# Print definition title
Write-PodeHost " '$key':" -ForegroundColor $titleColor -Force:$Force

# Determine endpoints for specification and documentation
if ($bookmarks.route.count -gt 1 -or $bookmarks.route.Endpoint.Name) {
# Specification
Write-PodeHost " - $($PodeLocale.specificationMessage):" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiTitles -Force:$Force
foreach ($endpoint in $bookmarks.route.Endpoint) {
Write-PodeHost " . $($endpoint.Protocol)://$($endpoint.Address)$($bookmarks.openApiUrl)" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiUrls -Force:$Force
# Directly use $bookmarks.route.Endpoint
Write-PodeHost " $($PodeLocale.specificationMessage):" -ForegroundColor $subtitleColor -Force:$Force
foreach ($endpoint in $bookmarks.route.Endpoint) {
Write-PodeHost " . $($endpoint.Protocol)://$($endpoint.Address)$($bookmarks.openApiUrl)" -ForegroundColor $urlColor -Force:$Force
}
# Documentation
Write-PodeHost " - $($PodeLocale.documentationMessage):" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiTitles -Force:$Force
foreach ($endpoint in $bookmarks.route.Endpoint) {
Write-PodeHost " . $($endpoint.Protocol)://$($endpoint.Address)$($bookmarks.path)" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiUrls -Force:$Force
Write-PodeHost " $($PodeLocale.documentationMessage):" -ForegroundColor $subtitleColor -Force:$Force
foreach ($endpoint in $bookmarks.route.Endpoint) {
Write-PodeHost " . $($endpoint.Protocol)://$($endpoint.Address)$($bookmarks.path)" -ForegroundColor $urlColor -Force:$Force
}
}
else {
# Specification
Write-PodeHost " - $($PodeLocale.specificationMessage):" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiTitles -Force:$Force
# Use EndpointsInfo for fallback
Write-PodeHost " $($PodeLocale.specificationMessage):" -ForegroundColor $subtitleColor -Force:$Force
$PodeContext.Server.EndpointsInfo | ForEach-Object {
if ($_.Pool -eq 'web') {
$url = [System.Uri]::new( [System.Uri]::new($_.Url), $bookmarks.openApiUrl)
Write-PodeHost " . $url" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiUrls -Force:$Force
$url = [System.Uri]::new([System.Uri]::new($_.Url), $bookmarks.openApiUrl)
Write-PodeHost " - $url" -ForegroundColor $urlColor -Force:$Force
}
}
Write-PodeHost " - $($PodeLocale.documentationMessage):" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiTitles -Force:$Force
Write-PodeHost " $($PodeLocale.documentationMessage):" -ForegroundColor $subtitleColor -Force:$Force
$PodeContext.Server.EndpointsInfo | ForEach-Object {
if ($_.Pool -eq 'web') {
$url = [System.Uri]::new( [System.Uri]::new($_.Url), $bookmarks.path)
Write-PodeHost " . $url" -ForegroundColor $PodeContext.Server.Console.Colors.OpenApiUrls -Force:$Force
$url = [System.Uri]::new([System.Uri]::new($_.Url), $bookmarks.path)
Write-PodeHost " - $url" -ForegroundColor $urlColor -Force:$Force
}
}
}
}
if ($openAPIHeader) {
# Footer
Write-PodeHost
Write-PodeHost '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━' -ForegroundColor $dividerColor -Force:$Force
}
}


function Test-PodeOAEnabled {
foreach ($key in $PodeContext.Server.OpenAPI.Definitions.keys) {
$bookmarks = $PodeContext.Server.OpenAPI.Definitions[$key].hiddenComponents.bookmarks
Expand Down
Loading

0 comments on commit 41ab522

Please sign in to comment.