Skip to content

Commit 592799c

Browse files
Update cmdlet docs from Kestrun/Kestrun@38fd732
1 parent 375f071 commit 592799c

File tree

490 files changed

+16015
-643
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

490 files changed

+16015
-643
lines changed

docs/_includes/examples/pwsh/10.10-OpenAPI-Component-Link.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function createUser {
153153
[OpenApiRequestBody(Required = $true, ContentType = ('application/json', 'application/xml', 'application/yaml'))]
154154
[UserPayload]$Body
155155
)
156-
156+
Expand-KrObject -InputObject $Body -Label 'Creating User'
157157
if (-not $Body.firstName -or -not $Body.lastName -or -not $Body.email) {
158158
Write-KrJsonResponse @{ error = 'firstName, lastName, and email are required' } -StatusCode 400
159159
return

docs/_includes/examples/pwsh/10.11-OpenAPI-Component-Callback.ps1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,12 @@ function shippingorder {
392392
Add-KrOpenApiRoute # Default pattern '/openapi/{version}/openapi.{format}'
393393

394394
Build-KrOpenApiDocument
395-
Test-KrOpenApiDocument
395+
# Test and log OpenAPI document validation result
396+
if (Test-KrOpenApiDocument) {
397+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
398+
} else {
399+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
400+
}
396401

397402
# =========================================================
398403
# RUN SERVER

docs/_includes/examples/pwsh/10.14-OpenAPI-PetStore.ps1

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,8 @@ class Order {
143143
[bool]$complete
144144
}
145145

146-
[OpenApiSchemaComponent( Description = 'Inventory counts by status')]
147-
class Inventory {
148-
[OpenApiAdditionalProperties()]
149-
[int]$AdditionalProperties
150-
}
146+
[OpenApiSchemaComponent( Description = 'Inventory counts by status', AdditionalPropertiesAllowed = $true, AdditionalProperties = [OpenApiInt32])]
147+
class Inventory {}
151148

152149
#region COMPONENT REQUEST BODIES
153150
# =========================================================
@@ -693,7 +690,12 @@ Add-KrOpenApiRoute # Default Pattern '/openapi/{version}/openapi.{format}'
693690
# (If your builder collects from class attributes, this is already handled.)
694691

695692
Build-KrOpenApiDocument
696-
Test-KrOpenApiDocument
693+
# Test and log OpenAPI document validation result
694+
if (Test-KrOpenApiDocument) {
695+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
696+
} else {
697+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
698+
}
697699
#endregion
698700

699701
#region RUN SERVER

docs/_includes/examples/pwsh/10.17-OpenAPI-SignalR.ps1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,12 @@ Register-KrSchedule -Name 'AdminStatusUpdate' -Cron '0 * * * * *' -ScriptBlock {
369369
Add-KrOpenApiRoute # Default pattern '/openapi/{version}/openapi.{format}'
370370

371371
Build-KrOpenApiDocument
372-
Test-KrOpenApiDocument
372+
# Test and log OpenAPI document validation result
373+
if (Test-KrOpenApiDocument) {
374+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
375+
} else {
376+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
377+
}
373378

374379
## 8. Start Server
375380

docs/_includes/examples/pwsh/10.2-OpenAPI-Component-Schema.ps1

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ class ErrorResponse {
191191
[string]$message
192192
}
193193

194+
195+
196+
[OpenApiSchemaComponent(Description = "Inventory counts by status key.")]
197+
[OpenApiPatternProperties(KeyPattern = "^[a-z][a-z0-9_]*$", SchemaType = [int])]
198+
class InventoryCounts {}
199+
194200
# =========================================================
195201
# ROUTES / OPERATIONS
196202
# =========================================================

docs/_includes/examples/pwsh/10.21-OpenAPI-SseBroadcast.ps1

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,13 @@ function InvokeSseBroadcastProgress {
216216
Add-KrOpenApiRoute # Default pattern '/openapi/{version}/openapi.{format}'
217217

218218
Build-KrOpenApiDocument
219-
Test-KrOpenApiDocument
219+
220+
# Test and log OpenAPI document validation result
221+
if (Test-KrOpenApiDocument) {
222+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
223+
} else {
224+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
225+
}
220226

221227
Write-Host '🟢 Kestrun SSE Broadcast Demo (OpenAPI) Server Started' -ForegroundColor Green
222228
Write-Host "📍 Navigate to http://localhost:$Port" -ForegroundColor Cyan
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
<#
2+
Sample: OpenAPI AdditionalProperties + PatternProperties
3+
Purpose: Demonstrate schema components that allow arbitrary keys and pattern-constrained keys.
4+
File: 10.24-OpenAPI-Additional-Pattern-Properties.ps1
5+
Notes:
6+
- Shows AdditionalProperties with a typed value schema
7+
- Shows PatternProperties with regex-constrained keys
8+
#>
9+
param(
10+
[int]$Port = 5000,
11+
[IPAddress]$IPAddress = [IPAddress]::Loopback
12+
)
13+
14+
# --- Logging / Server ---
15+
New-KrLogger | Add-KrSinkConsole |
16+
Set-KrLoggerLevel -Value Debug |
17+
Register-KrLogger -Name 'console' -SetAsDefault
18+
19+
New-KrServer -Name 'OpenAPI AdditionalProperties + PatternProperties'
20+
21+
Add-KrEndpoint -Port $Port -IPAddress $IPAddress
22+
23+
# =========================================================
24+
# TOP-LEVEL OPENAPI
25+
# =========================================================
26+
27+
Add-KrOpenApiInfo -Title 'Additional/Pattern Properties API' `
28+
-Version '1.0.0' `
29+
-Description 'Demonstrates schema components with AdditionalProperties and PatternProperties.'
30+
31+
# =========================================================
32+
# COMPONENT SCHEMAS
33+
# =========================================================
34+
35+
# Inventory counts keyed by dynamic status names (pattern enforced)
36+
[OpenApiSchemaComponent(Description = 'Inventory counts by status key.')]
37+
[OpenApiPatternProperties(KeyPattern = '^[a-z][a-z0-9_]*$', SchemaType = [int])]
38+
class InventoryCounts {}
39+
40+
# Feature flags keyed by arbitrary name (additional properties typed as boolean)
41+
[OpenApiSchemaComponent(
42+
Description = 'Feature flags keyed by name.',
43+
AdditionalPropertiesAllowed = $true,
44+
AdditionalProperties = [OpenApiBoolean]
45+
)]
46+
class FeatureFlags {}
47+
48+
# Request combining both kinds of dynamic maps
49+
[OpenApiSchemaComponent(
50+
Description = 'Catalog update request.',
51+
AdditionalPropertiesAllowed = $true,
52+
AdditionalProperties = [OpenApiString]
53+
)]
54+
class CatalogUpdateRequest {
55+
[OpenApiProperty(Description = 'Item identifier.', Example = 'SKU-1001')]
56+
[string]$itemId
57+
58+
[OpenApiProperty(Description = 'Inventory counts by status key.')]
59+
[InventoryCounts]$inventory
60+
61+
[OpenApiProperty(Description = 'Feature flags for the item.')]
62+
[FeatureFlags]$flags
63+
}
64+
65+
# Response echoes the update
66+
[OpenApiSchemaComponent(Description = 'Catalog update response.')]
67+
class CatalogUpdateResponse {
68+
[OpenApiProperty(Description = 'Item identifier.', Example = 'SKU-1001')]
69+
[string]$itemId
70+
71+
[OpenApiProperty(Description = 'Inventory snapshot.')]
72+
[InventoryCounts]$inventory
73+
74+
[OpenApiProperty(Description = 'Feature flags snapshot.')]
75+
[FeatureFlags]$flags
76+
77+
[OpenApiProperty(Description = 'Server timestamp (RFC 3339).', Example = '2026-02-03T12:34:56.789Z')]
78+
[OpenApiDateTime]$updatedAt
79+
}
80+
81+
# =========================================================
82+
# ROUTES / OPERATIONS
83+
# =========================================================
84+
85+
Enable-KrConfiguration
86+
87+
Add-KrApiDocumentationRoute -DocumentType Swagger
88+
Add-KrApiDocumentationRoute -DocumentType Redoc
89+
90+
<#
91+
.SYNOPSIS
92+
Get sample inventory counts.
93+
.DESCRIPTION
94+
Returns an InventoryCounts object with pattern-constrained keys.
95+
#>
96+
function getInventoryCounts {
97+
[OpenApiPath(HttpVerb = 'get', Pattern = '/inventory/counts')]
98+
[OpenApiResponse(StatusCode = '200', Description = 'Inventory counts', Schema = [InventoryCounts], ContentType = 'application/json')]
99+
param()
100+
101+
$counts = [InventoryCounts]@{
102+
AdditionalProperties = @{ available = 120; reserved = 8; backorder = 3 }
103+
}
104+
105+
Write-KrResponse $counts.AdditionalProperties -StatusCode 200
106+
}
107+
108+
<#
109+
.SYNOPSIS
110+
Get sample feature flags.
111+
.DESCRIPTION
112+
Returns a FeatureFlags object backed by AdditionalProperties.
113+
#>
114+
function getFeatureFlags {
115+
[OpenApiPath(HttpVerb = 'get', Pattern = '/features/flags')]
116+
[OpenApiResponse(StatusCode = '200', Description = 'Feature flags', Schema = [FeatureFlags], ContentType = 'application/json')]
117+
param()
118+
119+
$flags = [FeatureFlags]@{
120+
AdditionalProperties = @{ betaPricing = $true; allowBackorder = $false }
121+
}
122+
123+
Write-KrResponse $flags.AdditionalProperties -StatusCode 200
124+
}
125+
126+
<#
127+
.SYNOPSIS
128+
Update catalog data.
129+
.DESCRIPTION
130+
Accepts dynamic inventory counts and feature flags, then echoes the update.
131+
.PARAMETER body
132+
Catalog update request payload.
133+
#>
134+
function updateCatalog {
135+
[OpenApiPath(HttpVerb = 'post', Pattern = '/catalog/update')]
136+
[OpenApiResponse(StatusCode = '200', Description = 'Updated catalog item', Schema = [CatalogUpdateResponse], ContentType = 'application/json')]
137+
param(
138+
[OpenApiRequestBody(Description = 'Catalog update request.', Required = $true, ContentType = 'application/json')]
139+
[CatalogUpdateRequest]$body
140+
)
141+
142+
$response = [CatalogUpdateResponse]@{
143+
itemId = $body.itemId
144+
inventory = $body.inventory
145+
flags = $body.flags
146+
updatedAt = (Get-Date).ToUniversalTime().ToString('o')
147+
}
148+
149+
$payload = @{
150+
itemId = $response.itemId
151+
inventory = $response.inventory.AdditionalProperties
152+
flags = $response.flags.AdditionalProperties
153+
updatedAt = $response.updatedAt
154+
}
155+
156+
Write-KrResponse $payload -StatusCode 200
157+
}
158+
159+
# =========================================================
160+
# OPENAPI DOC ROUTE / BUILD
161+
# =========================================================
162+
163+
Add-KrOpenApiRoute
164+
165+
Build-KrOpenApiDocument
166+
if (Test-KrOpenApiDocument) {
167+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
168+
} else {
169+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
170+
}
171+
172+
# =========================================================
173+
# RUN SERVER
174+
# =========================================================
175+
176+
Start-KrServer -CloseLogsOnExit

docs/_includes/examples/pwsh/10.5-OpenAPI-Component-Response.ps1

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ function getArticle {
234234
publishedAt = '2025-01-15'
235235
author = 'John Doe'
236236
}
237-
238237
Write-KrResponse $article -StatusCode 200
239238
}
240239

@@ -342,7 +341,12 @@ function deleteArticle {
342341
Add-KrOpenApiRoute
343342

344343
Build-KrOpenApiDocument
345-
Test-KrOpenApiDocument
344+
# Test and log OpenAPI document validation result
345+
if (Test-KrOpenApiDocument) {
346+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
347+
} else {
348+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
349+
}
346350

347351
# =========================================================
348352
# RUN SERVER

docs/_includes/examples/pwsh/10.7-OpenAPI-Tags.ps1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,12 @@ function getHealth {
115115

116116
# Build and validate the OpenAPI specification
117117
Build-KrOpenApiDocument
118-
Test-KrOpenApiDocument
118+
# Test and log OpenAPI document validation result
119+
if (Test-KrOpenApiDocument) {
120+
Write-KrLog -Level Information -Message 'OpenAPI document built and validated successfully.'
121+
} else {
122+
Write-KrLog -Level Error -Message 'OpenAPI document validation failed.'
123+
}
119124

120125
# Start the server and keep logs open until exit
121126
Start-KrServer -CloseLogsOnExit
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<#
2+
15.11 Request Decompression Demo
3+
4+
Demonstrates request-level decompression using RequestDecompression middleware.
5+
6+
Key idea:
7+
- Client compresses the entire request body (Content-Encoding: gzip)
8+
- Middleware decompresses before Kestrun reads/parses the body (e.g. JSON)
9+
10+
Try (PowerShell 7+):
11+
pwsh .\docs\_includes\examples\pwsh\15.11-Request-Decompression.ps1
12+
13+
$payloadObject = @{
14+
message = (('hello ' * 20000).Trim())
15+
count = 1
16+
items = 1..2000
17+
meta = @{ note = ('x' * 20000) }
18+
}
19+
$payload = $payloadObject | ConvertTo-Json -Compress -Depth 6
20+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($payload)
21+
$compressed = New-Object System.IO.MemoryStream
22+
$gzip = [System.IO.Compression.GZipStream]::new($compressed, [System.IO.Compression.CompressionMode]::Compress, $true)
23+
$gzip.Write($bytes, 0, $bytes.Length)
24+
$gzip.Dispose()
25+
26+
Invoke-WebRequest -Method Post -Uri "http://127.0.0.1:5000/api/echo" \
27+
-ContentType 'application/json' \
28+
-Headers @{ 'Content-Encoding' = 'gzip' } \
29+
-Body $compressed.ToArray()
30+
#>
31+
param(
32+
[int]$Port = 5000,
33+
[IPAddress]$IPAddress = [IPAddress]::Loopback
34+
)
35+
36+
if (-not (Get-Module Kestrun)) { Import-Module Kestrun }
37+
38+
Initialize-KrRoot -Path $PSScriptRoot
39+
40+
New-KrLogger |
41+
Set-KrLoggerLevel -Value Debug |
42+
Add-KrSinkConsole |
43+
Register-KrLogger -Name 'console' -SetAsDefault
44+
45+
New-KrServer -Name 'Request Decompression Demo'
46+
47+
Add-KrEndpoint -Port $Port -IPAddress $IPAddress | Out-Null
48+
49+
# Enable request-level decompression (entire body compressed; Content-Encoding: gzip)
50+
Add-KrRequestDecompressionMiddleware -AllowedEncoding gzip
51+
52+
Enable-KrConfiguration
53+
54+
Add-KrMapRoute -Verbs Get -Pattern '/' -ScriptBlock {
55+
Write-KrTextResponse -InputObject 'POST /api/echo with Content-Encoding: gzip (JSON body) to see request decompression in action.' -StatusCode 200
56+
}
57+
58+
Add-KrMapRoute -Verbs Post -Pattern '/api/echo' -ScriptBlock {
59+
$raw = Get-KrRequestBody -Raw
60+
$receivedBytes = [System.Text.Encoding]::UTF8.GetByteCount($raw)
61+
62+
$messageStartsWith = ''
63+
$receivedCount = $null
64+
try {
65+
$body = $raw | ConvertFrom-Json -AsHashtable
66+
$messageText = [string]($body.message ?? '')
67+
$messageStartsWith = if ($messageText.Length -ge 5) { $messageText.Substring(0, 5) } else { $messageText }
68+
$receivedCount = $body.count
69+
} catch {
70+
$messageStartsWith = ''
71+
$receivedCount = $null
72+
}
73+
74+
Write-KrJsonResponse -InputObject @{
75+
ok = $true
76+
receivedBytes = $receivedBytes
77+
receivedCount = $receivedCount
78+
messageStartsWith = $messageStartsWith
79+
} -StatusCode 200
80+
}
81+
82+
Add-KrMapRoute -Verbs Post -Pattern '/api/text' -ScriptBlock {
83+
$raw = Get-KrRequestBody -Raw
84+
$receivedBytes = [System.Text.Encoding]::UTF8.GetByteCount($raw)
85+
86+
Write-KrJsonResponse -InputObject @{
87+
ok = $true
88+
receivedBytes = $receivedBytes
89+
contentType = $Context.Request.ContentType
90+
} -StatusCode 200
91+
}
92+
93+
Start-KrServer -CloseLogsOnExit

0 commit comments

Comments
 (0)