├── .github └── workflows │ ├── on-pull-request.yml │ └── on-release-tag.yml ├── .gitignore ├── Directory.Build.props ├── LICENSE ├── OpenApi.Sample.Falco ├── FalcoOpenApi.fs ├── OpenApi.Sample.Falco.fsproj ├── Program.fs └── Properties │ └── launchSettings.json ├── OpenApi.Sample.Giraffe ├── OpenApi.Sample.Giraffe.fsproj ├── Program.fs └── Properties │ └── launchSettings.json ├── OpenApi.Sample.Routing ├── OpenApi.Sample.Routing.fsproj ├── Program.fs ├── Properties │ └── launchSettings.json ├── RoutingOpenApi.fs └── Superheroes.fs ├── OpenApi.sln ├── OpenApi ├── Builders │ ├── Callback.fs │ ├── Components.fs │ ├── Contact.fs │ ├── Discriminator.fs │ ├── Document.fs │ ├── Encoding.fs │ ├── Example.fs │ ├── ExternalDocs.fs │ ├── Header.fs │ ├── Helpers.fs │ ├── Info.fs │ ├── License.fs │ ├── Link.fs │ ├── MediaType.fs │ ├── OAuthFlow.fs │ ├── OAuthFlows.fs │ ├── Operation.fs │ ├── Parameter.fs │ ├── PathItem.fs │ ├── Reference.fs │ ├── RequestBody.fs │ ├── Response.fs │ ├── Schema.fs │ ├── SecurityRequirement.fs │ ├── SecurityScheme.fs │ ├── Server.fs │ ├── ServerVariable.fs │ └── Tag.fs ├── Expressions.fs ├── Factory.fs └── OpenApi.fsproj └── README.md /.github/workflows/on-pull-request.yml: -------------------------------------------------------------------------------- 1 | name: On Push 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout repository 10 | uses: actions/checkout@v2 11 | - name: Setup environment 12 | uses: actions/setup-dotnet@v1 13 | with: 14 | dotnet-version: | 15 | 8.0.x 16 | - name: Restore tools 17 | run: dotnet tool restore 18 | - name: Restore dependencies 19 | run: dotnet restore 20 | - name: Build 21 | run: dotnet build --configuration Release --no-restore 22 | -------------------------------------------------------------------------------- /.github/workflows/on-release-tag.yml: -------------------------------------------------------------------------------- 1 | name: On Release Tag 2 | 3 | on: 4 | release: 5 | types: [published] 6 | tags: 7 | - "v[0-9]+.[0-9]+.[0-9]+" 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build-publish: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v2 17 | - name: Setup environment 18 | uses: actions/setup-dotnet@v1 19 | with: 20 | dotnet-version: 8.0.x 21 | source-url: https://api.nuget.org/v3/index.json 22 | env: 23 | NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | - name: Setup variables 25 | run: | 26 | echo "TAG_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV 27 | echo "PUBLISH_PATH=./publish" >> $GITHUB_ENV 28 | echo "FSPROJ_PATH=./OpenApi/OpenApi.fsproj" >> $GITHUB_ENV 29 | - name: Restore dependencies 30 | run: dotnet restore ${{env.FSPROJ_PATH}} 31 | - name: Build 32 | run: dotnet build --configuration Release --no-restore -p:Version=${{env.TAG_VERSION}} ${{env.FSPROJ_PATH}} 33 | - name: Generate NuGet package 34 | run: dotnet pack --configuration Release --no-build --no-restore -p:PackageVersion=${{env.TAG_VERSION}} ${{env.FSPROJ_PATH}} --output ${{env.PUBLISH_PATH}} 35 | - name: Get NuGet package path 36 | run: | 37 | fileName=$(ls ${{env.PUBLISH_PATH}}/ | head -n 1) 38 | echo "NUGET_PACKAGE_PATH=${{env.PUBLISH_PATH}}/${fileName}" >> $GITHUB_ENV 39 | - name: Update NuGet package to release 40 | uses: softprops/action-gh-release@v1 41 | if: startsWith(github.ref, 'refs/tags/') 42 | with: 43 | files: ${{env.NUGET_PACKAGE_PATH}} 44 | env: 45 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 46 | - name: Publish NuGet package 47 | run: dotnet nuget push ${{env.NUGET_PACKAGE_PATH}} --api-key ${{secrets.NUGET_TOKEN}} --force-english-output 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | coverage.json 32 | 33 | # Visual Studio profiler 34 | *.psess 35 | *.vsp 36 | *.vspx 37 | *.sap 38 | 39 | # JetBrains 40 | .idea 41 | *.dotCover 42 | *.sln.iml 43 | 44 | # NCrunch 45 | _NCrunch_* 46 | .*crunch*.local.xml 47 | nCrunchTemp_* 48 | *.ncrunchsolution* 49 | *.ncrunchproject 50 | 51 | # vscode 52 | .ionide 53 | .vscode 54 | 55 | # NuGet Packages 56 | *.nupkg 57 | **/packages/* 58 | !**/packages/build/ 59 | *.nuget.props 60 | *.nuget.targets 61 | 62 | # Visual Studio cache files 63 | *.[Cc]ache 64 | !*.[Cc]ache/ 65 | 66 | # Paket dependency manager 67 | .paket/paket.exe 68 | paket-files/ 69 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | true 6 | 5 7 | 8 | 9 | 10 | true 11 | $(NoWarn);1591 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Amin KHANSARI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /OpenApi.Sample.Falco/FalcoOpenApi.fs: -------------------------------------------------------------------------------- 1 | module FalcoOpenApi 2 | 3 | open System 4 | open Microsoft.OpenApi.Models 5 | open Falco 6 | open OpenApi 7 | 8 | let toOperation = function 9 | | GET -> OperationType.Get 10 | | HEAD -> OperationType.Head 11 | | POST -> OperationType.Post 12 | | PUT -> OperationType.Put 13 | | PATCH -> OperationType.Patch 14 | | DELETE -> OperationType.Delete 15 | | OPTIONS -> OperationType.Options 16 | | TRACE -> OperationType.Trace 17 | | ANY -> NotSupportedException "HttpVerb" |> raise 18 | 19 | let addOperation (factory: OpenApiFactory) (endpoint: HttpEndpoint) operation = 20 | let httpVerb = endpoint.Handlers |> List.head |> fst |> toOperation 21 | factory.AddOperation httpVerb endpoint.Pattern operation 22 | endpoint 23 | -------------------------------------------------------------------------------- /OpenApi.Sample.Falco/OpenApi.Sample.Falco.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /OpenApi.Sample.Falco/Program.fs: -------------------------------------------------------------------------------- 1 | module Program 2 | 3 | open System.Net 4 | open System.Text.Json 5 | open Microsoft.AspNetCore.Builder 6 | open Falco 7 | open Falco.Routing 8 | open Falco.HostBuilder 9 | open Scalar.AspNetCore 10 | open OpenApi 11 | 12 | type Product = 13 | { Id: int32; Name: string } 14 | 15 | type SpecFactory (jsonOptions) = 16 | 17 | let v1Factory = OpenApiFactory.create jsonOptions "Products API" "v1" 18 | 19 | member _.V1 = v1Factory 20 | 21 | member _.GetProducts endpoint = 22 | apiOperation { 23 | tags [ apiTag { name "Products" } ] 24 | summary "Get the list of products." 25 | responses [ 26 | HttpStatusCode.OK, apiResponse { 27 | description "Success" 28 | jsonContent (v1Factory.MakeJsonContent [ { Id = 0; Name = "name" } ]) 29 | } ] 30 | } 31 | |> FalcoOpenApi.addOperation v1Factory endpoint 32 | 33 | let jsonOptions = JsonSerializerOptions JsonSerializerDefaults.Web 34 | 35 | let getProducts = 36 | [ { Id = 1; Name = "Cat Food" } ] 37 | |> Response.ofJsonOptions jsonOptions 38 | 39 | [] 40 | let main args = 41 | 42 | let spec = SpecFactory (jsonOptions) 43 | 44 | let useOpenApiUI (app: IApplicationBuilder) = 45 | app 46 | .UseRouting() 47 | .UseEndpoints(fun e -> e.MapScalarApiReference() |> ignore) 48 | 49 | webHost args { 50 | endpoints [ 51 | get "/products" getProducts |> spec.GetProducts 52 | get spec.V1.SpecificationUrl (spec.V1.Write Response.ofPlainText) 53 | ] 54 | use_middleware useOpenApiUI 55 | } 56 | 57 | 0 58 | -------------------------------------------------------------------------------- /OpenApi.Sample.Falco/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "OpenApi.Sample.Falco": { 4 | "commandName": "Project", 5 | "dotnetRunMessages": "true", 6 | "launchBrowser": true, 7 | "launchUrl": "scalar/v1", 8 | "applicationUrl": "http://localhost:5002", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /OpenApi.Sample.Giraffe/OpenApi.Sample.Giraffe.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /OpenApi.Sample.Giraffe/Program.fs: -------------------------------------------------------------------------------- 1 | module Program 2 | 3 | open System.Net 4 | open Microsoft.AspNetCore 5 | open Microsoft.AspNetCore.Builder 6 | open Microsoft.AspNetCore.Hosting 7 | open Microsoft.Extensions.DependencyInjection 8 | open Microsoft.OpenApi.Models 9 | open Scalar.AspNetCore 10 | open Giraffe 11 | open OpenApi 12 | 13 | type Product = { Id: int32; Name: string } 14 | 15 | type SpecFactory () = 16 | 17 | let v1Factory = 18 | OpenApiFactory.create Json.FsharpFriendlySerializer.DefaultOptions "Products API" "v1" 19 | 20 | let addOperation (factory: OpenApiFactory) verb path operation = 21 | factory.AddOperation verb path operation 22 | path 23 | 24 | member _.V1 = v1Factory 25 | 26 | member _.GetProducts path = 27 | apiOperation { 28 | tags [ apiTag { name "Products" } ] 29 | summary "Get the list of products." 30 | responses [ 31 | HttpStatusCode.OK, apiResponse { 32 | description "Success" 33 | jsonContent (v1Factory.MakeJsonContent [ { Id = 0; Name = "name" } ]) 34 | } ] 35 | } 36 | |> addOperation v1Factory OperationType.Get path 37 | 38 | let getProducts : HttpHandler = 39 | fun _ ctx -> 40 | [ { Id = 1; Name = "Cat Food" } ] 41 | |> ctx.WriteJsonAsync 42 | 43 | [] 44 | let main args = 45 | 46 | let spec = SpecFactory () 47 | 48 | let webApp = 49 | choose [ 50 | GET >=> choose [ 51 | route (spec.GetProducts "/products") >=> getProducts 52 | route spec.V1.SpecificationUrl >=> (spec.V1.Write text) 53 | ] 54 | ] 55 | 56 | let addGiraffe (services: IServiceCollection) = 57 | services 58 | .AddGiraffe() 59 | |> ignore 60 | 61 | let configureApp (app: IApplicationBuilder) = 62 | app 63 | .UseRouting() 64 | .UseEndpoints(fun e -> e.MapScalarApiReference() |> ignore) 65 | .UseGiraffe(webApp) 66 | |> ignore 67 | 68 | WebHost 69 | .CreateDefaultBuilder(args) 70 | .UseKestrel() 71 | .ConfigureServices(addGiraffe) 72 | .Configure(configureApp) 73 | .Build() 74 | .Run() 75 | 0 76 | -------------------------------------------------------------------------------- /OpenApi.Sample.Giraffe/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "OpenApi.Sample.Giraffe": { 4 | "commandName": "Project", 5 | "dotnetRunMessages": "true", 6 | "launchBrowser": true, 7 | "launchUrl": "scalar/v1", 8 | "applicationUrl": "http://localhost:5003", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /OpenApi.Sample.Routing/OpenApi.Sample.Routing.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /OpenApi.Sample.Routing/Program.fs: -------------------------------------------------------------------------------- 1 | module Program 2 | 3 | open System 4 | open System.Net 5 | open System.Text.Json 6 | open Microsoft.AspNetCore.Builder 7 | open Microsoft.AspNetCore.Http 8 | open Microsoft.OpenApi.Models 9 | open Scalar.AspNetCore 10 | open OpenApi 11 | 12 | type SpecFactory () = 13 | 14 | let jsonOptions = JsonSerializerOptions JsonSerializerDefaults.Web 15 | let v1Factory = OpenApiFactory.create jsonOptions "Heroes Open Data" "v1" 16 | 17 | let superheroesTag = apiTag { name "Superheroes" } 18 | 19 | let superheroSample: Repo.Superhero = 20 | { Name = "name" 21 | AlterEgo = "Alter ego" 22 | Powers = [ { Kind = "kind" } ] } 23 | 24 | member _.V1 = v1Factory 25 | 26 | member _.GetSuperheroes = 27 | apiOperation { 28 | tags [ superheroesTag ] 29 | summary "Get the list of superheroes." 30 | responses [ 31 | HttpStatusCode.OK, apiResponse { 32 | description "Success" 33 | jsonContent (v1Factory.MakeJsonContent [ superheroSample ]) 34 | } 35 | ] 36 | } 37 | 38 | member _.GetSuperhero = 39 | apiOperation { 40 | tags [ superheroesTag ] 41 | summary "Find a superhero." 42 | parameters [ 43 | apiParameter { 44 | name "name" 45 | location ParameterLocation.Path 46 | } 47 | ] 48 | responses [ 49 | HttpStatusCode.OK, apiResponse { 50 | description "Success" 51 | jsonContent (v1Factory.MakeJsonContent superheroSample) 52 | } 53 | HttpStatusCode.NotFound, apiResponse { description "Not found" } 54 | ] 55 | } 56 | 57 | member _.AddSuperheroes = 58 | apiOperation { 59 | tags [ superheroesTag ] 60 | summary "Add a superhero." 61 | requestBody (apiRequestBody { 62 | jsonContent (v1Factory.MakeJsonContent superheroSample) 63 | }) 64 | responses [ 65 | HttpStatusCode.OK, apiResponse { 66 | description "Success" 67 | jsonContent (v1Factory.MakeJsonContent superheroSample) 68 | } 69 | HttpStatusCode.NotFound, apiResponse { description "Not found" } 70 | ] 71 | } 72 | 73 | let getSuperhero name = 74 | match Repo.get name with 75 | | Some hero -> Results.Ok hero 76 | | None -> Results.NotFound () 77 | 78 | let addSuperhero model = 79 | Repo.add model 80 | Results.Created ($"/api/v1/superheroes/{model.Name}", model) 81 | 82 | [] 83 | let main args = 84 | let app = WebApplication.CreateBuilder(args).Build() 85 | 86 | let spec = SpecFactory () 87 | 88 | app.MapScalarApiReference() |> ignore 89 | 90 | app.MapGet("/api/v1/superheroes", Func<_> Repo.getAll, spec.V1, spec.GetSuperheroes) 91 | app.MapGet("/api/v1/superheroes/{name}", Func<_,_> (fun name -> getSuperhero name), spec.V1, spec.GetSuperhero) 92 | app.MapPost("/api/v1/superheroes", Func<_,_> (fun model -> addSuperhero model), spec.V1, spec.AddSuperheroes) 93 | 94 | app.MapGet(spec.V1.SpecificationUrl, RequestDelegate (fun ctx -> spec.V1.Write ctx.Response.WriteAsync)) |> ignore 95 | 96 | app.Run() 97 | 0 98 | -------------------------------------------------------------------------------- /OpenApi.Sample.Routing/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "OpenApi.Sample.Routing": { 4 | "commandName": "Project", 5 | "dotnetRunMessages": "true", 6 | "launchBrowser": true, 7 | "launchUrl": "scalar/v1", 8 | "applicationUrl": "http://localhost:5001", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /OpenApi.Sample.Routing/RoutingOpenApi.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module RoutingOpenApi 3 | 4 | open System 5 | open Microsoft.AspNetCore.Builder 6 | open Microsoft.AspNetCore.Routing 7 | open Microsoft.OpenApi.Models 8 | open OpenApi 9 | 10 | type IEndpointRouteBuilder with 11 | 12 | member this.MapGet(pattern: string, handler: Delegate, factory: OpenApiFactory, operation: OpenApiOperation) = 13 | factory.AddOperation OperationType.Get pattern operation 14 | this.MapGet(pattern, handler) |> ignore 15 | 16 | member this.MapPost(pattern: string, handler: Delegate, factory: OpenApiFactory, operation: OpenApiOperation) = 17 | factory.AddOperation OperationType.Post pattern operation 18 | this.MapPost(pattern, handler) |> ignore 19 | -------------------------------------------------------------------------------- /OpenApi.Sample.Routing/Superheroes.fs: -------------------------------------------------------------------------------- 1 | module Repo 2 | 3 | open System 4 | open System.Collections.Concurrent 5 | 6 | type Power = 7 | { Kind: string } 8 | 9 | type Superhero = 10 | { Name: string 11 | AlterEgo: string 12 | Powers: Power list } 13 | 14 | let private db = ConcurrentBag () 15 | 16 | let private addSamples () = 17 | [ { Name = "Batman"; AlterEgo = "Bruce Wayne"; Powers = [ { Kind = "Genius intellect" }; { Kind = "Expert detective" } ] } 18 | { Name = "Flash"; AlterEgo = "Barry Allen"; Powers = [ { Kind = "Speed force" } ] } ] 19 | |> Seq.iter db.Add 20 | addSamples () 21 | 22 | let add hero = db.Add hero 23 | let getAll () = List.ofSeq db 24 | let get name = Seq.tryFind (fun h -> String.Compare(h.Name, name, true) = 0) db 25 | -------------------------------------------------------------------------------- /OpenApi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.32014.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OpenApi.Sample.Routing", "OpenApi.Sample.Routing\OpenApi.Sample.Routing.fsproj", "{9FDD231D-7225-4CA7-AEDF-8ACAAD4CFBA1}" 7 | EndProject 8 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OpenApi", "OpenApi\OpenApi.fsproj", "{9FF40C47-B88E-4F37-90E4-9FE3BB768901}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFolder", "SolutionFolder", "{9E6D145E-B05C-4722-8453-D6E33E0FD0E0}" 11 | ProjectSection(SolutionItems) = preProject 12 | Directory.Build.props = Directory.Build.props 13 | .github\workflows\on-pull-request.yml = .github\workflows\on-pull-request.yml 14 | .github\workflows\on-release-tag.yml = .github\workflows\on-release-tag.yml 15 | README.md = README.md 16 | EndProjectSection 17 | EndProject 18 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OpenApi.Sample.Giraffe", "OpenApi.Sample.Giraffe\OpenApi.Sample.Giraffe.fsproj", "{912434AA-B6E7-4E02-A3B6-8177AB651C56}" 19 | EndProject 20 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "OpenApi.Sample.Falco", "OpenApi.Sample.Falco\OpenApi.Sample.Falco.fsproj", "{85E0390C-6D68-43A3-92BD-BDCF579791E4}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Release|Any CPU = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {9FDD231D-7225-4CA7-AEDF-8ACAAD4CFBA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {9FDD231D-7225-4CA7-AEDF-8ACAAD4CFBA1}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {9FDD231D-7225-4CA7-AEDF-8ACAAD4CFBA1}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {9FDD231D-7225-4CA7-AEDF-8ACAAD4CFBA1}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {9FF40C47-B88E-4F37-90E4-9FE3BB768901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {9FF40C47-B88E-4F37-90E4-9FE3BB768901}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {9FF40C47-B88E-4F37-90E4-9FE3BB768901}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {9FF40C47-B88E-4F37-90E4-9FE3BB768901}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {912434AA-B6E7-4E02-A3B6-8177AB651C56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {912434AA-B6E7-4E02-A3B6-8177AB651C56}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {912434AA-B6E7-4E02-A3B6-8177AB651C56}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {912434AA-B6E7-4E02-A3B6-8177AB651C56}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {85E0390C-6D68-43A3-92BD-BDCF579791E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {85E0390C-6D68-43A3-92BD-BDCF579791E4}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {85E0390C-6D68-43A3-92BD-BDCF579791E4}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {85E0390C-6D68-43A3-92BD-BDCF579791E4}.Release|Any CPU.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {3CDD5EF6-BAE6-4657-A662-B61EA74D7A11} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /OpenApi/Builders/Callback.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type CallbackBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiCallback () 10 | 11 | /// Describes a set of requests that may be initiated by the API provider and the expected responses. 12 | /// The key value used to identify the path item object is an expression, evaluated at runtime, 13 | /// that identifies a URL to use for the callback operation. 14 | [] 15 | member _.PathItems (state: OpenApiCallback, value: KVs) = 16 | value |> Seq.iter state.PathItems.Add 17 | state 18 | 19 | [] 20 | member _.UnresolvedReference (state: OpenApiCallback, value) = 21 | state.UnresolvedReference <- value 22 | state 23 | 24 | [] 25 | member _.Reference (state: OpenApiCallback, value) = 26 | state.Reference <- value 27 | state 28 | 29 | [] 30 | member _.Extensions (state: OpenApiCallback, value: KVs<_, Interfaces.IOpenApiExtension>) = 31 | value |> Seq.iter state.Extensions.Add 32 | state 33 | -------------------------------------------------------------------------------- /OpenApi/Builders/Components.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ComponentsBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiComponents () 10 | 11 | [] 12 | member _.Schemas (state: OpenApiComponents, value: KVs<_, OpenApiSchema>) = 13 | value |> Seq.iter state.Schemas.Add 14 | state 15 | 16 | [] 17 | member _.Responses (state: OpenApiComponents, value: KVs<_, OpenApiResponse>) = 18 | value |> Seq.iter state.Responses.Add 19 | state 20 | 21 | [] 22 | member _.Parameters (state: OpenApiComponents, value: KVs<_, OpenApiParameter>) = 23 | value |> Seq.iter state.Parameters.Add 24 | state 25 | 26 | [] 27 | member _.Examples (state: OpenApiComponents, value: KVs<_, OpenApiExample>) = 28 | value |> Seq.iter state.Examples.Add 29 | state 30 | 31 | [] 32 | member _.RequestBodies (state: OpenApiComponents, value: KVs<_, OpenApiRequestBody>) = 33 | value |> Seq.iter state.RequestBodies.Add 34 | state 35 | 36 | [] 37 | member _.Headers (state: OpenApiComponents, value: KVs<_, OpenApiHeader>) = 38 | value |> Seq.iter state.Headers.Add 39 | state 40 | 41 | [] 42 | member _.SecuritySchemes (state: OpenApiComponents, value: KVs<_, OpenApiSecurityScheme>) = 43 | value |> Seq.iter state.SecuritySchemes.Add 44 | state 45 | 46 | [] 47 | member _.Links (state: OpenApiComponents, value: KVs<_, OpenApiLink>) = 48 | value |> Seq.iter state.Links.Add 49 | state 50 | 51 | [] 52 | member _.Callbacks (state: OpenApiComponents, value: KVs<_, OpenApiCallback>) = 53 | value |> Seq.iter state.Callbacks.Add 54 | state 55 | 56 | [] 57 | member _.Extensions (state: OpenApiComponents, value: KVs<_, Interfaces.IOpenApiExtension>) = 58 | value |> Seq.iter state.Extensions.Add 59 | state 60 | -------------------------------------------------------------------------------- /OpenApi/Builders/Contact.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ContactBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiContact () 10 | 11 | /// The identifying name of the contact person/organization. 12 | [] 13 | member _.Name (state: OpenApiContact, value) = 14 | state.Name <- value 15 | state 16 | 17 | /// The URL pointing to the contact information. 18 | [] 19 | member _.Url (state: OpenApiContact, value) = 20 | state.Url <- value 21 | state 22 | 23 | /// The email address of the contact person/organization. 24 | [] 25 | member _.Email (state: OpenApiContact, value) = 26 | state.Email <- value 27 | state 28 | 29 | [] 30 | member _.Extensions (state: OpenApiContact, value: KVs<_, Interfaces.IOpenApiExtension>) = 31 | value |> Seq.iter state.Extensions.Add 32 | state 33 | -------------------------------------------------------------------------------- /OpenApi/Builders/Discriminator.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi.Models 4 | 5 | type DiscriminatorBuilder () = 6 | 7 | member _.Yield _ = 8 | OpenApiDiscriminator () 9 | 10 | /// REQUIRED. The name of the property in the payload that will hold the discriminator value. 11 | [] 12 | member _.PropertyName (state: OpenApiDiscriminator, value) = 13 | state.PropertyName <- value 14 | state 15 | 16 | /// An object to hold mappings between payload values and schema names or references. 17 | [] 18 | member _.Mapping (state: OpenApiDiscriminator, value: KVs<_, string>) = 19 | value |> Seq.iter state.Mapping.Add 20 | state 21 | -------------------------------------------------------------------------------- /OpenApi/Builders/Document.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type DocumentBuilder () = 7 | 8 | member _.Yield _ = 9 | let doc = OpenApiDocument () 10 | doc.Paths <- OpenApiPaths () 11 | doc 12 | 13 | [] 14 | member _.Info (state: OpenApiDocument, value) = 15 | state.Info <- value 16 | state 17 | 18 | [] 19 | member _.Servers (state: OpenApiDocument, value) = 20 | Seq.iter state.Servers.Add value 21 | state 22 | 23 | [] 24 | member _.Paths (state: OpenApiDocument, value) = 25 | Seq.iter state.Paths.Add value 26 | state 27 | 28 | [] 29 | member _.Components (state: OpenApiDocument, value) = 30 | state.Components <- value 31 | state 32 | 33 | [] 34 | member _.SecurityRequirements (state: OpenApiDocument, value) = 35 | Seq.iter state.SecurityRequirements.Add value 36 | state 37 | 38 | [] 39 | member _.Tags (state: OpenApiDocument, value) = 40 | Seq.iter state.Tags.Add value 41 | state 42 | 43 | [] 44 | member _.ExternalDocs (state: OpenApiDocument, value) = 45 | state.ExternalDocs <- value 46 | state 47 | 48 | [] 49 | member _.Extensions (state: OpenApiDocument, value: KVs<_, Interfaces.IOpenApiExtension>) = 50 | value |> Seq.iter state.Extensions.Add 51 | state 52 | -------------------------------------------------------------------------------- /OpenApi/Builders/Encoding.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open System 4 | open Microsoft.OpenApi 5 | open Microsoft.OpenApi.Models 6 | 7 | type EncodingBuilder () = 8 | 9 | member _.Yield _ = 10 | OpenApiEncoding () 11 | 12 | /// The Content-Type for encoding a specific property. Default value depends on the property type: 13 | /// for string with format being binary – application/octet-stream; 14 | /// for other primitive types – text/plain; 15 | /// for object - application/json; 16 | /// for array – the default is defined based on the inner type. 17 | /// The value can be a specific media type (e.g. application/json), 18 | /// a wildcard media type (e.g. image/*), or a comma-separated list of the two types. 19 | [] 20 | member _.ContentType (state: OpenApiEncoding, value) = 21 | state.ContentType <- value 22 | state 23 | 24 | /// A map allowing additional information to be provided as headers, for example Content-Disposition. 25 | /// Content-Type is described separately and SHALL be ignored in this section. 26 | /// This property SHALL be ignored if the request body media type is not a multipart. 27 | [] 28 | member _.Headers (state: OpenApiEncoding, value: KVs<_, OpenApiHeader>) = 29 | value |> Seq.iter state.Headers.Add 30 | state 31 | 32 | /// Describes how a specific property value will be serialized depending on its type. 33 | /// See Parameter Object for details on the style property. 34 | /// The behavior follows the same values as query parameters, including default values. 35 | /// This property SHALL be ignored if the request body media type is not application/x-www-form-urlencoded. 36 | [] 37 | member _.Style (state: OpenApiEncoding, value) = 38 | state.Style <- Nullable value 39 | state 40 | 41 | /// When this is true, property values of type array or object generate separate parameters 42 | /// for each value of the array, or key-value-pair of the map. 43 | /// For other types of properties this property has no effect. 44 | /// When style is form, the default value is true. For all other styles, the default value is false. 45 | /// This property SHALL be ignored if the request body media type is not application/x-www-form-urlencoded. 46 | [] 47 | member _.Explode (state: OpenApiEncoding, value) = 48 | state.Explode <- Nullable value 49 | state 50 | 51 | /// Determines whether the parameter value SHOULD allow reserved characters, as defined by 52 | /// RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. 53 | /// The default value is false. This property SHALL be ignored if the request body media type is not application/x-www-form-urlencoded. 54 | [] 55 | member _.AllowReserved (state: OpenApiEncoding, value) = 56 | state.AllowReserved <- Nullable value 57 | state 58 | 59 | [] 60 | member _.Extensions (state: OpenApiEncoding, value: KVs<_, Interfaces.IOpenApiExtension>) = 61 | value |> Seq.iter state.Extensions.Add 62 | state 63 | -------------------------------------------------------------------------------- /OpenApi/Builders/Example.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ExampleBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiExample () 10 | 11 | /// Short description for the example. 12 | [] 13 | member _.Summary (state: OpenApiExample, value) = 14 | state.Summary <- value 15 | state 16 | 17 | /// Long description for the example. CommonMark syntax. 18 | [] 19 | member _.Description (state: OpenApiExample, value) = 20 | state.Description <- value 21 | state 22 | 23 | /// Embedded literal example. The value field and externalValue field are mutually exclusive. 24 | /// To represent examples of media types that cannot naturally represented in JSON or YAML, 25 | /// use a string value to contain the example, escaping where necessary. 26 | [] 27 | member _.Value (state: OpenApiExample, value) = 28 | state.Value <- value 29 | state 30 | 31 | /// A URL that points to the literal example. This provides the capability to reference examples 32 | /// that cannot easily be included in JSON or YAML documents. 33 | /// The value field and externalValue field are mutually exclusive. 34 | [] 35 | member _.ExternalValue (state: OpenApiExample, value) = 36 | state.ExternalValue <- value 37 | state 38 | 39 | [] 40 | member _.Extensions (state: OpenApiExample, value: KVs<_, Interfaces.IOpenApiExtension>) = 41 | value |> Seq.iter state.Extensions.Add 42 | state 43 | 44 | [] 45 | member _.Reference (state: OpenApiExample, value) = 46 | state.Reference <- value 47 | state 48 | 49 | [] 50 | member _.UnresolvedReference (state: OpenApiExample, value) = 51 | state.UnresolvedReference <- value 52 | state 53 | -------------------------------------------------------------------------------- /OpenApi/Builders/ExternalDocs.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ExternalDocsBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiExternalDocs () 10 | 11 | /// REQUIRED. The URL for the target documentation. Value MUST be in the format of a URL. 12 | [] 13 | member _.Url (state: OpenApiExternalDocs, value) = 14 | state.Url <- value 15 | state 16 | 17 | /// A short description of the target documentation. CommonMark syntax. 18 | [] 19 | member _.Description (state: OpenApiExternalDocs, value) = 20 | state.Description <- value 21 | state 22 | 23 | [] 24 | member _.Extensions (state: OpenApiExternalDocs, value: KVs<_, Interfaces.IOpenApiExtension>) = 25 | value |> Seq.iter state.Extensions.Add 26 | state 27 | -------------------------------------------------------------------------------- /OpenApi/Builders/Header.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open System 4 | open Microsoft.OpenApi 5 | open Microsoft.OpenApi.Models 6 | 7 | type HeaderBuilder () = 8 | 9 | member _.Yield _ = 10 | OpenApiHeader () 11 | 12 | [] 13 | member _.Description (state: OpenApiHeader, value) = 14 | state.Description <- value 15 | state 16 | 17 | [] 18 | member _.Required (state: OpenApiHeader, value) = 19 | state.Required <- value 20 | state 21 | 22 | [] 23 | member _.Deprecated (state: OpenApiHeader, value) = 24 | state.Deprecated <- value 25 | state 26 | 27 | [] 28 | member _.AllowEmptyValue (state: OpenApiHeader, value) = 29 | state.AllowEmptyValue <- value 30 | state 31 | 32 | [] 33 | member _.Style (state: OpenApiHeader, value) = 34 | state.Style <- Nullable value 35 | state 36 | 37 | [] 38 | member _.Explode (state: OpenApiHeader, value) = 39 | state.Explode <- value 40 | state 41 | 42 | [] 43 | member _.AllowReserved (state: OpenApiHeader, value) = 44 | state.AllowReserved <- value 45 | state 46 | 47 | [] 48 | member _.Schema (state: OpenApiHeader, value) = 49 | state.Schema <- value 50 | state 51 | 52 | [] 53 | member _.Example (state: OpenApiHeader, value) = 54 | state.Example <- value 55 | state 56 | 57 | [] 58 | member _.Examples (state: OpenApiHeader, value: KVs<_, OpenApiExample>) = 59 | value |> Seq.iter state.Examples.Add 60 | state 61 | 62 | [] 63 | member _.Content (state: OpenApiHeader, value: KVs<_, OpenApiMediaType>) = 64 | value |> Seq.iter state.Content.Add 65 | state 66 | 67 | [] 68 | member _.Extensions (state: OpenApiHeader, value: KVs<_, Interfaces.IOpenApiExtension>) = 69 | value |> Seq.iter state.Extensions.Add 70 | state 71 | 72 | [] 73 | member _.UnresolvedReference (state: OpenApiHeader, value) = 74 | state.UnresolvedReference <- value 75 | state 76 | 77 | [] 78 | member _.Reference (state: OpenApiHeader, value) = 79 | state.Reference <- value 80 | state 81 | -------------------------------------------------------------------------------- /OpenApi/Builders/Helpers.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | type private KVs<'TKey, 'TValue> = ('TKey * 'TValue) seq 4 | 5 | module internal MediaTypes = 6 | 7 | let [] Json = "application/json" 8 | -------------------------------------------------------------------------------- /OpenApi/Builders/Info.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type InfoBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiInfo () 10 | 11 | /// REQUIRED. The title of the API. 12 | [] 13 | member _.Title (state: OpenApiInfo, value) = 14 | state.Title <- value 15 | state 16 | 17 | /// REQUIRED. The version of the OpenAPI document. 18 | [] 19 | member _.Version (state: OpenApiInfo, value) = 20 | state.Version <- value 21 | state 22 | 23 | /// A short description of the API. CommonMark syntax. 24 | [] 25 | member _.Description (state: OpenApiInfo, value) = 26 | state.Description <- value 27 | state 28 | 29 | /// A URL to the Terms of Service for the API. MUST be in the format of a URL. 30 | [] 31 | member _.TermsOfService (state: OpenApiInfo, value) = 32 | state.TermsOfService <- value 33 | state 34 | 35 | /// The contact information for the exposed API. 36 | [] 37 | member _.Contact (state: OpenApiInfo, value) = 38 | state.Contact <- value 39 | state 40 | 41 | /// The license information for the exposed API. 42 | [] 43 | member _.License (state: OpenApiInfo, value) = 44 | state.License <- value 45 | state 46 | 47 | [] 48 | member _.Extensions (state: OpenApiInfo, value: KVs<_, Interfaces.IOpenApiExtension>) = 49 | value |> Seq.iter state.Extensions.Add 50 | state 51 | -------------------------------------------------------------------------------- /OpenApi/Builders/License.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type LicenseBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiLicense () 10 | 11 | /// REQUIRED. The license name used for the API. 12 | [] 13 | member _.Name (state: OpenApiLicense, value) = 14 | state.Name <- value 15 | state 16 | 17 | /// A URL to the license used for the API. MUST be in the format of a URL. 18 | [] 19 | member _.Url (state: OpenApiLicense, value) = 20 | state.Url <- value 21 | state 22 | 23 | [] 24 | member _.Extensions (state: OpenApiLicense, value: KVs<_, Interfaces.IOpenApiExtension>) = 25 | value |> Seq.iter state.Extensions.Add 26 | state 27 | -------------------------------------------------------------------------------- /OpenApi/Builders/Link.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type LinkBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiLink () 10 | 11 | /// A relative or absolute URI reference to an OAS operation. 12 | /// This field is mutually exclusive of the operationId field, and MUST point to an Operation Object. 13 | /// Relative operationRef values MAY be used to locate an existing Operation Object in the OpenAPI definition. 14 | [] 15 | member _.OperationRef (state: OpenApiLink, value) = 16 | state.OperationRef <- value 17 | state 18 | 19 | /// The name of an existing, resolvable OAS operation, as defined with a unique operationId. 20 | /// This field is mutually exclusive of the operationRef field. 21 | [] 22 | member _.OperationId (state: OpenApiLink, value) = 23 | state.OperationId <- value 24 | state 25 | 26 | /// A map representing parameters to pass to an operation as specified with operationId or identified via operationRef. 27 | /// The key is the parameter name to be used, whereas the value can be a constant or an expression 28 | /// to be evaluated and passed to the linked operation. 29 | /// The parameter name can be qualified using the parameter location [{in}.]{name} for operations 30 | /// that use the same parameter name in different locations (e.g. path.id). 31 | [] 32 | member _.Parameters (state: OpenApiLink, value: KVs<_, RuntimeExpressionAnyWrapper>) = 33 | value |> Seq.iter state.Parameters.Add 34 | state 35 | 36 | /// A literal value or {expression} to use as a request body when calling the target operation. 37 | [] 38 | member _.RequestBody (state: OpenApiLink, value) = 39 | state.RequestBody <- value 40 | state 41 | 42 | /// A description of the link. CommonMark syntax MAY be used for rich text representation. 43 | [] 44 | member _.Description (state: OpenApiLink, value) = 45 | state.Description <- value 46 | state 47 | 48 | /// A server object to be used by the target operation. 49 | [] 50 | member _.Server (state: OpenApiLink, value) = 51 | state.Server <- value 52 | state 53 | 54 | [] 55 | member _.Extensions (state: OpenApiLink, value: KVs<_, Interfaces.IOpenApiExtension>) = 56 | value |> Seq.iter state.Extensions.Add 57 | state 58 | 59 | [] 60 | member _.UnresolvedReference (state: OpenApiLink, value) = 61 | state.UnresolvedReference <- value 62 | state 63 | 64 | [] 65 | member _.Reference (state: OpenApiLink, value) = 66 | state.Reference <- value 67 | state 68 | -------------------------------------------------------------------------------- /OpenApi/Builders/MediaType.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type MediaTypeBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiMediaType () 10 | 11 | /// The schema defining the content of the request, response, or parameter. 12 | [] 13 | member _.Schema (state: OpenApiMediaType, value) = 14 | state.Schema <- value 15 | state 16 | 17 | /// Example of the media type. The example object SHOULD be in the correct format as specified by the media type. 18 | /// The example field is mutually exclusive of the examples field. 19 | /// Furthermore, if referencing a schema which contains an example, 20 | /// the example value SHALL override the example provided by the schema. 21 | [] 22 | member _.Example (state: OpenApiMediaType, value) = 23 | state.Example <- value 24 | state 25 | 26 | /// Examples of the media type. 27 | [] 28 | member _.Examples (state: OpenApiMediaType, value: KVs<_, OpenApiExample>) = 29 | value |> Seq.iter state.Examples.Add 30 | state 31 | 32 | /// A map between a property name and its encoding information. 33 | /// The key, being the property name, MUST exist in the schema as a property. 34 | /// The encoding object SHALL only apply to requestBody objects when the media type is multipart or application/x-www-form-urlencoded. 35 | [] 36 | member _.Encoding (state: OpenApiMediaType, value: KVs<_, OpenApiEncoding>) = 37 | value |> Seq.iter state.Encoding.Add 38 | state 39 | 40 | [] 41 | member _.Extensions (state: OpenApiMediaType, value: KVs<_, Interfaces.IOpenApiExtension>) = 42 | value |> Seq.iter state.Extensions.Add 43 | state 44 | -------------------------------------------------------------------------------- /OpenApi/Builders/OAuthFlow.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type OAuthFlowBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiOAuthFlow () 10 | 11 | /// REQUIRED. The authorization URL to be used for this flow. This MUST be in the form of a URL. 12 | [] 13 | member _.AuthorizationUrl (state: OpenApiOAuthFlow, value) = 14 | state.AuthorizationUrl <- value 15 | state 16 | 17 | /// REQUIRED. The token URL to be used for this flow. This MUST be in the form of a URL. 18 | [] 19 | member _.TokenUrl (state: OpenApiOAuthFlow, value) = 20 | state.TokenUrl <- value 21 | state 22 | 23 | /// The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. 24 | [] 25 | member _.RefreshUrl (state: OpenApiOAuthFlow, value) = 26 | state.RefreshUrl <- value 27 | state 28 | 29 | /// The available scopes for the OAuth2 security scheme. 30 | /// A map between the scope name and a short description for it. The map MAY be empty. 31 | [] 32 | member _.Scopes (state: OpenApiOAuthFlow, value: KVs) = 33 | value |> Seq.iter state.Scopes.Add 34 | state 35 | 36 | [] 37 | member _.Extensions (state: OpenApiOAuthFlow, value: KVs<_, Interfaces.IOpenApiExtension>) = 38 | value |> Seq.iter state.Extensions.Add 39 | state 40 | -------------------------------------------------------------------------------- /OpenApi/Builders/OAuthFlows.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type OAuthFlowsBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiOAuthFlows () 10 | 11 | /// Configuration for the OAuth Implicit flow. 12 | [] 13 | member _.Implicit (state: OpenApiOAuthFlows, value) = 14 | state.Implicit <- value 15 | state 16 | 17 | /// Configuration for the OAuth Resource Owner Password flow. 18 | [] 19 | member _.Password (state: OpenApiOAuthFlows, value) = 20 | state.Password <- value 21 | state 22 | 23 | /// Configuration for the OAuth Client Credentials flow. 24 | [] 25 | member _.ClientCredentials (state: OpenApiOAuthFlows, value) = 26 | state.ClientCredentials <- value 27 | state 28 | 29 | /// Configuration for the OAuth Authorization Code flow. 30 | [] 31 | member _.AuthorizationCode (state: OpenApiOAuthFlows, value) = 32 | state.AuthorizationCode <- value 33 | state 34 | 35 | [] 36 | member _.Extensions (state: OpenApiOAuthFlows, value: KVs<_, Interfaces.IOpenApiExtension>) = 37 | value |> Seq.iter state.Extensions.Add 38 | state 39 | -------------------------------------------------------------------------------- /OpenApi/Builders/Operation.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type OperationBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiOperation () 10 | 11 | /// REQUIRED. The list of possible responses as they are returned from executing this operation. 12 | [] 13 | member _.Responses (state: OpenApiOperation, value: KVs<'HttpStatusCode, OpenApiResponse>) = 14 | value |> Seq.iter (fun (k, v) -> state.Responses.Add (string k, v)) 15 | state 16 | 17 | /// A list of tags for API documentation control. 18 | /// Tags can be used for logical grouping of operations by resources or any other qualifier. 19 | [] 20 | member _.Tags (state: OpenApiOperation, value: OpenApiTag seq) = 21 | Seq.iter state.Tags.Add value 22 | state 23 | 24 | /// A short summary of what the operation does. 25 | [] 26 | member _.Summary (state: OpenApiOperation, value) = 27 | state.Summary <- value 28 | state 29 | 30 | /// A verbose explanation of the operation behavior. CommonMark syntax. 31 | [] 32 | member _.Description (state: OpenApiOperation, value) = 33 | state.Description <- value 34 | state 35 | 36 | /// Additional external documentation for this operation. 37 | [] 38 | member _.ExternalDocs (state: OpenApiOperation, value) = 39 | state.ExternalDocs <- value 40 | state 41 | 42 | /// Unique string used to identify the operation. 43 | /// The id MUST be unique among all operations described in the API. 44 | /// The operationId value is case-sensitive. 45 | /// Tools and libraries MAY use the operationId to uniquely identify an operation, 46 | /// therefore, it is RECOMMENDED to follow common programming naming conventions. 47 | [] 48 | member _.OperationId (state: OpenApiOperation, value) = 49 | state.OperationId <- value 50 | state 51 | 52 | /// A list of parameters that are applicable for this operation. 53 | /// If a parameter is already defined at the Path Item, 54 | /// the new definition will override it but can never remove it. 55 | /// The list MUST NOT include duplicated parameters. 56 | /// A unique parameter is defined by a combination of a name and location. 57 | /// The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters. 58 | [] 59 | member _.Parameters (state: OpenApiOperation, value: OpenApiParameter seq) = 60 | Seq.iter state.Parameters.Add value 61 | state 62 | 63 | /// The request body applicable for this operation. 64 | /// The requestBody is only supported in HTTP methods where the HTTP 1.1 specification RFC7231 has explicitly defined semantics for request bodies. 65 | /// In other cases where the HTTP spec is vague, requestBody SHALL be ignored by consumers. 66 | [] 67 | member _.RequestBody (state: OpenApiOperation, value) = 68 | state.RequestBody <- value 69 | state 70 | 71 | /// A map of possible out-of band callbacks related to the parent operation. 72 | /// The key is a unique identifier for the Callback Object. 73 | /// Each value in the map is a Callback Object that describes a request 74 | /// that may be initiated by the API provider and the expected responses. 75 | [] 76 | member _.CallBacks (state: OpenApiOperation, value: KVs<_, OpenApiCallback>) = 77 | value |> Seq.iter state.Callbacks.Add 78 | state 79 | 80 | /// Declares this operation to be deprecated. Consumers SHOULD refrain from usage of the declared operation. 81 | /// Default value is false. 82 | [] 83 | member _.Deprecated (state: OpenApiOperation, value) = 84 | state.Deprecated <- value 85 | state 86 | 87 | /// A declaration of which security mechanisms can be used for this operation. 88 | /// The list of values includes alternative security requirement objects that can be used. 89 | /// Only one of the security requirement objects need to be satisfied to authorize a request. 90 | /// To make security optional, an empty security requirement ({}) can be included in the array. 91 | /// This definition overrides any declared top-level security. 92 | /// To remove a top-level security declaration, an empty array can be used. 93 | [] 94 | member _.Security (state: OpenApiOperation, value: OpenApiSecurityRequirement seq) = 95 | value |> Seq.iter state.Security.Add 96 | state 97 | 98 | /// An alternative server array to service this operation. 99 | /// If an alternative server object is specified at the Path Item Object or Root level, 100 | /// it will be overridden by this value. 101 | [] 102 | member _.Servers (state: OpenApiOperation, value: OpenApiServer seq) = 103 | value |> Seq.iter state.Servers.Add 104 | state 105 | 106 | [] 107 | member _.Extensions (state: OpenApiOperation, value: KVs<_, Interfaces.IOpenApiExtension>) = 108 | value |> Seq.iter state.Extensions.Add 109 | state 110 | -------------------------------------------------------------------------------- /OpenApi/Builders/Parameter.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open System 4 | open Microsoft.OpenApi 5 | open Microsoft.OpenApi.Models 6 | 7 | type ParameterBuilder () = 8 | 9 | member _.Yield _ = 10 | OpenApiParameter () 11 | 12 | /// REQUIRED. The name of the parameter. Parameter names are case sensitive. 13 | /// If in is "path", the name field MUST correspond to a template expression occurring within the path field in the Paths Object. See Path Templating for further information. 14 | /// If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored. 15 | /// For all other cases, the name corresponds to the parameter name used by the in property. 16 | [] 17 | member _.Name (state: OpenApiParameter, value) = 18 | state.Name <- value 19 | state 20 | 21 | /// REQUIRED. The location of the parameter. Possible values are "query", "header", "path" or "cookie". 22 | [] 23 | member _.In (state: OpenApiParameter, value) = 24 | state.In <- Nullable value 25 | state 26 | 27 | /// A brief description of the parameter. This could contain examples of use. CommonMark syntax. 28 | [] 29 | member _.Description (state: OpenApiParameter, value) = 30 | state.Description <- value 31 | state 32 | 33 | /// Determines whether this parameter is mandatory. 34 | /// If the parameter location is "path", this property is REQUIRED and its value MUST be true. 35 | /// Otherwise, the property MAY be included and its default value is false. 36 | [] 37 | member _.Required (state: OpenApiParameter, value) = 38 | state.Required <- value 39 | state 40 | 41 | /// Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. 42 | /// Default value is false. 43 | [] 44 | member _.Deprecated (state: OpenApiParameter, value) = 45 | state.Deprecated <- value 46 | state 47 | 48 | /// Sets the ability to pass empty-valued parameters. 49 | /// This is valid only for query parameters and allows sending a parameter with an empty value. 50 | /// Default value is false. 51 | /// If style is used, and if behavior is n/a (cannot be serialized), the value of allowEmptyValue SHALL be ignored. 52 | /// Use of this property is NOT RECOMMENDED, as it is likely to be removed in a later revision. 53 | [] 54 | member _.AllowEmptyValue (state: OpenApiParameter, value) = 55 | state.AllowEmptyValue <- value 56 | state 57 | 58 | /// Describes how the parameter value will be serialized depending on the type of the parameter value. 59 | /// Default values (based on value of in): for query - form; for path - simple; for header - simple; for cookie - form. 60 | [] 61 | member _.Style (state: OpenApiParameter, value) = 62 | state.Style <- Nullable value 63 | state 64 | 65 | /// When this is true, parameter values of type array or object generate separate parameters 66 | /// for each value of the array or key-value pair of the map. 67 | /// For other types of parameters this property has no effect. When style is form, the default value is true. 68 | /// For all other styles, the default value is false. 69 | [] 70 | member _.Explode (state: OpenApiParameter, value) = 71 | state.Explode <- value 72 | state 73 | 74 | /// Determines whether the parameter value SHOULD allow reserved characters, 75 | /// as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. 76 | /// This property only applies to parameters with an in value of query. The default value is false. 77 | [] 78 | member _.AllowReserved (state: OpenApiParameter, value) = 79 | state.AllowReserved <- value 80 | state 81 | 82 | /// The schema defining the type used for the parameter. 83 | [] 84 | member _.Schema (state: OpenApiParameter, value) = 85 | state.Schema <- value 86 | state 87 | 88 | /// Examples of the parameter's potential value. 89 | [] 90 | member _.Examples (state: OpenApiParameter, value: KVs<_, OpenApiExample>) = 91 | value |> Seq.iter state.Examples.Add 92 | state 93 | 94 | /// Example of the parameter's potential value. 95 | /// The example SHOULD match the specified schema and encoding properties if present. 96 | /// The example field is mutually exclusive of the examples field. 97 | /// Furthermore, if referencing a schema that contains an example, 98 | /// the example value SHALL override the example provided by the schema. 99 | /// To represent examples of media types that cannot naturally be represented in JSON or YAML, 100 | /// a string value can contain the example with escaping where necessary. 101 | [] 102 | member _.Example (state: OpenApiParameter, value) = 103 | state.Example <- value 104 | state 105 | 106 | /// A map containing the representations for the parameter. 107 | /// The key is the media type and the value describes it. 108 | /// The map MUST only contain one entry. 109 | [] 110 | member _.Content (state: OpenApiParameter, value: KVs) = 111 | value |> Seq.iter state.Content.Add 112 | state 113 | 114 | [] 115 | member _.Extensions (state: OpenApiParameter, value: KVs<_, Interfaces.IOpenApiExtension>) = 116 | value |> Seq.iter state.Extensions.Add 117 | state 118 | 119 | [] 120 | member _.UnresolvedReference (state: OpenApiParameter, value) = 121 | state.UnresolvedReference <- value 122 | state 123 | 124 | [] 125 | member _.Reference (state: OpenApiParameter, value) = 126 | state.Reference <- value 127 | state 128 | -------------------------------------------------------------------------------- /OpenApi/Builders/PathItem.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type PathItemBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiPathItem () 10 | 11 | /// An optional, string summary, intended to apply to all operations in this path. 12 | [] 13 | member _.Summary (state: OpenApiPathItem, value) = 14 | state.Summary <- value 15 | state 16 | 17 | /// An optional, string description, intended to apply to all operations in this path. CommonMark syntax. 18 | [] 19 | member _.Description (state: OpenApiPathItem, value) = 20 | state.Description <- value 21 | state 22 | 23 | /// A definition of a HTTP operation on this path. 24 | [] 25 | member _.Operations (state: OpenApiPathItem, value: KVs<_, OpenApiOperation>) = 26 | value |> Seq.iter state.Operations.Add 27 | state 28 | 29 | /// An alternative server array to service all operations in this path. 30 | [] 31 | member _.Servers (state: OpenApiPathItem, value: OpenApiServer seq) = 32 | value |> Seq.iter state.Servers.Add 33 | state 34 | 35 | /// A list of parameters that are applicable for all the operations described under this path. 36 | /// These parameters can be overridden at the operation level, but cannot be removed there. 37 | /// The list MUST NOT include duplicated parameters. 38 | /// A unique parameter is defined by a combination of a name and location. 39 | /// The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters. 40 | [] 41 | member _.Parameters (state: OpenApiPathItem, value: OpenApiParameter seq) = 42 | value |> Seq.iter state.Parameters.Add 43 | state 44 | 45 | [] 46 | member _.Extensions (state: OpenApiPathItem, value: KVs<_, Interfaces.IOpenApiExtension>) = 47 | value |> Seq.iter state.Extensions.Add 48 | state 49 | 50 | type PathsBuilder () = 51 | 52 | member _.Yield _ = 53 | OpenApiPaths () 54 | 55 | [] 56 | member _.PathItems (state: OpenApiPaths, value: KVs<_, OpenApiPathItem>) = 57 | value |> Seq.iter state.Add 58 | state 59 | -------------------------------------------------------------------------------- /OpenApi/Builders/Reference.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi.Models 4 | 5 | type ReferenceBuilder () = 6 | 7 | member _.Yield _ = 8 | OpenApiReference () 9 | 10 | [] 11 | member _.ExternalResource (state: OpenApiReference, value) = 12 | state.ExternalResource <- value 13 | state 14 | 15 | [] 16 | member _.Type (state: OpenApiReference, value) = 17 | state.Type <- value 18 | state 19 | 20 | [] 21 | member _.Id (state: OpenApiReference, value) = 22 | state.Id <- value 23 | state 24 | -------------------------------------------------------------------------------- /OpenApi/Builders/RequestBody.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Any 5 | open Microsoft.OpenApi.Models 6 | 7 | type RequestBodyBuilder () = 8 | 9 | member _.Yield _ = 10 | OpenApiRequestBody () 11 | 12 | /// REQUIRED. The content of the request body. 13 | /// The key is a media type or media type range and the value describes it. 14 | /// For requests that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* 15 | [] 16 | member _.Content (state: OpenApiRequestBody, value: KVs<_, OpenApiMediaType>) = 17 | value |> Seq.iter state.Content.Add 18 | state 19 | 20 | /// JSON content. 21 | [] 22 | member _.JsonContent (state: OpenApiRequestBody, example: OpenApiString) = 23 | let mediaType = OpenApiMediaType (Example = example, Schema = OpenApiSchema ()) 24 | state.Content.Add (MediaTypes.Json, mediaType) 25 | state 26 | 27 | /// A brief description of the request body. This could contain examples of use. CommonMark syntax. 28 | [] 29 | member _.Description (state: OpenApiRequestBody, value) = 30 | state.Description <- value 31 | state 32 | 33 | /// Determines if the request body is required in the request. Defaults to false. 34 | [] 35 | member _.Required (state: OpenApiRequestBody, value) = 36 | state.Required <- value 37 | state 38 | 39 | [] 40 | member _.UnresolvedReference (state: OpenApiRequestBody, value) = 41 | state.UnresolvedReference <- value 42 | state 43 | 44 | [] 45 | member _.Reference (state: OpenApiRequestBody, value) = 46 | state.Reference <- value 47 | state 48 | 49 | [] 50 | member _.Extensions (state: OpenApiRequestBody, value: KVs<_, Interfaces.IOpenApiExtension>) = 51 | value |> Seq.iter state.Extensions.Add 52 | state 53 | -------------------------------------------------------------------------------- /OpenApi/Builders/Response.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Any 5 | open Microsoft.OpenApi.Models 6 | 7 | type ResponseBuilder () = 8 | 9 | member _.Yield _ = 10 | OpenApiResponse () 11 | 12 | /// REQUIRED. A short description of the response. CommonMark syntax. 13 | [] 14 | member _.Description (state: OpenApiResponse, value) = 15 | state.Description <- value 16 | state 17 | 18 | /// Maps a header name to its definition. RFC7230 states header names are case insensitive. 19 | /// If a response header is defined with the name "Content-Type", it SHALL be ignored. 20 | [] 21 | member _.Headers (state: OpenApiResponse, value: KVs<_, OpenApiHeader>) = 22 | value |> Seq.iter state.Headers.Add 23 | state 24 | 25 | /// A map containing descriptions of potential response payloads. 26 | /// The key is a media type or media type range and the value describes it. 27 | /// For responses that match multiple keys, only the most specific key is applicable. e.g. text/plain overrides text/* 28 | [] 29 | member _.Content (state: OpenApiResponse, value: KVs<_, OpenApiMediaType>) = 30 | value |> Seq.iter state.Content.Add 31 | state 32 | 33 | /// JSON content. 34 | [] 35 | member _.JsonContent (state: OpenApiResponse, example: OpenApiString) = 36 | let mediaType = OpenApiMediaType (Example = example) 37 | state.Content.Add (MediaTypes.Json, mediaType) 38 | state 39 | 40 | /// A map of operations links that can be followed from the response. 41 | /// The key of the map is a short name for the link, following the naming constraints of the names for Component Objects. 42 | [] 43 | member _.Links (state: OpenApiResponse, value: KVs<_, OpenApiLink>) = 44 | value |> Seq.iter state.Links.Add 45 | state 46 | 47 | [] 48 | member _.Extensions (state: OpenApiResponse, value: KVs<_, Interfaces.IOpenApiExtension>) = 49 | value |> Seq.iter state.Extensions.Add 50 | state 51 | 52 | [] 53 | member _.UnresolvedReference (state: OpenApiResponse, value) = 54 | state.UnresolvedReference <- value 55 | state 56 | 57 | [] 58 | member _.Reference (state: OpenApiResponse, value) = 59 | state.Reference <- value 60 | state 61 | 62 | type ResponsesBuilder () = 63 | 64 | member _.Yield _ = 65 | OpenApiResponses () 66 | 67 | [] 68 | member _.Responses (state: OpenApiResponses, value: KVs<_, OpenApiResponse>) = 69 | value |> Seq.iter state.Add 70 | state 71 | -------------------------------------------------------------------------------- /OpenApi/Builders/Schema.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open System 4 | open Microsoft.OpenApi 5 | open Microsoft.OpenApi.Any 6 | open Microsoft.OpenApi.Models 7 | 8 | type SchemaBuilder () = 9 | 10 | member _.Yield _ = 11 | OpenApiSchema () 12 | 13 | [] 14 | member _.Title (state: OpenApiSchema, value) = 15 | state.Title <- value 16 | state 17 | 18 | [] 19 | member _.Type (state: OpenApiSchema, value) = 20 | state.Type <- value 21 | state 22 | 23 | [] 24 | member _.Format (state: OpenApiSchema, value) = 25 | state.Format <- value 26 | state 27 | 28 | [] 29 | member _.Description (state: OpenApiSchema, value) = 30 | state.Description <- value 31 | state 32 | 33 | [] 34 | member _.Maximum (state: OpenApiSchema, value) = 35 | state.Maximum <- Nullable value 36 | state 37 | 38 | [] 39 | member _.ExclusiveMaximum (state: OpenApiSchema, value) = 40 | state.ExclusiveMaximum <- Nullable value 41 | state 42 | 43 | [] 44 | member _.Minimum (state: OpenApiSchema, value) = 45 | state.Minimum <- Nullable value 46 | state 47 | 48 | [] 49 | member _.ExclusiveMinimum (state: OpenApiSchema, value) = 50 | state.ExclusiveMinimum <- Nullable value 51 | state 52 | 53 | [] 54 | member _.MaxLength (state: OpenApiSchema, value) = 55 | state.MaxLength <- Nullable value 56 | state 57 | 58 | [] 59 | member _.MinLength (state: OpenApiSchema, value) = 60 | state.MinLength <- Nullable value 61 | state 62 | 63 | [] 64 | member _.Pattern (state: OpenApiSchema, value) = 65 | state.Pattern <- value 66 | state 67 | 68 | [] 69 | member _.MultipleOf (state: OpenApiSchema, value) = 70 | state.MultipleOf <- Nullable value 71 | state 72 | 73 | [] 74 | member _.ReadOnly (state: OpenApiSchema, value) = 75 | state.ReadOnly <- value 76 | state 77 | 78 | [] 79 | member _.WriteOnly (state: OpenApiSchema, value) = 80 | state.WriteOnly <- value 81 | state 82 | 83 | [] 84 | member _.Not (state: OpenApiSchema, value) = 85 | state.Not <- value 86 | state 87 | 88 | [] 89 | member _.Required (state: OpenApiSchema, value) = 90 | value |> Seq.iter (fun v -> state.Required.Add v |> ignore) 91 | state 92 | 93 | [] 94 | member _.Items (state: OpenApiSchema, value) = 95 | state.Items <- value 96 | state 97 | 98 | [] 99 | member _.MaxItems (state: OpenApiSchema, value) = 100 | state.MaxItems <- Nullable value 101 | state 102 | 103 | [] 104 | member _.MinItems (state: OpenApiSchema, value) = 105 | state.MinItems <- Nullable value 106 | state 107 | 108 | [] 109 | member _.UniqueItems (state: OpenApiSchema, value) = 110 | state.UniqueItems <- value 111 | state 112 | 113 | [] 114 | member _.Properties (state: OpenApiSchema, value: KVs<_, OpenApiSchema>) = 115 | value |> Seq.iter state.Properties.Add 116 | state 117 | 118 | [] 119 | member _.MaxProperties (state: OpenApiSchema, value) = 120 | state.MaxProperties <- Nullable value 121 | state 122 | 123 | [] 124 | member _.MinProperties (state: OpenApiSchema, value) = 125 | state.MinProperties <- Nullable value 126 | state 127 | 128 | [] 129 | member _.AdditionalPropertiesAllowed (state: OpenApiSchema, value) = 130 | state.AdditionalPropertiesAllowed <- value 131 | state 132 | 133 | [] 134 | member _.AdditionalProperties (state: OpenApiSchema, value) = 135 | state.AdditionalProperties <- value 136 | state 137 | 138 | [] 139 | member _.Discriminator (state: OpenApiSchema, value) = 140 | state.Discriminator <- value 141 | state 142 | 143 | [] 144 | member _.Example (state: OpenApiSchema, value) = 145 | state.Example <- value 146 | state 147 | 148 | [] 149 | member _.Enums (state: OpenApiSchema, value: IOpenApiAny seq) = 150 | Seq.iter state.Enum.Add value 151 | state 152 | 153 | [] 154 | member _.Nullable (state: OpenApiSchema, value) = 155 | state.Nullable <- value 156 | state 157 | 158 | [] 159 | member _.Deprecated (state: OpenApiSchema, value) = 160 | state.Deprecated <- value 161 | state 162 | 163 | [] 164 | member _.Xml (state: OpenApiSchema, value) = 165 | state.Xml <- value 166 | state 167 | 168 | [] 169 | member _.Extension (state: OpenApiSchema, value: KVs<_, Interfaces.IOpenApiExtension>) = 170 | value |> Seq.iter state.Extensions.Add 171 | state 172 | 173 | [] 174 | member _.UnresolvedReference (state: OpenApiSchema, value) = 175 | state.UnresolvedReference <- value 176 | state 177 | 178 | [] 179 | member _.Reference (state: OpenApiSchema, value) = 180 | state.Reference <- value 181 | state 182 | 183 | [] 184 | member _.Default (state: OpenApiSchema, value) = 185 | state.Default <- value 186 | state 187 | -------------------------------------------------------------------------------- /OpenApi/Builders/SecurityRequirement.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi.Models 4 | 5 | type SecurityRequirementBuilder () = 6 | 7 | member _.Yield _ = 8 | OpenApiSecurityRequirement () 9 | 10 | [] 11 | member _.SecurityRequirements (state: OpenApiSecurityRequirement, value: KVs) = 12 | value |> Seq.iter (fun (k, v) -> state.Add (k, ResizeArray v)) 13 | state 14 | -------------------------------------------------------------------------------- /OpenApi/Builders/SecurityScheme.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type SecuritySchemeBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiSecurityScheme () 10 | 11 | /// REQUIRED. The type of the security scheme. Valid values are "apiKey", "http", "oauth2", "openIdConnect". 12 | [] 13 | member _.Type (state: OpenApiSecurityScheme, value) = 14 | state.Type <- value 15 | state 16 | 17 | /// REQUIRED. The name of the header, query or cookie parameter to be used. 18 | [] 19 | member _.Name (state: OpenApiSecurityScheme, value) = 20 | state.Name <- value 21 | state 22 | 23 | /// REQUIRED. The location of the API key. Valid values are "query", "header" or "cookie". 24 | [] 25 | member _.In (state: OpenApiSecurityScheme, value) = 26 | state.In <- value 27 | state 28 | 29 | /// REQUIRED. The name of the HTTP Authorization scheme to be used in the Authorization header as defined in RFC7235. 30 | /// The values used SHOULD be registered in the IANA Authentication Scheme registry. 31 | [] 32 | member _.Scheme (state: OpenApiSecurityScheme, value) = 33 | state.Scheme <- value 34 | state 35 | 36 | /// REQUIRED. An object containing configuration information for the flow types supported. 37 | [] 38 | member _.Flows (state: OpenApiSecurityScheme, value) = 39 | state.Flows <- value 40 | state 41 | 42 | /// REQUIRED. OpenId Connect URL to discover OAuth2 configuration values. 43 | [] 44 | member _.OpenIdConnectUrl (state: OpenApiSecurityScheme, value) = 45 | state.OpenIdConnectUrl <- value 46 | state 47 | 48 | 49 | /// A short description for security scheme. CommonMark syntax. 50 | [] 51 | member _.Description (state: OpenApiSecurityScheme, value) = 52 | state.Description <- value 53 | state 54 | 55 | /// A hint to the client to identify how the bearer token is formatted. 56 | /// Bearer tokens are usually generated by an authorization server, 57 | /// so this information is primarily for documentation purposes. 58 | [] 59 | member _.BearerFormat (state: OpenApiSecurityScheme, value) = 60 | state.BearerFormat <- value 61 | state 62 | 63 | [] 64 | member _.Extensions (state: OpenApiSecurityScheme, value: KVs<_, Interfaces.IOpenApiExtension>) = 65 | value |> Seq.iter state.Extensions.Add 66 | state 67 | 68 | [] 69 | member _.UnresolvedReference (state: OpenApiSecurityScheme, value) = 70 | state.UnresolvedReference <- value 71 | state 72 | 73 | [] 74 | member _.Reference (state: OpenApiSecurityScheme, value) = 75 | state.Reference <- value 76 | state 77 | -------------------------------------------------------------------------------- /OpenApi/Builders/Server.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ServerBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiServer () 10 | 11 | /// REQUIRED. A URL to the target host. 12 | /// This URL supports Server Variables and MAY be relative, 13 | /// to indicate that the host location is relative to the location 14 | /// where the OpenAPI document is being served. 15 | /// Variable substitutions will be made when a variable is named in {brackets}. 16 | [] 17 | member _.Url (state: OpenApiServer, value) = 18 | state.Url <- value 19 | state 20 | 21 | /// An optional string describing the host designated by the URL. CommonMark syntax. 22 | [] 23 | member _.Description (state: OpenApiServer, value) = 24 | state.Description <- value 25 | state 26 | 27 | /// A map between a variable name and its value. 28 | /// The value is used for substitution in the server's URL template. 29 | [] 30 | member _.Variables (state: OpenApiServer, value: KVs<_, OpenApiServerVariable>) = 31 | value |> Seq.iter state.Variables.Add 32 | state 33 | 34 | [] 35 | member _.Extensions (state: OpenApiServer, value: KVs<_, Interfaces.IOpenApiExtension>) = 36 | value |> Seq.iter state.Extensions.Add 37 | state 38 | -------------------------------------------------------------------------------- /OpenApi/Builders/ServerVariable.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type ServerVariableBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiServerVariable () 10 | 11 | [] 12 | member _.Description (state: OpenApiServerVariable, value) = 13 | state.Description <- value 14 | state 15 | 16 | [] 17 | member _.Default (state: OpenApiServerVariable, value) = 18 | state.Default <- value 19 | state 20 | 21 | [] 22 | member _.Enums (state: OpenApiServerVariable, value) = 23 | Seq.iter state.Enum.Add value 24 | state 25 | 26 | [] 27 | member _.Extensions (state: OpenApiServerVariable, value: KVs<_, Interfaces.IOpenApiExtension>) = 28 | value |> Seq.iter state.Extensions.Add 29 | state 30 | -------------------------------------------------------------------------------- /OpenApi/Builders/Tag.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi.Builders 2 | 3 | open Microsoft.OpenApi 4 | open Microsoft.OpenApi.Models 5 | 6 | type TagBuilder () = 7 | 8 | member _.Yield _ = 9 | OpenApiTag () 10 | 11 | [] 12 | member _.Name (state: OpenApiTag, value) = 13 | state.Name <- value 14 | state 15 | 16 | [] 17 | member _.Description (state: OpenApiTag, value) = 18 | state.Description <- value 19 | state 20 | 21 | [] 22 | member _.ExternalDocs (state: OpenApiTag, value) = 23 | state.ExternalDocs <- value 24 | state 25 | 26 | [] 27 | member _.Extensions (state: OpenApiTag, value: KVs<_, Interfaces.IOpenApiExtension>) = 28 | value |> Seq.iter state.Extensions.Add 29 | state 30 | 31 | [] 32 | member _.UnresolvedReference (state: OpenApiTag, value) = 33 | state.UnresolvedReference <- value 34 | state 35 | 36 | [] 37 | member _.Reference (state: OpenApiTag, value) = 38 | state.Reference <- value 39 | state 40 | -------------------------------------------------------------------------------- /OpenApi/Expressions.fs: -------------------------------------------------------------------------------- 1 | [] 2 | module OpenApi.Expressions 3 | 4 | open OpenApi.Builders 5 | 6 | (* 7 | Documentation from version 3.0.3 8 | https://swagger.io/specification/ 9 | *) 10 | 11 | /// A map of possible out-of band callbacks related to the parent operation. 12 | let apiCallback = CallbackBuilder () 13 | 14 | /// Holds a set of reusable objects for different aspects of the OAS. 15 | /// All objects defined within the components object will have no effect on the API 16 | /// unless they are explicitly referenced from properties outside the components object. 17 | let apiComponents = ComponentsBuilder () 18 | 19 | /// Contact information for the exposed API. 20 | let apiContact = ContactBuilder () 21 | 22 | /// When request bodies or response payloads may be one of a number of different schemas, 23 | /// a discriminator object can be used to aid in serialization, deserialization, and validation. 24 | /// The discriminator is a specific object in a schema which is used 25 | /// to inform the consumer of the specification of an alternative schema based on the value associated with it. 26 | /// When using the discriminator, inline schemas will not be considered. 27 | let apiDiscriminator = DiscriminatorBuilder () 28 | 29 | let apiDocument = DocumentBuilder () 30 | 31 | /// A single encoding definition applied to a single schema property. 32 | let apiEncoding = EncodingBuilder () 33 | 34 | /// Example object. 35 | let apiExample = ExampleBuilder () 36 | 37 | /// Allows referencing an external resource for extended documentation. 38 | let apiExternalDocs = ExternalDocsBuilder () 39 | 40 | /// The Header Object follows the structure of the Parameter object. 41 | let apiHeader = HeaderBuilder () 42 | 43 | /// The object provides metadata about the API. 44 | /// The metadata MAY be used by the clients if needed, 45 | /// and MAY be presented in editing or documentation generation tools for convenience. 46 | let apiInfo = InfoBuilder () 47 | 48 | /// License information for the exposed API. 49 | let apiLicense = LicenseBuilder () 50 | 51 | /// The Link object represents a possible design-time link for a response. 52 | /// The presence of a link does not guarantee the caller's ability to successfully invoke it, 53 | /// rather it provides a known relationship and traversal mechanism between responses and other operations. 54 | /// Unlike dynamic links (i.e. links provided in the response payload), 55 | /// the OAS linking mechanism does not require link information in the runtime response. 56 | let apiLink = LinkBuilder () 57 | 58 | /// Each Media Type Object provides schema and examples for the media type identified by its key. 59 | let apiMediaType = MediaTypeBuilder () 60 | 61 | /// Configuration details for a supported OAuth Flow 62 | let apiOAuthFlow = OAuthFlowBuilder () 63 | 64 | /// Allows configuration of the supported OAuth Flows. 65 | let apiOAuthFlows = OAuthFlowsBuilder () 66 | 67 | /// Describes a single API operation on a path. 68 | let apiOperation = OperationBuilder () 69 | 70 | /// Describes a single operation parameter. 71 | /// A unique parameter is defined by a combination of a name and location. 72 | let apiParameter = ParameterBuilder () 73 | 74 | /// Describes the operations available on a single path. 75 | /// A Path Item MAY be empty, due to ACL constraints. 76 | /// The path itself is still exposed to the documentation viewer 77 | /// but they will not know which operations and parameters are available. 78 | let apiPathItem = PathItemBuilder () 79 | 80 | /// Holds the relative paths to the individual endpoints and their operations. 81 | /// The path is appended to the URL from the Server Object in order to construct the full URL. 82 | /// The Paths MAY be empty, due to ACL constraints. 83 | let apiPaths = PathsBuilder () 84 | 85 | let apiReference = ReferenceBuilder () 86 | 87 | /// Describes a single request body. 88 | let apiRequestBody = RequestBodyBuilder () 89 | 90 | /// Describes a single response from an API Operation, including design-time, static links to operations based on the response. 91 | let apiResponse = ResponseBuilder () 92 | 93 | /// A container for the expected responses of an operation. 94 | /// The container maps a HTTP response code to the expected response. 95 | let apiResponses = ResponsesBuilder () 96 | 97 | /// The Schema Object allows the definition of input and output data types. 98 | let apiSchema = SchemaBuilder () 99 | 100 | /// Lists the required security schemes to execute this operation. 101 | let apiSecurityRequirement = SecurityRequirementBuilder () 102 | 103 | /// Defines a security scheme that can be used by the operations. 104 | /// Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter), 105 | /// OAuth2's common flows (implicit, password, client credentials and authorization code) as defined in RFC6749, and OpenID Connect Discovery. 106 | let apiSecurityScheme = SecuritySchemeBuilder () 107 | 108 | /// An object representing a Server. 109 | let apiServer = ServerBuilder () 110 | 111 | /// An object representing a Server Variable for server URL template substitution. 112 | let apiServerVariable = ServerVariableBuilder () 113 | 114 | let apiTag = TagBuilder () 115 | -------------------------------------------------------------------------------- /OpenApi/Factory.fs: -------------------------------------------------------------------------------- 1 | namespace OpenApi 2 | 3 | open System 4 | open System.Text.Json 5 | open Microsoft.OpenApi 6 | open Microsoft.OpenApi.Any 7 | open Microsoft.OpenApi.Extensions 8 | open Microsoft.OpenApi.Models 9 | open OpenApi.Expressions 10 | 11 | [] 12 | type OpenApiFactory = 13 | { Document: OpenApiDocument 14 | JsonSerializerOptions: JsonSerializerOptions } 15 | 16 | member this.Version = 17 | this.Document.Info.Version 18 | 19 | member this.SpecificationUrl = 20 | if String.IsNullOrWhiteSpace this.Version 21 | then "/openapi/v1.json" 22 | else $"/openapi/{this.Version}.json" 23 | 24 | member this.Serialize () = 25 | this.Document.Serialize (OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json) 26 | 27 | member this.MakeJsonContent content = 28 | JsonSerializer.Serialize (content, this.JsonSerializerOptions) 29 | |> OpenApiString 30 | 31 | member this.Write (writer: string -> 'T) = 32 | this.Serialize () |> writer 33 | 34 | member this.AddOperation operationType path operation = 35 | if this.Document.Paths.ContainsKey path then 36 | this.Document.Paths[path].Operations.Add (operationType, operation) 37 | else 38 | let item = apiPathItem { operations [ operationType, operation ] } 39 | this.Document.Paths.Add (path, item) 40 | 41 | [] 42 | module OpenApiFactory = 43 | 44 | let create (jsonSerializerOptions: JsonSerializerOptions) docTitle docVersion = 45 | jsonSerializerOptions.WriteIndented <- true 46 | let document = 47 | apiDocument { 48 | info (apiInfo { title docTitle; version docVersion }) 49 | } 50 | { JsonSerializerOptions = jsonSerializerOptions 51 | Document = document } 52 | -------------------------------------------------------------------------------- /OpenApi/OpenApi.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | FSharp.OpenApi 6 | Amin Khansari 7 | https://github.com/akhansari/FSharp.OpenApi 8 | F# Wrapper for Microsoft.OpenApi 9 | fsharp, openapi, swagger 10 | MIT 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## FSharp OpenAPI [![NuGet Status](https://img.shields.io/nuget/v/FSharp.OpenApi.svg)](https://www.nuget.org/packages/FSharp.OpenApi) 2 | 3 | F# Wrapper for [OpenAPI.NET SDK](https://github.com/microsoft/OpenAPI.NET). 4 | 5 | - Describe API specifications with computation expressions. 6 | - Provide helpers for F# libraries to write specifications and exposing them to Scalar UI. 7 | 8 | This is still a work in progress project and breaking changes could be frequent.\ 9 | Contributions are welcome. 10 | 11 | ### Example Usage 12 | 13 | Creating an OpenAPI document 14 | 15 | ```fsharp 16 | let document = 17 | apiDocument { 18 | info (apiInfo { 19 | version "1.0.0" 20 | title "Swagger Petstore (Simple)" 21 | }) 22 | servers [ 23 | apiServer { 24 | url "http://petstore.swagger.io/api" 25 | } 26 | ] 27 | paths [ 28 | "/pets", apiPathItem { 29 | operations [ 30 | OperationType.Get, apiOperation { 31 | description "Returns all pets from the system that the user has access to" 32 | responses [ 33 | HttpStatusCode.OK, apiResponse { 34 | description "OK" 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | 43 | let outputString = 44 | document.Serialize (OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json) 45 | ``` 46 | --------------------------------------------------------------------------------