diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000..4a7869c7e
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,19 @@
+{
+ "name": "Codespace with PowerShell, Pester, Invoke-Build, and .NET 8",
+ "image": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu",
+ "features": {
+ "ghcr.io/devcontainers/features/powershell:1": {},
+ "ghcr.io/devcontainers/features/dotnet:1": {
+ "version": "8.0"
+ }
+ },
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "ms-vscode.powershell",
+ "pspester.pester-test"
+ ]
+ }
+ },
+ "postCreateCommand": "pwsh -Command 'Install-Module -Name InvokeBuild,Pester -Force -SkipPublisherCheck; sleep 5; Invoke-Build Build '"
+}
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 9122555d5..b326b5548 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -30,6 +30,7 @@ The following is a set of guidelines for contributing to Pode on GitHub. These a
- [Where-Object](#where-object)
- [Select-Object](#select-object)
- [Measure-Object](#measure-object)
+ - [New-Object](#new-object)
## Code of Conduct
@@ -245,3 +246,15 @@ Instead of using the `Measure-Object` commandlet, please use either the `.Length
(@(1, 2, 3)).Length
(@{ Name = 'Rick' }).Count
```
+
+#### New-Object
+
+Instead of using the `New-Object` commandlet, please use `::new()` as this is far faster than the former.
+
+```powershell
+# instead of
+$stream = New-Object System.IO.MemoryStream
+
+# do this
+$stream = [System.IO.MemoryStream]::new()
+```
diff --git a/.github/workflows/PSScriptAnalyzer.yml b/.github/workflows/PSScriptAnalyzer.yml
index 8673d21f4..d1af32421 100644
--- a/.github/workflows/PSScriptAnalyzer.yml
+++ b/.github/workflows/PSScriptAnalyzer.yml
@@ -3,7 +3,7 @@
# separate terms of service, privacy policy, and support
# documentation.
#
-# https://github.com/microsoft/action-psscriptanalyzer
+# https://github.com/microsoft/psscriptanalyzer-action
# For more information on PSScriptAnalyzer in general, see
# https://github.com/PowerShell/PSScriptAnalyzer
@@ -48,15 +48,11 @@ jobs:
- name: Run PSScriptAnalyzer
uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f
with:
- # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options.
- # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules.
- path: .\
+ path: .\src
recurse: true
- # Include your own basic security rules. Removing this option will run all the rules
- includeRule: '"PSAvoidUsingCmdletAliases" ,"PSAvoidUsingPlainTextForPassword","PSAvoidUsingWriteHost","PSAvoidUsingInvokeExpression","PSUseShouldProcessForStateChangingFunctions","PSAvoidUsingUsernameAndPasswordParams","PSUseProcessBlockForPipelineCommand","PSAvoidUsingConvertToSecureStringWithPlainText","PSUseSingularNouns","PSReviewUnusedParameter"'
+ settings: .\PSScriptAnalyzerSettings.psd1
output: results.sarif
- # Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
diff --git a/.github/workflows/ci-no-build-needed.yml b/.github/workflows/ci-no-build-needed.yml
index e27e5bafe..3345471f0 100644
--- a/.github/workflows/ci-no-build-needed.yml
+++ b/.github/workflows/ci-no-build-needed.yml
@@ -12,7 +12,8 @@ on:
- 'src/**'
- 'tests/**'
- '.github/workflows/ci-docs.yml'
- - '.github/workflows/ci-pwsh*.yml'
+ - '.github/workflows/ci-pwsh_lts.yml'
+ - '.github/workflows/ci-pwsh7_2.yml'
- '.github/workflows/ci-powershell.yml'
- '.github/workflows/ci-coverage.yml'
- '.github/workflows/PSScriptAnalyzer.yml'
@@ -30,7 +31,8 @@ on:
- 'src/**'
- 'tests/**'
- '.github/workflows/ci-docs.yml'
- - '.github/workflows/ci-pwsh*.yml'
+ - '.github/workflows/ci-pwsh_lts.yml'
+ - '.github/workflows/ci-pwsh7_2.yml'
- '.github/workflows/ci-powershell.yml'
- '.github/workflows/ci-coverage.yml'
- '.github/workflows/PSScriptAnalyzer.yml'
diff --git a/.github/workflows/ci-pwsh_preview.yml b/.github/workflows/ci-pwsh_preview.yml
index 56c9dde71..81bb80c3d 100644
--- a/.github/workflows/ci-pwsh_preview.yml
+++ b/.github/workflows/ci-pwsh_preview.yml
@@ -28,7 +28,7 @@ env:
POWERSHELL_VERSION: 'Preview'
jobs:
- build:
+ build-preview:
runs-on: ${{ matrix.os }}
strategy:
diff --git a/.github/workflows/label-issue-project.yml b/.github/workflows/label-issue-project.yml
index 3abc4d15e..17b146d85 100644
--- a/.github/workflows/label-issue-project.yml
+++ b/.github/workflows/label-issue-project.yml
@@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- - uses: actions/add-to-project@v1.0.1
+ - uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/users/Badgerati/projects/2
github-token: ${{ secrets.PROJECT_TOKEN }}
diff --git a/.github/workflows/open-issue-project.yml b/.github/workflows/open-issue-project.yml
index 5928986fc..6a8d134bb 100644
--- a/.github/workflows/open-issue-project.yml
+++ b/.github/workflows/open-issue-project.yml
@@ -10,7 +10,7 @@ jobs:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- - uses: actions/add-to-project@v1.0.1
+ - uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/users/Badgerati/projects/2
github-token: ${{ secrets.PROJECT_TOKEN }}
diff --git a/.gitignore b/.gitignore
index aa5c0e490..079cb2f3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -265,3 +265,4 @@ examples/PetStore/data/PetData.json
packers/choco/pode.nuspec
packers/choco/tools/ChocolateyInstall.ps1
+docs/Getting-Started/Samples.md
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 559d3ecf2..6f817660d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -21,6 +21,7 @@
"powershell.codeFormatting.whitespaceBetweenParameters": false,
"powershell.codeFormatting.whitespaceInsideBrace": true,
"powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
+ "powershell.scriptAnalysis.enable": true,
"files.trimTrailingWhitespace": true,
"files.associations": {
"*.pode": "html"
diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1
index 2141ac49d..15486f3d7 100644
--- a/PSScriptAnalyzerSettings.psd1
+++ b/PSScriptAnalyzerSettings.psd1
@@ -1,15 +1,33 @@
-# PSScriptAnalyzerSettings.psd1
@{
- Severity = @('Error', 'Warning', 'Information')
+ Severity = @('Error', 'Warning', 'Information')
+ IncludeDefaultRules = $true
- Rules = @{
+ CustomRulePath = @(
+ './analyzers/AvoidNewObjectRule.psm1'
+ )
+
+ Rules = @{
PSReviewUnusedParameter = @{
CommandsToTraverse = @(
- 'Where-Object','Remove-PodeRoute'
+ 'Where-Object',
+ 'Remove-PodeRoute'
)
}
+ AvoidNewObjectRule = @{
+ Severity = 'Warning'
+ }
}
- ExcludeRules = @('PSAvoidUsingCmdletAliases' ,'PSAvoidUsingPlainTextForPassword','PSAvoidUsingWriteHost','PSAvoidUsingInvokeExpression','PSUseShouldProcessForStateChangingFunctions',
- 'PSAvoidUsingUsernameAndPasswordParams','PSUseProcessBlockForPipelineCommand','PSAvoidUsingConvertToSecureStringWithPlainText','PSUseSingularNouns','PSReviewUnusedParameter' )
+
+ ExcludeRules = @(
+ 'PSAvoidUsingPlainTextForPassword',
+ 'PSUseShouldProcessForStateChangingFunctions',
+ 'PSAvoidUsingUsernameAndPasswordParams',
+ 'PSUseProcessBlockForPipelineCommand',
+ 'PSAvoidUsingConvertToSecureStringWithPlainText',
+ 'PSReviewUnusedParameter',
+ 'PSAvoidAssignmentToAutomaticVariable',
+ 'PSUseBOMForUnicodeEncodedFile',
+ 'PSAvoidTrailingWhitespace'
+ )
}
\ No newline at end of file
diff --git a/README.md b/README.md
index 4d14d2289..3ffdf9f6f 100644
--- a/README.md
+++ b/README.md
@@ -26,9 +26,16 @@
Pode is a Cross-Platform framework for creating web servers to host [REST APIs](https://badgerati.github.io/Pode/Tutorials/Routes/Overview/), [Web Pages](https://badgerati.github.io/Pode/Tutorials/Routes/Examples/WebPages/), and [SMTP/TCP](https://badgerati.github.io/Pode/Servers/) Servers. Pode also allows you to render dynamic files using [`.pode`](https://badgerati.github.io/Pode/Tutorials/Views/Pode/) files, which are just embedded PowerShell, or other [Third-Party](https://badgerati.github.io/Pode/Tutorials/Views/ThirdParty/) template engines. Plus many more features, including [Azure Functions](https://badgerati.github.io/Pode/Hosting/AzureFunctions/) and [AWS Lambda](https://badgerati.github.io/Pode/Hosting/AwsLambda/) support!
-
-
-
+```powershell
+
+Start-PodeServer -ScriptBlock {
+ Add-PodeEndPoint -Address localhost -port 32005 -Protocol Http
+ Add-PodeRoute -Method Get -Path '/ping' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{value = 'pong' }
+ }
+}
+
+```
See [here](https://badgerati.github.io/Pode/Getting-Started/FirstApp) for building your first app! Don't know HTML, CSS, or JavaScript? No problem! [Pode.Web](https://github.com/Badgerati/Pode.Web) is currently a work in progress, and lets you build web pages using purely PowerShell!
@@ -49,8 +56,9 @@ Then navigate to `http://127.0.0.1:8000` in your browser.
* Cross-platform using PowerShell Core (with support for PS5)
* Docker support, including images for ARM/Raspberry Pi
* Azure Functions, AWS Lambda, and IIS support
-* OpenAPI, Swagger, and ReDoc support
-* Listen on a single or multiple IP address/hostnames
+* OpenAPI specification version 3.0.x and 3.1.0
+* OpenAPI documentation with Swagger, Redoc, RapidDoc, StopLight, OpenAPI-Explorer and RapiPdf
+* Listen on a single or multiple IP(v4/v6) address/hostnames
* Cross-platform support for HTTP(S), WS(S), SSE, SMTP(S), and TCP(S)
* Host REST APIs, Web Pages, and Static Content (with caching)
* Support for custom error pages
@@ -73,6 +81,8 @@ Then navigate to `http://127.0.0.1:8000` in your browser.
* Support for File Watchers
* In-memory caching, with optional support for external providers (such as Redis)
* (Windows) Open the hosted server as a desktop application
+* FileBrowsing support
+* Localization (i18n) in Arabic, German, Spanish, France, Italian, Japanese, Korean, Polish, Portuguese, and Chinese
## 📦 Install
diff --git a/analyzers/AvoidNewObjectRule.psm1 b/analyzers/AvoidNewObjectRule.psm1
new file mode 100644
index 000000000..c6b47f231
--- /dev/null
+++ b/analyzers/AvoidNewObjectRule.psm1
@@ -0,0 +1,38 @@
+function Measure-AvoidNewObjectRule {
+ [CmdletBinding()]
+ [OutputType([Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
+ param(
+ [Parameter(Mandatory = $true)]
+ [ValidateNotNullOrEmpty()]
+ [System.Management.Automation.Language.ScriptBlockAst]
+ $ScriptBlockAst
+ )
+
+ # Initialize an empty array to collect diagnostic records
+ $diagnostics = @()
+
+ try {
+ # Traverse the AST to find all instances of New-Object cmdlet
+ $ScriptBlockAst.FindAll({
+ param($Ast)
+ $Ast -is [System.Management.Automation.Language.CommandAst] -and
+ $Ast.CommandElements[0].Extent.Text -eq 'New-Object'
+ }, $true) | ForEach-Object {
+ $diagnostics += [PSCustomObject]@{
+ Message = "Avoid using 'New-Object' and use '::new()' instead."
+ Extent = $_.Extent
+ RuleName = 'AvoidNewObjectRule'
+ Severity = 'Warning'
+ ScriptName = $FileName
+ }
+ }
+
+ # Return the diagnostic records
+ return $diagnostics
+ }
+ catch {
+ $PSCmdlet.ThrowTerminatingError($PSItem)
+ }
+}
+
+Export-ModuleMember -Function Measure-AvoidNewObjectRule
\ No newline at end of file
diff --git a/docs/Getting-Started/Debug.md b/docs/Getting-Started/Debug.md
index a4647d3c5..0baef9a75 100644
--- a/docs/Getting-Started/Debug.md
+++ b/docs/Getting-Started/Debug.md
@@ -174,3 +174,75 @@ The steps to attach to the Pode process are as follows:
5. You'll also be able to query variables as well, such as `$WebEvent` and other variables you might have created.
6. When you are done debugging the current request, hit the `d` key.
+
+
+
+## Managing Runspace Names
+
+### Internal Runspace Naming
+
+In Pode, internal runspaces are automatically assigned distinct names. This built-in naming convention is crucial for identifying and managing runspaces efficiently, particularly during debugging or when monitoring multiple concurrent processes.
+
+Pode uses specific naming patterns for its internal runspaces, which include:
+
+- **Pode_Web_Listener_1**
+- **Pode_Signals_Broadcaster_1**
+- **Pode_Signals_Listener_1**
+- **Pode_Web_KeepAlive_1**
+- **Pode_Files_Watcher_1**
+- **Pode_Main_Logging_1**
+- **Pode_Timers_Scheduler_1**
+- **Pode_Schedules_[Schedule Name]_1** – where `[Schedule Name]` is the name of the schedule.
+- **Pode_Tasks_[Task Name]_1** – where `[Task Name]` is the name of the task.
+
+These default names are automatically assigned by Pode, making it easier to identify the purpose of each runspace during execution.
+
+### Customizing Runspace Names
+
+By default, Pode’s Tasks, Schedules, and Timers label their associated runspaces with their own names (as shown above). This simplifies the identification of runspaces when debugging or reviewing logs.
+
+However, if a different runspace name is needed, Pode allows you to customize it. Inside the script block of `Add-PodeTask`, `Add-PodeSchedule`, or `Add-PodeTimer`, you can use the `Set-PodeCurrentRunspaceName` cmdlet to assign any custom name you prefer.
+
+```powershell
+Set-PodeCurrentRunspaceName -Name 'Custom Runspace Name'
+```
+
+This cmdlet sets a custom name for the runspace, making it easier to track during execution.
+
+#### Example
+
+Here’s an example that demonstrates how to set a custom runspace name in a Pode task:
+
+```powershell
+Add-PodeTask -Name 'Test2' -ScriptBlock {
+ param($value)
+ # Set a custom name for the current runspace
+ Set-PodeCurrentRunspaceName -Name 'My Fancy Runspace'
+ Start-Sleep -Seconds 10
+ "A $($value) is never late, it arrives exactly when it means to" | Out-Default
+}
+```
+
+In this example, the `Set-PodeCurrentRunspaceName` cmdlet assigns the custom name `'My Fancy Runspace'` to the task's runspace. This is especially useful for debugging or when examining logs, as the custom name makes the runspace more recognizable.
+
+### Retrieving Runspace Names
+
+Pode also provides the `Get-PodeCurrentRunspaceName` cmdlet to retrieve the name of the current runspace. This is particularly helpful when you need to log or display the runspace name dynamically during execution.
+
+```powershell
+Get-PodeCurrentRunspaceName
+```
+
+This cmdlet returns the name of the current runspace, allowing for easier tracking and management in complex scenarios with multiple concurrent runspaces.
+
+#### Example
+
+Here’s an example that uses `Get-PodeCurrentRunspaceName` to output the runspace name during the execution of a schedule:
+
+```powershell
+Add-PodeSchedule -Name 'TestSchedule' -Cron '@hourly' -ScriptBlock {
+ Write-PodeHost "Runspace name: $(Get-PodeCurrentRunspaceName)"
+}
+```
+
+In this example, the schedule outputs the name of the runspace executing the script block every hour. This can be useful for logging and monitoring purposes when dealing with multiple schedules or tasks.
diff --git a/docs/Getting-Started/FirstApp.md b/docs/Getting-Started/FirstApp.md
index df2cdc0da..c1e52ceab 100644
--- a/docs/Getting-Started/FirstApp.md
+++ b/docs/Getting-Started/FirstApp.md
@@ -36,6 +36,16 @@ Success, saved package.json
Import-Module -Name Pode -MaximumVersion 2.99.99
```
+* To ensure that any errors during the import process are caught and handled appropriately, use a try-catch block:
+
+```powershell
+try {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99.99 -ErrorAction Stop
+} catch {
+ # exception management code
+}
+```
+
* Within your `server.ps1` file, first you need to start the Server. This is where the main script will go that defines how the server should function:
```powershell
diff --git a/docs/Getting-Started/GitHubCodespace.md b/docs/Getting-Started/GitHubCodespace.md
new file mode 100644
index 000000000..78fa890de
--- /dev/null
+++ b/docs/Getting-Started/GitHubCodespace.md
@@ -0,0 +1,55 @@
+
+# GitHub Codespace and Pode
+
+GitHub Codespaces provides a cloud-based development environment directly integrated with GitHub. This allows you to set up your development environment with pre-configured settings, tools, and extensions. In this guide, we will walk you through using GitHub Codespace to work with Pode, a web framework for building web applications and APIs in PowerShell.
+
+## Prerequisites
+
+- A GitHub account
+- A repository set up for your Pode project, including the `devcontainer.json` configuration file.
+
+## Launching GitHub Codespace
+
+1. **Open GitHub Codespace:**
+
+ Go to your GitHub repository on the web. Click on the green `Code` button, and then select `Open with Codespaces`. If you don't have any Codespaces created, you can create a new one by clicking `New codespace`.
+
+2. **Codespace Initialization:**
+
+ Once the Codespace is created, it will use the existing `devcontainer.json` configuration to set up the environment. This includes installing the necessary VS Code extensions and PowerShell modules specified in the configuration.
+
+3. **Verify the Setup:**
+
+ - The terminal in the Codespace will default to PowerShell (`pwsh`).
+ - Check that the required PowerShell modules are installed by running:
+
+ ```powershell
+ Get-Module -ListAvailable
+ ```
+
+ You should see `InvokeBuild` and `Pester` listed among the available modules.
+
+## Running a Pode Application
+
+1. **Use an Example Pode Project:**
+
+ Pode comes with several examples in the `examples` folder. You can run one of these examples to verify that your setup is working. For instance, let's use the `HelloWorld` example.
+
+2. **Open HelloWorld**
+
+ Navigate to the `examples/HelloWorld` directory and open the `HelloWorld.ps1` file
+
+3. **Run the sample**
+
+ Run the Pode server by executing the `HelloWorld.ps1` script in the PowerShell terminal:
+
+ ```powershell
+ ./examples/HelloWorld/HelloWorld.ps1
+ ```
+ or using the `Run/Debug` on the UI
+
+4. **Access the Pode Application:**
+
+ Once the Pode server is running, you can access your Pode application by navigating to the forwarded port provided by GitHub Codespaces. This is usually indicated by a URL in the terminal or in the Codespaces interface.
+
+For more information on using Pode and its features, refer to the [Pode documentation](https://badgerati.github.io/Pode/).
diff --git a/docs/Getting-Started/KnownIssues.md b/docs/Getting-Started/KnownIssues.md
index 9ceee09a5..c4ca375ea 100644
--- a/docs/Getting-Started/KnownIssues.md
+++ b/docs/Getting-Started/KnownIssues.md
@@ -18,13 +18,30 @@ New-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\HTTP\Parameters'
## PowerShell Classes
-Pode uses Runspaces to deal with multithreading and other background tasks. Due to this, PowerShell classes do not work as intended and are unsafe to use.
+Pode utilizes Runspaces for multithreading and other background tasks, which makes PowerShell classes behave unpredictably and renders them unsafe to use. This is primarily because an instance of a class created in one Runspace will always be marshaled back to the original Runspace whenever it is accessed again, potentially causing Routes and Middleware to become contaminated.
-You can find more information about this issue [here on PowerShell](https://github.com/PowerShell/PowerShell/issues/3651).
+For more details on this issue, you can refer to the [PowerShell GitHub issue](https://github.com/PowerShell/PowerShell/issues/3651).
-The crux of the issue is that if you create an instance of a class in one Runspace, then every time you try to use that instance again it will always be marshaled back to the original Runspace. This means Routes and Middleware can become contaminated.
+To avoid these problems, it is recommended to use Hashtables or PSObjects instead.
-It's recommended to switch to either Hashtables or PSObjects, but if you need to use classes then the following should let classes work:
+However, if you need to use classes, PowerShell 7.4 introduces the `[NoRunspaceAffinity()]` attribute that makes classes thread-safe by solving this issue.
+
+Here's an example of a class definition with the `[NoRunspaceAffinity()]` attribute:
+
+```powershell
+# Class definition with NoRunspaceAffinity attribute
+[NoRunspaceAffinity()]
+class SafeClass {
+ static [object] ShowRunspaceId($val) {
+ return [PSCustomObject]@{
+ ThreadId = [Threading.Thread]::CurrentThread.ManagedThreadId
+ RunspaceId = [runspace]::DefaultRunspace.Id
+ }
+ }
+}
+```
+
+If you need to support versions prior to PowerShell 7.4, you can use the following approach:
* Create a module (CreateClassInstanceHelper.psm1) with the content:
diff --git a/docs/Servers/TCP.md b/docs/Servers/TCP.md
index 7a2acd44a..10425897c 100644
--- a/docs/Servers/TCP.md
+++ b/docs/Servers/TCP.md
@@ -172,14 +172,14 @@ Start-PodeServer {
Verbs will be passed the `$TcpEvent` object, that contains the Request, Response, and other properties:
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| Request | object | The raw Request object |
-| Response | object | The raw Response object |
-| Lockable | hashtable | A synchronized hashtable that can be used with `Lock-PodeObject` |
-| Endpoint | hashtable | Contains the Address and Protocol of the endpoint being hit - such as "pode.example.com" or "127.0.0.2", or HTTP or HTTPS for the Protocol |
-| Parameters | hashtable | Contains the parsed parameter values from the Verb's path |
-| Timestamp | datetime | The current date and time of the Request |
+| Name | Type | Description |
+| ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| Request | object | The raw Request object |
+| Response | object | The raw Response object |
+| Lockable | hashtable | A synchronized hashtable that can be used with `Lock-PodeObject` |
+| Endpoint | hashtable | Contains the Address and Protocol of the endpoint being hit - such as "pode.example.com" or "127.0.0.2", or HTTP or HTTPS for the Protocol |
+| Parameters | hashtable | Contains the parsed parameter values from the Verb's path |
+| Timestamp | datetime | The current date and time of the Request |
## Test Send
@@ -189,11 +189,11 @@ The following function can be used to test sending messages to a TCP server. Thi
function Send-TCPMessage($Endpoint, $Port, $Message) {
# Setup connection
$Address = [System.Net.IPAddress]::Parse([System.Net.Dns]::GetHostAddresses($EndPoint))
- $Socket = New-Object System.Net.Sockets.TCPClient($Address,$Port)
+ $Socket = [System.Net.Sockets.TcpClient]::new($Address, $Port)
- # Setup stream wrtier
+ # Setup stream writer
$Stream = $Socket.GetStream()
- $Writer = New-Object System.IO.StreamWriter($Stream)
+ $Writer = [System.IO.StreamWriter]::new($Stream)
# Write message to stream
$Writer.WriteLine($Message)
diff --git a/docs/Tutorials/Authentication/Inbuilt/UserFile.md b/docs/Tutorials/Authentication/Inbuilt/UserFile.md
index 564c54dbc..4b9109809 100644
--- a/docs/Tutorials/Authentication/Inbuilt/UserFile.md
+++ b/docs/Tutorials/Authentication/Inbuilt/UserFile.md
@@ -20,14 +20,14 @@ The default users file is `./users.json` at the root of the server. You can supp
The users file is a JSON array of user objects, each user object must contain the following (metadata is optional):
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| Username | string | The user's username |
-| Name | string | The user's fullname |
-| Email | string | The user's email address |
-| Password | string | Either a SHA256 or an HMAC SHA256 of the user's password |
-| Groups | string[] | An array of groups which the the user is a member |
-| Metadata | psobject | Custom metadata for the user |
+| Name | Type | Description |
+| -------- | -------- | -------------------------------------------------------- |
+| Username | string | The user's username |
+| Name | string | The user's fullname |
+| Email | string | The user's email address |
+| Password | string | Either a SHA256 or an HMAC SHA256 of the user's password |
+| Groups | string[] | An array of groups which the the user is a member |
+| Metadata | psobject | Custom metadata for the user |
For example:
@@ -66,7 +66,7 @@ Regardless of whether the password is a standard SHA256 hash or HMAC hash, the h
```powershell
function ConvertTo-SHA256([string]$String)
{
- $SHA256 = New-Object System.Security.Cryptography.SHA256Managed
+ $SHA256 = [System.Security.Cryptography.SHA256Managed]::new()
$SHA256Hash = $SHA256.ComputeHash([Text.Encoding]::ASCII.GetBytes($String))
$SHA256HashString = [Convert]::ToBase64String($SHA256Hash)
return $SHA256HashString
@@ -77,7 +77,7 @@ function ConvertTo-SHA256([string]$String)
```powershell
function ConvertTo-HMACSHA256([string]$String, [string]$Secret) {
- $HMACSHA256 = New-Object System.Security.Cryptography.HMACSHA256
+ $HMACSHA256 = [System.Security.Cryptography.HMACSHA256]::new()
$HMACSHA256.Secret = [Text.Encoding]::ASCII.GetBytes($Secret)
$HMACSHA256Hash = $HMACSHA256.ComputeHash([Text.Encoding]::ASCII.GetBytes($String))
$HMACSHA256HashString = [Convert]::ToBase64String($HMACSHA256Hash)
@@ -89,13 +89,13 @@ function ConvertTo-HMACSHA256([string]$String, [string]$Secret) {
The User object returned, and accessible on Routes, and other functions via the [web event](../../../WebEvent)'s `$WebEvent.Auth.User` property, will contain the following information:
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| Username | string | The user's username |
-| Name | string | The user's fullname |
-| Email | string | The user's email address |
-| Groups | string[] | An array of groups which the the user is a member |
-| Metadata | psobject | Custom metadata for the user |
+| Name | Type | Description |
+| -------- | -------- | ------------------------------------------------- |
+| Username | string | The user's username |
+| Name | string | The user's fullname |
+| Email | string | The user's email address |
+| Groups | string[] | An array of groups which the the user is a member |
+| Metadata | psobject | Custom metadata for the user |
Such as:
diff --git a/docs/Tutorials/Basics.md b/docs/Tutorials/Basics.md
index 482ba68ae..137aa8b29 100644
--- a/docs/Tutorials/Basics.md
+++ b/docs/Tutorials/Basics.md
@@ -1,15 +1,25 @@
# Basics
+ !!! Warning
+You can initiate only one server per PowerShell instance. To run multiple servers, start additional PowerShell, or pwsh, sessions. Each session can run its own server. This is fundamental to how Pode operates, so consider it when designing your scripts and infrastructure.
-!!! warning
- You can only start one server in your script
-
-Although not required, it is recommended to import the Pode module using a maximum version, to avoid any breaking changes from new major versions:
+While it’s not mandatory, we strongly recommend importing the Pode module with a specified maximum version. This practice helps to prevent potential issues arising from breaking changes introduced in new major versions:
```powershell
Import-Module -Name Pode -MaximumVersion 2.99.99
```
+To further enhance the robustness of your code, consider wrapping the import statement within a try/catch block. This way, if the module fails to load, your script won’t proceed, preventing possible errors or unexpected behavior:
+
+```powershell
+try {
+ Import-Module -Name Pode -MaximumVersion 2.99.99
+} catch {
+ Write-Error "Failed to load the Pode module"
+ throw
+}
+```
+
The script for your server should be set in the [`Start-PodeServer`](../../Functions/Core/Start-PodeServer) function, via the `-ScriptBlock` parameter. The following example will listen over HTTP on port 8080, and expose a simple HTML page of running processes at `http://localhost:8080/processes`:
```powershell
@@ -72,3 +82,29 @@ PS> Start-PodeServer -FilePath './File.ps1'
!!! tip
Normally when you restart your Pode server any changes to the main scriptblock don't reflect. However, if you reference a file instead, then restarting the server will reload the scriptblock from that file - so any changes will reflect.
+
+## Internationalization
+
+Pode has built-in support for internationalization (i18n). By default, Pode uses the `$PsUICulture` variable to determine the User Interface Culture (UICulture).
+
+You can enforce a specific localization when importing the Pode module by using the UICulture argument. This argument accepts a culture code, which specifies the language and regional settings to use.
+
+Here’s an example of how to enforce Korean localization:
+
+```powershell
+Import-Module -Name Pode -ArgumentList 'ko-KR'
+```
+
+In this example, 'ko-KR' is the culture code for Korean as used in South Korea. You can replace 'ko-KR' with the culture code for any other language or region.
+
+As an alternative to specifying the UICulture when importing the Pode module, you can also change the UICulture within the PowerShell environment itself.
+
+This can be done using the following command:
+
+```powershell
+[System.Threading.Thread]::CurrentThread.CurrentUICulture = 'ko-KR'
+```
+
+This command changes the UICulture for the current PowerShell session to Korean as used in South Korea.
+
+Please note that this change is temporary and will only affect the current session. If you open a new PowerShell session, it will use the default UICulture.
\ No newline at end of file
diff --git a/docs/Tutorials/CORS.md b/docs/Tutorials/CORS.md
new file mode 100644
index 000000000..b4496cb55
--- /dev/null
+++ b/docs/Tutorials/CORS.md
@@ -0,0 +1,93 @@
+
+# CORS
+
+## What is CORS?
+Cross-Origin Resource Sharing (CORS) is a security feature implemented by web browsers to restrict web pages from making requests to a different domain than the one that served the web page. This is a critical aspect of web security, helping to prevent malicious sites from accessing sensitive data from another domain.
+
+## CORS Challenges
+When developing web applications, you may encounter situations where your web page needs to request resources from a different domain. This can lead to CORS errors if the appropriate headers are not set to allow these cross-origin requests. Common challenges include:
+- Handling pre-flight requests.
+- Allowing specific methods and headers.
+- Managing credentials in cross-origin requests.
+- Setting the appropriate origins.
+
+## Addressing CORS Challenges
+
+Pode simplifies handling CORS by providing the `Set-PodeSecurityAccessControl` function, which allows you to define the necessary headers to manage cross-origin requests effectively.
+
+### Key Headers for CORS
+
+1. **Access-Control-Allow-Origin**: Specifies which origins are permitted to access the resource.
+2. **Access-Control-Allow-Methods**: Lists the HTTP methods that are allowed when accessing the resource.
+3. **Access-Control-Allow-Headers**: Indicates which HTTP headers can be used during the actual request.
+4. **Access-Control-Max-Age**: Specifies how long the results of a pre-flight request can be cached.
+5. **Access-Control-Allow-Credentials**: Indicates whether credentials are allowed in the request.
+
+### Setting CORS Headers instead
+
+The `Set-PodeSecurityAccessControl` function allows you to set these headers easily. Here’s how you can address common CORS challenges using this function:
+
+1. **Allowing All Origins**
+ ```powershell
+ Set-PodeSecurityAccessControl -Origin '*'
+ ```
+ This sets the `Access-Control-Allow-Origin` header to allow requests from any origin.
+
+2. **Specifying Allowed Methods**
+ ```powershell
+ Set-PodeSecurityAccessControl -Methods 'GET', 'POST', 'OPTIONS'
+ ```
+ This sets the `Access-Control-Allow-Methods` header to allow only the specified methods.
+
+3. **Specifying Allowed Headers**
+ ```powershell
+ Set-PodeSecurityAccessControl -Headers 'Content-Type', 'Authorization'
+ ```
+ This sets the `Access-Control-Allow-Headers` header to allow the specified headers.
+
+4. **Handling Credentials**
+ ```powershell
+ Set-PodeSecurityAccessControl -Credentials
+ ```
+ This sets the `Access-Control-Allow-Credentials` header to allow credentials in requests.
+
+5. **Setting Cache Duration for Pre-flight Requests**
+ ```powershell
+ Set-PodeSecurityAccessControl -Duration 3600
+ ```
+ This sets the `Access-Control-Max-Age` header to cache the pre-flight request for one hour.
+
+6. **Automatic Header and Method Detection**
+ ```powershell
+ Set-PodeSecurityAccessControl -AutoHeaders -AutoMethods
+ ```
+ These parameters automatically populate the list of allowed headers and methods based on your OpenApi definition and defined routes, respectively.
+
+7. **Enabling Global OPTIONS Route**
+ ```powershell
+ Set-PodeSecurityAccessControl -WithOptions
+ ```
+ This creates a global OPTIONS route to handle pre-flight requests automatically.
+
+8. **Additional Security with Cross-Domain XHR Requests**
+ ```powershell
+ Set-PodeSecurityAccessControl -CrossDomainXhrRequests
+ ```
+ This adds the 'x-requested-with' header to the list of allowed headers, enhancing security.
+
+### Example Configuration
+
+Here is an example of configuring CORS settings in Pode using `Set-PodeSecurityAccessControl`:
+
+```powershell
+Set-PodeSecurityAccessControl -Origin 'https://example.com' -Methods 'GET', 'POST' -Headers 'Content-Type', 'Authorization' -Duration 7200 -Credentials -WithOptions -AutoHeaders -AutoMethods -CrossDomainXhrRequests
+```
+
+This example sets up CORS to allow requests from `https://example.com`, allows `GET` and `POST` methods, permits `Content-Type` and `Authorization` headers, enables credentials, caches pre-flight requests for two hours, automatically detects headers and methods, and allows cross-domain XHR requests.
+
+### More Information on CORS
+
+For more information on CORS, you can refer to the following resources:
+- [Fetch Living Standard](https://fetch.spec.whatwg.org/)
+- [CORS in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-7.0#credentials-in-cross-origin-requests)
+- [MDN Web Docs on CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
diff --git a/docs/Tutorials/Compression/Requests.md b/docs/Tutorials/Compression/Requests.md
index 804cea5e8..f5604a307 100644
--- a/docs/Tutorials/Compression/Requests.md
+++ b/docs/Tutorials/Compression/Requests.md
@@ -94,8 +94,8 @@ $message = ($data | ConvertTo-Json)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($message)
# compress the message using gzip
-$ms = New-Object -TypeName System.IO.MemoryStream
-$gzip = New-Object System.IO.Compression.GZipStream($ms, [IO.Compression.CompressionMode]::Compress, $true)
+$ms = [System.IO.MemoryStream]::new()
+$gzip = [System.IO.Compression.GZipStream]::new($ms, [IO.Compression.CompressionMode]::Compress, $true)
$gzip.Write($bytes, 0, $bytes.Length)
$gzip.Close()
$ms.Position = 0
diff --git a/docs/Tutorials/Configuration.md b/docs/Tutorials/Configuration.md
index 89c59d724..6b18e04fa 100644
--- a/docs/Tutorials/Configuration.md
+++ b/docs/Tutorials/Configuration.md
@@ -68,19 +68,22 @@ A "path" like `Server.Ssl.Protocols` looks like the below in the file:
}
```
-| Path | Description | Docs |
-| -------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------ |
-| Server.Ssl.Protocols | Indicates the SSL Protocols that should be used | [link](../Certificates) |
-| Server.Request | Defines request timeout and maximum body size | [link](../RequestLimits) |
-| Server.AutoImport | Defines the AutoImport scoping rules for Modules, SnapIns and Functions | [link](../Scoping) |
-| Server.Logging | Defines extra configuration for Logging, like masking sensitive data | [link](../Logging/Overview) |
-| Server.Root | Overrides root path of the server | [link](../Misc/ServerRoot) |
-| Server.Restart | Defines configuration for automatically restarting the server | [link](../Restarting/Types/AutoRestarting) |
-| Server.FileMonitor | Defines configuration for restarting the server based on file updates | [link](../Restarting/Types/FileMonitoring) |
-| Web.OpenApi.DefaultDefinitionTag | Define the primary tag name for OpenAPI ( 'default' is the default) | [link](../OpenAPI/OpenAPI) |
-| Web.Static.ValidateLast | Changes the way routes are processed. | [link](../Routes/Utilities/StaticContent) |
-| Web.TransferEncoding | Sets the Request TransferEncoding | [link](../Compression/Requests) |
-| Web.Compression | Sets any compression to use on the Response | [link](../Compression/Responses) |
-| Web.ContentType | Define expected Content Types for certain Routes | [link](../Routes/Utilities/ContentTypes) |
-| Web.ErrorPages | Defines configuration for custom error pages | [link](../Routes/Utilities/ErrorPages) |
-| Web.Static | Defines configuration for static content, such as caching | [link](../Routes/Utilities/StaticContent) |
+| Path | Description | Docs |
+| -------------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
+| Server.Ssl.Protocols | Indicates the SSL Protocols that should be used | [link](../Certificates) |
+| Server.Request | Defines request timeout and maximum body size | [link](../RequestLimits) |
+| Server.AutoImport | Defines the AutoImport scoping rules for Modules, SnapIns and Functions | [link](../Scoping) |
+| Server.Logging | Defines extra configuration for Logging, like masking sensitive data | [link](../Logging/Overview) |
+| Server.Root | Overrides root path of the server | [link](../Misc/ServerRoot) |
+| Server.Restart | Defines configuration for automatically restarting the server | [link](../Restarting/Types/AutoRestarting) |
+| Server.FileMonitor | Defines configuration for restarting the server based on file updates | [link](../Restarting/Types/FileMonitoring) |
+| Server.ReceiveTimeout | Define the amount of time a Receive method call will block waiting for data | [link](../Endpoints/Basic/StaticContent/#server-timeout) |
+| Server.DefaultFolders | Set the Default Folders paths | [link](../Routes/Utilities/StaticContent/#changing-the-default-folders) |
+| Web.OpenApi.DefaultDefinitionTag | Define the primary tag name for OpenAPI ( `default` is the default) | [link](../OpenAPI/Overview) |
+| Web.OpenApi.UsePodeYamlInternal | Force the use of the internal YAML converter (`False` is the default) | |
+| Web.Static.ValidateLast | Changes the way routes are processed. | [link](../Routes/Utilities/StaticContent) |
+| Web.TransferEncoding | Sets the Request TransferEncoding | [link](../Compression/Requests) |
+| Web.Compression | Sets any compression to use on the Response | [link](../Compression/Responses) |
+| Web.ContentType | Define expected Content Types for certain Routes | [link](../Routes/Utilities/ContentTypes) |
+| Web.ErrorPages | Defines configuration for custom error pages | [link](../Routes/Utilities/ErrorPages) |
+| Web.Static | Defines configuration for static content, such as caching | [link](../Routes/Utilities/StaticContent) |
\ No newline at end of file
diff --git a/docs/Tutorials/Endpoints/Basics.md b/docs/Tutorials/Endpoints/Basics.md
index f4dbd93f8..888a529ba 100644
--- a/docs/Tutorials/Endpoints/Basics.md
+++ b/docs/Tutorials/Endpoints/Basics.md
@@ -174,3 +174,17 @@ The following is the structure of the Endpoint object internally, as well as the
| Protocol | string | The protocol of the Endpoint. Such as: HTTP, HTTPS, WS, etc. |
| Type | string | The type of the Endpoint. Such as: HTTP, WS, SMTP, TCP |
| Certificate | hashtable | Details about the certificate that will be used for SSL Endpoints |
+
+## Server timeout
+
+The timeout is configurable using the `ReceiveTimeout` property in the `server.psd1` configuration file, the amount of time is in milliseconds. The meaning is that the server will wait for data to be received before timing out. This is useful for controlling how long the server should wait during data reception operations, enhancing the performance and responsiveness.
+
+To set this property, include it in `server.psd1` configuration file as shown below:
+
+```powershell
+@{
+ Server = @{
+ ReceiveTimeout = 5000 # Timeout in milliseconds
+ }
+}
+```
diff --git a/docs/Tutorials/Middleware/Types/Sessions.md b/docs/Tutorials/Middleware/Types/Sessions.md
index ba622c0e2..90221f1dc 100644
--- a/docs/Tutorials/Middleware/Types/Sessions.md
+++ b/docs/Tutorials/Middleware/Types/Sessions.md
@@ -111,7 +111,7 @@ For example, the following is a mock up of a Storage for Redis. Note that the fu
```powershell
# create the object
-$store = New-Object -TypeName psobject
+$store = [psobject]::new()
# add a Get property for retreiving a session's data by SessionId
$store | Add-Member -MemberType NoteProperty -Name Get -Value {
diff --git a/docs/Tutorials/OpenAPI/1Overview.md b/docs/Tutorials/OpenAPI/1Overview.md
new file mode 100644
index 000000000..65cf5ebe6
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/1Overview.md
@@ -0,0 +1,312 @@
+# Overview
+
+Pode has built-in support for converting your routes into OpenAPI 3.0 definitions. There is also support for enabling simple Swagger and/or ReDoc viewers and others.
+
+The OpenApi module has been extended with many more functions, and some old ones have been improved.
+
+For more detailed information regarding OpenAPI and Pode, please refer to [OpenAPI Specification and Pode](../Specification/v3_0_3.md)
+
+You can enable OpenAPI in Pode, and a straightforward definition will be generated. However, to get a more complex definition with request bodies, parameters, and response payloads, you'll need to use the relevant OpenAPI functions detailed below.
+
+## Enabling OpenAPI
+
+To enable support for generating OpenAPI definitions you'll need to use the [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi) function. This will allow you to set a title and version for your API. You can also set a default route to retrieve the OpenAPI definition for tools like Swagger or ReDoc, the default is at `/openapi`.
+
+You can also set a route filter (such as `/api/*`, the default is `/*` for everything), so only those routes are included in the definition.
+
+An example of enabling OpenAPI is a follows:
+
+```powershell
+Enable-PodeOpenApi -Title 'My Awesome API' -Version 9.0.0.1
+```
+
+An example of setting the OpenAPI route is a follows. This will create a route accessible at `/docs/openapi`:
+
+```powershell
+Enable-PodeOpenApi -Path '/docs/openapi' -Title 'My Awesome API' -Version 9.0.0.1
+```
+
+### Default Setup
+
+In the very simplest of scenarios, just enabling OpenAPI will generate a minimal definition. It can be viewed in Swagger/ReDoc etc, but won't be usable for trying calls.
+
+When you enable OpenAPI, and don't set any other OpenAPI data, the following is the minimal data that is included:
+
+* Every route will have a 200 and Default response
+* Although routes will be included, no request bodies, parameters or response payloads will be defined
+* If you have multiple endpoints, then the servers section will be included
+* Any authentication will be included
+
+This can be changed with [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi)
+
+For example to change the default response 404 and 500
+
+```powershell
+Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -DefaultResponses (
+ New-PodeOAResponse -StatusCode 404 -Description 'User not found' | Add-PodeOAResponse -StatusCode 500
+ )
+```
+
+For disabling the Default Response use:
+
+```powershell
+Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -NoDefaultResponses
+```
+
+For disabling the Minimal Definitions feature use:
+
+```powershell
+Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -DisableMinimalDefinitions
+```
+
+### Get Definition
+
+Instead of defining a route to return the definition, you can write the definition to the response whenever you want, and in any route, using the [`Get-PodeOADefinition`](../../../Functions/OpenApi/Get-PodeOADefinition) function. This could be useful in certain scenarios like in Azure Functions, where you can enable OpenAPI, and then write the definition to the response of a GET request if some query parameter is set; eg: `?openapi=1`.
+
+For example:
+
+```powershell
+Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ if ($WebEvent.Query.openapi -eq 1) {
+ Get-PodeOpenApiDefinition | Write-PodeJsonResponse
+ }
+}
+```
+
+## OpenAPI Info object
+
+In previous releases some of the Info object properties like Version and Title were defined by [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi).
+Starting from version 2.10 a new [`Add-PodeOAInfo`](../../../Functions/OpenApi/Add-PodeOAInfo) function has been added to create a full OpenAPI Info spec.
+
+```powershell
+Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' `
+ -Version 1.0.17 `
+ -Description $InfoDescription `
+ -TermsOfService 'http://swagger.io/terms/' `
+ -LicenseName 'Apache 2.0' `
+ -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' `
+ -ContactName 'API Support' `
+ -ContactEmail 'apiteam@swagger.io'
+```
+
+## OpenAPI configuration Best Practice
+
+Pode is rich of functions to create and configure an complete OpenApi spec. Here is a typical code you should use to initiate an OpenApi spec
+
+```powershell
+#Initialize OpenApi
+Enable-PodeOpenApi -Path '/docs/openapi' -Title 'Swagger Petstore - OpenAPI 3.0' `
+ -OpenApiVersion 3.1 -DisableMinimalDefinitions -NoDefaultResponses
+
+# OpenApi Info
+Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' `
+ -Version 1.0.17 `
+ -Description 'This is a sample Pet Store Server based on the OpenAPI 3.0 specification. ...' `
+ -TermsOfService 'http://swagger.io/terms/' `
+ -LicenseName 'Apache 2.0' `
+ -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' `
+ -ContactName 'API Support' `
+ -ContactEmail 'apiteam@swagger.io' `
+ -ContactUrl 'http://example.com/support'
+
+# Endpoint for the API
+ Add-PodeOAServerEndpoint -url '/api/v3.1' -Description 'default endpoint'
+
+ # OpenApi external documentation links
+ $extDoc = New-PodeOAExternalDoc -Name 'SwaggerDocs' -Description 'Find out more about Swagger' -Url 'http://swagger.io'
+ $extDoc | Add-PodeOAExternalDoc
+
+ # OpenApi documentation viewer
+ Enable-PodeOAViewer -Type Swagger -Path '/docs/swagger'
+ Enable-PodeOAViewer -Type ReDoc -Path '/docs/redoc'
+ Enable-PodeOAViewer -Type RapiDoc -Path '/docs/rapidoc'
+ Enable-PodeOAViewer -Type StopLight -Path '/docs/stoplight'
+ Enable-PodeOAViewer -Type Explorer -Path '/docs/explorer'
+ Enable-PodeOAViewer -Bookmarks -Path '/docs'
+```
+
+## Authentication
+
+Any authentication defined, either by [`Add-PodeAuthMiddleware`](../../../Functions/Authentication/Add-PodeAuthMiddleware), or using the `-Authentication` parameter on Routes, will be automatically added to the `security` section of the OpenAPI definition.
+
+
+## Tags
+
+In OpenAPI, a "tag" is used to group related operations. Tags are often used to organize and categorize endpoints in an API specification, making it easier to understand and navigate the API documentation. Each tag can be associated with one or more API operations, and these tags are then used in tools like Swagger UI to group and display operations in a more organized way.
+
+Here's an example of how to define and use tags:
+
+```powershell
+# create an External Doc reference
+$swaggerDocs = New-PodeOAExternalDoc -Description 'Find out more about Swagger' -Url 'http://swagger.io'
+
+# create a Tag
+Add-PodeOATag -Name 'pet' -Description 'Everything about your Pets' -ExternalDoc $swaggerDocs
+
+Add-PodeRoute -PassThru -Method get -Path '/pet/findByStatus' -Authentication 'Login-OAuth2' -Scope 'read' -AllowAnon -ScriptBlock {
+ #route code
+} | Set-PodeOARouteInfo -Summary 'Finds Pets by status' -Description 'Multiple status values can be provided with comma-separated strings' `
+ -Tags 'pet' -OperationId 'findPetsByStatus'
+```
+
+## Routes
+
+To extend the definition of a route, you can use the `-PassThru` switch on the [`Add-PodeRoute`](../../../Functions/Routes/Add-PodeRoute) function. This will cause the route that was created to be returned, so you can pass it down the pipe into more OpenAPI functions.
+
+To add metadata to a route's definition you can use the [`Set-PodeOARouteInfo`](../../../Functions/OpenApi/Set-PodeOARouteInfo) function. This will allow you to define a summary/description for the route, as well as tags for grouping:
+
+```powershell
+Add-PodeRoute -Method Get -Path "/api/resources" -ScriptBlock {
+ Set-PodeResponseStatus -Code 200
+} -PassThru |
+ Set-PodeOARouteInfo -Summary 'Retrieve some resources' -Tags 'Resources'
+```
+
+Each of the following OpenAPI functions have a `-PassThru` switch, allowing you to chain many of them together.
+
+### Responses
+
+You can define multiple responses for a route, but only one of each status code, using the [`Add-PodeOAResponse`](../../../Functions/OpenApi/Add-PodeOAResponse) function. You can either just define the response and status code, with a custom description, or with a schema defining the payload of the response.
+
+The following is an example of defining simple 200 and 404 responses on a route:
+
+```powershell
+Add-PodeRoute -Method Get -Path "/api/user/:userId" -ScriptBlock {
+ # logic
+} -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -PassThru |
+ Add-PodeOAResponse -StatusCode 404 -Description 'User not found'
+```
+
+Whereas the following is a more complex definition, which also defines the responses JSON payload. This payload is defined as an object with a string Name, and integer UserId:
+
+```powershell
+Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Parameters['userId']
+ }
+} -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'A user object' --Content @{
+ 'application/json' = (New-PodeOAStringProperty -Name 'Name'|
+ New-PodeOAIntProperty -Name 'UserId'| New-PodeOAObjectProperty)
+ }
+```
+
+the JSON response payload defined is as follows:
+
+```json
+{
+ "Name": [string],
+ "UserId": [integer]
+}
+```
+
+In case the response JSON payload is an array
+
+```powershell
+Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Parameters['userId']
+ }
+ } -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'A user object' -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json' -Array -Content (
+ New-PodeOAStringProperty -Name 'Name' |
+ New-PodeOAIntProperty -Name 'UserId' |
+ New-PodeOAObjectProperty
+ )
+ )
+```
+
+```json
+[
+ {
+ "Name": [string],
+ "UserId": [integer]
+ }
+]
+```
+
+Internally, each route is created with an empty default 200 and 500 response. You can remove these, or other added responses, by using [`Remove-PodeOAResponse`](../../../Functions/OpenApi/Remove-PodeOAResponse):
+
+```powershell
+Add-PodeRoute -Method Get -Path "/api/user/:userId" -ScriptBlock {
+ # route logic
+} -PassThru |
+ Remove-PodeOAResponse -StatusCode 200
+```
+
+### Requests
+
+#### Parameters
+
+You can set route parameter definitions, such as parameters passed in the path/query, by using the [`Set-PodeOARequest`](../../../Functions/OpenApi/Set-PodeOARequest) function with the `-Parameters` parameter. The parameter takes an array of properties converted into parameters, using the [`ConvertTo-PodeOAParameter`](../../../Functions/OpenApi/ConvertTo-PodeOAParameter) function.
+
+For example, to create some integer `userId` parameter that is supplied in the path of the request, the following will work:
+
+```powershell
+Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Parameters['userId']
+ }
+} -PassThru |
+ Set-PodeOARequest -Parameters @(
+ (New-PodeOAIntProperty -Name 'userId' -Required | ConvertTo-PodeOAParameter -In Path)
+ )
+```
+
+Whereas you could use the next example to define 2 query parameters, both strings:
+
+```powershell
+Add-PodeRoute -Method Get -Path '/api/users' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Query['name']
+ }
+} -PassThru |
+ Set-PodeOARequest -Parameters (
+ (New-PodeOAStringProperty -Name 'name' -Required | ConvertTo-PodeOAParameter -In Query),
+ (New-PodeOAStringProperty -Name 'city' -Required | ConvertTo-PodeOAParameter -In Query)
+ )
+```
+
+#### Payload
+
+You can set request payload schemas by using the [`Set-PodeOARequest`](../../../Functions/OpenApi/Set-PodeOARequest)function, with the `-RequestBody` parameter. The request body can be defined using the [`New-PodeOARequestBody`](../../../Functions/OpenApi/New-PodeOARequestBody) function, and supplying schema definitions for content types - this works in very much a similar way to defining responses above.
+
+For example, to define a request JSON payload of some `userId` and `name` you could use the following:
+
+```powershell
+Add-PodeRoute -Method Patch -Path '/api/users' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = $WebEvent.Data.name
+ UserId = $WebEvent.Data.userId
+ }
+} -PassThru |
+ Set-PodeOARequest -RequestBody (
+ New-PodeOARequestBody -Required -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json','application/xml' -Content ( New-PodeOAStringProperty -Name 'Name'| New-PodeOAIntProperty -Name 'UserId'| New-PodeOAObjectProperty ) )
+
+ )
+```
+
+The expected payload would look as follows:
+
+```json
+{
+ "name": [string],
+ "userId": [integer]
+}
+```
+
+```xml
+
+
+```
+
diff --git a/docs/Tutorials/OpenAPI/2Properties.md b/docs/Tutorials/OpenAPI/2Properties.md
new file mode 100644
index 000000000..207c94966
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/2Properties.md
@@ -0,0 +1,297 @@
+
+# Properties
+
+Properties are used to create all Parameters and Schemas in OpenAPI. You can use the simple types on their own, or you can combine multiple of them together to form complex objects.
+
+### Simple Types
+
+There are 5 simple property types: Integers, Numbers, Strings, Booleans, and Schemas. Each of which can be created using the following functions:
+
+* [`New-PodeOAIntProperty`](../../../Functions/OAProperties/New-PodeOAIntProperty)
+* [`New-PodeOANumberProperty`](../../../Functions/OAProperties/New-PodeOANumberProperty)
+* [`New-PodeOAStringProperty`](../../../Functions/OAProperties/New-PodeOAStringProperty)
+* [`New-PodeOABoolProperty`](../../../Functions/OAProperties/New-PodeOABoolProperty)
+* [`New-PodeOASchemaProperty`](../../../Functions//New-PodeOASchemaProperty)
+* [`New-PodeOAMultiTypeProperty`](../../../Functions/OAProperties/New-PodeOAMultiTypeProperty) (Note: OpenAPI 3.1 only)
+
+These properties can be created with a Name, and other flags such as Required and/or a Description:
+
+```powershell
+# simple integer
+New-PodeOAIntProperty -Name 'userId'
+
+# a float number with a max value of 100
+New-PodeOANumberProperty -Name 'ratio' -Format Float -Maximum 100
+
+# a string with a default value, and enum of options
+New-PodeOAStringProperty -Name 'type' -Default 'admin' -Enum @('admin', 'user')
+
+# a boolean that's required
+New-PodeOABoolProperty -Name 'enabled' -Required
+
+# a schema property that references another component schema
+New-PodeOASchemaProperty -Name 'Config' -Reference 'ConfigSchema'
+
+# a string or an integer or a null value (only available with OpenAPI 3.1)
+New-PodeOAMultiTypeProperty -Name 'multi' -Type integer,string -Nullable
+```
+
+On their own, like above, the simple properties don't really do much. However, you can combine that together to make complex objects/arrays as defined below.
+
+### Arrays
+
+There isn't a dedicated function to create an array property, instead there is an `-Array` switch on each of the property functions - both Object and the above simple properties.
+
+If you supply the `-Array` switch to any of the above simple properties, this will define an array of that type - the `-Name` parameter can also be omitted if only a simple array if required.
+
+For example, the below will define an integer array:
+
+```powershell
+New-PodeOAIntProperty -Array
+```
+
+When used in a Response, this could return the following JSON example:
+
+```json
+[
+ 0,
+ 1,
+ 2
+]
+```
+
+### Objects
+
+An object property is a combination of multiple other properties - both simple, array of more objects.
+
+There are two ways to define objects:
+
+1. Similar to arrays, you can use the `-Object` switch on the simple properties.
+2. You can use the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function to combine multiple properties.
+
+#### Simple
+
+If you use the `-Object` switch on the simple property function, this will automatically wrap the property as an object. The Name for this is required.
+
+For example, the below will define a simple `userId` integer object:
+
+```powershell
+New-PodeOAIntProperty -Name 'userId' -Object
+```
+
+In a response as JSON, this could look as follows:
+
+```json
+{
+ "userId": 0
+}
+```
+
+Furthermore, you can also supply both `-Array` and `-Object` switches:
+
+```powershell
+New-PodeOAIntProperty -Name 'userId' -Object -Array
+```
+
+This wil result in something like the following JSON:
+
+```json
+{
+ "userId": [ 0, 1, 2 ]
+}
+```
+
+#### Complex
+
+Unlike the `-Object` switch that simply converts a single property into an object, the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function can combine and convert multiple properties.
+
+For example, the following will create an object using an Integer, String, and a Boolean:
+
+Legacy Definition
+
+```powershell
+New-PodeOAObjectProperty -Properties (
+ (New-PodeOAIntProperty -Name 'userId'),
+ (New-PodeOAStringProperty -Name 'name'),
+ (New-PodeOABoolProperty -Name 'enabled')
+)
+```
+
+Using piping (new in Pode 2.10)
+
+```powershell
+New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
+ New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty
+```
+
+As JSON, this could look as follows:
+
+```json
+{
+ "userId": 0,
+ "name": "Gary Goodspeed",
+ "enabled": true
+}
+```
+
+You can also supply the `-Array` switch to the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function. This will result in an array of objects. For example, if we took the above:
+
+```powershell
+New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
+ New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty -Array
+```
+
+As JSON, this could look as follows:
+
+```json
+[
+ {
+ "userId": 0,
+ "name": "Gary Goodspeed",
+ "enabled": true
+ },
+ {
+ "userId": 1,
+ "name": "Kevin",
+ "enabled": false
+ }
+]
+```
+
+You can also combine objects into other objects:
+
+```powershell
+$usersArray = New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
+ New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty -Array
+
+New-PodeOAObjectProperty -Properties @(
+ (New-PodeOAIntProperty -Name 'found'),
+ $usersArray
+)
+```
+
+As JSON, this could look as follows:
+
+```json
+{
+ "found": 2,
+ "users": [
+ {
+ "userId": 0,
+ "name": "Gary Goodspeed",
+ "enabled": true
+ },
+ {
+ "userId": 1,
+ "name": "Kevin",
+ "enabled": false
+ }
+ ]
+}
+```
+
+### oneOf, anyOf and allOf Keywords
+
+OpenAPI 3.x provides several keywords which you can use to combine schemas. You can use these keywords to create a complex schema or validate a value against multiple criteria.
+
+* oneOf - validates the value against exactly one of the sub-schemas
+* allOf - validates the value against all the sub-schemas
+* anyOf - validates the value against any (one or more) of the sub-schemas
+
+You can use the [`Merge-PodeOAProperty`](../../../Functions/OAProperties/Merge-PodeOAProperty) will instead define a relationship between the properties.
+
+Unlike [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) which combines and converts multiple properties into an Object, [`Merge-PodeOAProperty`](../../../Functions/OAProperties/Merge-PodeOAProperty) will instead define a relationship between the properties.
+
+For example, the following will create an something like an C Union object using an Integer, String, and a Boolean:
+
+```powershell
+Merge-PodeOAProperty -Type OneOf -ObjectDefinitions @(
+ (New-PodeOAIntProperty -Name 'userId' -Object),
+ (New-PodeOAStringProperty -Name 'name' -Object),
+ (New-PodeOABoolProperty -Name 'enabled' -Object)
+ )
+```
+
+Or
+
+```powershell
+New-PodeOAIntProperty -Name 'userId' -Object |
+ New-PodeOAStringProperty -Name 'name' -Object |
+ New-PodeOABoolProperty -Name 'enabled' -Object |
+ Merge-PodeOAProperty -Type OneOf
+```
+
+As JSON, this could look as follows:
+
+```json
+{
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "userId": {
+ "type": "integer"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ }
+ ]
+}
+```
+
+You can also supply a Component Schema created using [`Add-PodeOAComponentSchema`](../../../Functions/OAComponents/Add-PodeOAComponentSchema). For example, if we took the above:
+
+```powershell
+ New-PodeOAIntProperty -Name 'id'-Format Int64 -Example 1 -ReadOnly |
+ New-PodeOAStringProperty -Name 'username' -Example 'theUser' -Required |
+ New-PodeOAStringProperty -Name 'firstName' -Example 'John' |
+ New-PodeOAStringProperty -Name 'lastName' -Example 'James' |
+ New-PodeOAStringProperty -Name 'email' -Format email -Example 'john@email.com' |
+ New-PodeOAStringProperty -Name 'lastName' -Example 'James' |
+ New-PodeOAStringProperty -Name 'password' -Format Password -Example '12345' -Required |
+ New-PodeOAStringProperty -Name 'phone' -Example '12345' |
+ New-PodeOAIntProperty -Name 'userStatus'-Format int32 -Description 'User Status' -Example 1|
+ New-PodeOAObjectProperty -Name 'User' -XmlName 'user' |
+ Add-PodeOAComponentSchema
+
+ New-PodeOAStringProperty -Name 'street' -Example '437 Lytton' -Required |
+ New-PodeOAStringProperty -Name 'city' -Example 'Palo Alto' -Required |
+ New-PodeOAStringProperty -Name 'state' -Example 'CA' -Required |
+ New-PodeOAStringProperty -Name 'zip' -Example '94031' -Required |
+ New-PodeOAObjectProperty -Name 'Address' -XmlName 'address' -Description 'Shipping Address' |
+ Add-PodeOAComponentSchema
+
+ Merge-PodeOAProperty -Type AllOf -ObjectDefinitions 'Address','User'
+
+```
+
+As JSON, this could look as follows:
+
+```json
+{
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Address"
+ },
+ {
+ "$ref": "#/components/schemas/User"
+ }
+ ]
+}
+```
\ No newline at end of file
diff --git a/docs/Tutorials/OpenAPI/3Components.md b/docs/Tutorials/OpenAPI/3Components.md
new file mode 100644
index 000000000..2610eb604
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/3Components.md
@@ -0,0 +1,231 @@
+# Components
+
+You can define reusable OpenAPI components in Pode. Currently supported are Schemas, Parameters, Request Bodies, and Responses.
+
+### Schemas
+
+To define a reusable schema that can be used in request bodies, and responses, you can use the [`Add-PodeOAComponentSchema`](../../../Functions/OAComponents/Add-PodeOAComponentSchema) function. You'll need to supply a Name, and a Schema that can be reused.
+
+The following is an example of defining a schema which is a object of Name, UserId, and Age:
+
+```powershell
+# define a reusable schema user object
+New-PodeOAStringProperty -Name 'Name' |
+ New-PodeOAIntProperty -Name 'UserId' |
+ New-PodeOAIntProperty -Name 'Age' |
+ New-PodeOAObjectProperty |
+ Add-PodeOAComponentSchema -Name 'UserSchema'
+
+# reuse the above schema in a response
+Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Parameters['userId']
+ Age = 42
+ }
+} -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'A list of users' -Content @{
+ 'application/json' = 'UserSchema'
+ }
+```
+
+### Request Bodies
+
+To define a reusable request bodies you can use the [`Add-PodeOAComponentRequestBody`](../../../Functions/OAComponents/Add-PodeOAComponentRequestBody) function. You'll need to supply a Name, as well as the needed schemas for each content type.
+
+The following is an example of defining a JSON object that a Name, UserId, and an Enable flag:
+
+```powershell
+# define a reusable request body
+New-PodeOAContentMediaType -ContentType 'application/json', 'application/x-www-form-urlencoded' -Content (
+ New-PodeOAStringProperty -Name 'Name' |
+ New-PodeOAIntProperty -Name 'UserId' |
+ New-PodeOABoolProperty -Name 'Enabled' |
+ New-PodeOAObjectProperty
+ ) | Add-PodeOAComponentRequestBody -Name 'UserBody' -Required
+
+# use the request body in a route
+Add-PodeRoute -Method Patch -Path '/api/users' -ScriptBlock {
+ Set-PodeResponseStatus -StatusCode 200
+} -PassThru |
+ Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'UserBody')
+```
+
+The JSON payload expected is of the format:
+
+```json
+{
+ "Name": [string],
+ "UserId": [integer],
+ "Enabled": [boolean]
+}
+```
+
+### Parameters
+
+To define reusable parameters that are used on requests, you can use the [`Add-PodeOAComponentParameter`](../../../Functions/OAComponents/Add-PodeOAComponentParameter) function. You'll need to supply a Name and the Parameter definition.
+
+The following is an example of defining an integer path parameter for a `userId`, and then using that parameter on a route.
+
+```powershell
+# define a reusable {userid} path parameter
+New-PodeOAIntProperty -Name 'userId' -Required | ConvertTo-PodeOAParameter -In Path |Add-PodeOAComponentParameter -Name 'UserId'
+
+# use this parameter in a route
+Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{
+ Name = 'Rick'
+ UserId = $WebEvent.Parameters['userId']
+ }
+} -PassThru |
+ Set-PodeOARequest -Parameters @(ConvertTo-PodeOAParameter -Reference 'UserId')
+```
+
+### Responses
+
+To define a reusable response definition you can use the [`Add-PodeOAComponentResponse`](../../../Functions/OAComponents/Add-PodeOAComponentResponse) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
+
+The following is an example of defining a 200 response with a JSON payload of an array of objects for Name/UserId. The Response component can be used by a route referencing the name:
+
+```powershell
+# defines a response with a json payload using New-PodeOAContentMediaType
+Add-PodeOAComponentResponse -Name 'OK' -Description 'A user object' -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json' -Array -Content (
+ New-PodeOAStringProperty -Name 'Name' |
+ New-PodeOAIntProperty -Name 'UserId' |
+ New-PodeOAObjectProperty
+ )
+ )
+
+# reuses the above response on a route using its "OK" name
+Add-PodeRoute -Method Get -Path "/api/users" -ScriptBlock {
+ Write-PodeJsonResponse -Value @(
+ @{ Name = 'Rick'; UserId = 123 },
+ @{ Name = 'Geralt'; UserId = 124 }
+ )
+} -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Reference 'OK'
+```
+
+the JSON response payload defined is as follows:
+
+```json
+[
+ {
+ "Name": [string],
+ "UserId": [integer]
+ }
+]
+```
+
+
+### Examples
+
+To define a reusable example definition you can use the [`Add-PodeOAComponentExample`](../../../Functions/OAComponents/Add-PodeOAComponentExample) function. You'll need to supply a Name, a Summary and a list of value representing the object.
+
+The following is an example that defines three Pet examples request bodies, and how they're used in a Route's OpenAPI definition:
+
+```powershell
+ # defines the frog example
+Add-PodeOAComponentExample -name 'frog-example' -Summary "An example of a frog with a cat's name" -Value @{
+ name = 'Jaguar'; petType = 'Panthera'; color = 'Lion'; gender = 'Male'; breed = 'Mantella Baroni'
+}
+# defines the cat example
+Add-PodeOAComponentExample -Name 'cat-example' -Summary 'An example of a cat' -Value @{
+ name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian'
+}
+# defines the dog example
+Add-PodeOAComponentExample -Name 'dog-example' -Summary "An example of a dog with a cat's name" -Value @{
+ name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed'
+}
+
+# reuses the examples
+Add-PodeRoute -PassThru -Method Put -Path '/pet/:petId' -ScriptBlock {
+ # route code
+} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' `
+ -OperationId 'updatepet' -PassThru |
+ Set-PodeOARequest -Parameters @(
+ (New-PodeOAStringProperty -Name 'petId' -Description 'ID of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Path -Required)
+ ) -RequestBody (
+ New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'Pet' } -Examples (
+ New-PodeOAExample -ContentType 'application/json', 'application/xml' -Reference 'cat-example' |
+ New-PodeOAExample -ContentType 'application/json', 'application/xml' -Reference 'dog-example' |
+ New-PodeOAExample -ContentType 'application/json', 'application/xml' -Reference 'frog-example'
+ )
+ ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.'
+```
+
+### Headers
+
+To define a reusable header definition you can use the [`Add-PodeOAComponentHeader`](../../../Functions/OAComponents/Add-PodeOAComponentHeader) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
+
+```powershell
+ # define Headers
+New-PodeOAIntProperty -Format Int32 -Description 'calls per hour allowed by the user' |
+ Add-PodeOAComponentHeader -Name 'X-Rate-Limit'
+New-PodeOAStringProperty -Format Date-Time -Description 'date in UTC when token expires' |
+ Add-PodeOAComponentHeader -Name 'X-Expires-After'
+
+Add-PodeRoute -PassThru -Method Get -Path '/user/login' -ScriptBlock {
+ # route code
+} | Set-PodeOARouteInfo -Summary 'Logs user into the system.' -Description 'Logs user into the system.' `
+ -Tags 'user' -OperationId 'loginUser' -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' `
+ -Header @('X-Rate-Limit', 'X-Expires-After') -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'string'
+ ) -PassThru |
+ Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username/password supplied'
+```
+
+
+### CallBacks
+
+To define a reusable callback definition you can use the [`Add-PodeOAComponentCallBack`](../../../Functions/OAComponents/Add-PodeOAComponentCallBack) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
+
+```powershell
+Add-PodeRoute -PassThru -Method Post -Path '/petcallbackReference' -Authentication 'Login-OAuth2' `
+ -Scope 'write' -ScriptBlock {
+ #route code
+} | Set-PodeOARouteInfo -Summary 'Add a new pet to the store' -Description 'Add a new pet to the store' `
+ -Tags 'pet' -OperationId 'petcallbackReference' -PassThru |
+ Set-PodeOARequest -RequestBody ( New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet'
+ ) -PassThru |
+ Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
+ 'application / json' = ( New-PodeOAStringProperty -Name 'result' |
+ New-PodeOAStringProperty -Name 'message' |
+ New-PodeOAObjectProperty )
+ } -PassThru |
+ Add-PodeOACallBack -Name 'test1' -Reference 'test'
+```
+
+### Response Links
+
+To define a reusable response link definition you can use the [`Add-PodeOAComponentResponseLink`](../../../Functions/OAComponents/Add-PodeOAComponentResponseLink) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
+
+```powershell
+#Add link reference
+Add-PodeOAComponentResponseLink -Name 'address' -OperationId 'getUserByName' -Parameters @{
+ 'username' = '$request.path.username'
+}
+
+#use link reference
+Add-PodeRoute -PassThru -Method Put -Path '/userLinkByRef/:username' -ScriptBlock {
+ Write-PodeJsonResponse -Value 'done' -StatusCode 200
+} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' `
+ -Tags 'user' -OperationId 'updateUserLinkByRef' -PassThru |
+ Set-PodeOARequest -Parameters (
+ ( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
+ ) -RequestBody (
+ New-PodeOARequestBody -Required -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )
+ ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Content @{'application/json' = 'User' } -PassThru -Links (
+ New-PodeOAResponseLink -Name 'address2' -Reference 'address'
+ ) |
+ Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
+ Add-PodeOAResponse -StatusCode 404 -Description 'User not found' -PassThru |
+ Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
+```
\ No newline at end of file
diff --git a/docs/Tutorials/OpenAPI/4DocumentationTools.md b/docs/Tutorials/OpenAPI/4DocumentationTools.md
new file mode 100644
index 000000000..34b6822b7
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/4DocumentationTools.md
@@ -0,0 +1,41 @@
+
+# Documentation Tools
+
+If you're not using a custom OpenAPI viewer, then you can use one or more of the inbuilt which Pode supports: ones with Pode:
+
+* Swagger
+* ReDoc
+* RapiDoc
+* StopLight
+* Explorer
+* RapiPdf
+
+For each you can customise the Route path to access the page on, but by default Swagger is at `/swagger`, ReDoc is at `/redoc`, etc. If you've written your own custom OpenAPI definition then you can also set a custom Route path to fetch the definition on.
+
+To enable a viewer you can use the [`Enable-PodeOAViewer`](../../../Functions/OpenApi/Enable-PodeOAViewer) function:
+
+```powershell
+# for swagger at "/docs/swagger"
+Enable-PodeOAViewer -Type Swagger -Path '/docs/swagger' -DarkMode
+
+# and ReDoc at the default "/redoc"
+Enable-PodeOAViewer -Type ReDoc -Path '/docs/redoc'
+
+# and RapiDoc at "/docs/rapidoc"
+Enable-PodeOAViewer -Type RapiDoc -Path '/docs/rapidoc'
+
+# and StopLight at "/docs/stoplight"
+Enable-PodeOAViewer -Type StopLight -Path '/docs/stoplight'
+
+# and Explorer at "/docs/explorer"
+Enable-PodeOAViewer -Type Explorer -Path '/docs/explorer'
+
+# and RapiPdf at "/docs/rapipdf"
+Enable-PodeOAViewer -Type RapiPdf -Path '/docs/rapipdf'
+
+# plus a bookmark page with the link to all documentation
+Enable-PodeOAViewer -Bookmarks -Path '/docs'
+
+# there is also an OpenAPI editor (only for v3.0.x)
+Enable-PodeOAViewer -Editor -Path '/docs/swagger-editor'
+```
diff --git a/docs/Tutorials/OpenAPI/5ParameterValidation.md b/docs/Tutorials/OpenAPI/5ParameterValidation.md
new file mode 100644
index 000000000..e1693997a
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/5ParameterValidation.md
@@ -0,0 +1,50 @@
+
+## Parameter Validation
+
+Is possible to validate any parameter submitted by clients against an OpenAPI schema, ensuring adherence to defined standards.
+
+
+First, schema validation has to be enabled using :
+
+```powershell
+Enable-PodeOpenApi -EnableSchemaValidation #any other parameters needed
+```
+
+This command activates the OpenAPI feature with schema validation enabled, ensuring strict adherence to specified schemas.
+
+Next, is possible to validate any route using `Test-PodeOAJsonSchemaCompliance`.
+In this example, we'll create a route for updating a pet:
+
+```powershell
+Add-PodeRoute -PassThru -Method Post -Path '/user' -ScriptBlock {
+ $contentType = Get-PodeHeader -Name 'Content-Type'
+ $responseMediaType = Get-PodeHeader -Name 'Accept'
+ switch ($contentType) {
+ 'application/xml' {
+ $user = ConvertFrom-PodeXml -node $WebEvent.data | ConvertTo-Json
+ }
+ 'application/json' { $user = ConvertTo-Json $WebEvent.data }
+ 'application/x-www-form-urlencoded' { $user = ConvertTo- Json $WebEvent.data }
+ default {
+ Write-PodeHtmlResponse -StatusCode 415
+ return
+ }
+ }
+ $Validate = Test-PodeOAJsonSchemaCompliance -Json $user -SchemaReference 'User'
+ if ($Validate.result) {
+ $newUser = Add-user -User (convertfrom-json -InputObject $user -AsHashtable)
+ Save-PodeState -Path $using:PetDataJson
+ switch ($responseMediaType) {
+ 'application/xml' { Write-PodeXmlResponse -Value $newUser -StatusCode 200 }
+ 'application/json' { Write-PodeJsonResponse -Value $newUser -StatusCode 200 }
+ default { Write-PodeHtmlResponse -StatusCode 415 }
+ }
+ }
+ else {
+ Write-PodeHtmlResponse -StatusCode 405 -Value ($Validate.message -join ', ')
+ }
+} | Set-PodeOARouteInfo -Summary 'Create user.' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'createUser' -PassThru |
+ Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input' -PassThru |
+ Add-PodeOAResponse -Default -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'User' )
+```
diff --git a/docs/Tutorials/OpenAPI/6MultipleDefinitions.md b/docs/Tutorials/OpenAPI/6MultipleDefinitions.md
new file mode 100644
index 000000000..c3278723f
--- /dev/null
+++ b/docs/Tutorials/OpenAPI/6MultipleDefinitions.md
@@ -0,0 +1,129 @@
+
+# Multiple definitions
+
+It's possible to create multiple OpenAPI definitions inside the same Server instance. This feature could be useful in situations such as:
+
+* Multiple versions of the OpenAPI specification for different use cases
+* The same OpenAPI definition, but one using OpenAPI v3.0.3 and another using v3.1.0
+* Different APIs based on the IP or URL
+
+
+### How to use it
+Any Pode function that interacts with OpenAPI has a `-DefinitionTag [string[]]` parameter available. This allows you to specify within which OpenAPI definition(s) the API's definition should be available.
+
+!!! note
+ These functions accept a simple string, and not an array
+
+ * Get-PodeOADefinition
+ * Enable-PodeOpenApi
+ * Enable-PodeOAViewer
+ * Add-PodeOAInfo
+ * Test-PodeOAJsonSchemaCompliance
+
+A new OpenAPI definition has to be created using the `Enable-PodeOpenApi` function
+
+```powershell
+Enable-PodeOpenApi -Path '/docs/openapi/v3.0' -OpenApiVersion '3.0.3' -DefinitionTag 'v3'
+Enable-PodeOpenApi -Path '/docs/openapi/v3.1' -OpenApiVersion '3.1.0' -DefinitionTag 'v3.1'
+Enable-PodeOpenApi -Path '/docs/openapi/admin' -OpenApiVersion '3.1.0' -DefinitionTag 'admin'
+```
+
+There is also [`Select-PodeOADefinition`](../../../Functions/OpenApi/Select-PodeOADefinition), which simplifies the selection of which OpenAPI definition to use as a wrapper around multiple OpenAPI functions, or Route functions. Meaning you don't have to specify `-DefinitionTag` on embedded OpenAPI/Route calls:
+
+```powershell
+Select-PodeOADefinition -Tag 'v3', 'v3.1' -Scriptblock {
+ Add-PodeRouteGroup -Path '/api/v5' -Routes {
+ Add-PodeRoute -Method Get -Path '/petbyRef/:petId' -ScriptBlock {
+ Write-PodeJsonResponse -Value 'done' -StatusCode 2005
+ }
+ }
+}
+
+Select-PodeOADefinition -Tag 'admin' -ScriptBlock {
+ # your admin definition
+}
+```
+
+The default `Definition Tag` is named "default". This can be changed using the `Server.psd1` file and the `Web.OpenApi.DefaultDefinitionTag` property
+
+```powershell
+@{
+ Web=@{
+ OpenApi=@{
+ DefaultDefinitionTag= 'NewDefault'
+ }
+ }
+}
+```
+
+### Renaming a Definition Tag
+
+A Definition Tag can be renamed at any time using the `Rename-PodeOADefinitionTagName` function. This allows you to update the tag name for an existing OpenAPI definition, ensuring your tags remain organized and meaningful.
+
+```powershell
+Rename-PodeOADefinitionTagName -Tag 'v.3' -NewTag 'v.3.0.3'
+```
+
+In this example, the tag `'v.3'` is renamed to `'v.3.0.3'`.
+
+### Renaming the Default Definition Tag
+
+You can also rename the default `Definition Tag` without specifying the `Tag` parameter. This updates the default tag to the new name provided.
+
+```powershell
+Rename-PodeOADefinitionTagName -NewTag 'NewDefault'
+```
+
+In this example, the default definition tag is renamed to `'NewDefault'`.
+
+!!! note
+ The `Rename-PodeOADefinitionTagName` function cannot be used inside a `Select-PodeOADefinition` `[Scriptblock]`. Attempting to do so will result in an error.
+
+### OpenAPI example
+
+A simple OpenAPI definition
+
+```powershell
+Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' -Version 1.0.17 -Description $InfoDescription -TermsOfService 'http://swagger.io/terms/' -LicenseName 'Apache 2.0' `
+ -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' -ContactName 'API Support' -ContactEmail 'apiteam@swagger.io' -DefinitionTag 'v3'
+
+Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.1' -Version 1.0.17 -Description $InfoDescription -TermsOfService 'http://swagger.io/terms/' -LicenseName 'Apache 2.0' `
+ -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' -ContactName 'API Support' -ContactEmail 'apiteam@swagger.io' -DefinitionTag 'v3.1'
+
+Add-PodeOAServerEndpoint -url '/api/v3' -Description 'default endpoint' -DefinitionTag 'v3', 'v3.1'
+
+#OpenAPI 3.0
+Enable-PodeOAViewer -Type Swagger -Path '/docs/swagger' -DefinitionTag 'v3'
+Enable-PodeOAViewer -Type Bookmarks -Path '/docs' -DefinitionTag 'v3'
+
+#OpenAPI 3.1
+Enable-PodeOAViewer -Type Swagger -Path '/docs/v3.1/swagger' -DefinitionTag 'v3.1'
+Enable-PodeOAViewer -Type ReDoc -Path '/docs/v3.1/redoc' -DarkMode -DefinitionTag 'v3.1'
+Enable-PodeOAViewer -Type Bookmarks -Path '/docs/v3.1' -DefinitionTag 'v3.1'
+
+Select-PodeOADefinition -Tag 'v3', 'v3.1' -ScriptBlock {
+ New-PodeOAIntProperty -Name 'id'-Format Int64 -Example 10 -Required |
+ New-PodeOAStringProperty -Name 'name' -Example 'doggie' -Required |
+ New-PodeOASchemaProperty -Name 'category' -Reference 'Category' |
+ New-PodeOAStringProperty -Name 'photoUrls' -Array -XmlWrapped -XmlItemName 'photoUrl' -Required |
+ New-PodeOASchemaProperty -Name 'tags' -Reference 'Tag' -Array -XmlWrapped |
+ New-PodeOAStringProperty -Name 'status' -Description 'pet status in the store' -Enum @('available', 'pending', 'sold') |
+ New-PodeOAObjectProperty -XmlName 'pet' |
+ Add-PodeOAComponentSchema -Name 'Pet'
+
+
+ Add-PodeRouteGroup -Path '/api/v3' -Routes {
+ Add-PodeRoute -PassThru -Method Put -Path '/pet' -Authentication 'merged_auth_nokey' -Scope 'write:pets', 'read:pets' -ScriptBlock {
+ #code
+ } | Set-PodeOARouteInfo -Summary 'Update an existing pet' -Description 'Update an existing pet by Id' -Tags 'pet' -OperationId 'updatePet' -PassThru |
+ Set-PodeOARequest -RequestBody (
+ New-PodeOARequestBody -Description 'Update an existent pet in the store' -Required -Content (
+ New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' )
+ ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
+ Add-PodeOAResponse -StatusCode 404 -Description 'Pet not found' -PassThru |
+ Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception'
+ }
+}
+```
diff --git a/docs/Tutorials/OpenAPI/Overview.md b/docs/Tutorials/OpenAPI/Overview.md
deleted file mode 100644
index 66098b2e5..000000000
--- a/docs/Tutorials/OpenAPI/Overview.md
+++ /dev/null
@@ -1,1043 +0,0 @@
-# Overview
-
-Pode has built-in support for converting your routes into OpenAPI 3.0 definitions. There is also support for enabling simple Swagger and/or ReDoc viewers and others.
-
-The OpenApi module has been extended with many more functions, and some old ones have been improved.
-
-For more detailed information regarding OpenAPI and Pode, please refer to [OpenAPI Specification and Pode](../Specification/v3_0_3.md)
-
-You can enable OpenAPI in Pode, and a straightforward definition will be generated. However, to get a more complex definition with request bodies, parameters, and response payloads, you'll need to use the relevant OpenAPI functions detailed below.
-
-## Enabling OpenAPI
-
-To enable support for generating OpenAPI definitions you'll need to use the [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi) function. This will allow you to set a title and version for your API. You can also set a default route to retrieve the OpenAPI definition for tools like Swagger or ReDoc, the default is at `/openapi`.
-
-You can also set a route filter (such as `/api/*`, the default is `/*` for everything), so only those routes are included in the definition.
-
-An example of enabling OpenAPI is a follows:
-
-```powershell
-Enable-PodeOpenApi -Title 'My Awesome API' -Version 9.0.0.1
-```
-
-An example of setting the OpenAPI route is a follows. This will create a route accessible at `/docs/openapi`:
-
-```powershell
-Enable-PodeOpenApi -Path '/docs/openapi' -Title 'My Awesome API' -Version 9.0.0.1
-```
-
-### Default Setup
-
-In the very simplest of scenarios, just enabling OpenAPI will generate a minimal definition. It can be viewed in Swagger/ReDoc etc, but won't be usable for trying calls.
-
-When you enable OpenAPI, and don't set any other OpenAPI data, the following is the minimal data that is included:
-
-* Every route will have a 200 and Default response
-* Although routes will be included, no request bodies, parameters or response payloads will be defined
-* If you have multiple endpoints, then the servers section will be included
-* Any authentication will be included
-
-This can be changed with [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi)
-
-For example to change the default response 404 and 500
-
-```powershell
-Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -DefaultResponses (
- New-PodeOAResponse -StatusCode 404 -Description 'User not found' | Add-PodeOAResponse -StatusCode 500
- )
-```
-
-For disabling the Default Response use:
-
-```powershell
-Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -NoDefaultResponses
-```
-
-For disabling the Minimal Definitions feature use:
-
-```powershell
-Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.3' -DisableMinimalDefinitions
-```
-
-### Get Definition
-
-Instead of defining a route to return the definition, you can write the definition to the response whenever you want, and in any route, using the [`Get-PodeOADefinition`](../../../Functions/OpenApi/Get-PodeOADefinition) function. This could be useful in certain scenarios like in Azure Functions, where you can enable OpenAPI, and then write the definition to the response of a GET request if some query parameter is set; eg: `?openapi=1`.
-
-For example:
-
-```powershell
-Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
- if ($WebEvent.Query.openapi -eq 1) {
- Get-PodeOpenApiDefinition | Write-PodeJsonResponse
- }
-}
-```
-
-## OpenAPI Info object
-
-In previous releases some of the Info object properties like Version and Title were defined by [`Enable-PodeOpenApi`](../../../Functions/OpenApi/Enable-PodeOpenApi).
-Starting from version 2.10 a new [`Add-PodeOAInfo`](../../../Functions/OpenApi/Add-PodeOAInfo) function has been added to create a full OpenAPI Info spec.
-
-```powershell
-Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' `
- -Version 1.0.17 `
- -Description $InfoDescription `
- -TermsOfService 'http://swagger.io/terms/' `
- -LicenseName 'Apache 2.0' `
- -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' `
- -ContactName 'API Support' `
- -ContactEmail 'apiteam@swagger.io'
-```
-
-## OpenAPI configuration Best Practice
-
-Pode is rich of functions to create and configure an complete OpenApi spec. Here is a typical code you should use to initiate an OpenApi spec
-
-```powershell
-#Initialize OpenApi
-Enable-PodeOpenApi -Path '/docs/openapi' -Title 'Swagger Petstore - OpenAPI 3.0' `
- -OpenApiVersion 3.1 -DisableMinimalDefinitions -NoDefaultResponses
-
-# OpenApi Info
-Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' `
- -Version 1.0.17 `
- -Description 'This is a sample Pet Store Server based on the OpenAPI 3.0 specification. ...' `
- -TermsOfService 'http://swagger.io/terms/' `
- -LicenseName 'Apache 2.0' `
- -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' `
- -ContactName 'API Support' `
- -ContactEmail 'apiteam@swagger.io' `
- -ContactUrl 'http://example.com/support'
-
-# Endpoint for the API
- Add-PodeOAServerEndpoint -url '/api/v3.1' -Description 'default endpoint'
-
- # OpenApi external documentation links
- $extDoc = New-PodeOAExternalDoc -Name 'SwaggerDocs' -Description 'Find out more about Swagger' -Url 'http://swagger.io'
- $extDoc | Add-PodeOAExternalDoc
-
- # OpenApi documentation viewer
- Enable-PodeOAViewer -Type Swagger -Path '/docs/swagger'
- Enable-PodeOAViewer -Type ReDoc -Path '/docs/redoc'
- Enable-PodeOAViewer -Type RapiDoc -Path '/docs/rapidoc'
- Enable-PodeOAViewer -Type StopLight -Path '/docs/stoplight'
- Enable-PodeOAViewer -Type Explorer -Path '/docs/explorer'
- Enable-PodeOAViewer -Bookmarks -Path '/docs'
-```
-
-## Authentication
-
-Any authentication defined, either by [`Add-PodeAuthMiddleware`](../../../Functions/Authentication/Add-PodeAuthMiddleware), or using the `-Authentication` parameter on Routes, will be automatically added to the `security` section of the OpenAPI definition.
-
-
-## Tags
-
-In OpenAPI, a "tag" is used to group related operations. Tags are often used to organize and categorize endpoints in an API specification, making it easier to understand and navigate the API documentation. Each tag can be associated with one or more API operations, and these tags are then used in tools like Swagger UI to group and display operations in a more organized way.
-
-Here's an example of how to define and use tags:
-
-```powershell
-# create an External Doc reference
-$swaggerDocs = New-PodeOAExternalDoc -Description 'Find out more about Swagger' -Url 'http://swagger.io'
-
-# create a Tag
-Add-PodeOATag -Name 'pet' -Description 'Everything about your Pets' -ExternalDoc $swaggerDocs
-
-Add-PodeRoute -PassThru -Method get -Path '/pet/findByStatus' -Authentication 'Login-OAuth2' -Scope 'read' -AllowAnon -ScriptBlock {
- #route code
-} | Set-PodeOARouteInfo -Summary 'Finds Pets by status' -Description 'Multiple status values can be provided with comma-separated strings' `
- -Tags 'pet' -OperationId 'findPetsByStatus'
-```
-
-## Routes
-
-To extend the definition of a route, you can use the `-PassThru` switch on the [`Add-PodeRoute`](../../../Functions/Routes/Add-PodeRoute) function. This will cause the route that was created to be returned, so you can pass it down the pipe into more OpenAPI functions.
-
-To add metadata to a route's definition you can use the [`Set-PodeOARouteInfo`](../../../Functions/OpenApi/Set-PodeOARouteInfo) function. This will allow you to define a summary/description for the route, as well as tags for grouping:
-
-```powershell
-Add-PodeRoute -Method Get -Path "/api/resources" -ScriptBlock {
- Set-PodeResponseStatus -Code 200
-} -PassThru |
- Set-PodeOARouteInfo -Summary 'Retrieve some resources' -Tags 'Resources'
-```
-
-Each of the following OpenAPI functions have a `-PassThru` switch, allowing you to chain many of them together.
-
-### Responses
-
-You can define multiple responses for a route, but only one of each status code, using the [`Add-PodeOAResponse`](../../../Functions/OpenApi/Add-PodeOAResponse) function. You can either just define the response and status code, with a custom description, or with a schema defining the payload of the response.
-
-The following is an example of defining simple 200 and 404 responses on a route:
-
-```powershell
-Add-PodeRoute -Method Get -Path "/api/user/:userId" -ScriptBlock {
- # logic
-} -PassThru |
- Add-PodeOAResponse -StatusCode 200 -PassThru |
- Add-PodeOAResponse -StatusCode 404 -Description 'User not found'
-```
-
-Whereas the following is a more complex definition, which also defines the responses JSON payload. This payload is defined as an object with a string Name, and integer UserId:
-
-```powershell
-Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Parameters['userId']
- }
-} -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'A user object' --Content @{
- 'application/json' = (New-PodeOAStringProperty -Name 'Name'|
- New-PodeOAIntProperty -Name 'UserId'| New-PodeOAObjectProperty)
- }
-```
-
-the JSON response payload defined is as follows:
-
-```json
-{
- "Name": [string],
- "UserId": [integer]
-}
-```
-
-In case the response JSON payload is an array
-
-```powershell
-Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Parameters['userId']
- }
- } -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'A user object' -Content (
- New-PodeOAContentMediaType -ContentMediaType 'application/json' -Array -Content (
- New-PodeOAStringProperty -Name 'Name' |
- New-PodeOAIntProperty -Name 'UserId' |
- New-PodeOAObjectProperty
- )
- )
-```
-
-```json
-[
- {
- "Name": [string],
- "UserId": [integer]
- }
-]
-```
-
-Internally, each route is created with an empty default 200 and 500 response. You can remove these, or other added responses, by using [`Remove-PodeOAResponse`](../../../Functions/OpenApi/Remove-PodeOAResponse):
-
-```powershell
-Add-PodeRoute -Method Get -Path "/api/user/:userId" -ScriptBlock {
- # route logic
-} -PassThru |
- Remove-PodeOAResponse -StatusCode 200
-```
-
-### Requests
-
-#### Parameters
-
-You can set route parameter definitions, such as parameters passed in the path/query, by using the [`Set-PodeOARequest`](../../../Functions/OpenApi/Set-PodeOARequest) function with the `-Parameters` parameter. The parameter takes an array of properties converted into parameters, using the [`ConvertTo-PodeOAParameter`](../../../Functions/OpenApi/ConvertTo-PodeOAParameter) function.
-
-For example, to create some integer `userId` parameter that is supplied in the path of the request, the following will work:
-
-```powershell
-Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Parameters['userId']
- }
-} -PassThru |
- Set-PodeOARequest -Parameters @(
- (New-PodeOAIntProperty -Name 'userId' -Required | ConvertTo-PodeOAParameter -In Path)
- )
-```
-
-Whereas you could use the next example to define 2 query parameters, both strings:
-
-```powershell
-Add-PodeRoute -Method Get -Path '/api/users' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Query['name']
- }
-} -PassThru |
- Set-PodeOARequest -Parameters (
- (New-PodeOAStringProperty -Name 'name' -Required | ConvertTo-PodeOAParameter -In Query),
- (New-PodeOAStringProperty -Name 'city' -Required | ConvertTo-PodeOAParameter -In Query)
- )
-```
-
-#### Payload
-
-You can set request payload schemas by using the [`Set-PodeOARequest`](../../../Functions/OpenApi/Set-PodeOARequest)function, with the `-RequestBody` parameter. The request body can be defined using the [`New-PodeOARequestBody`](../../../Functions/OpenApi/New-PodeOARequestBody) function, and supplying schema definitions for content types - this works in very much a similar way to defining responses above.
-
-For example, to define a request JSON payload of some `userId` and `name` you could use the following:
-
-```powershell
-Add-PodeRoute -Method Patch -Path '/api/users' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = $WebEvent.Data.name
- UserId = $WebEvent.Data.userId
- }
-} -PassThru |
- Set-PodeOARequest -RequestBody (
- New-PodeOARequestBody -Required -Content (
- New-PodeOAContentMediaType -ContentMediaType 'application/json','application/xml' -Content ( New-PodeOAStringProperty -Name 'Name'| New-PodeOAIntProperty -Name 'UserId'| New-PodeOAObjectProperty ) )
-
- )
-```
-
-The expected payload would look as follows:
-
-```json
-{
- "name": [string],
- "userId": [integer]
-}
-```
-
-```xml
-
-
-```
-
-## Components
-
-You can define reusable OpenAPI components in Pode. Currently supported are Schemas, Parameters, Request Bodies, and Responses.
-
-### Schemas
-
-To define a reusable schema that can be used in request bodies, and responses, you can use the [`Add-PodeOAComponentSchema`](../../../Functions/OAComponents/Add-PodeOAComponentSchema) function. You'll need to supply a Name, and a Schema that can be reused.
-
-The following is an example of defining a schema which is a object of Name, UserId, and Age:
-
-```powershell
-# define a reusable schema user object
-New-PodeOAStringProperty -Name 'Name' |
- New-PodeOAIntProperty -Name 'UserId' |
- New-PodeOAIntProperty -Name 'Age' |
- New-PodeOAObjectProperty |
- Add-PodeOAComponentSchema -Name 'UserSchema'
-
-# reuse the above schema in a response
-Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Parameters['userId']
- Age = 42
- }
-} -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'A list of users' -Content @{
- 'application/json' = 'UserSchema'
- }
-```
-
-### Request Bodies
-
-To define a reusable request bodies you can use the [`Add-PodeOAComponentRequestBody`](../../../Functions/OAComponents/Add-PodeOAComponentRequestBody) function. You'll need to supply a Name, as well as the needed schemas for each content type.
-
-The following is an example of defining a JSON object that a Name, UserId, and an Enable flag:
-
-```powershell
-# define a reusable request body
-New-PodeOAContentMediaType -ContentMediaType 'application/json', 'application/x-www-form-urlencoded' -Content (
- New-PodeOAStringProperty -Name 'Name' |
- New-PodeOAIntProperty -Name 'UserId' |
- New-PodeOABoolProperty -Name 'Enabled' |
- New-PodeOAObjectProperty
- ) | Add-PodeOAComponentRequestBody -Name 'UserBody' -Required
-
-# use the request body in a route
-Add-PodeRoute -Method Patch -Path '/api/users' -ScriptBlock {
- Set-PodeResponseStatus -StatusCode 200
-} -PassThru |
- Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'UserBody')
-```
-
-The JSON payload expected is of the format:
-
-```json
-{
- "Name": [string],
- "UserId": [integer],
- "Enabled": [boolean]
-}
-```
-
-### Parameters
-
-To define reusable parameters that are used on requests, you can use the [`Add-PodeOAComponentParameter`](../../../Functions/OAComponents/Add-PodeOAComponentParameter) function. You'll need to supply a Name and the Parameter definition.
-
-The following is an example of defining an integer path parameter for a `userId`, and then using that parameter on a route.
-
-```powershell
-# define a reusable {userid} path parameter
-New-PodeOAIntProperty -Name 'userId' -Required | ConvertTo-PodeOAParameter -In Path |Add-PodeOAComponentParameter -Name 'UserId'
-
-# use this parameter in a route
-Add-PodeRoute -Method Get -Path '/api/users/:userId' -ScriptBlock {
- Write-PodeJsonResponse -Value @{
- Name = 'Rick'
- UserId = $WebEvent.Parameters['userId']
- }
-} -PassThru |
- Set-PodeOARequest -Parameters @(ConvertTo-PodeOAParameter -Reference 'UserId')
-```
-
-### Responses
-
-To define a reusable response definition you can use the [`Add-PodeOAComponentResponse`](../../../Functions/OAComponents/Add-PodeOAComponentResponse) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
-
-The following is an example of defining a 200 response with a JSON payload of an array of objects for Name/UserId. The Response component can be used by a route referencing the name:
-
-```powershell
-# defines a response with a json payload using New-PodeOAContentMediaType
-Add-PodeOAComponentResponse -Name 'OK' -Description 'A user object' -Content (
- New-PodeOAContentMediaType -MediaType 'application/json' -Array -Content (
- New-PodeOAStringProperty -Name 'Name' |
- New-PodeOAIntProperty -Name 'UserId' |
- New-PodeOAObjectProperty
- )
- )
-
-# reuses the above response on a route using its "OK" name
-Add-PodeRoute -Method Get -Path "/api/users" -ScriptBlock {
- Write-PodeJsonResponse -Value @(
- @{ Name = 'Rick'; UserId = 123 },
- @{ Name = 'Geralt'; UserId = 124 }
- )
-} -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Reference 'OK'
-```
-
-the JSON response payload defined is as follows:
-
-```json
-[
- {
- "Name": [string],
- "UserId": [integer]
- }
-]
-```
-
-
-### Examples
-
-To define a reusable example definition you can use the [`Add-PodeOAComponentExample`](../../../Functions/OAComponents/Add-PodeOAComponentExample) function. You'll need to supply a Name, a Summary and a list of value representing the object.
-
-The following is an example that defines three Pet examples request bodies, and how they're used in a Route's OpenAPI definition:
-
-```powershell
- # defines the frog example
-Add-PodeOAComponentExample -name 'frog-example' -Summary "An example of a frog with a cat's name" -Value @{
- name = 'Jaguar'; petType = 'Panthera'; color = 'Lion'; gender = 'Male'; breed = 'Mantella Baroni'
-}
-# defines the cat example
-Add-PodeOAComponentExample -Name 'cat-example' -Summary 'An example of a cat' -Value @{
- name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian'
-}
-# defines the dog example
-Add-PodeOAComponentExample -Name 'dog-example' -Summary "An example of a dog with a cat's name" -Value @{
- name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed'
-}
-
-# reuses the examples
-Add-PodeRoute -PassThru -Method Put -Path '/pet/:petId' -ScriptBlock {
- # route code
-} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' `
- -OperationId 'updatepet' -PassThru |
- Set-PodeOARequest -Parameters @(
- (New-PodeOAStringProperty -Name 'petId' -Description 'ID of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Path -Required)
- ) -RequestBody (
- New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'Pet' } -Examples (
- New-PodeOAExample -ContentMediaType 'application/json', 'application/xml' -Reference 'cat-example' |
- New-PodeOAExample -ContentMediaType 'application/json', 'application/xml' -Reference 'dog-example' |
- New-PodeOAExample -ContentMediaType 'application/json', 'application/xml' -Reference 'frog-example'
- )
- ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.'
-```
-
-### Headers
-
-To define a reusable header definition you can use the [`Add-PodeOAComponentHeader`](../../../Functions/OAComponents/Add-PodeOAComponentHeader) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
-
-```powershell
- # define Headers
-New-PodeOAIntProperty -Format Int32 -Description 'calls per hour allowed by the user' |
- Add-PodeOAComponentHeader -Name 'X-Rate-Limit'
-New-PodeOAStringProperty -Format Date-Time -Description 'date in UTC when token expires' |
- Add-PodeOAComponentHeader -Name 'X-Expires-After'
-
-Add-PodeRoute -PassThru -Method Get -Path '/user/login' -ScriptBlock {
- # route code
-} | Set-PodeOARouteInfo -Summary 'Logs user into the system.' -Description 'Logs user into the system.' `
- -Tags 'user' -OperationId 'loginUser' -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' `
- -Header @('X-Rate-Limit', 'X-Expires-After') -Content (
- New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'string'
- ) -PassThru |
- Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username/password supplied'
-```
-
-
-### CallBacks
-
-To define a reusable callback definition you can use the [`Add-PodeOAComponentCallBack`](../../../Functions/OAComponents/Add-PodeOAComponentCallBack) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
-
-```powershell
-Add-PodeRoute -PassThru -Method Post -Path '/petcallbackReference' -Authentication 'Login-OAuth2' `
- -Scope 'write' -ScriptBlock {
- #route code
-} | Set-PodeOARouteInfo -Summary 'Add a new pet to the store' -Description 'Add a new pet to the store' `
- -Tags 'pet' -OperationId 'petcallbackReference' -PassThru |
- Set-PodeOARequest -RequestBody ( New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (
- New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet'
- ) -PassThru |
- Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
- 'application / json' = ( New-PodeOAStringProperty -Name 'result' |
- New-PodeOAStringProperty -Name 'message' |
- New-PodeOAObjectProperty )
- } -PassThru |
- Add-PodeOACallBack -Name 'test1' -Reference 'test'
-```
-
-### Response Links
-
-To define a reusable response link definition you can use the [`Add-PodeOAComponentResponseLink`](../../../Functions/OAComponents/Add-PodeOAComponentResponseLink) function. You'll need to supply a Name, and optionally any Content/Header schemas that define the responses payload.
-
-```powershell
-#Add link reference
-Add-PodeOAComponentResponseLink -Name 'address' -OperationId 'getUserByName' -Parameters @{
- 'username' = '$request.path.username'
-}
-
-#use link reference
-Add-PodeRoute -PassThru -Method Put -Path '/userLinkByRef/:username' -ScriptBlock {
- Write-PodeJsonResponse -Value 'done' -StatusCode 200
-} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' `
- -Tags 'user' -OperationId 'updateUserLinkByRef' -PassThru |
- Set-PodeOARequest -Parameters (
- ( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
- ) -RequestBody (
- New-PodeOARequestBody -Required -Content (
- New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )
- ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Content @{'application/json' = 'User' } -PassThru -Links (
- New-PodeOAResponseLink -Name 'address2' -Reference 'address'
- ) |
- Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
- Add-PodeOAResponse -StatusCode 404 -Description 'User not found' -PassThru |
- Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
-```
-
-## Properties
-
-Properties are used to create all Parameters and Schemas in OpenAPI. You can use the simple types on their own, or you can combine multiple of them together to form complex objects.
-
-### Simple Types
-
-There are 5 simple property types: Integers, Numbers, Strings, Booleans, and Schemas. Each of which can be created using the following functions:
-
-* [`New-PodeOAIntProperty`](../../../Functions/OAProperties/New-PodeOAIntProperty)
-* [`New-PodeOANumberProperty`](../../../Functions/OAProperties/New-PodeOANumberProperty)
-* [`New-PodeOAStringProperty`](../../../Functions/OAProperties/New-PodeOAStringProperty)
-* [`New-PodeOABoolProperty`](../../../Functions/OAProperties/New-PodeOABoolProperty)
-* [`New-PodeOASchemaProperty`](../../../Functions//New-PodeOASchemaProperty)
-* [`New-PodeOAMultiTypeProperty`](../../../Functions/OAProperties/New-PodeOAMultiTypeProperty) (Note: OpenAPI 3.1 only)
-
-These properties can be created with a Name, and other flags such as Required and/or a Description:
-
-```powershell
-# simple integer
-New-PodeOAIntProperty -Name 'userId'
-
-# a float number with a max value of 100
-New-PodeOANumberProperty -Name 'ratio' -Format Float -Maximum 100
-
-# a string with a default value, and enum of options
-New-PodeOAStringProperty -Name 'type' -Default 'admin' -Enum @('admin', 'user')
-
-# a boolean that's required
-New-PodeOABoolProperty -Name 'enabled' -Required
-
-# a schema property that references another component schema
-New-PodeOASchemaProperty -Name 'Config' -Reference 'ConfigSchema'
-
-# a string or an integer or a null value (only available with OpenAPI 3.1)
-New-PodeOAMultiTypeProperty -Name 'multi' -Type integer,string -Nullable
-```
-
-On their own, like above, the simple properties don't really do much. However, you can combine that together to make complex objects/arrays as defined below.
-
-### Arrays
-
-There isn't a dedicated function to create an array property, instead there is an `-Array` switch on each of the property functions - both Object and the above simple properties.
-
-If you supply the `-Array` switch to any of the above simple properties, this will define an array of that type - the `-Name` parameter can also be omitted if only a simple array if required.
-
-For example, the below will define an integer array:
-
-```powershell
-New-PodeOAIntProperty -Array
-```
-
-When used in a Response, this could return the following JSON example:
-
-```json
-[
- 0,
- 1,
- 2
-]
-```
-
-### Objects
-
-An object property is a combination of multiple other properties - both simple, array of more objects.
-
-There are two ways to define objects:
-
-1. Similar to arrays, you can use the `-Object` switch on the simple properties.
-2. You can use the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function to combine multiple properties.
-
-#### Simple
-
-If you use the `-Object` switch on the simple property function, this will automatically wrap the property as an object. The Name for this is required.
-
-For example, the below will define a simple `userId` integer object:
-
-```powershell
-New-PodeOAIntProperty -Name 'userId' -Object
-```
-
-In a response as JSON, this could look as follows:
-
-```json
-{
- "userId": 0
-}
-```
-
-Furthermore, you can also supply both `-Array` and `-Object` switches:
-
-```powershell
-New-PodeOAIntProperty -Name 'userId' -Object -Array
-```
-
-This wil result in something like the following JSON:
-
-```json
-{
- "userId": [ 0, 1, 2 ]
-}
-```
-
-#### Complex
-
-Unlike the `-Object` switch that simply converts a single property into an object, the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function can combine and convert multiple properties.
-
-For example, the following will create an object using an Integer, String, and a Boolean:
-
-Legacy Definition
-
-```powershell
-New-PodeOAObjectProperty -Properties (
- (New-PodeOAIntProperty -Name 'userId'),
- (New-PodeOAStringProperty -Name 'name'),
- (New-PodeOABoolProperty -Name 'enabled')
-)
-```
-
-Using piping (new in Pode 2.10)
-
-```powershell
-New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
- New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty
-```
-
-As JSON, this could look as follows:
-
-```json
-{
- "userId": 0,
- "name": "Gary Goodspeed",
- "enabled": true
-}
-```
-
-You can also supply the `-Array` switch to the [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) function. This will result in an array of objects. For example, if we took the above:
-
-```powershell
-New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
- New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty -Array
-```
-
-As JSON, this could look as follows:
-
-```json
-[
- {
- "userId": 0,
- "name": "Gary Goodspeed",
- "enabled": true
- },
- {
- "userId": 1,
- "name": "Kevin",
- "enabled": false
- }
-]
-```
-
-You can also combine objects into other objects:
-
-```powershell
-$usersArray = New-PodeOAIntProperty -Name 'userId'| New-PodeOAStringProperty -Name 'name'|
- New-PodeOABoolProperty -Name 'enabled' |New-PodeOAObjectProperty -Array
-
-New-PodeOAObjectProperty -Properties @(
- (New-PodeOAIntProperty -Name 'found'),
- $usersArray
-)
-```
-
-As JSON, this could look as follows:
-
-```json
-{
- "found": 2,
- "users": [
- {
- "userId": 0,
- "name": "Gary Goodspeed",
- "enabled": true
- },
- {
- "userId": 1,
- "name": "Kevin",
- "enabled": false
- }
- ]
-}
-```
-
-### oneOf, anyOf and allOf Keywords
-
-OpenAPI 3.x provides several keywords which you can use to combine schemas. You can use these keywords to create a complex schema or validate a value against multiple criteria.
-
-* oneOf - validates the value against exactly one of the sub-schemas
-* allOf - validates the value against all the sub-schemas
-* anyOf - validates the value against any (one or more) of the sub-schemas
-
-You can use the [`Merge-PodeOAProperty`](../../../Functions/OAProperties/Merge-PodeOAProperty) will instead define a relationship between the properties.
-
-Unlike [`New-PodeOAObjectProperty`](../../../Functions/OAProperties/New-PodeOAObjectProperty) which combines and converts multiple properties into an Object, [`Merge-PodeOAProperty`](../../../Functions/OAProperties/Merge-PodeOAProperty) will instead define a relationship between the properties.
-
-For example, the following will create an something like an C Union object using an Integer, String, and a Boolean:
-
-```powershell
-Merge-PodeOAProperty -Type OneOf -ObjectDefinitions @(
- (New-PodeOAIntProperty -Name 'userId' -Object),
- (New-PodeOAStringProperty -Name 'name' -Object),
- (New-PodeOABoolProperty -Name 'enabled' -Object)
- )
-```
-
-Or
-
-```powershell
-New-PodeOAIntProperty -Name 'userId' -Object |
- New-PodeOAStringProperty -Name 'name' -Object |
- New-PodeOABoolProperty -Name 'enabled' -Object |
- Merge-PodeOAProperty -Type OneOf
-```
-
-As JSON, this could look as follows:
-
-```json
-{
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "userId": {
- "type": "integer"
- }
- }
- },
- {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- }
- }
- },
- {
- "type": "object",
- "properties": {
- "enabled": {
- "type": "boolean",
- "default": false
- }
- }
- }
- ]
-}
-```
-
-You can also supply a Component Schema created using [`Add-PodeOAComponentSchema`](../../../Functions/OAComponents/Add-PodeOAComponentSchema). For example, if we took the above:
-
-```powershell
- New-PodeOAIntProperty -Name 'id'-Format Int64 -Example 1 -ReadOnly |
- New-PodeOAStringProperty -Name 'username' -Example 'theUser' -Required |
- New-PodeOAStringProperty -Name 'firstName' -Example 'John' |
- New-PodeOAStringProperty -Name 'lastName' -Example 'James' |
- New-PodeOAStringProperty -Name 'email' -Format email -Example 'john@email.com' |
- New-PodeOAStringProperty -Name 'lastName' -Example 'James' |
- New-PodeOAStringProperty -Name 'password' -Format Password -Example '12345' -Required |
- New-PodeOAStringProperty -Name 'phone' -Example '12345' |
- New-PodeOAIntProperty -Name 'userStatus'-Format int32 -Description 'User Status' -Example 1|
- New-PodeOAObjectProperty -Name 'User' -XmlName 'user' |
- Add-PodeOAComponentSchema
-
- New-PodeOAStringProperty -Name 'street' -Example '437 Lytton' -Required |
- New-PodeOAStringProperty -Name 'city' -Example 'Palo Alto' -Required |
- New-PodeOAStringProperty -Name 'state' -Example 'CA' -Required |
- New-PodeOAStringProperty -Name 'zip' -Example '94031' -Required |
- New-PodeOAObjectProperty -Name 'Address' -XmlName 'address' -Description 'Shipping Address' |
- Add-PodeOAComponentSchema
-
- Merge-PodeOAProperty -Type AllOf -ObjectDefinitions 'Address','User'
-
-```
-
-As JSON, this could look as follows:
-
-```json
-{
- "allOf": [
- {
- "$ref": "#/components/schemas/Address"
- },
- {
- "$ref": "#/components/schemas/User"
- }
- ]
-}
-```
-## Implementing Parameter Validation
-
-Is possible to validate any parameter submitted by clients against an OpenAPI schema, ensuring adherence to defined standards.
-
-
-First, schema validation has to be enabled using :
-
-```powershell
-Enable-PodeOpenApi -EnableSchemaValidation #any other parameters needed
-```
-
-This command activates the OpenAPI feature with schema validation enabled, ensuring strict adherence to specified schemas.
-
-Next, is possible to validate any route using `PodeOAJsonSchemaCompliance`.
-In this example, we'll create a route for updating a pet:
-
-```powershell
-Add-PodeRoute -PassThru -Method Post -Path '/user' -ScriptBlock {
- $contentType = Get-PodeHeader -Name 'Content-Type'
- $responseMediaType = Get-PodeHeader -Name 'Accept'
- switch ($contentType) {
- 'application/xml' {
- $user = ConvertFrom-PodeXml -node $WebEvent.data | ConvertTo-Json
- }
- 'application/json' { $user = ConvertTo-Json $WebEvent.data }
- 'application/x-www-form-urlencoded' { $user = ConvertTo-Json $WebEvent.data }
- default {
- Write-PodeHtmlResponse -StatusCode 415
- return
- }
- }
- $Validate = Test-PodeOAJsonSchemaCompliance -Json $user -SchemaReference 'User'
- if ($Validate.result) {
- $newUser = Add-user -User (convertfrom-json -InputObject $user -AsHashtable)
- Save-PodeState -Path $using:PetDataJson
- switch ($responseMediaType) {
- 'application/xml' { Write-PodeXmlResponse -Value $newUser -StatusCode 200 }
- 'application/json' { Write-PodeJsonResponse -Value $newUser -StatusCode 200 }
- default { Write-PodeHtmlResponse -StatusCode 415 }
- }
- }
- else {
- Write-PodeHtmlResponse -StatusCode 405 -Value ($Validate.message -join ', ')
- }
-} | Set-PodeOARouteInfo -Summary 'Create user.' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'createUser' -PassThru |
- Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
- Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input' -PassThru |
- Add-PodeOAResponse -Default -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'User' )
-```
-#### Explanation
-- The route handles different content types (JSON/XML) and converts them to JSON for validation.
-- It validates the received pet object against the 'User' schema using the 'Test-PodeOAJsonSchemaCompliance' function.
-- Depending on the validation result, appropriate HTTP responses are returned.
-- OpenAPI metadata such as summary, description, request body, and responses are also defined for documentation purposes.
-
-
-
-## OpenApi Documentation pages
-
-If you're not using a custom OpenAPI viewer, then you can use one or more of the inbuilt which Pode supports: ones with Pode:
-
-* Swagger
-* ReDoc
-* RapiDoc
-* StopLight
-* Explorer
-* RapiPdf
-
-For each you can customise the Route path to access the page on, but by default Swagger is at `/swagger`, ReDoc is at `/redoc`, etc. If you've written your own custom OpenAPI definition then you can also set a custom Route path to fetch the definition on.
-
-To enable a viewer you can use the [`Enable-PodeOAViewer`](../../../Functions/OpenApi/Enable-PodeOAViewer) function:
-
-```powershell
-# for swagger at "/docs/swagger"
-Enable-PodeOpenApiViewer -Type Swagger -Path '/docs/swagger' -DarkMode
-
-# and ReDoc at the default "/redoc"
-Enable-PodeOpenApiViewer -Type ReDoc
-
-# and RapiDoc at "/docs/rapidoc"
-Enable-PodeOAViewer -Type RapiDoc -Path '/docs/rapidoc' -DarkMode
-
-# and StopLight at "/docs/stoplight"
-Enable-PodeOAViewer -Type StopLight -Path '/docs/stoplight'
-
-# and Explorer at "/docs/explorer"
-Enable-PodeOAViewer -Type Explorer -Path '/docs/explorer'
-
-# and RapiPdf at "/docs/rapipdf"
-Enable-PodeOAViewer -Type RapiPdf -Path '/docs/rapipdf'
-
-# plus a bookmark page with the link to all documentation
-Enable-PodeOAViewer -Bookmarks -Path '/docs'
-
-# there is also an OpenAPI editor (only for v3.0.x)
-Enable-PodeOAViewer -Editor -Path '/docs/swagger-editor'
-```
-
-## Multiple OpenAPI definition
-
-It's possible to create multiple OpenAPI definitions inside the same Server instance. This feature could be useful in situations such as:
-
-* Multiple versions of the OpenAPI specification for different use cases
-* The same OpenAPI definition, but one using OpenAPI v3.0.3 and another using v3.1.0
-* Different APIs based on the IP or URL
-
-
-### How to use it
-Any Pode function that interacts with OpenAPI has a `-DefinitionTag [string[]]` parameter available. This allows you to specify within which OpenAPI definition(s) the API's definition should be available.
-
-!!! note
- These functions accept a simple string, and not an array
-
- * Get-PodeOADefinition
- * Enable-PodeOpenApi
- * Enable-PodeOAViewer
- * Add-PodeOAInfo
- * Test-PodeOAJsonSchemaCompliance
-
-A new OpenAPI definition has to be created using the `Enable-PodeOpenApi` function
-
-```powershell
-Enable-PodeOpenApi -Path '/docs/openapi/v3.0' -OpenApiVersion '3.0.3' -DefinitionTag 'v3'
-Enable-PodeOpenApi -Path '/docs/openapi/v3.1' -OpenApiVersion '3.1.0' -DefinitionTag 'v3.1'
-Enable-PodeOpenApi -Path '/docs/openapi/admin' -OpenApiVersion '3.1.0' -DefinitionTag 'admin'
-```
-
-There is also [`Select-PodeOADefinition`](../../../Functions/OpenApi/Select-PodeOADefinition), which simplifies the selection of which OpenAPI definition to use as a wrapper around multiple OpenAPI functions, or Route functions. Meaning you don't have to specify `-DefinitionTag` on embedded OpenAPI/Route calls:
-
-```powershell
-Select-PodeOADefinition -Tag 'v3', 'v3.1' -Scriptblock {
- Add-PodeRouteGroup -Path '/api/v5' -Routes {
- Add-PodeRoute -Method Get -Path '/petbyRef/:petId' -ScriptBlock {
- Write-PodeJsonResponse -Value 'done' -StatusCode 2005
- }
- }
-}
-
-Select-PodeOADefinition -Tag 'admin' -ScriptBlock {
- # your admin definition
-}
-```
-
-The default `Definition Tag` is named "default". This can be changed using the `Server.psd1` file and the `Web.OpenApi.DefaultDefinitionTag` property
-
-```powershell
-@{
- Web=@{
- OpenApi=@{
- DefaultDefinitionTag= 'NewDfault'
- }
- }
-}
-```
-
-### OpenAPI example
-
-A simple OpenAPI definition
-
-```powershell
-Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.0' -Version 1.0.17 -Description $InfoDescription -TermsOfService 'http://swagger.io/terms/' -LicenseName 'Apache 2.0' `
- -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' -ContactName 'API Support' -ContactEmail 'apiteam@swagger.io' -DefinitionTag 'v3'
-
-Add-PodeOAInfo -Title 'Swagger Petstore - OpenAPI 3.1' -Version 1.0.17 -Description $InfoDescription -TermsOfService 'http://swagger.io/terms/' -LicenseName 'Apache 2.0' `
- -LicenseUrl 'http://www.apache.org/licenses/LICENSE-2.0.html' -ContactName 'API Support' -ContactEmail 'apiteam@swagger.io' -DefinitionTag 'v3.1'
-
-Add-PodeOAServerEndpoint -url '/api/v3' -Description 'default endpoint' -DefinitionTag 'v3', 'v3.1'
-
-#OpenAPI 3.0
-Enable-PodeOAViewer -Type Swagger -Path '/docs/swagger' -DefinitionTag 'v3'
-Enable-PodeOAViewer -Type Bookmarks -Path '/docs' -DefinitionTag 'v3'
-
-#OpenAPI 3.1
-Enable-PodeOAViewer -Type Swagger -Path '/docs/v3.1/swagger' -DefinitionTag 'v3.1'
-Enable-PodeOAViewer -Type ReDoc -Path '/docs/v3.1/redoc' -DarkMode -DefinitionTag 'v3.1'
-Enable-PodeOAViewer -Type Bookmarks -Path '/docs/v3.1' -DefinitionTag 'v3.1'
-
-Select-PodeOADefinition -Tag 'v3', 'v3.1' -ScriptBlock {
- New-PodeOAIntProperty -Name 'id'-Format Int64 -Example 10 -Required |
- New-PodeOAStringProperty -Name 'name' -Example 'doggie' -Required |
- New-PodeOASchemaProperty -Name 'category' -Reference 'Category' |
- New-PodeOAStringProperty -Name 'photoUrls' -Array -XmlWrapped -XmlItemName 'photoUrl' -Required |
- New-PodeOASchemaProperty -Name 'tags' -Reference 'Tag' -Array -XmlWrapped |
- New-PodeOAStringProperty -Name 'status' -Description 'pet status in the store' -Enum @('available', 'pending', 'sold') |
- New-PodeOAObjectProperty -XmlName 'pet' |
- Add-PodeOAComponentSchema -Name 'Pet'
-
-
- Add-PodeRouteGroup -Path '/api/v3' -Routes {
- Add-PodeRoute -PassThru -Method Put -Path '/pet' -Authentication 'merged_auth_nokey' -Scope 'write:pets', 'read:pets' -ScriptBlock {
- #code
- } | Set-PodeOARouteInfo -Summary 'Update an existing pet' -Description 'Update an existing pet by Id' -Tags 'pet' -OperationId 'updatePet' -PassThru |
- Set-PodeOARequest -RequestBody (
- New-PodeOARequestBody -Description 'Update an existent pet in the store' -Required -Content (
- New-PodeOAContentMediaType -ContentMediaType 'application/json', 'application/xml' -Content 'Pet' )
- ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentMediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
- Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
- Add-PodeOAResponse -StatusCode 404 -Description 'Pet not found' -PassThru |
- Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception'
- }
-}
-```
diff --git a/docs/Tutorials/OpenAPI/Specification/v3.0.3.md b/docs/Tutorials/OpenAPI/Specification/v3.0.3.md
index 55274d89b..9d9ae153f 100644
--- a/docs/Tutorials/OpenAPI/Specification/v3.0.3.md
+++ b/docs/Tutorials/OpenAPI/Specification/v3.0.3.md
@@ -161,10 +161,10 @@ Types that are not accompanied by a `format` property follow the type definition
The formats defined by the OAS are:
-| [`type`](#dataTypes) | [`format`](#dataTypeFormat) | [`Pode CmdLet`](https://badgerati.github.io/Pode/Tutorials/OpenAPI/) | Comments |
-| -------------------- | --------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
-| `integer` | `int32` | [`New-PodeOAIntProperty -Name 'anInteger' -Format Int32`] | signed 32 bits |
-| `integer` | `int64` | [`New-PodeOAIntProperty -Name 'aLong' -Format Int64`] | signed 64 bits (a.k.a long) |
+| [`type`](#dataTypes) | [`format`](#dataTypeFormat) | [`Pode CmdLet`](https://badgerati.github.io/Pode/Tutorials/OpenAPI/) | Comments |
+|----------------------|-----------------------------|----------------------------------------------------------------------|-----------------------------|
+| `integer` | `int32` | [`New-PodeOAIntProperty -Name 'anInteger' -Format Int32`] | signed 32 bits |
+| `integer` | `int64` | [`New-PodeOAIntProperty -Name 'aLong' -Format Int64`] | signed 64 bits (a.k.a long) |
| `number` | `float` | [`New-PodeOANumberProperty -Name 'aFloat' -Format Float`] |
| `number` | `double` | [`New-PodeOANumberProperty -Name 'aDouble' -Format Double`] |
| `string` | | [`New-PodeOAStringProperty -Name 'aString'`] |
@@ -198,7 +198,7 @@ This is the root document object of the [OpenAPI document](#oasDocument).
##### Fixed Fields
| Field Name | Type | Pode CmdLets | Description |
-| ------------------------------------------ | :-----------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------|:-------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| openapi | `string` | [`Enable-PodeOpenApi`](../../../../Functions/OpenApi/Enable-PodeOpenApi) | **REQUIRED**. This string MUST be the [semantic version number](https://semver.org/spec/v2.0.0.html) of the [OpenAPI Specification version](#versions) that the OpenAPI document uses. The `openapi` field SHOULD be used by tooling specifications and clients to interpret the OpenAPI document. This is *not* related to the API [`info.version`](#infoVersion) string. |
| info | [Info Object](#infoObject) | [`Add-PodeOAInfo`](../../../../Functions/OpenApi/Add-PodeOAInfo) | **REQUIRED**. Provides metadata about the API. The metadata MAY be used by tooling as required. |
| servers | [[Server Object](#serverObject)] | [`Add-PodeOAServerEndpoint`](../../../../Functions/OpenApi/Add-PodeOAServerEndpoint) | An array of Server Objects, which provide connectivity information to a target server. If the `servers` property is not provided, or is an empty array, the default value would be a [Server Object](#serverObject) with a [url](#serverUrl) value of `/`. |
@@ -218,7 +218,7 @@ The metadata MAY be used by the clients if needed, and MAY be presented in editi
##### Fixed Fields
| Field Name | Type | `Add-PodeOAInfo` | Description |
-| ----------------------------------------------- | :------------------------------: | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-------------------------------------------------|:--------------------------------:|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| title | `string` | `-Title` | **REQUIRED**. The title of the API. |
| description | `string` | `-Description` | A short description of the API. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| termsOfService | `string` | `-TermOfService` | A URL to the Terms of Service for the API. MUST be in the format of a URL. |
@@ -278,7 +278,7 @@ Contact information for the exposed API.
##### Fixed Fields
| Field Name | Type | `Add-PodeOAInfo` | Description |
-| -------------------------------- | :------: | ---------------- | ------------------------------------------------------------------------------------------------ |
+|----------------------------------|:--------:|------------------|--------------------------------------------------------------------------------------------------|
| name | `string` | `-ContactName` | The identifying name of the contact person/organization. |
| url | `string` | `-ContactUrl` | The URL pointing to the contact information. MUST be in the format of a URL. |
| email | `string` | `-ContactEmail` | The email address of the contact person/organization. MUST be in the format of an email address. |
@@ -312,7 +312,7 @@ License information for the exposed API.
##### Fixed Fields
| Field Name | Type | `Add-PodeOAInfo` | Description |
-| ------------------------------ | :------: | ---------------- | ---------------------------------------------------------------------- |
+|--------------------------------|:--------:|------------------|------------------------------------------------------------------------|
| name | `string` | `-LicenseName` | **REQUIRED**. The license name used for the API. |
| url | `string` | `-LicenseUrl` | A URL to the license used for the API. MUST be in the format of a URL. |
@@ -342,7 +342,7 @@ An object representing a Server.
##### Fixed Fields
| Field Name | Type | `Add-PodeOAServerEndpoint` | Description |
-| ------------------------------------------- | :------------------------------------------------------------: | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+|---------------------------------------------|:--------------------------------------------------------------:|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| url | `string` | `-Url` | **REQUIRED**. A URL to the target host. This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in `{`brackets`}`. |
| description | `string` | `-Description` | An optional string describing the host designated by the URL. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| variables | Map[`string`, [Server Variable Object](#serverVariableObject)] | `-Variable` | A map between a variable name and its value. The value is used for substitution in the server's URL template. In Pode the OpenAPI Object's [`servers`](#oasServers) with variables can be defined using a `[ordered]@{}` [System.Collections.Specialized.OrderedDictionary](https://learn.microsoft.com/en-us/dotnet/api/system.collections.specialized.ordereddictionary?view=net-7.0) |
@@ -481,7 +481,7 @@ An object representing a Server Variable for server URL template substitution.
##### Fixed Fields
| Field Name | Type | Description |
-| --------------------------------------------------- | :--------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------------|:----------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| enum | [`string`] | An enumeration of string values to be used if the substitution options are from a limited set. The array SHOULD NOT be empty. |
| default | `string` | **REQUIRED**. The default value to use for substitution, which SHALL be sent if an alternate value is _not_ supplied. Note this behavior is different than the [Schema Object's](#schemaObject) treatment of default values, because in those cases parameter values are optional. If the [`enum`](#serverVariableEnum) is defined, the value SHOULD exist in the enum's values. |
| description | `string` | An optional description for the server variable. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
@@ -496,10 +496,10 @@ All objects defined within the components object will have no effect on the API
##### Fixed Fields
-| Field Name | Type | Pode | Description |
-| -------------------------------------------------------- | :----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
-| schemas | Map[`string`, [Schema Object](#schemaObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentSchema`](../../../../Functions/OAComponents/Add-PodeOAComponentSchema) | An object to hold reusable [Schema Objects](#schemaObject). |
-| responses | Map[`string`, [Response Object](#responseObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentResponse`](../../../../Functions/OAComponents/Add-PodeOAComponentResponse) | An object to hold reusable [Response Objects](#responseObject). |
+| Field Name | Type | Pode | Description |
+|----------------------------------------------|:------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|
+| schemas | Map[`string`, [Schema Object](#schemaObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentSchema`](../../../../Functions/OAComponents/Add-PodeOAComponentSchema) | An object to hold reusable [Schema Objects](#schemaObject). |
+| responses | Map[`string`, [Response Object](#responseObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentResponse`](../../../../Functions/OAComponents/Add-PodeOAComponentResponse) | An object to hold reusable [Response Objects](#responseObject). |
| parameters | Map[`string`, [Parameter Object](#parameterObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentParameter`](../../../../Functions/OAComponents/Add-PodeOAComponentParameter) | An object to hold reusable [Parameter Objects](#parameterObject). | PodeOAComponentExample |
| examples | Map[`string`, [Example Object](#exampleObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentExample`](../../../../Functions/OAComponents/Add-PodeOAComponentExample) | An object to hold reusable [Example Objects](#exampleObject). |
| requestBodies | Map[`string`, [Request Body Object](#requestBodyObject) \| [Reference Object](#referenceObject)] | [`Add-PodeOAComponentRequestBody`](../../../../Functions/OAComponents/Add-PodeOAComponentRequestBody) | An object to hold reusable [Request Body Objects](#requestBodyObject). |
@@ -752,7 +752,7 @@ The path is appended to the URL from the [`Server Object`](#serverObject) in ord
##### Patterned Fields
| Field Pattern | Type | Description |
-| ------------------------------- | :---------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|---------------------------------|:-----------------------------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| /{path} | [Path Item Object](#pathItemObject) | A relative path to an individual endpoint. The field name MUST begin with a forward slash (`/`). The path is **appended** (no relative URL resolution) to the expanded URL from the [`Server Object`](#serverObject)'s `url` field in order to construct the full URL. [Path templating](#pathTemplating) is allowed. When matching URLs, concrete (non-templated) paths would be matched before their templated counterparts. Templated paths with the same hierarchy but different templated names MUST NOT exist as they are identical. In case of ambiguous matching, it's up to the tooling to decide which one to use. |
This object MAY be extended with [Specification Extensions](#specificationExtensions).
@@ -839,7 +839,7 @@ The path itself is still exposed to the documentation viewer but they will not k
##### Fixed Fields
| Field Name | Type | Description |
-| --------------------------------------------- | :----------------------------------------------------------------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------|:------------------------------------------------------------------------------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| $ref | `string` | (Unsupported by Pode) Allows for an external definition of this path item. The referenced structure MUST be in the format of a [Path Item Object](#pathItemObject). In case a Path Item Object field appears both in the defined object and the referenced object, the behavior is undefined. |
| summary | `string` | An optional, string summary, intended to apply to all operations in this path. |
| description | `string` | An optional, string description, intended to apply to all operations in this path. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
@@ -1096,7 +1096,7 @@ $Route = Add-PodeRoute -PassThru -Method Get -Path '/pet/:petId' -ScriptBlock {
```
| Field Name | Type | `Set-PodeOARouteInfo` | Description |
-| ------------------------------------------------ | :---------------------------------------------------------------------------------------: | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+|--------------------------------------------------|:-----------------------------------------------------------------------------------------:|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| tags | `string` | `-Tags` | A list of tags for API documentation control. Tags can be used for logical grouping of operations by resources or any other qualifier. |
| summary | `string` | `-Summary` | A short summary of what the operation does. |
| description | `string` | `-Description` | A verbose explanation of the operation behavior. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
@@ -1107,25 +1107,25 @@ $Route = Add-PodeRoute -PassThru -Method Get -Path '/pet/:petId' -ScriptBlock {
| servers | [[Server Object](#serverObject)] | TBD | An alternative `server` array to service this operation. If an alternative `server` object is specified at the Path Item Object or Root level, it will be overridden by this value. |
| Field Name | Type | `Set-PodeOARequest` | Description |
-| ---------------------------------------------- | :-------------------------------------------------------------------------------: | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|------------------------------------------------|:---------------------------------------------------------------------------------:|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| parameters | [[Parameter Object](#parameterObject) \| [Reference Object](#referenceObject)] | `-Parameters` | A list of parameters that are applicable for this operation. If a parameter is already defined at the [Path Item](#pathItemParameters), the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters. A unique parameter is defined by a combination of a [name](#parameterName) and [location](#parameterIn). The list can use the [Reference Object](#referenceObject) to link to parameters that are defined at the [OpenAPI Object's components/parameters](#componentsParameters). |
| requestBody | [Request Body Object](#requestBodyObject) \| [Reference Object](#referenceObject) | `-RequestBody` | The request body applicable for this operation. The `requestBody` is only supported in HTTP methods where the HTTP 1.1 specification [RFC7231](https://tools.ietf.org/html/rfc7231#section-4.3.1) has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague, `requestBody` SHALL be ignored by consumers. |
| Field Name | Type | `Set-PodeOAResponse` | Description |
-| ------------------------------------------ | :----------------------------------: | -------------------- | ------------------------------------------------------------------------------------------------ |
+|--------------------------------------------|:------------------------------------:|----------------------|--------------------------------------------------------------------------------------------------|
| responses | [Responses Object](#responsesObject) | | **REQUIRED**. The list of possible responses as they are returned from executing this operation. |
| Field Name | Type | `Add-PodeRoute` | Description |
-| ---------------------------------------- | :---------------------------------------------------------: | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|------------------------------------------|:-----------------------------------------------------------:|-------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| security | [[Security Requirement Object](#securityRequirementObject)] | `-Authentication` `-Scope ` | A declaration of which security mechanisms can be used for this operation. The list of values includes alternative security requirement objects that can be used. Only one of the security requirement objects need to be satisfied to authorize a request. To make security optional, an empty security requirement (`{}`) can be included in the array. This definition overrides any declared top-level [`security`](#oasSecurity). To remove a top-level security declaration, an empty array can be used. |
| Field Name | Type | Unsupported | Description |
-| ------------------------------------------ | :---------------------------------------------------------------------------------------: | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------|:-----------------------------------------------------------------------------------------:|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| callbacks | Map[`string`, [Callback Object](#callbackObject) \| [Reference Object](#referenceObject)] | | A map of possible out-of band callbacks related to the parent operation. The key is a unique identifier for the Callback Object. Each value in the map is a [Callback Object](#callbackObject) that describes a request that may be initiated by the API provider and the expected responses. |
| servers | [[Server Object](#serverObject)] | | An alternative `server` array to service this operation. If an alternative `server` object is specified at the Path Item Object or Root level, it will be overridden by this value. |
@@ -1275,7 +1275,7 @@ Allows referencing an external resource for extended documentation.
##### Fixed Fields
| Field Name | Type | `New-PodeOAExternalDoc` | Description |
-| ------------------------------------------------ | :------: | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------------|:--------:|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| description | `string` | `-Description` | A short description of the target documentation. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| url | `string` | `-Url` | **REQUIRED**. The URL for the target documentation. Value MUST be in the format of a URL. |
@@ -1317,7 +1317,7 @@ There are four possible parameter locations specified by the `in` field:
##### Fixed Fields
| Field Name | Type | `ConvertTo-PodeOAParameter` | Description |
-| ------------------------------------------------------- | :-------: | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+|---------------------------------------------------------|:---------:|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | `string` | `-Name` | **REQUIRED**. The name of the parameter. Parameter names are *case sensitive*.
If [`in`](#parameterIn) is `"path"`, the `name` field MUST correspond to a template expression occurring within the [path](#pathsPath) field in the [Paths Object](#pathsObject). See [Path Templating](#pathTemplating) for further information.
If [`in`](#parameterIn) is `"header"` and the `name` field is `"Accept"`, `"Content-Type"` or `"Authorization"`, the parameter definition SHALL be ignored.
For all other cases, the `name` corresponds to the parameter name used by the [`in`](#parameterIn) property.
Note. In Pode if the -Name parameter is not used the name of the Property created by `New-PodeOAIntProperty`, `New-PodeOANumberProperty`, `New-PodeOABoolProperty `, `New-PodeOAStringProperty`, `New-PodeOAObjectProperty` is used. |
| in | `string` | `-In` | **REQUIRED**. The location of the parameter. Possible values are `"query"`, `"header"`, `"path"` or `"cookie"`. |
| description | `string` | `-Description` | A brief description of the parameter. This could contain examples of use. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
@@ -1329,7 +1329,7 @@ The rules for serialization of the parameter are specified in one of two ways.
For simpler scenarios, a [`schema`](#parameterSchema) and [`style`](#parameterStyle) can describe the structure and syntax of the parameter.
| Field Name | Type | `ConvertTo-PodeOAParameter` | Description |
-| -------------------------------------------------- | :--------------------------------------------------------------------------------------: | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|----------------------------------------------------|:----------------------------------------------------------------------------------------:|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| style | `string` | `-Style` | Describes how the parameter value will be serialized depending on the type of the parameter value. Default values (based on value of `in`): for `query` - `form`; for `path` - `simple`; for `header` - `simple`; for `cookie` - `form`. |
| explode | `boolean` | `-Explode` | When this is true, parameter values of type `array` or `object` generate separate parameters for each value of the array or key-value pair of the map. For other types of parameters this property has no effect. When [`style`](#parameterStyle) is `form`, the default value is `true`. For all other styles, the default value is `false`. |
| allowReserved | `boolean` | `-AllowReserved` | Determines whether the parameter value SHOULD allow reserved characters, as defined by [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.2) `:/?#[]@!$&'()*+,;=` to be included without percent-encoding. This property only applies to parameters with an `in` value of `query`. The default value is `false`. |
@@ -1343,7 +1343,7 @@ When `example` or `examples` are provided in conjunction with the `schema` objec
| Field Name | Type | `ConvertTo-PodeOAParameter` | Description |
-| -------------------------------------- | :--------------------------------------------------: | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+|----------------------------------------|:----------------------------------------------------:|-----------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| content | Map[`string`, [Media Type Object](#mediaTypeObject)] | `-Content` | A map containing the representations for the parameter. The key is the media type and the value describes it. The map MUST only contain one entry. |
##### Style Values
@@ -1351,7 +1351,7 @@ When `example` or `examples` are provided in conjunction with the `schema` objec
In order to support common ways of serializing simple parameters, a set of `style` values are defined.
| `style` | [`type`](#dataTypes) | `in` | Comments |
-| -------------- | ------------------------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|----------------|--------------------------------|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| matrix | `primitive`, `array`, `object` | `path` | Path-style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7) |
| label | `primitive`, `array`, `object` | `path` | Label style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.5) |
| form | `primitive`, `array`, `object` | `query`, `cookie` | Form style parameters defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.8). This option replaces `collectionFormat` with a `csv` (when `explode` is false) or `multi` (when `explode` is true) value from OpenAPI 2.0. |
@@ -1372,7 +1372,7 @@ Assume a parameter named `color` has one of the following values:
The following table shows examples of rendering differences for each value.
| [`style`](#dataTypeFormat) | `explode` | `empty` | `string` | `array` | `object` |
-| -------------------------- | --------- | ------- | ----------- | ----------------------------------- | -------------------------------------- |
+|----------------------------|-----------|---------|-------------|-------------------------------------|----------------------------------------|
| matrix | false | ;color | ;color=blue | ;color=blue,black,brown | ;color=R,100,G,200,B,150 |
| matrix | true | ;color | ;color=blue | ;color=blue;color=black;color=brown | ;R=100;G=200;B=150 |
| label | false | . | .blue | .blue.black.brown | .R.100.G.200.B.150 |
@@ -1575,7 +1575,7 @@ Describes a single request body.
##### Fixed Fields
| Field Name | Type | `New-PodeOARequestBody` | Description |
-| ------------------------------------------------ | :--------------------------------------------------: | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------------|:----------------------------------------------------:|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| description | `string` | `-Description` | A brief description of the request body. This could contain examples of use. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| content | Map[`string`, [Media Type Object](#mediaTypeObject)] | `-Content` | **REQUIRED**. The content of the request body. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) and the value describes it. For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* |
| required | `boolean` | `-Required` | Determines if the request body is required in the request. Defaults to `false`. |
@@ -1587,10 +1587,10 @@ This object MAY be extended with [Specification Extensions](#specificationExtens
A request body with a referenced model definition.
```powershell
New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'User'; 'application/xml' = 'User'} -Examples (
- New-PodeOAExample -MediaType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
- New-PodeOAExample -MediaType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
- New-PodeOAExample -MediaType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
- New-PodeOAExample -MediaType '*/*' -Name 'user' -Summary 'User example in other format' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
+ New-PodeOAExample -ContentType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
+ New-PodeOAExample -ContentType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
+ New-PodeOAExample -ContentType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
+ New-PodeOAExample -ContentType '*/*' -Name 'user' -Summary 'User example in other format' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
)
```
@@ -1709,7 +1709,7 @@ Each Media Type Object provides schema and examples for the media type identifie
##### Fixed Fields
| Field Name | Type | `New-PodeOARequestBody` | Description |
-| ---------------------------------------- | :--------------------------------------------------------------------------------------: | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|------------------------------------------|:----------------------------------------------------------------------------------------:|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| schema | [Schema Object](#schemaObject) \| [Reference Object](#referenceObject) | `-Schema` | The schema defining the content of the request, response, or parameter. |
| example | Any | `Not Supported` | Example of the media type. The example object SHOULD be in the correct format as specified by the media type. The `example` field is mutually exclusive of the `examples` field. Furthermore, if referencing a `schema` which contains an example, the `example` value SHALL _override_ the example provided by the schema. |
| examples | Map[ `string`, [Example Object](#exampleObject) \| [Reference Object](#referenceObject)] | `-Examples` | Examples of the media type. Each example object SHOULD match the media type and specified schema if present. The `examples` field is mutually exclusive of the `example` field. Furthermore, if referencing a `schema` which contains an example, the `examples` value SHALL _override_ the example provided by the schema. |
@@ -1721,9 +1721,9 @@ This object MAY be extended with [Specification Extensions](#specificationExtens
```powershell
New-PodeOARequestBody -Content @{ 'application/json' = 'Pet' } -Examples (
- New-PodeOAExample -MediaType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
- New-PodeOAExample -MediaType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' }|
- New-PodeOAExample -MediaType 'application/json' -Reference 'frog-example'
+ New-PodeOAExample -ContentType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
+ New-PodeOAExample -ContentType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' }|
+ New-PodeOAExample -ContentType 'application/json' -Reference 'frog-example'
)
```
@@ -1834,7 +1834,7 @@ In addition, specific media types MAY be specified:
or
```powershell
-New-PodeOAContentMediaType -MediaType 'image/jpeg','image/png' -Content (New-PodeOAStringProperty -Format binary)
+New-PodeOAContentMediaType -ContentType 'image/jpeg','image/png' -Content (New-PodeOAStringProperty -Format binary)
```
```yaml
@@ -1933,7 +1933,7 @@ Examples:
```powershell
Set-PodeOARequest -RequestBody (
New-PodeOARequestBody -Content (
- New-PodeOAContentMediaType -MediaType 'multipart/form-data' -Content (
+ New-PodeOAContentMediaType -ContentType 'multipart/form-data' -Content (
New-PodeOAStringProperty -name 'id' -format 'uuid' |
New-PodeOAObjectProperty -name 'address' -NoProperties |
New-PodeOAStringProperty -name 'children' -array |
@@ -1982,7 +1982,7 @@ A single encoding definition applied to a single schema property.
##### Fixed Fields
| Field Name | Type | `New-PodeOAEncodingObject` | Description |
-| ------------------------------------------------- | :-----------------------------------------------------------------------------------: | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|---------------------------------------------------|:-------------------------------------------------------------------------------------:|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| contentType | `string` | `-ContentType` | The Content-Type for encoding a specific property. Default value depends on the property type: for `string` with `format` being `binary` ? `application/octet-stream`; for other primitive types ? `text/plain`; for `object` - `application/json`; for `array` ? the default is defined based on the inner type. The value can be a specific media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of the two types. |
| headers | Map[`string`, [Header Object](#headerObject) \| [Reference Object](#referenceObject)] | `-Headers` | A map allowing additional information to be provided as headers, for example `Content-Disposition`. `Content-Type` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the request body media type is not a `multipart`. |
| style | `string` | `-Style` | Describes how a specific property value will be serialized depending on its type. See [Parameter Object](#parameterObject) for details on the [`style`](#parameterStyle) property. The behavior follows the same values as `query` parameters, including default values. This property SHALL be ignored if the request body media type is not `application/x-www-form-urlencoded`. |
@@ -1994,7 +1994,7 @@ This object MAY be extended with [Specification Extensions](#specificationExtens
##### Encoding Object Example
```powershell
-New-PodeOARequestBody -Content (New-PodeOAContentMediaType -MediaType 'multipart/mixed' -Content (
+New-PodeOARequestBody -Content (New-PodeOAContentMediaType -ContentType 'multipart/mixed' -Content (
New-PodeOAStringProperty -name 'id' -format 'uuid' |
New-PodeOAObjectProperty -name 'address' -NoProperties |
New-PodeOAObjectProperty -name 'historyMetadata' -Description 'metadata in XML format' -NoProperties |
@@ -2063,12 +2063,12 @@ SHOULD be the response for a successful operation call.
##### Fixed Fields
| Field Name | Type | `Add-PodeOAResponse` | Description |
-| -------------------------------------- | :------------------------------------------------------------------------: | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|----------------------------------------|:--------------------------------------------------------------------------:|----------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| default | [Response Object](#responseObject) \| [Reference Object](#referenceObject) | `-Default` | The documentation of responses other than the ones declared for specific HTTP response codes. Use this field to cover undeclared responses. A [Reference Object](#referenceObject) can link to a response that the [OpenAPI Object's components/responses](#componentsResponses) section defines. |
##### Patterned Fields
| Field Pattern | Type | `Add-PodeOAResponse` | Description |
-| ---------------------------------------------------------- | :------------------------------------------------------------------------: | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|------------------------------------------------------------|:--------------------------------------------------------------------------:|----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [HTTP Status Code](#httpCodes) | [Response Object](#responseObject) \| [Reference Object](#referenceObject) | `-StatusCode` | Any [HTTP status code](#httpCodes) can be used as the property name, but only one property per code, to describe the expected response for that HTTP status code. A [Reference Object](#referenceObject) can link to a response that is defined in the [OpenAPI Object's components/responses](#componentsResponses) section. This field MUST be enclosed in quotation marks (for example, "200") for compatibility between JSON and YAML. To define a range of response codes, this field MAY contain the uppercase wildcard character `X`. For example, `2XX` represents all response codes between `[200-299]`. Only the following range definitions are allowed: `1XX`, `2XX`, `3XX`, `4XX`, and `5XX`. If a response is defined using an explicit code, the explicit code definition takes precedence over the range definition for that code. |
@@ -2129,7 +2129,7 @@ Describes a single response from an API Operation, including design-time, static
##### Fixed Fields
| Field Name | Type | `Add-PodeOAResponse` | Description |
-| --------------------------------------------- | :------------------------------------------------------------------------------------: | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------|:--------------------------------------------------------------------------------------:|----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| description | `string` | `-Description` | **REQUIRED**. A short description of the response. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| headers | Map[`string`, [Header Object](#headerObject) \| [Reference Object](#referenceObject)] | `-Headers` | Maps a header name to its definition. [RFC7230](https://tools.ietf.org/html/rfc7230#page-22) states header names are case insensitive. If a response header is defined with the name `"Content-Type"`, it SHALL be ignored. |
| content | Map[`string`, [Media Type Object](#mediaTypeObject)] | `-Content` | A map containing descriptions of potential response payloads. The key is a media type or [media type range](https://tools.ietf.org/html/rfc7231#appendix-D) and the value describes it. For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* |
@@ -2143,7 +2143,7 @@ Response of an array of a complex type:
```powershell
Add-PodeOAResponse -StatusCode 200 -Description 'A complex object array response' -Content (
- New-PodeOAMediaContentType -MediaType 'application/json' -Content 'VeryComplexType' -Array
+ New-PodeOAMediaContentType -ContentType 'application/json' -Content 'VeryComplexType' -Array
)
```
@@ -2179,13 +2179,13 @@ Add-PodeOAResponse -StatusCode 200 -Description 'A complex object array response
Response with a string type:
```powershell
-Add-PodeOAResponse -StatusCode 200 -Description 'A simple string response' -Content (New-PodeOAMediaContentType -MediaType 'text/plain' -Content (New-PodeOAStringProperty) -Array)
+Add-PodeOAResponse -StatusCode 200 -Description 'A simple string response' -Content (New-PodeOAMediaContentType -ContentType 'text/plain' -Content (New-PodeOAStringProperty) -Array)
```
or
```powershell
-Add-PodeOAResponse -StatusCode 200 -Description 'A simple string response' -Content (New-PodeOAMediaContentType -MediaType 'text/plain' -Content 'string' -Array)
+Add-PodeOAResponse -StatusCode 200 -Description 'A simple string response' -Content (New-PodeOAMediaContentType -ContentType 'text/plain' -Content 'string' -Array)
```
```json
@@ -2310,7 +2310,7 @@ The key value used to identify the path item object is an expression, evaluated
##### Patterned Fields
| Field Pattern | Type | Description |
-| --------------------------------------------- | :---------------------------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------|:-----------------------------------:|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| {expression} | [Path Item Object](#pathItemObject) | A Path Item Object used to define a callback request and expected responses. A [complete example](../examples/v3.0/callback-example.yaml) is available. |
This object MAY be extended with [Specification Extensions](#specificationExtensions).
@@ -2346,7 +2346,7 @@ Location: http://example.org/subscription/1
The following examples show how the various expressions evaluate, assuming the callback operation has a path parameter named `eventType` and a query parameter named `queryUrl`.
| Expression | Value |
-| ---------------------------- | :--------------------------------------------------------------------------------- |
+|------------------------------|:-----------------------------------------------------------------------------------|
| $url | http://example.org/subscribe/myevent?queryUrl=http://clientdomain.com/stillrunning |
| $method | POST |
| $request.path.eventType | myevent |
@@ -2404,7 +2404,7 @@ transactionCallback:
##### Fixed Fields
| Field Name | Type | `New-PodeOAExample ` | Description |
-| ------------------------------------------------ | :------: | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------------|:--------:|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| summary | `string` | `-Summary` | Short description for the example. |
| description | `string` | `-Description` | Long description for the example. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| value | Any | `-Value` | Embedded literal example. The `value` field and `externalValue` field are mutually exclusive. To represent examples of media types that cannot naturally represented in JSON or YAML, use a string value to contain the example, escaping where necessary. |
@@ -2422,10 +2422,10 @@ In a request body:
```powershell
New-PodeOARequestBody -Content @{ 'application/json' = 'Address' } -Examples (
- New-PodeOAExample -MediaType 'application/json' -Name 'foo' -Summary 'A foo example' -Value @{foo = 'bar' } |
- New-PodeOAExample -MediaType 'application/json' -Name 'bar' -Summary 'A bar example' -Value @{'bar' = 'baz' }|
- New-PodeOAExample -MediaType 'application/xml' -Name 'xmlExample' -Summary 'This is an example in XML' -ExternalValue 'http://example.org/examples/address-example.xml' |
- New-PodeOAExample -MediaType 'text/plain' -Name 'textExample' -Summary 'This is an example' -ExternalValue 'http://example.org/examples/address-example.txt' |
+ New-PodeOAExample -ContentType 'application/json' -Name 'foo' -Summary 'A foo example' -Value @{foo = 'bar' } |
+ New-PodeOAExample -ContentType 'application/json' -Name 'bar' -Summary 'A bar example' -Value @{'bar' = 'baz' }|
+ New-PodeOAExample -ContentType 'application/xml' -Name 'xmlExample' -Summary 'This is an example in XML' -ExternalValue 'http://example.org/examples/address-example.xml' |
+ New-PodeOAExample -ContentType 'text/plain' -Name 'textExample' -Summary 'This is an example' -ExternalValue 'http://example.org/examples/address-example.txt' |
)
```
@@ -2503,7 +2503,7 @@ For computing links, and providing instructions to execute them, a [runtime expr
##### Fixed Fields
| Field Name | Type | Description |
-| ------------------------------------------- | :------------------------------------------------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|---------------------------------------------|:--------------------------------------------------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| operationRef | `string` | A relative or absolute URI reference to an OAS operation. This field is mutually exclusive of the `operationId` field, and MUST point to an [Operation Object](#operationObject). Relative `operationRef` values MAY be used to locate an existing [Operation Object](#operationObject) in the OpenAPI definition. |
| operationId | `string` | The name of an _existing_, resolvable OAS operation, as defined with a unique `operationId`. This field is mutually exclusive of the `operationRef` field. |
| parameters | Map[`string`, Any \| [{expression}](#runtimeExpression)] | A map representing parameters to pass to an operation as specified with `operationId` or identified via `operationRef`. The key is the parameter name to be used, whereas the value can be a constant or an expression to be evaluated and passed to the linked operation. The parameter name can be qualified using the [parameter location](#parameterIn) `[{in}.]{name}` for operations that use the same parameter name in different locations (e.g. path.id). |
@@ -2649,9 +2649,9 @@ The table below provides examples of runtime expressions and examples of their u
##### Examples
-| Source Location | example expression | notes |
-| --------------------- | :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
-| HTTP Method | `$method` | The allowable values for the `$method` will be those for the HTTP operation. |
+| Source Location | example expression | notes |
+|-----------------|:-------------------|:-----------------------------------------------------------------------------|
+| HTTP Method | `$method` | The allowable values for the `$method` will be those for the HTTP operation. |
| Requested media type | `$request.header.accept` |
| Request parameter | `$request.path.id` | Request parameters MUST be declared in the `parameters` section of the parent operation or they cannot be evaluated. This includes request headers. |
| Request body property | `$request.body#/user/uuid` | In operations which accept payloads, references may be made to portions of the `requestBody` or the entire body. |
@@ -2696,7 +2696,7 @@ It is not mandatory to have a Tag Object per tag defined in the Operation Object
##### Fixed Fields
| Field Name | Type | `Add-PodeOATag` | Description |
-| ------------------------------------------ | :-----------------------------------------------------------: | --------------- | ---------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------------|:-------------------------------------------------------------:|-----------------|------------------------------------------------------------------------------------------------------------------------------|
| name | `string` | `-Name` | **REQUIRED**. The name of the tag. |
| description | `string` | `-Description` | A short description for the tag. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| externalDocs | [External Documentation Object](#externalDocumentationObject) | `-ExternalDocs` | Additional external documentation for this tag. In Pode is an ExternalDoc object created with `New-PodeOAExternalDoc` |
@@ -2730,7 +2730,7 @@ For this specification, reference resolution is accomplished as defined by the J
##### Fixed Fields
| Field Name | Type | Description |
-| ------------------------------- | :------: | ----------------------------------- |
+|---------------------------------|:--------:|-------------------------------------|
| $ref | `string` | **REQUIRED**. The reference string. |
This object cannot be extended with additional properties and any properties added SHALL be ignored.
@@ -2807,7 +2807,7 @@ The following properties are taken directly from the JSON Schema definition and
type - Value MUST be a string. Multiple types via an array are not supported.
| type | cmdlet |
-| ------ | -------------------------- |
+|--------|----------------------------|
| int | `New-PodeOAIntProperty` |
| string | `New-PodeOAStringProperty` |
| object | `New-PodeOAObjectProperty` |
@@ -2839,7 +2839,7 @@ type - Value MUST be a string. Multiple types via an array are not supported.
| properties | `-properties` | `New-PodeOAObjectProperty` Property definitions MUST be a [Schema Object](#schemaObject) and not a standard JSON Schema (inline or referenced). |
| type | `Merge-PodeOAProperty` | Note |
-| ----------------------------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-------------------------------------------------|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| allOf | `-Type AllOf` | |
| oneOf | `-Type OneOf` | (Pode) Doesn't support schema validation |
| anyOf | `-Type AnyOf` | (Pode)Doesn't support schema validation |
@@ -2862,7 +2862,7 @@ Other than the JSON Schema subset fields, the following fields MAY be used for f
##### Fixed Fields
| Field Name | Type | | Description |
-| --------------------------------------------- | :-----------------------------------------------------------: | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------|:-------------------------------------------------------------:|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| nullable | `boolean` | `-Nullable` | A `true` value adds `"null"` to the allowed type specified by the `type` keyword, only if `type` is explicitly defined within the same Schema Object. Other Schema Object constraints retain their defined behavior, and therefore may disallow the use of `null` as a value. A `false` value leaves the specified or default `type` unmodified. The default value is `false`. |
| readOnly | `boolean` | `-ReadOnly` | Relevant only for Schema `"properties"` definitions. Declares the property as "read only". This means that it MAY be sent as part of a response but SHOULD NOT be sent as part of the request. If the property is marked as `readOnly` being `true` and is in the `required` list, the `required` will take effect on the response only. A property MUST NOT be marked as both `readOnly` and `writeOnly` being `true`. Default value is `false`. |
| writeOnly | `boolean` | `-WriteOnly` | Relevant only for Schema `"properties"` definitions. Declares the property as "write only". Therefore, it MAY be sent as part of a request but SHOULD NOT be sent as part of the response. If the property is marked as `writeOnly` being `true` and is in the `required` list, the `required` will take effect on the request only. A property MUST NOT be marked as both `readOnly` and `writeOnly` being `true`. Default value is `false`. |
@@ -3279,7 +3279,7 @@ When using the discriminator, _inline_ schemas will not be considered.
##### Fixed Fields
| Field Name | Type | `New-PodeOAObjectProperty` | Description |
-| ------------------------------------------- | :---------------------: | -------------------------- | --------------------------------------------------------------------------------------------- |
+|---------------------------------------------|:-----------------------:|----------------------------|-----------------------------------------------------------------------------------------------|
| propertyName | `string` | `-DiscriminatorProperty` | **REQUIRED**. The name of the property in the payload that will hold the discriminator value. |
| mapping | Map[`string`, `string`] | `-DiscriminatorMapping` | An object to hold mappings between payload values and schema names or references. |
@@ -3442,7 +3442,7 @@ See examples for expected behavior.
##### Fixed Fields
| Field Name | Type | `New-PodeOA(*)Property` | Description |
-| ------------------------------------ | :-------: | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|--------------------------------------|:---------:|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| name | `string` | `-XmlName` | Replaces the name of the element/attribute used for the described schema property. When defined within `items`, it will affect the name of the individual XML elements within the list. When defined alongside `type` being `array` (outside the `items`), it will affect the wrapping element and only if `wrapped` is `true`. If `wrapped` is `false`, it will be ignored. |
| namespace | `string` | `-XmlNameSpace` | The URI of the namespace definition. Value MUST be in the form of an absolute URI. |
| prefix | `string` | `-XmlPrefix` | The prefix to be used for the [name](#xmlName). |
@@ -3832,7 +3832,7 @@ Supported schemes are HTTP authentication, an API key (either as a header, a coo
##### Fixed Fields
| Field Name | Type | Applies To | Description |
-| ------------------------------------------------------------- | :-------------------------------------: | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|---------------------------------------------------------------|:---------------------------------------:|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| type | `string` | Any | **REQUIRED**. The type of the security scheme. Valid values are `"apiKey"`, `"http"`, `"oauth2"`, `"openIdConnect"`. |
| description | `string` | Any | A short description for security scheme. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation. |
| name | `string` | `apiKey` | **REQUIRED**. The name of the header, query or cookie parameter to be used. |
@@ -3962,7 +3962,7 @@ Allows configuration of the supported OAuth Flows.
##### Fixed Fields
| Field Name | Type | Description |
-| ----------------------------------------------------------- | :-----------------------------------: | ----------------------------------------------------------------------------------------------------- |
+|-------------------------------------------------------------|:-------------------------------------:|-------------------------------------------------------------------------------------------------------|
| implicit | [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Implicit flow |
| password | [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Resource Owner Password flow |
| clientCredentials | [OAuth Flow Object](#oauthFlowObject) | Configuration for the OAuth Client Credentials flow. Previously called `application` in OpenAPI 2.0. |
@@ -3976,7 +3976,7 @@ Configuration details for a supported OAuth Flow
##### Fixed Fields
| Field Name | Type | Applies To | Description |
-| -------------------------------------------------------- | :---------------------: | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
+|----------------------------------------------------------|:-----------------------:|-----------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| authorizationUrl | `string` | `oauth2` (`"implicit"`, `"authorizationCode"`) | **REQUIRED**. The authorization URL to be used for this flow. This MUST be in the form of a URL. |
| tokenUrl | `string` | `oauth2` (`"password"`, `"clientCredentials"`, `"authorizationCode"`) | **REQUIRED**. The token URL to be used for this flow. This MUST be in the form of a URL. |
| refreshUrl | `string` | `oauth2` | The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. |
@@ -4038,7 +4038,7 @@ When a list of Security Requirement Objects is defined on the [OpenAPI Object](#
##### Patterned Fields
| Field Pattern | Type | Description |
-| --------------------------------------------- | :--------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+|-----------------------------------------------|:----------:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| {name} | [`string`] | Each name MUST correspond to a security scheme which is declared in the [Security Schemes](#componentsSecuritySchemes) under the [Components Object](#componentsObject). If the security scheme is of type `"oauth2"` or `"openIdConnect"`, then the value is a list of scope names required for the execution, and the list MAY be empty if authorization does not require a specified scope. For other security scheme types, the array MUST be empty. |
##### Security Requirement Object Examples
@@ -4227,9 +4227,9 @@ While the OpenAPI Specification tries to accommodate most use cases, additional
The extensions properties are implemented as patterned fields that are always prefixed by `"x-"`.
-| Field Pattern | Type | Description |
-| -------------------------------- | :---: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| ^x- | Any | Allows extensions to the OpenAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. Can have any valid JSON format value. |
+| Field Pattern | Type | Description |
+|----------------------------------|:----:|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| ^x- | Any | Allows extensions to the OpenAPI Schema. The field name MUST begin with `x-`, for example, `x-internal-id`. The value can be `null`, a primitive, an array or an object. Can have any valid JSON format value. |
The extensions may or may not be supported by the available tooling, but those may be extended as well to add requested support (if tools are internal or open-sourced).
@@ -4248,7 +4248,7 @@ Two examples of this:
## Appendix A: Revision History
| Version | Date | Notes |
-| ---------- | ---------- | ------------------------------------------------- |
+|------------|------------|---------------------------------------------------|
| 3.0.3-Pode | 2023-11-20 | OpenAPI Specification 3.0.3 Pode Version |
| 3.0.3 | 2020-02-20 | Patch release of the OpenAPI Specification 3.0.3 |
| 3.0.2 | 2018-10-08 | Patch release of the OpenAPI Specification 3.0.2 |
diff --git a/docs/Tutorials/Routes/Overview.md b/docs/Tutorials/Routes/Overview.md
index 9fbcae868..a9acd7efe 100644
--- a/docs/Tutorials/Routes/Overview.md
+++ b/docs/Tutorials/Routes/Overview.md
@@ -298,4 +298,4 @@ Static routes have a slightly different format:
| OpenApi | hashtable[] | The OpenAPI definition/settings for the route |
| Path | string | The path of the route - this path will have regex in place of dynamic file names |
| Source | string | The source path within the server that is used for the route |
-| TransferEncoding | string | The transfer encoding to use when parsing the payload in the request |
+| TransferEncoding | string | The transfer encoding to use when parsing the payload in the request |
\ No newline at end of file
diff --git a/docs/Tutorials/Routes/Utilities/ContentTypes.md b/docs/Tutorials/Routes/Utilities/ContentTypes.md
index 41800c84a..57816670b 100644
--- a/docs/Tutorials/Routes/Utilities/ContentTypes.md
+++ b/docs/Tutorials/Routes/Utilities/ContentTypes.md
@@ -21,6 +21,10 @@ Start-PodeServer {
Add-PodeRoute -Method Get -Path '/api/xml' -ContentType 'text/xml' -ScriptBlock {
Write-PodeXmlResponse -Value @{}
}
+
+ Add-PodeRoute -Method Get -Path '/api/yaml' -ContentType 'text/yaml' -ScriptBlock {
+ Write-PodeYamlResponse -Value @{}
+ }
}
```
diff --git a/docs/Tutorials/Routes/Utilities/ErrorPages.md b/docs/Tutorials/Routes/Utilities/ErrorPages.md
index ff2d05938..6801b265b 100644
--- a/docs/Tutorials/Routes/Utilities/ErrorPages.md
+++ b/docs/Tutorials/Routes/Utilities/ErrorPages.md
@@ -132,6 +132,9 @@ Above you'll see that the exception supplied to `status` will also be supplied t
Once set to `true`, any available exception details for status codes will be available to error pages - a useful setting to have in a [`server.dev.psd1`](../../../Configuration#environments) file.
+!!! important
+ This setting is not recommended for production environments due to the security risk associated with exposing internal exception details.
+
### Content Types
Using the `server.psd1` configuration file, you can define which file content types to attempt when generating error pages for routes. You can either:
diff --git a/docs/Tutorials/Schedules.md b/docs/Tutorials/Schedules.md
index 9c754bfb1..2665501d0 100644
--- a/docs/Tutorials/Schedules.md
+++ b/docs/Tutorials/Schedules.md
@@ -126,6 +126,29 @@ Get-PodeSchedule -Name Name1
Get-PodeSchedule -Name Name1, Name2
```
+## Getting Schedule Processes
+
+You can retrieve a list of processes triggered by Schedules via [`Get-PodeScheduleProcess`](../../Functions/Schedules/Get-PodeScheduleProcess) - this will return processes created either by a Schedule's natural time-based trigger, or via [`Invoke-PodeSchedule`](../../Functions/Schedules/Invoke-PodeSchedule).
+
+You can either retrieve all processes, or filter them by Schedule Name, or Process ID/Status:
+
+```powershell
+# retrieves all schedule processes
+Get-PodeScheduleProcess
+
+# retrieves all schedule processes for the "ScheduleName" process
+Get-PodeScheduleProcess -Name 'ScheduleName'
+
+# retrieves the schedule process with ID "ScheduleId"
+Get-PodeScheduleProcess -Id 'ScheduleId'
+
+# retrieves all running schedule processes
+Get-PodeScheduleProcess -State 'Running'
+
+# retrieves all pending schedule processes for "ScheduleName"
+Get-PodeScheduleProcess -Name 'ScheduleName' -State 'Running'
+```
+
## Next Trigger Time
When you retrieve a Schedule using [`Get-PodeSchedule`](../../Functions/Schedules/Get-PodeSchedule), each Schedule object will already have its next trigger time as `NextTriggerTime`. However, if you want to get a trigger time further ino the future than this, then you can use the [`Get-PodeScheduleNextTrigger`](../../Functions/Schedules/Get-PodeScheduleNextTrigger) function.
diff --git a/docs/Tutorials/Tasks.md b/docs/Tutorials/Tasks.md
index ac257a98c..f6a98e339 100644
--- a/docs/Tutorials/Tasks.md
+++ b/docs/Tutorials/Tasks.md
@@ -51,7 +51,7 @@ Add-PodeTask -Name 'Example' -ArgumentList @{ Name = 'Rick'; Environment = 'Mult
}
```
-Tasks parameters **must** be bound in the param block in order to be used, but the values for the paramters can be set through the `-ArgumentList` hashtable parameter in either the Add-PodeTask definition or when invoking the task. The following snippet would populate the parameters to the task with the same values as the above example but the `-ArgumentList` parameter is populated during invocation. Note that Keys in the `-ArgumentList` hashtable parameter set during invocation override the same Keys set during task creation:
+Tasks parameters **must** be bound in the param block in order to be used, but the values for the paramters can be set through the `-ArgumentList` hashtable parameter in either the Add-PodeTask definition or when invoking the task. The following snippet would populate the parameters to the task with the same values as the above example but the `-ArgumentList` parameter is populated during invocation. Note that Keys in the `-ArgumentList` hashtable parameter set during invocation override the same Keys set during task creation:
```powershell
Add-PodeTask -Name 'Example' -ScriptBlock {
@@ -184,6 +184,29 @@ Get-PodeTask -Name Example1
Get-PodeTask -Name Example1, Example2
```
+## Getting Task Processes
+
+You can retrieve a list of processes triggered by Tasks via [`Get-PodeTaskProcess`](../../Functions/Tasks/Get-PodeTaskProcess) - this will return processes created via [`Invoke-PodeTask`](../../Functions/Tasks/Invoke-PodeTask).
+
+You can either retrieve all processes, or filter them by Task Name, or Process ID/Status:
+
+```powershell
+# retrieves all task processes
+Get-PodeTaskProcess
+
+# retrieves all task processes for the "TaskName" process
+Get-PodeTaskProcess -Name 'TaskName'
+
+# retrieves the task process with ID "TaskId"
+Get-PodeTaskProcess -Id 'TaskId'
+
+# retrieves all running task processes
+Get-PodeTaskProcess -State 'Running'
+
+# retrieves all pending task processes for "TaskName"
+Get-PodeTaskProcess -Name 'TaskName' -State 'Running'
+```
+
## Task Object
!!! warning
@@ -191,8 +214,8 @@ Get-PodeTask -Name Example1, Example2
The following is the structure of the Task object internally, as well as the object that is returned from [`Get-PodeTask`](../../Functions/Tasks/Get-PodeTask):
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| Name | string | The name of the Task |
-| Script | scriptblock | The scriptblock of the Task |
-| Arguments | hashtable | The arguments supplied from ArgumentList |
+| Name | Type | Description |
+| --------- | ----------- | ---------------------------------------- |
+| Name | string | The name of the Task |
+| Script | scriptblock | The scriptblock of the Task |
+| Arguments | hashtable | The arguments supplied from ArgumentList |
diff --git a/docs/index.md b/docs/index.md
index 533d2603b..25d0d9dd9 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -21,8 +21,9 @@ Pode is a Cross-Platform framework to create web servers that host REST APIs, We
* Cross-platform using PowerShell Core (with support for PS5)
* Docker support, including images for ARM/Raspberry Pi
* Azure Functions, AWS Lambda, and IIS support
-* OpenAPI, Swagger, and ReDoc support
-* Listen on a single or multiple IP address/hostnames
+* OpenAPI specification version 3.0.x and 3.1.0
+* OpenAPI documentation with Swagger, Redoc, RapidDoc, StopLight, OpenAPI-Explorer and RapiPdf
+* Listen on a single or multiple IP(v4/v6) addresses/hostnames
* Cross-platform support for HTTP(S), WS(S), SSE, SMTP(S), and TCP(S)
* Host REST APIs, Web Pages, and Static Content (with caching)
* Support for custom error pages
@@ -45,6 +46,8 @@ Pode is a Cross-Platform framework to create web servers that host REST APIs, We
* Support for File Watchers
* In-memory caching, with optional support for external providers (such as Redis)
* (Windows) Open the hosted server as a desktop application
+* FileBrowsing support
+* Localization (i18n) in Arabic, German, Spanish, France, Italian, Japanese, Korean, Polish, Portuguese, and Chinese
## 🏢 Companies using Pode
diff --git a/docs/release-notes.md b/docs/release-notes.md
index c96072d0d..969c65a6d 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,8 +1,70 @@
# Release Notes
+## v2.11.0
+
+Date: 29th September 2024
+
+```plain
+### Features
+* #1320: Enhanced Internationalization Support (i18n) (thanks @mdaneri!)
+
+### Enhancements
+* #1338: Automate Endpoint Assignment for OAViewer in Pode (thanks @mdaneri!)
+* #1339: Add 'Rename-PodeOADefinitionTag' Function (thanks @mdaneri!)
+* #1340: Add configuration parameter 'Web.OpenApi.UsePodeYamlInternal' (thanks @mdaneri!)
+* #1352: Update MIME types to comply with RFC9512 and RFC5323 (thanks @mdaneri!)
+* #1356: Dutch language support (thanks @mdaneri!)
+* #1373: Dynamically load the Pode DLL relevant to the version of PowerShell (thanks @mdaneri!)
+* #1384: Customizing and Managing Runspace Names (thanks @mdaneri!)
+* #1388: Support passing Arrays to Functions Using Piping (thanks @mdaneri!)
+* #1393: Adds functions for retrieving Schedule and Task Processes
+* #1393: Improves Error Handling in Schedules, Timers, Tasks, and Logging
+* #1393: Removes Global scope from TimerEvent
+* #1399: Replaces occurrences of New-Object with new()
+
+### Bugs
+* #1319: Fixes the Write-Pode(*)Response functions so the Value parameter appropriately handles when an array is passed using piping (thanks @mdaneri!)
+* #1321: Fixes a misspelled variable in Add-PodeOAExternalRoute (thanks @mdaneri!)
+* #1347: '-AdditionalProperties' doesn't appear on the OpenAPI document despite using the '-NoAdditionalProperties' parameter. (thanks @mdaneri!)
+* #1358: Fixes [ordered] comparisons in PowerShell 5.1 (thanks @mdaneri!)
+* #1358: Fixes for various OpenAPI issues (thanks @mdaneri!)
+* #1358: Fixes OpenAPI version validation check in PowerShell 5.1 (thanks @mdaneri!)
+* #1359: Fixes the login redirect URL logic for OAuth2 flows when using -SuccessUseOrigin
+* #1360: Fixes a bug when exporting more than 1 module
+* #1369: Accurate Output with -NoDefaultResponses (thanks @mdaneri!)
+* #1369: Correct Schema with -NoProperties (thanks @mdaneri!)
+* #1369: Fixes for OpenAPI Generation: Exception with oneOf/anyOf/allOf (thanks @mdaneri!)
+* #1369: Include Min/Max Properties (thanks @mdaneri!)
+* #1369: Prevent Request Body on GET Operations (thanks @mdaneri!)
+* #1379: Fixes SSL timeouts when running Pode in PS7.4+
+* #1390: Changes "-ContentMediaType" and "-MediaType" parameters to "-ContentType" on most OpenAPI functions (thanks @mdaneri!)
+* #1390: Ensures the generated OpenAPI document now maintains element ordering (thanks @mdaneri!)
+* #1390: Fixes OpenAPI DefinitionTag being null in some functions (thanks @mdaneri!)
+* #1390: Fixes OpenAPI PowerShell 5.1 compatibility issue while testing schemas (thanks @mdaneri!)
+* #1397: Fixes retrieving DNS domain name on macOS
+* #1400: Fixes session scoped variable when remapping while setting values
+* #1400: Fixes User being needlessly splatted when passed to scriptblock for some Authentication methods
+
+### Documentation
+* #1332: Adds documentation for CORS (thanks @mdaneri!)
+* #1332: Adds missing features to the Feature List (thanks @mdaneri!)
+* #1332: Splits OpenAPI documentation into multiple pages (thanks @mdaneri!)
+* #1332: Updates Known Issues for PowerShell classes with PS7.4's SafeThread support (thanks @mdaneri!)
+* #1333: Cleans up the Examples in the repository, and adds them to the Documentation (thanks @mdaneri!)
+
+### Packaging
+* #1322: Applies a fix for a PS7.5 bug with Remove-Item throwing divide by zero error
+* #1323: Fix build error when dotnet tries to restore from offline NuGet cache
+* #1328: Make preview builds optional for PR merges
+* #1342: Add GitHub Codespace Configuration and Getting Started Guide for Pode (thanks @mdaneri!)
+
+### Dependencies
+* #1341: Bump actions/add-to-project from 1.0.1 to 1.0.2
+```
+
## v2.10.1
-Data: 27th May 2024
+Date: 27th May 2024
```plain
### Bugs
diff --git a/examples/Caching.ps1 b/examples/Caching.ps1
new file mode 100644
index 000000000..a0dff16ca
--- /dev/null
+++ b/examples/Caching.ps1
@@ -0,0 +1,104 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server and integrate with Redis for caching.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081 with Redis integration for caching.
+ It checks for the existence of the `redis-cli` command and sets up a Pode server with routes
+ that demonstrate caching with Redis.
+
+.EXAMPLE
+ To run the sample: ./Caching.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Caching.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+try {
+ if (Get-Command redis-cli -ErrorAction Stop) {
+ Write-Output 'redis-cli exists.'
+ }
+}
+catch {
+ throw 'Cannot continue redis-cli does not exist.'
+}
+
+# create a server, and start listening on port 8081
+Start-PodeServer -Threads 3 {
+ # listen on localhost:8081
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+
+ # log errors
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+
+ Set-PodeCacheDefaultTtl -Value 60
+
+ $params = @{
+ Set = {
+ param($key, $value, $ttl)
+ $null = redis-cli -h localhost -p 6379 SET $key "$($value)" EX $ttl
+ }
+ Get = {
+ param($key, $metadata)
+ $result = redis-cli -h localhost -p 6379 GET $key
+ $result = [System.Management.Automation.Internal.StringDecorated]::new($result).ToString('PlainText')
+ if ([string]::IsNullOrEmpty($result) -or ($result -ieq '(nil)')) {
+ return $null
+ }
+ return $result
+ }
+ Test = {
+ param($key)
+ $result = redis-cli -h localhost -p 6379 EXISTS $key
+ return [System.Management.Automation.Internal.StringDecorated]::new($result).ToString('PlainText')
+ }
+ Remove = {
+ param($key)
+ $null = redis-cli -h localhost -p 6379 EXPIRE $key -1
+ }
+ Clear = {}
+ }
+ if ($params) {
+ Add-PodeCacheStorage -Name 'Redis' @params
+
+ # set default value for cache
+ $cache:cpu = (Get-Random -Minimum 1 -Maximum 1000)
+
+ # get cpu, and cache it
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ if ((Test-PodeCache -Key 'cpu') -and ($null -ne $cache:cpu)) {
+ Write-PodeJsonResponse -Value @{ CPU = $cache:cpu }
+ # Write-PodeHost 'here - cached'
+ return
+ }
+
+ # $cache:cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
+ Start-Sleep -Milliseconds 500
+ $cache:cpu = (Get-Random -Minimum 1 -Maximum 1000)
+ Write-PodeJsonResponse -Value @{ CPU = $cache:cpu }
+ # $cpu = (Get-Random -Minimum 1 -Maximum 1000)
+ # Write-PodeJsonResponse -Value @{ CPU = $cpu }
+ # Write-PodeHost 'here - raw'
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/examples/Create-Routes.ps1 b/examples/Create-Routes.ps1
new file mode 100644
index 000000000..05ebeb1c0
--- /dev/null
+++ b/examples/Create-Routes.ps1
@@ -0,0 +1,58 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with multiple routes using different approaches.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081 with various routes demonstrating different
+ approaches to route creation. These include using script blocks, file paths, and direct script inclusion.
+
+.EXAMPLE
+ To run the sample: ./Create-Routes.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Create-Routes.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+#crete routes using different approaches
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+Start-PodeServer -Threads 1 -ScriptBlock {
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+
+ Add-PodeRoute -PassThru -Method Get -Path '/routeCreateScriptBlock/:id' -ScriptBlock ([ScriptBlock]::Create( (Get-Content -Path "$ScriptPath\scripts\routeScript.ps1" -Raw))) |
+ Set-PodeOARouteInfo -Summary 'Test' -OperationId 'routeCreateScriptBlock' -PassThru |
+ Set-PodeOARequest -Parameters @((New-PodeOAStringProperty -Name 'id' | ConvertTo-PodeOAParameter -In Path -Required) )
+
+
+ Add-PodeRoute -PassThru -Method Post -Path '/routeFilePath/:id' -FilePath '.\scripts\routeScript.ps1' | Set-PodeOARouteInfo -Summary 'Test' -OperationId 'routeFilePath' -PassThru |
+ Set-PodeOARequest -Parameters @((New-PodeOAStringProperty -Name 'id' | ConvertTo-PodeOAParameter -In Path -Required) )
+
+
+ Add-PodeRoute -PassThru -Method Get -Path '/routeScriptBlock/:id' -ScriptBlock { $Id = $WebEvent.Parameters['id'] ; Write-PodeJsonResponse -StatusCode 200 -Value @{'id' = $Id } } |
+ Set-PodeOARouteInfo -Summary 'Test' -OperationId 'routeScriptBlock' -PassThru |
+ Set-PodeOARequest -Parameters @((New-PodeOAStringProperty -Name 'id' | ConvertTo-PodeOAParameter -In Path -Required) )
+
+
+ Add-PodeRoute -PassThru -Method Get -Path '/routeScriptSameScope/:id' -ScriptBlock { . $ScriptPath\scripts\routeScript.ps1 } |
+ Set-PodeOARouteInfo -Summary 'Test' -OperationId 'routeScriptSameScope' -PassThru |
+ Set-PodeOARequest -Parameters @((New-PodeOAStringProperty -Name 'id' | ConvertTo-PodeOAParameter -In Path -Required) )
+
+}
\ No newline at end of file
diff --git a/examples/Dockerfile b/examples/Dockerfile
index 65ff8c543..67cb0d221 100644
--- a/examples/Dockerfile
+++ b/examples/Dockerfile
@@ -1,4 +1,4 @@
FROM badgerati/pode:test
COPY . /usr/src/app/
-EXPOSE 8085
-CMD [ "pwsh", "-c", "cd /usr/src/app; ./web-pages-docker.ps1" ]
+EXPOSE 8081
+CMD [ "pwsh", "-c", "cd /usr/src/app; ./Web-PagesDocker.ps1" ]
diff --git a/examples/Dot-SourceScript.ps1 b/examples/Dot-SourceScript.ps1
new file mode 100644
index 000000000..cd97e396f
--- /dev/null
+++ b/examples/Dot-SourceScript.ps1
@@ -0,0 +1,45 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server and run a script from an external file.
+
+.DESCRIPTION
+ This script sets up a Pode server, enables terminal logging for errors, and uses an external
+ script for additional logic. It imports the Pode module from the source path if available,
+ otherwise from the installed modules.
+
+.EXAMPLE
+ To run the sample: ./Dot-SourceScript.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Dot-SourceScript.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# runs the logic once, then exits
+Start-PodeServer {
+
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+ Use-PodeScript -Path './modules/Script1.ps1'
+
+}
diff --git a/examples/External-Funcs.ps1 b/examples/External-Funcs.ps1
new file mode 100644
index 000000000..21ef57a82
--- /dev/null
+++ b/examples/External-Funcs.ps1
@@ -0,0 +1,52 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server and use an external module function.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081, imports an external module containing functions,
+ and includes a route that uses a function from the external module to generate a response.
+
+.EXAMPLE
+ To run the sample: ./External-Funcs.ps1
+
+ Invoke-RestMethod -Uri http://localhost:8081 -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/External-Funcs.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ } else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+} catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# include the external function module
+Import-PodeModule -Path './modules/External-Funcs.psm1'
+
+# create a server, and start listening on port 8081
+Start-PodeServer {
+
+ # listen on localhost:8085
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+
+ # GET request for "localhost:8085/"
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{ 'result' = (Get-Greeting) }
+ }
+
+}
\ No newline at end of file
diff --git a/examples/File-Monitoring.ps1 b/examples/File-Monitoring.ps1
new file mode 100644
index 000000000..10be1b4ac
--- /dev/null
+++ b/examples/File-Monitoring.ps1
@@ -0,0 +1,51 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with a view engine and file monitoring.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081, uses Pode's view engine for rendering
+ web pages, and configures the server to monitor file changes and restart automatically.
+
+.EXAMPLE
+ To run the sample: ./File-Monitoring.ps1
+
+ Invoke-RestMethod -Uri http://localhost:8081 -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/File-Monitoring.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# create a server listening on port 8081, set to monitor file changes and restart the server
+Start-PodeServer {
+
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+ Set-PodeViewEngine -Type Pode
+
+ # GET request for web page on "localhost:8081/"
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ Write-PodeViewResponse -Path 'simple' -Data @{ 'numbers' = @(1, 2, 3); }
+ }
+
+}
diff --git a/examples/File-Watchers.ps1 b/examples/File-Watchers.ps1
new file mode 100644
index 000000000..eac1ec9ce
--- /dev/null
+++ b/examples/File-Watchers.ps1
@@ -0,0 +1,47 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with file watcher and logging.
+
+.DESCRIPTION
+ This script sets up a Pode server, enables terminal logging for errors, and adds a file watcher
+ to monitor changes in PowerShell script files (*.ps1) within the script directory. The server
+ logs file change events and outputs them to the terminal.
+
+.EXAMPLE
+ To run the sample: ./File-Watchers.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/File-Watchers.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+Start-PodeServer -Verbose {
+
+ # enable logging
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+
+ Add-PodeFileWatcher -Path $ScriptPath -Include '*.ps1' -ScriptBlock {
+ "[$($FileEvent.Type)][$($FileEvent.Parameters['project'])]: $($FileEvent.FullPath)" | Out-Default
+ }
+}
\ No newline at end of file
diff --git a/examples/FileBrowser/FileBrowser.ps1 b/examples/FileBrowser/FileBrowser.ps1
index ab94f1977..da79d9a40 100644
--- a/examples/FileBrowser/FileBrowser.ps1
+++ b/examples/FileBrowser/FileBrowser.ps1
@@ -1,11 +1,43 @@
-$FileBrowserPath = Split-Path -Parent -Path $MyInvocation.MyCommand.Path
-$podePath = Split-Path -Parent -Path (Split-Path -Parent -Path $FileBrowserPath)
-if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
- Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
-}
-else {
- Import-Module -Name 'Pode'
+<#
+.SYNOPSIS
+ PowerShell script to set up a Pode server with static file browsing and authentication.
+
+.DESCRIPTION
+ This script sets up a Pode server that listens on port 8081. It includes static file browsing
+ with different routes, some of which require authentication. The script also demonstrates
+ how to set up basic authentication using Pode.
+
+ The server includes routes for downloading files, browsing files without downloading, and
+ accessing files with authentication.
+
+.EXAMPLE
+ To run the sample: ./FileBrowser/FileBrowser.ps1
+
+ Access the file browser:
+ Navigate to 'http://localhost:8081/' to browse the files in the specified directory.
+ Download a file:
+ Navigate to 'http://localhost:8081/download' to download files.
+ Access a file with authentication:
+ Navigate to 'http://localhost:8081/auth' and provide the username 'morty' and password 'pickle'.
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/FileBrowser/FileBrowser.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+try {
+ $FileBrowserPath = Split-Path -Parent -Path $MyInvocation.MyCommand.Path
+ $podePath = Split-Path -Parent -Path (Split-Path -Parent -Path $FileBrowserPath)
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
}
+catch { throw }
$directoryPath = $podePath
# Start Pode server
diff --git a/examples/HelloWorld/HelloWorld.ps1 b/examples/HelloWorld/HelloWorld.ps1
new file mode 100644
index 000000000..949e00c22
--- /dev/null
+++ b/examples/HelloWorld/HelloWorld.ps1
@@ -0,0 +1,56 @@
+<#
+.SYNOPSIS
+ PowerShell script to set up a Pode server with a simple GET endpoint.
+
+.DESCRIPTION
+ This script sets up a Pode server that listens on port 8080. It includes a single route for GET requests
+ to the root path ('/') that returns a simple text response.
+
+.EXAMPLE
+ To run the sample: ./HelloWorld/HelloWorld.ps1
+
+ # HTML responses 'Hello, world!
+ Invoke-RestMethod -Uri http://localhost:8081/ -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/HelloWorld/HelloWorld.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+try {
+ # Get the path of the script being executed
+ $ScriptPath = (Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path))
+ # Get the parent directory of the script's path
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Check if the Pode module file exists in the specified path
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ # If the Pode module file exists, import it
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ # If the Pode module file does not exist, import the Pode module from the system
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch {
+ # If there is any error during the module import, throw the error
+ throw
+}
+
+# Alternatively, you can directly import the Pode module from the system
+# Import-Module Pode
+
+# Start the Pode server
+Start-PodeServer {
+ # Add an HTTP endpoint listening on localhost at port 8080
+ Add-PodeEndpoint -Address localhost -Port 8080 -Protocol Http
+
+ # Add a route for GET requests to the root path '/'
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ # Send a text response with 'Hello, world!'
+ Write-PodeTextResponse -Value 'Hello, world!'
+ }
+}
diff --git a/examples/IIS-Example.ps1 b/examples/IIS-Example.ps1
new file mode 100644
index 000000000..11afa61b5
--- /dev/null
+++ b/examples/IIS-Example.ps1
@@ -0,0 +1,67 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with logging and task scheduling.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081, enables terminal logging for requests and errors,
+ and includes a scheduled task. The server has two routes: one for a simple JSON response and another to
+ invoke a task that demonstrates delayed execution.
+
+.EXAMPLE
+ To run the sample: ./IIS-Example.ps1
+
+
+ Invoke-RestMethod -Uri http://localhost:8081 -Method Get
+
+ Invoke-RestMethod -Uri http://localhost:8081/run-task -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/IIS-Example.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# create a server, and start listening on port 8081
+Start-PodeServer {
+
+ # listen on localhost:8081
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+ New-PodeLoggingMethod -Terminal | Enable-PodeRequestLogging
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+
+ Add-PodeTask -Name 'Test' -ScriptBlock {
+ Start-Sleep -Seconds 10
+ 'a message is never late, it arrives exactly when it means to' | Out-Default
+ }
+
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ Write-PodeJsonResponse -Value @{ Message = 'Hello' }
+ $WebEvent.Request | out-default
+ }
+
+ Add-PodeRoute -Method Get -Path '/run-task' -ScriptBlock {
+ Invoke-PodeTask -Name 'Test' | Out-Null
+ Write-PodeJsonResponse -Value @{ Result = 'jobs done' }
+ }
+
+}
\ No newline at end of file
diff --git a/examples/Logging.ps1 b/examples/Logging.ps1
new file mode 100644
index 000000000..2625991bf
--- /dev/null
+++ b/examples/Logging.ps1
@@ -0,0 +1,85 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with configurable logging, view engine, and various routes.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081, configures a view engine, and allows for different
+ types of request logging (terminal, file, custom). It includes routes for serving a web page, simulating a
+ server error, and downloading a file.
+
+.EXAMPLE
+ To run the sample: ./Logging.ps1
+
+ Invoke-RestMethod -Uri http://localhost:8081/ -Method Get
+ Invoke-RestMethod -Uri http://localhost:8081/error -Method Get
+ Invoke-RestMethod -Uri http://localhost:8081/download -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Logging.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+$LOGGING_TYPE = 'terminal' # Terminal, File, Custom
+
+# create a server, and start listening on port 8081
+Start-PodeServer {
+
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
+ Set-PodeViewEngine -Type Pode
+
+ switch ($LOGGING_TYPE.ToLowerInvariant()) {
+ 'terminal' {
+ New-PodeLoggingMethod -Terminal | Enable-PodeRequestLogging
+ }
+
+ 'file' {
+ New-PodeLoggingMethod -File -Name 'requests' -MaxDays 4 | Enable-PodeRequestLogging
+ }
+
+ 'custom' {
+ $type = New-PodeLoggingMethod -Custom -ScriptBlock {
+ param($item)
+ # send request row to S3
+ }
+
+ $type | Enable-PodeRequestLogging
+ }
+ }
+
+ # GET request for web page on "localhost:8081/"
+ Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
+ Write-PodeViewResponse -Path 'simple' -Data @{ 'numbers' = @(1, 2, 3); }
+ }
+
+ # GET request throws fake "500" server error status code
+ Add-PodeRoute -Method Get -Path '/error' -ScriptBlock {
+ Set-PodeResponseStatus -Code 500
+ }
+
+ # GET request to download a file
+ Add-PodeRoute -Method Get -Path '/download' -ScriptBlock {
+ Set-PodeResponseAttachment -Path 'Anger.jpg'
+ }
+
+}
diff --git a/examples/Looping-Service.ps1 b/examples/Looping-Service.ps1
new file mode 100644
index 000000000..22b70e8bd
--- /dev/null
+++ b/examples/Looping-Service.ps1
@@ -0,0 +1,53 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with interval-based service handlers.
+
+.DESCRIPTION
+ This script sets up a Pode server that runs with a specified interval, adding service handlers
+ that execute at each interval. The handlers include logging messages to the terminal and using
+ lock mechanisms.
+
+.EXAMPLE
+ To run the sample: ./Looping-Service.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Looping-Service.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# create a server, and start looping
+Start-PodeServer -Interval 3 {
+
+ Add-PodeHandler -Type Service -Name 'Hello' -ScriptBlock {
+ Write-PodeHost 'hello, world!'
+ Lock-PodeObject -ScriptBlock {
+ "Look I'm locked!" | Out-PodeHost
+ }
+ }
+
+ Add-PodeHandler -Type Service -Name 'Bye' -ScriptBlock {
+ Write-PodeHost 'goodbye!'
+ }
+
+}
diff --git a/examples/Mail-Server.ps1 b/examples/Mail-Server.ps1
new file mode 100644
index 000000000..e3bc9ce41
--- /dev/null
+++ b/examples/Mail-Server.ps1
@@ -0,0 +1,80 @@
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with SMTP and SMTPS protocols.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on SMTP (port 25) and SMTPS (with explicit and implicit TLS).
+ It includes logging for errors and debug information and demonstrates handling incoming SMTP emails with
+ potential attachments.
+
+.EXAMPLE
+ To run the sample: ./Mail-Server.ps1
+
+ Send-MailMessage -SmtpServer localhost -To 'to@pode.com' -From 'from@pode.com' -Body 'Hello' -Subject 'Hi there' -Port 25
+
+.EXAMPLE
+ To run the sample: ./Mail-Server.ps1
+ [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { return $true }
+ Send-MailMessage -SmtpServer localhost -To 'to@pode.com' -From 'from@pode.com' -Body 'Hello' -Subject 'Hi there' -Port 587 -UseSSL
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Mail-Server.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# create a server, and start listening on port 25
+Start-PodeServer -Threads 2 {
+
+ Add-PodeEndpoint -Address localhost -Protocol Smtp
+ Add-PodeEndpoint -Address localhost -Protocol Smtps -SelfSigned -TlsMode Explicit
+ Add-PodeEndpoint -Address localhost -Protocol Smtps -SelfSigned -TlsMode Implicit
+
+ # enable logging
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging -Levels Error, Debug
+
+ # allow the local ip
+ #Add-PodeAccessRule -Access Allow -Type IP -Values 127.0.0.1
+
+ # setup an smtp handler
+ Add-PodeHandler -Type Smtp -Name 'Main' -ScriptBlock {
+ Write-PodeHost '- - - - - - - - - - - - - - - - - -'
+ Write-PodeHost $SmtpEvent.Email.From
+ Write-PodeHost $SmtpEvent.Email.To
+ Write-PodeHost '|'
+ Write-PodeHost $SmtpEvent.Email.Body
+ Write-PodeHost '|'
+ # Write-PodeHost $SmtpEvent.Email.Data
+ # Write-PodeHost '|'
+ $SmtpEvent.Email.Attachments | Out-Default
+ if ($SmtpEvent.Email.Attachments.Length -gt 0) {
+ #$SmtpEvent.Email.Attachments[0].Save('C:\temp')
+ }
+ Write-PodeHost '|'
+ $SmtpEvent.Email | Out-Default
+ $SmtpEvent.Request | out-default
+ $SmtpEvent.Email.Headers | out-default
+ Write-PodeHost '- - - - - - - - - - - - - - - - - -'
+ }
+
+}
\ No newline at end of file
diff --git a/examples/middleware.ps1 b/examples/Middleware.ps1
similarity index 61%
rename from examples/middleware.ps1
rename to examples/Middleware.ps1
index 575d93678..01e489e32 100644
--- a/examples/middleware.ps1
+++ b/examples/Middleware.ps1
@@ -1,13 +1,49 @@
-$path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
-Import-Module "$($path)/src/Pode.psm1" -Force -ErrorAction Stop
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with rate limiting and middleware.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on port 8081 with various middleware implementations
+ and rate limiting for incoming requests. It includes middleware for route-specific logic, blocking
+ specific user agents, and rejecting requests from certain IP addresses.
+
+.EXAMPLE
+ To run the sample: ./Middleware.ps1
+
+ Invoke-RestMethod -Uri http://localhost:8081/users -Method Get
+ Invoke-RestMethod -Uri http://localhost:8081/alive -Method Get
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/Middleware.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
# or just:
# Import-Module Pode
Start-PodeServer {
- # listen on localhost:8085
- Add-PodeEndpoint -Address * -Port $port -Protocol Http
+ # listen on localhost:8081
+ Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http
# limit localhost to 5 request per 10 seconds
Add-PodeLimitRule -Type IP -Values @('127.0.0.1', '[::1]') -Limit 5 -Seconds 10
diff --git a/examples/OneOff-Script.ps1 b/examples/OneOff-Script.ps1
new file mode 100644
index 000000000..e3547babf
--- /dev/null
+++ b/examples/OneOff-Script.ps1
@@ -0,0 +1,44 @@
+<#
+.SYNOPSIS
+ A simple PowerShell script to set up a Pode server and log a message.
+
+.DESCRIPTION
+ This script sets up a Pode server, enables terminal logging for errors, and writes a "hello, world!" message to the terminal.
+ The server runs the logic once and then exits.
+
+.EXAMPLE
+ To run the sample: ./OneOff-Script.ps1
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/OneOff-Script.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
+}
+catch { throw }
+
+# or just:
+# Import-Module Pode
+
+# runs the logic once, then exits
+Start-PodeServer {
+
+ New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
+ Write-PodeHost 'hello, world!'
+
+}
diff --git a/examples/OpenApiTuttiFrutti.ps1 b/examples/OpenApi-TuttiFrutti.ps1
similarity index 86%
rename from examples/OpenApiTuttiFrutti.ps1
rename to examples/OpenApi-TuttiFrutti.ps1
index 691c1043b..358906a22 100644
--- a/examples/OpenApiTuttiFrutti.ps1
+++ b/examples/OpenApi-TuttiFrutti.ps1
@@ -1,12 +1,74 @@
-$path = Split-Path -Parent -Path (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
-if (Test-Path -Path "$($path)/src/Pode.psm1" -PathType Leaf) {
- Import-Module "$($path)/src/Pode.psm1" -Force -ErrorAction Stop
-} else {
- Import-Module -Name 'Pode'
+<#
+.SYNOPSIS
+ A sample PowerShell script to set up a Pode server with OpenAPI 3.0 and 3.1 specifications.
+
+.DESCRIPTION
+ This script sets up a Pode server listening on ports 8081 and 8082 with OpenAPI 3.0 and 3.1 specifications.
+ It includes multiple endpoints, OpenAPI documentation, various route definitions, authentication schemes,
+ and middleware for enhanced API functionality.
+
+.PARAMETER PortV3
+ The port on which the Pode server will listen for OpenAPI v3. Default is 8080.
+
+.PARAMETER PortV3_1
+ The port on which the Pode server will listen for OpenAPI v3_1. Default is 8081.
+
+.PARAMETER Quiet
+ Suppresses output when the server is running.
+
+.PARAMETER DisableTermination
+ Prevents the server from being terminated.
+
+.EXAMPLE
+ To run the sample: ./OpenApi-TuttiFrutti.ps1
+
+ Using a browser to access the OpenAPI Info:
+ 'v3.1': http://127.0.0.1:8082/docs/openapi/v3.1
+ Documentation: http://127.0.0.1:8082/docs/v3.1
+
+ 'v3': http://127.0.0.1:8081/docs/openapi/v3.0
+ Documentation: http://127.0.0.1:8081/docs
+
+.LINK
+ https://github.com/Badgerati/Pode/blob/develop/examples/OpenApi-TuttiFrutti.ps1
+
+.NOTES
+ Author: Pode Team
+ License: MIT License
+#>
+param(
+ [Parameter()]
+ [int]
+ $PortV3 = 8080,
+
+ [int]
+ $PortV3_1 = 8081,
+
+ [switch]
+ $Quiet,
+
+ [switch]
+ $DisableTermination
+)
+
+try {
+ # Determine the script path and Pode module path
+ $ScriptPath = (Split-Path -Parent -Path $MyInvocation.MyCommand.Path)
+ $podePath = Split-Path -Parent -Path $ScriptPath
+
+ # Import the Pode module from the source path if it exists, otherwise from installed modules
+ if (Test-Path -Path "$($podePath)/src/Pode.psm1" -PathType Leaf) {
+ Import-Module "$($podePath)/src/Pode.psm1" -Force -ErrorAction Stop
+ }
+ else {
+ Import-Module -Name 'Pode' -MaximumVersion 2.99 -ErrorAction Stop
+ }
}
+catch { throw }
-Start-PodeServer -Threads 2 -ScriptBlock {
- Add-PodeEndpoint -Address localhost -Port 8081 -Protocol Http -Default
+Start-PodeServer -Threads 1 -Quiet:$Quiet -DisableTermination:$DisableTermination -ScriptBlock {
+ Add-PodeEndpoint -Address localhost -Port $PortV3 -Protocol Http -Default -Name 'endpoint_v3'
+ Add-PodeEndpoint -Address localhost -Port $PortV3_1 -Protocol Http -Default -Name 'endpoint_v3.1'
New-PodeLoggingMethod -Terminal | Enable-PodeErrorLogging
$InfoDescription = @'
This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about Swagger at [http://swagger.io](http://swagger.io).
@@ -19,14 +81,8 @@ Some useful links:
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
'@
-
-
- #Enable-PodeOpenApi -Path '/docs/openapi' -OpenApiVersion '3.0.0' -EnableSchemaValidation -DisableMinimalDefinitions -DefaultResponses @{}
- # New-PodeOAExternalDoc -Name 'SwaggerDocs' -Description 'Find out more about Swagger' -Url 'http://swagger.io'
- # Add-PodeOAExternalDoc -Reference 'SwaggerDocs'
-
- Enable-PodeOpenApi -Path '/docs/openapi/v3.0' -OpenApiVersion '3.0.3' -EnableSchemaValidation -DisableMinimalDefinitions -NoDefaultResponses -DefinitionTag 'v3'
- Enable-PodeOpenApi -Path '/docs/openapi/v3.1' -OpenApiVersion '3.1.0' -EnableSchemaValidation -DisableMinimalDefinitions -NoDefaultResponses -DefinitionTag 'v3.1'
+ Enable-PodeOpenApi -Path '/docs/openapi/v3.0' -OpenApiVersion '3.0.3' -EnableSchemaValidation:($PSVersionTable.PSEdition -eq 'Core') -DisableMinimalDefinitions -NoDefaultResponses -DefinitionTag 'v3' -EndpointName 'endpoint_v3'
+ Enable-PodeOpenApi -Path '/docs/openapi/v3.1' -OpenApiVersion '3.1.0' -EnableSchemaValidation:($PSVersionTable.PSEdition -eq 'Core') -DisableMinimalDefinitions -NoDefaultResponses -DefinitionTag 'v3.1' -EndpointName 'endpoint_v3.1'
$swaggerDocs = New-PodeOAExternalDoc -Description 'Find out more about Swagger' -Url 'http://swagger.io'
$swaggerDocs | Add-PodeOAExternalDoc -DefinitionTag 'v3', 'v3.1'
@@ -201,7 +257,7 @@ Some useful links:
(New-PodeOAStringProperty -Name 'photoUrls' -Array),
(New-PodeOASchemaProperty -Name 'tags' -Component 'Tag')
(New-PodeOAStringProperty -Name 'status' -Description 'pet status in the store' -Enum @('available', 'pending', 'sold'))
- )) #>
+ )) #>
<# Add-PodeOAComponentSchema -Name 'Cat' -Schema ( New-PodeOAObjectProperty -Name 'testcat' -Description 'Type of cat' -Properties (
New-PodeOAStringProperty -Name 'breed' -Description 'Type of Breed' -Enum @( 'Abyssinian', 'Balinese-Javanese', 'Burmese', 'British Shorthair') |
@@ -295,7 +351,8 @@ Some useful links:
Code = 401
Challenge = 'qop="auth", nonce=""'
}
- } else {
+ }
+ else {
return @{
Message = 'No Authorization header found'
Code = 401
@@ -329,7 +386,6 @@ Some useful links:
$clientId = '123123123'
$clientSecret = 'acascascasca>zzzcz'
- $tenantId = '56456232'
<# $InnerScheme = New-PodeAuthScheme -Form
$scheme = New-PodeAuthScheme `
@@ -360,10 +416,10 @@ Some useful links:
Merge-PodeAuth -Name 'test' -Authentication 'Login-OAuth2', 'api_key'
$ex =
- New-PodeOAExample -MediaType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
- New-PodeOAExample -MediaType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
- New-PodeOAExample -MediaType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
- New-PodeOAExample -MediaType '*/*' -Name 'user' -Summary 'User example in other forma' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
+ New-PodeOAExample -ContentType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
+ New-PodeOAExample -ContentType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
+ New-PodeOAExample -ContentType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
+ New-PodeOAExample -ContentType '*/*' -Name 'user' -Summary 'User example in other forma' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
Select-PodeOADefinition -Tag 'v3' -Scriptblock {
Add-PodeRouteGroup -Path '/api/v4' -Routes {
@@ -371,7 +427,8 @@ Some useful links:
$JsonPet = ConvertTo-Json $WebEvent.data
if ( Update-Pet -Id $WebEvent.Parameters['petId'] -Data $JsonPet) {
Write-PodeJsonResponse -Value @{} -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -Value @{} -StatusCode 405
}
} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' -OperationId 'updatePasdadaetWithForm' -PassThru |
@@ -381,14 +438,15 @@ Some useful links:
New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'User'; 'application/xml' = 'User' } -Examples $ex
) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.' -Content (@{ 'application/json' = '' ; 'application/xml' = '' }) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.' -Content (@{ 'application/json' = '' ; 'application/xml' = '' }) -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Method Not Allowed' -Content (@{ 'application/json' = '' ; 'application/xml' = '' })
Add-PodeRoute -PassThru -Method Put -Path '/paet/:petId' -ScriptBlock {
$JsonPet = ConvertTo-Json $WebEvent.data
if ( Update-Pet -Id $WebEvent.Parameters['id'] -Data $JsonPet) {
Write-PodeJsonResponse -Value @{} -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -Value @{} -StatusCode 405
}
} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' -OperationId 'updatepaet' -PassThru |
@@ -416,7 +474,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters (
New-PodeOAIntProperty -Name 'petId' -Description 'ID of pet to return' -Format Int64 |
ConvertTo-PodeOAParameter -In Path -Required ) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet') -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet') -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'Pet not found' -PassThru |
Add-PodeOAResponse -StatusCode 415
@@ -432,7 +490,8 @@ Some useful links:
$JsonPet = ConvertTo-Json $WebEvent.data
if ( Update-Pet -Id $WebEvent.Parameters['id'] -Data $JsonPet) {
Write-PodeJsonResponse -Value @{} -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -Value @{} -StatusCode 405
}
} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' -OperationId 'updatepaet2' -PassThru |
@@ -445,10 +504,10 @@ Some useful links:
$ex =
- New-PodeOAExample -MediaType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
- New-PodeOAExample -MediaType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
- New-PodeOAExample -MediaType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
- New-PodeOAExample -MediaType '*/*' -Name 'user' -Summary 'User example in other forma' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
+ New-PodeOAExample -ContentType 'application/json' -Name 'user' -Summary 'User Example' -ExternalValue 'http://foo.bar/examples/user-example.json' |
+ New-PodeOAExample -ContentType 'application/xml' -Name 'user' -Summary 'User Example in XML' -ExternalValue 'http://foo.bar/examples/user-example.xml' |
+ New-PodeOAExample -ContentType 'text/plain' -Name 'user' -Summary 'User Example in Plain text' -ExternalValue 'http://foo.bar/examples/user-example.txt' |
+ New-PodeOAExample -ContentType '*/*' -Name 'user' -Summary 'User example in other forma' -ExternalValue 'http://foo.bar/examples/user-example.whatever'
Add-PodeOAComponentExample -name 'frog-example' -Summary "An example of a frog with a cat's name" -Value @{name = 'Jaguar'; petType = 'Panthera'; color = 'Lion'; gender = 'Male'; breed = 'Mantella Baroni' }
@@ -456,16 +515,17 @@ Some useful links:
$JsonPet = ConvertTo-Json $WebEvent.data
if ( Update-Pet -Id $WebEvent.Parameters['id'] -Data $JsonPet) {
Write-PodeJsonResponse -Value @{} -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -Value @{} -StatusCode 405
}
} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' -OperationId 'updatepaet3' -PassThru |
Set-PodeOARequest -Parameters @(
(New-PodeOAStringProperty -Name 'petId' -Description 'ID of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Path -Required)
) -RequestBody (New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'NewCat' } -Examples (
- New-PodeOAExample -MediaType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
- New-PodeOAExample -MediaType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' } |
- New-PodeOAExample -MediaType 'application/json' -Reference 'frog-example'
+ New-PodeOAExample -ContentType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
+ New-PodeOAExample -ContentType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' } |
+ New-PodeOAExample -ContentType 'application/json' -Reference 'frog-example'
)
) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.' -Content (@{ 'application/json' = '' ; 'application/xml' = '' }) -PassThru |
@@ -476,26 +536,33 @@ Some useful links:
$JsonPet = ConvertTo-Json $WebEvent.data
if ( Update-Pet -Id $WebEvent.Parameters['id'] -Data $JsonPet) {
Write-PodeJsonResponse -Value @{} -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -Value @{} -StatusCode 405
}
} | Set-PodeOARouteInfo -Summary 'Updates a pet in the store with form data' -Tags 'pet' -OperationId 'updatepaet4' -PassThru |
Set-PodeOARequest -Parameters @(
(New-PodeOAStringProperty -Name 'petId' -Description 'ID of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Path -Required -ContentType 'application/json')
) -RequestBody (New-PodeOARequestBody -Description 'user to add to the system' -Content @{ 'application/json' = 'Pet' } -Examples (
- New-PodeOAExample -MediaType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
- New-PodeOAExample -MediaType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' } |
- New-PodeOAExample -MediaType 'application/json' -Reference 'frog-example'
+ New-PodeOAExample -ContentType 'application/json' -Name 'cat' -Summary 'An example of a cat' -Value @{name = 'Fluffy'; petType = 'Cat'; color = 'White'; gender = 'male'; breed = 'Persian' } |
+ New-PodeOAExample -ContentType 'application/json' -Name 'dog' -Summary "An example of a dog with a cat's name" -Value @{name = 'Puma'; petType = 'Dog'; color = 'Black'; gender = 'Female'; breed = 'Mixed' } |
+ New-PodeOAExample -ContentType 'application/json' -Reference 'frog-example'
)
) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content '') -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Pet updated.' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content '') -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Method Not Allowed' -Content (@{ 'application/json' = '' ; 'application/xml' = '' })
}
}
Add-PodeAuthMiddleware -Name test -Authentication 'test' -Route '/api/*'
Select-PodeOADefinition -Tag 'v3.1', 'v3' -Scriptblock {
+
+ Add-PodeRoute -Method 'Post' -Path '/close' -ScriptBlock {
+ Close-PodeServer
+ } -PassThru | Set-PodeOARouteInfo -Summary 'Shutdown the server' -PassThru | Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation'
+
+
Add-PodeRouteGroup -Path '/api/v3' -Routes {
#PUT
Add-PodeRoute -PassThru -Method Put -Path '/pet' -ScriptBlock {
@@ -505,7 +572,8 @@ Some useful links:
$Pet = $WebEvent.data
$Pet.tags.id = Get-Random -Minimum 1 -Maximum 9999999
Write-PodeJsonResponse -Value ($Pet | ConvertTo-Json -Depth 20 ) -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -StatusCode 405 -Value @{
result = $Validate.result
message = $Validate.message -join ', '
@@ -513,11 +581,11 @@ Some useful links:
}
} | Set-PodeOARouteInfo -Summary 'Update an existing pet' -Description 'Update an existing pet by Id' -Tags 'pet' -OperationId 'updatePet' -PassThru |
Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'Pet not found' -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
- 'application/json' = (New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message') ))
+ 'application/json' = (New-PodeOAObjectProperty -Properties @((New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message')))
}
Add-PodeRoute -PassThru -Method Post -Path '/pet' -Authentication 'Login-OAuth2' -Scope 'write' -ScriptBlock {
@@ -528,7 +596,8 @@ Some useful links:
$Pet = $WebEvent.data
$Pet.tags.id = Get-Random -Minimum 1 -Maximum 9999999
Write-PodeJsonResponse -Value ($Pet | ConvertTo-Json -Depth 20 ) -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -StatusCode 405 -Value @{
result = $Validate.result
message = $Validate.message -join ', '
@@ -536,9 +605,9 @@ Some useful links:
}
} | Set-PodeOARouteInfo -Summary 'Add a new pet to the store' -Description 'Add a new pet to the store' -Tags 'pet' -OperationId 'addPet' -PassThru |
Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
- 'application/json' = (New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message') ))
+ 'application/json' = (New-PodeOAObjectProperty -Properties @((New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message')))
}
Add-PodeRoute -PassThru -Method Post -Path '/petcallback' -Authentication 'Login-OAuth2' -Scope 'write' -ScriptBlock {
@@ -548,7 +617,8 @@ Some useful links:
$Pet = $WebEvent.data
$Pet.tags.id = Get-Random -Minimum 1 -Maximum 9999999
Write-PodeJsonResponse -Value ($Pet | ConvertTo-Json -Depth 20 ) -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -StatusCode 405 -Value @{
result = $Validate.result
message = $Validate.message -join ', '
@@ -556,13 +626,13 @@ Some useful links:
}
} | Set-PodeOARouteInfo -Summary 'Add a new pet to the store' -Description 'Add a new pet to the store' -Tags 'pet' -OperationId 'addPetcallback' -PassThru |
Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
- 'application/json' = (New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message') ))
+ 'application/json' = (New-PodeOAObjectProperty -Properties @((New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message')))
} -PassThru |
Add-PodeOACallBack -Name 'test' -Path '{$request.body#/id}' -Method Post -RequestBody (New-PodeOARequestBody -Content @{'*/*' = (New-PodeOAStringProperty -Name 'id') } ) `
-Response (
- New-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' -Array) |
+ New-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' -Array) |
New-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' |
New-PodeOAResponse -StatusCode 404 -Description 'Pet not found' |
New-PodeOAResponse -Default -Description 'Something is wrong'
@@ -572,7 +642,7 @@ Some useful links:
Add-PodeOAComponentCallBack -Name 'test' -Path '{$request.body#/id}' -Method Post -RequestBody (New-PodeOARequestBody -Content @{'*/*' = (New-PodeOAStringProperty -Name 'id') } ) `
-Response (
- New-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' -Array) |
+ New-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' -Array) |
New-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' |
New-PodeOAResponse -StatusCode 404 -Description 'Pet not found' |
New-PodeOAResponse -Default -Description 'Something is wrong'
@@ -586,7 +656,8 @@ Some useful links:
$Pet = $WebEvent.data
$Pet.tags.id = Get-Random -Minimum 1 -Maximum 9999999
Write-PodeJsonResponse -Value ($Pet | ConvertTo-Json -Depth 20 ) -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -StatusCode 405 -Value @{
result = $Validate.result
message = $Validate.message -join ', '
@@ -594,7 +665,7 @@ Some useful links:
}
} | Set-PodeOARouteInfo -Summary 'Add a new pet to the store' -Description 'Add a new pet to the store' -Tags 'pet' -OperationId 'petcallbackReference' -PassThru |
Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Reference 'PetBodySchema' ) -PassThru |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Validation exception' -Content @{
'application/json' = ( New-PodeOAStringProperty -Name 'result' | New-PodeOAStringProperty -Name 'message' | New-PodeOAObjectProperty )
} -PassThru |
@@ -607,30 +678,22 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(
( New-PodeOAStringProperty -Name 'status' -Description 'Status values that need to be considered for filter' -Default 'available' -Enum @('available', 'pending', 'sold') | ConvertTo-PodeOAParameter -In Query )
) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' -Array) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' -Array) -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid status value'
-
-
-
-
-
-
-
-
Add-PodeRoute -PassThru -Method get -Path '/pet/findByTag' -Authentication 'test' -Scope 'read' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
} | Set-PodeOARouteInfo -Summary 'Finds Pets by tags' -Description 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.' -Tags 'pet' -OperationId 'findPetsByTags' -PassThru |
Set-PodeOARequest -PassThru -Parameters @(
( New-PodeOAStringProperty -Name 'tag' -Description 'Tags to filter by' -Array | ConvertTo-PodeOAParameter -In Query -Explode)
) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru | #missing array application/json:
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'Pet' ) -PassThru | #missing array application/json:
# schema:
# type: array
# items:
# $ref: '#/components/schemas/Pet'
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid status value' -PassThru |
- Add-PodeOAResponse -Default -Description 'Unexpected error' -Content (New-PodeOAContentMediaType -MediaType 'application/json' -Content 'ErrorModel' )
+ Add-PodeOAResponse -Default -Description 'Unexpected error' -Content (New-PodeOAContentMediaType -ContentType 'application/json' -Content 'ErrorModel' )
Add-PodeRoute -PassThru -Method Get -Path '/pet/:petId' -Authentication 'Login-OAuth2' -Scope 'read' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
@@ -646,9 +709,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(( ConvertTo-PodeOAParameter -Reference 'PetIdParam' ),
( New-PodeOAStringProperty -Name 'name' -Description 'Name of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query ) ,
( New-PodeOAStringProperty -Name 'status' -Description 'Status of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query )
- ) -RequestBody (
- # New-PodeOARequestBody -Content @{
- # 'application/x-www-form-urlencoded' = (New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -format 'uuid'), (New-PodeOAObjectProperty -Properties @())))
+ ) -RequestBody (
New-PodeOARequestBody -Properties -Content @{
'multipart/form-data' = (New-PodeOAStringProperty -Name 'file' -Format binary -Array)
}) | Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -PassThru |
@@ -663,7 +724,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(( ConvertTo-PodeOAParameter -Reference 'PetIdParam' ),
( New-PodeOAStringProperty -Name 'name' -Description 'Name of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query ) ,
( New-PodeOAStringProperty -Name 'status' -Description 'Status of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query )
- ) -RequestBody (
+ ) -RequestBody (
New-PodeOARequestBody -Content @{
'application/x-www-form-urlencoded' = (New-PodeOAObjectProperty -Properties @(
(New-PodeOAStringProperty -name 'id' -format 'uuid'), (New-PodeOAObjectProperty -name 'address' -NoProperties)))
@@ -678,7 +739,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(( ConvertTo-PodeOAParameter -Reference 'PetIdParam' ),
( New-PodeOAStringProperty -Name 'name' -Description 'Name of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query ) ,
( New-PodeOAStringProperty -Name 'status' -Description 'Status of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query )
- ) -RequestBody (New-PodeOARequestBody -Content @{'multipart/form-data' =
+ ) -RequestBody (New-PodeOARequestBody -Content @{'multipart/form-data' =
New-PodeOAStringProperty -name 'id' -format 'uuid' |
New-PodeOAObjectProperty -name 'address' -NoProperties |
New-PodeOAStringProperty -name 'children' -array |
@@ -695,7 +756,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(( ConvertTo-PodeOAParameter -Reference 'PetIdParam' ),
( New-PodeOAStringProperty -Name 'name' -Description 'Name of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query ) ,
( New-PodeOAStringProperty -Name 'status' -Description 'Status of pet that needs to be updated' | ConvertTo-PodeOAParameter -In Query )
- ) -RequestBody (New-PodeOARequestBody -Content @{'multipart/form-data' =
+ ) -RequestBody (New-PodeOARequestBody -Content @{'multipart/form-data' =
New-PodeOAStringProperty -name 'id' -format 'uuid' |
New-PodeOAObjectProperty -name 'address' -NoProperties |
New-PodeOAObjectProperty -name 'historyMetadata' -Description 'metadata in XML format' -NoProperties |
@@ -708,7 +769,7 @@ Some useful links:
New-PodeOAIntProperty -Name 'X-Rate-Limit-Reset' -Description 'The number of seconds left in the current period' -Minimum 2
)
)
- ) | Add-PodeOAResponse -StatusCode 200 -PassThru -Description 'A simple string response' -Content ( New-PodeOAContentMediaType -MediaType 'text/plain' -Content ( New-PodeOAStringProperty) ) |
+ ) | Add-PodeOAResponse -StatusCode 200 -PassThru -Description 'A simple string response' -Content ( New-PodeOAContentMediaType -ContentType 'text/plain' -Content ( New-PodeOAStringProperty)) |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
@@ -722,7 +783,7 @@ Some useful links:
( New-PodeOAStringProperty -Name 'additionalMetadata' -Description 'Additional Metadata' | ConvertTo-PodeOAParameter -In Query )
) -RequestBody (New-PodeOARequestBody -Required -Content @{ 'multipart/form-data' = New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -Name 'image' -Format Binary )) } ) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Description 'A simple string response' -Content (
- New-PodeOAContentMediaType -MediaType 'text/plain' -Content ( New-PodeOAStringProperty -Example 'whoa!') ) -Headers (
+ New-PodeOAContentMediaType -ContentType 'text/plain' -Content ( New-PodeOAStringProperty -Example 'whoa!')) -Headers (
New-PodeOAIntProperty -Name 'X-Rate-Limit-Limit' -Description 'The number of allowed requests in the current period' |
New-PodeOAIntProperty -Name 'X-Rate-Limit-Remaining' -Description 'The number of remaining requests in the current period' |
New-PodeOAIntProperty -Name 'X-Rate-Limit-Reset' -Description 'The number of seconds left in the current period' -Maximum 3
@@ -743,7 +804,7 @@ Some useful links:
( New-PodeOAIntProperty -Name 'petId' -Format Int64 -Description 'ID of pet that needs to be updated' -Required | ConvertTo-PodeOAParameter -In Path ),
( New-PodeOAStringProperty -Name 'additionalMetadata' -Description 'Additional Metadata' | ConvertTo-PodeOAParameter -In Query )
) -RequestBody (
- New-PodeOARequestBody -Required -Content ( New-PodeOAContentMediaType -MediaType 'multipart/form-data' -Upload -PartContentMediaType 'application/octect-stream' -Content (
+ New-PodeOARequestBody -Required -Content ( New-PodeOAContentMediaType -ContentType 'multipart/form-data' -Upload -PartContentMediaType 'application/octect-stream' -Content (
New-PodeOAIntProperty -name 'orderId' | New-PodeOAStringProperty -Name 'image' -Format Binary | New-PodeOAObjectProperty ))
) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content @{'application/json' = 'ApiResponse' } -PassThru |
@@ -758,7 +819,7 @@ Some useful links:
( New-PodeOAIntProperty -Name 'petId' -Format Int64 -Description 'ID of pet that needs to be updated' -Required | ConvertTo-PodeOAParameter -In Path ),
( New-PodeOAStringProperty -Name 'additionalMetadata' -Description 'Additional Metadata' | ConvertTo-PodeOAParameter -In Query )
) -RequestBody (
- New-PodeOARequestBody -Required -Content ( New-PodeOAContentMediaType -MediaType 'application/octet-stream' -Upload )
+ New-PodeOARequestBody -Required -Content ( New-PodeOAContentMediaType -ContentType 'application/octet-stream' -Upload )
) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content @{'application/json' = 'ApiResponse' } -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
@@ -773,7 +834,7 @@ Some useful links:
Add-PodeRoute -PassThru -Method post -Path '/store/order' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
} | Set-PodeOARouteInfo -Deprecated -Summary 'Place an order for a pet' -Description 'Place a new order in the store' -Tags 'store' -OperationId 'placeOrder' -PassThru |
- Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' )) -PassThru |
+ Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (@{ 'application/json' = 'Order' ; 'application/xml' = 'Order' }) -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
@@ -789,7 +850,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(
( New-PodeOAIntProperty -Name 'orderId' -Format Int64 -Description 'ID of order that needs to be fetched' -Required | ConvertTo-PodeOAParameter -In Path )
) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' ) -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'Order not found'
@@ -811,23 +872,24 @@ Some useful links:
$User = $WebEvent.data
$User.id = Get-Random -Minimum 1 -Maximum 9999999
Write-PodeJsonResponse -Value ($User | ConvertTo-Json -Depth 20 ) -StatusCode 200
- } else {
+ }
+ else {
Write-PodeJsonResponse -StatusCode 405 -Value @{
result = $Validate.result
message = $Validate.message -join ', '
}
}
} | Set-PodeOARouteInfo -Summary 'Create user.' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'createUser' -PassThru |
- Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Reference 'UserOpSuccess' -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input' -Content @{
- 'application/json' = (New-PodeOAObjectProperty -Properties @( (New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message') ))
+ 'application/json' = (New-PodeOAObjectProperty -Properties @((New-PodeOAStringProperty -Name 'result'), (New-PodeOAStringProperty -Name 'message')))
}
Add-PodeRoute -PassThru -Method post -Path '/user/createWithList' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
} | Set-PodeOARouteInfo -Summary 'Creates list of users with given input array.' -Description 'Creates list of users with given input array.' -Tags 'user' -OperationId 'createUsersWithListInput' -PassThru |
- Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ Set-PodeOARequest -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Reference 'UserOpSuccess' -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
@@ -838,7 +900,7 @@ Some useful links:
( New-PodeOAStringProperty -Name 'username' -Description 'The user name for login' | ConvertTo-PodeOAParameter -In Query )
( New-PodeOAStringProperty -Name 'password' -Description 'The password for login in clear text' -Format Password | ConvertTo-PodeOAParameter -In Query )
) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml' -Content 'string' ) `
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml' -Content 'string' ) `
-Header @('X-Rate-Limit', 'X-Expires-After') -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username/password supplied'
@@ -869,7 +931,7 @@ Some useful links:
} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'updateUser_1' -PassThru |
Set-PodeOARequest -Parameters @(
( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
- ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'StructPart' ))
+ ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'StructPart' ))
Add-PodeRoute -PassThru -Method Put -Path '/user/:username' -ScriptBlock {
@@ -877,7 +939,7 @@ Some useful links:
} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'updateUser' -PassThru |
Set-PodeOARequest -Parameters @(
( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
- ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Reference 'UserOpSuccess' -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'User not found' -PassThru |
@@ -890,7 +952,7 @@ Some useful links:
} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'updateUserLink' -PassThru |
Set-PodeOARequest -Parameters @(
( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
- ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Content @{'application/json' = 'User' } -PassThru `
-Links (New-PodeOAResponseLink -Name address -OperationId 'getUserByName' -Parameters @{'username' = '$request.path.username' } ) |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
@@ -906,14 +968,14 @@ Some useful links:
} | Set-PodeOARouteInfo -Summary 'Update user' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'updateUserLinkByRef' -PassThru |
Set-PodeOARequest -Parameters @(
( New-PodeOAStringProperty -Name 'username' -Description ' name that need to be updated.' -Required | ConvertTo-PodeOAParameter -In Path )
- ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
+ ) -RequestBody (New-PodeOARequestBody -Required -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'User' )) -PassThru |
Add-PodeOAResponse -StatusCode 200 -Content @{'application/json' = 'User' } -PassThru `
-Links (New-PodeOAResponseLink -Name 'address2' -Reference 'address' ) |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'User not found' -PassThru |
Add-PodeOAResponse -StatusCode 405 -Description 'Invalid Input'
-
+ #region Test remove route
Add-PodeRoute -PassThru -Method Delete -Path '/usera/:username' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
@@ -928,7 +990,6 @@ Some useful links:
Remove-PodeRoute -Method Delete -Path '/api/v3/usera/:username'
-
Add-PodeRoute -PassThru -Method Delete -Path '/user/:username' -ScriptBlock {
Write-PodeJsonResponse -Value 'done' -StatusCode 200
} | Set-PodeOARouteInfo -Summary 'Delete user' -Description 'This can only be done by the logged in user.' -Tags 'user' -OperationId 'deleteUser' -PassThru |
@@ -938,7 +999,7 @@ Some useful links:
Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid username supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'User not found'
-
+ #endregion
Add-PodeOAExternalRoute -Method Get -Path '/stores/order/:orderId' -Servers (
@@ -949,7 +1010,7 @@ Some useful links:
Set-PodeOARequest -PassThru -Parameters @(
( New-PodeOAIntProperty -Name 'orderId' -Format Int64 -Description 'ID of order that needs to be fetched' -Required | ConvertTo-PodeOAParameter -In Path )
) |
- Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -MediaType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' ) -PassThru |
+ Add-PodeOAResponse -StatusCode 200 -Description 'Successful operation' -Content (New-PodeOAContentMediaType -ContentType 'application/json', 'application/xml', 'application/x-www-form-urlencoded' -Content 'Order' ) -PassThru |
Add-PodeOAResponse -StatusCode 400 -Description 'Invalid ID supplied' -PassThru |
Add-PodeOAResponse -StatusCode 404 -Description 'Order not found'
}
@@ -965,8 +1026,8 @@ Some useful links:
}
- $yaml = PodeOADefinition -Format Yaml -DefinitionTag 'v3.1'
- $json = PodeOADefinition -Format Json -DefinitionTag 'v3'
+ $yaml = Get-PodeOADefinition -Format Yaml -DefinitionTag 'v3.1'
+ $json = Get-PodeOADefinition -Format Json -DefinitionTag 'v3'
Write-PodeHost "`rYAML Tag: v3.1 Output:`r $yaml"
diff --git a/examples/PetStore/Petstore-openApi.ps1 b/examples/PetStore/Petstore-OpenApi.ps1
similarity index 85%
rename from examples/PetStore/Petstore-openApi.ps1
rename to examples/PetStore/Petstore-OpenApi.ps1
index dafd4dfd3..bf2578bf5 100644
--- a/examples/PetStore/Petstore-openApi.ps1
+++ b/examples/PetStore/Petstore-OpenApi.ps1
@@ -1,33 +1,67 @@
+<#
+.SYNOPSIS
+ PowerShell script to set up a Pode server for a Pet Store API using OpenAPI 3.0 specifications.
+
+.DESCRIPTION
+ This script sets up a Pode server that listens on a specified port and uses OpenAPI 3.0 specifications
+ for defining the API. It supports multiple endpoints for managing pets, orders, and users with various
+ authentication methods including API key, Basic, and OAuth2.
+
+ This example shows how to use session persistent authentication using Windows Active Directory.
+ The example used here is Form authentication, sent from the