# {{packageName}}

An [F# Azure Functions](https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-fsharp) server stub for the {{packageName}} package, created via the [OpenAPI generator](https://github.com/OpenAPITools/openapi-generator/).

## Models

The following models have been auto-generated from the provided OpenAPI schema:

{{#apiInfo}}
{{#models}}
{{#model}}
- model/{{classname}}Model.fs
{{/model}}
{{/models}}
{{/apiInfo}}

## Operations

Handlers have been auto-generated from the operations specified in the OpenAPI schema as follows:

{{#apiInfo}}
{{#operations}}
{{#operation}}
- api/{{classname}}Handler.fs
{{/operation}}
{{/operations}}
{{/apiInfo}}

## Operation Parameters

Types have been generated for the URL, query, form, header and cookie parameters passed to each handler in the following files:

{{#apiInfo}}
{{#apis}}
- api/{{classname}}HandlerParams.fs
{{/apis}}
{{/apiInfo}}

## Service Interfaces

Handlers will attempt to bind parameters to the applicable type and pass to a Service specific to that Handler. Service interfaces have been generated as follows:

{{#apiInfo}}
{{#apis}}
- api/{{classname}}ServiceInterface.fs
{{/apis}}
{{/apiInfo}}

Each Service contains functions for each [OperationId], each accepting a [OperationId]Params object that wraps the operation's parameters.

If a requestBody is a ref type (i.e. a Model) or a single simple type, the operation parameter will be typed as the expected Model:

`type AddPetBodyParams = Pet`

If a requestBody is a simple type with named properties, the operation parameters will be typed to reflect those properties:

`type AddFooBodyParams = {
  Name:string;
  Age:int
}

Each Service/operation function must accept the [OperationId]Params object and return a [OperationId]Result type. For example:

`type AddPetArgs = { bodyParams:AddPetBodyParams }
type IPetApiService = abstract member AddPet:HttpContext -> AddPetArgs->AddPetResult`

[OperationId]Result is a discriminated union of all possible OpenAPI response types for that operation.

This means that service implementations can only return status codes that have been declared in the OpenAPI specification.
However, if the OpenAPI spec declares a default Response for an operation, the service can manually set the status code.

For example:

`type FindPetsByStatusDefaultStatusCodeResponse = { content:Pet[];}
type FindPetsByStatusStatusCode400Response = { content:string; }
type FindPetsByStatusResult = FindPetsByStatusDefaultStatusCode of FindPetsByStatusDefaultStatusCodeResponse | FindPetsByStatusStatusCode400 of FindPetsByStatusStatusCode400Response`

## Service Implementations

Stubbed service implementations of those interfaces have been generated as follows:

{{#apiInfo}}
{{#apis}}
- impl/{{classname}}Service.fs
{{/apis}}
{{/apiInfo}}

You should manually edit these files to implement your business logic.

## Additional Handlers

Additional handlers can be configured in the Customization.fs

`let handlers : HttpHandler list = [
    // insert your handlers here
    GET >=>
      choose [
        route "/login" >=> redirectToLogin
        route "/logout" >=> logout
      ]
  ]`

## TODO/currently unsupported

- form request bodies (URL-encoded or multipart)
- limit handler access to specified oAuth scheme when multiple oAuth schemes defined
- XML content/response types
- http authentication
- testing header params

## .openapi-generator-ignore

It is recommended to add src/impl/** and the project's .fsproj file to the .openapi-generator-ignore file.

This will allow you to regenerate model, operation and parameter files without overriding your implementations of business logic, authentication, data layers, and so on.

## Build and test the application

### Windows

Run the `build.bat` script in order to restore, build and test (if you've selected to include tests) the application:

```
> ./build.bat
```

### Linux/macOS

Run the `build.sh` script in order to restore, build and test (if you've selected to include tests) the application:

```
$ ./build.sh
```

## Run the application

After a successful build you can start the web application by executing the following command in your terminal:

```
dotnet run --project src/{{packageName}
```

After the application has started visit [http://localhost:5000](http://localhost:5000) in your preferred browser.