Skip to content

Commit

Permalink
Merge pull request #623 from christianhelle/docs
Browse files Browse the repository at this point in the history
JSON Schema generator for documentation
  • Loading branch information
christianhelle authored Feb 26, 2025
2 parents d35f50a + 343b579 commit fb51de7
Show file tree
Hide file tree
Showing 17 changed files with 955 additions and 244 deletions.
41 changes: 24 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,28 @@
<!-- ALL-CONTRIBUTORS-BADGE:END -->

# Refitter

Refitter is a tool for generating a C# REST API Client using the [Refit](https://github.com/reactiveui/refit) library. Refitter can generate the Refit interface and contracts from OpenAPI specifications. Refitter could format the generated Refit interface to be managed by [Apizr](https://www.apizr.net) (v6+) and generate some registration helpers too.

Refitter comes in 2 forms:

- A [.NET CLI Tool](#cli-tool) distributed via [nuget.org](http://www.nuget.org/packages/refitter) that outputs a single C# file on disk
- A [C# Source Generator](#source-generator) via the [Refitter.SourceGenerator](http://www.nuget.org/packages/refitter.sourcegenerator) package that generates code on compile time based on a [.refitter](#.refitter-file-format) within the project directory.

## CLI Tool

### Installation:
### Installation

The tool is packaged as a .NET Tool and is published to nuget.org. You can install the latest version of this tool like this:

```shell
dotnet tool install --global Refitter
```

### Usage:
### Usage

```shell
$ refitter --help
refitter --help
```

```text
Expand Down Expand Up @@ -131,7 +133,7 @@ OPTIONS:
To generate code from an OpenAPI specifications file, run the following:

```shell
$ refitter [path to OpenAPI spec file] --namespace "[Your.Namespace.Of.Choice.GeneratedCode]"
refitter [path to OpenAPI spec file] --namespace "[Your.Namespace.Of.Choice.GeneratedCode]"
```

This will generate a file called `Output.cs` which contains the Refit interface and contract classes generated using [NSwag](https://github.com/RicoSuter/NSwag)
Expand Down Expand Up @@ -177,6 +179,7 @@ The following is an example `.refitter` file
"generateStatusCodeComments": true, // Optional. Default=true
"addAutoGeneratedHeader": true, // Optional. Default=true
"addAcceptHeaders": true, // Optional. Default=true
"addContentTypeHeaders": true, // Optional. Default=true
"returnIApiResponse": false, // Optional. Default=false
"responseTypeOverride": { // Optional. Default={}
"File_Upload": "IApiResponse",
Expand Down Expand Up @@ -270,6 +273,7 @@ The following is an example `.refitter` file
"generateDefaultValues": true,
"inlineNamedAny": false,
"dateFormat": "yyyy-MM-dd",
"dateTimeFormat": "yyyy-MM-dd",
"excludedTypeNames": [
"ExcludedTypeFoo",
"ExcludedTypeBar"
Expand Down Expand Up @@ -307,16 +311,16 @@ The following is an example `.refitter` file
- `keepSchemaPatterns`: A collection of regular expressions to force to keep matching schema. This is used together with `trimUnusedSchema`
- `includeInheritanceHierarchy`: Set to true to keep all possible type-instances of inheritance/union types. If this is false only directly referenced types will be kept. This works in conjunction with `trimUnusedSchema`
- `generateDefaultAdditionalProperties`: Set to `false` to skip default additional properties. Default is `true`
- `operationNameGenerator`: The NSwag `IOperationNameGenerator` implementation to use. See https://refitter.github.io/api/Refitter.Core.OperationNameGeneratorTypes.html
- `operationNameGenerator`: The NSwag `IOperationNameGenerator` implementation to use. See <https://refitter.github.io/api/Refitter.Core.OperationNameGeneratorTypes.html>
- `immutableRecords`: Set to `true` to generate contracts as immutable records instead of classes. Default is `false`
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping). See https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters for more information.
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping). See <https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters> for more information.
- `dependencyInjectionSettings` - Setting this will generated extension methods to `IServiceCollection` for configuring Refit clients
- `baseUrl` - Used as the HttpClient base address. Leave this blank to manually set the base URL
- `httpMessageHandlers` - A collection of `HttpMessageHandler` that is added to the HttpClient pipeline
- `usePolly` - Set this to `true` to configure the HttpClient to use Polly using a retry policy with a jittered backoff. This is **DEPRECATED**, use `transientErrorHandler` instead
- `transientErrorHandler`: Set this to configure transient error handling with a retry policy that uses a jittered backoff. See https://refitter.github.io/api/Refitter.Core.TransientErrorHandler.html
- `transientErrorHandler`: Set this to configure transient error handling with a retry policy that uses a jittered backoff. See <https://refitter.github.io/api/Refitter.Core.TransientErrorHandler.html>
- `firstBackoffRetryInSeconds` - This is the duration of the initial retry backoff. Default is 1 second
- `apizrSettings` - Setting this will format Refit interface to be managed by Apizr. See https://www.apizr.net for more information
- `apizrSettings` - Setting this will format Refit interface to be managed by Apizr. See <https://www.apizr.net> for more information
- `withRequestOptions` - Tells if the Refit interface methods should have a final IApizrRequestOptions options parameter
- `withRegistrationHelper` - Tells if Refitter should generate Apizr registration helpers (extended with dependencyInjectionSettings set, otherwise static)
- `withCacheProvider` - Set the cache provider to be used
Expand Down Expand Up @@ -354,7 +358,8 @@ The following is an example `.refitter` file
- `generateNativeRecords` - Default is false
- `generateDefaultValues` - Default is true
- `inlineNamedAny` - Default is false
- `dateFormat` - Default is `yyyy-MM-dd`
- `dateFormat` - Default is null
- `dateTimeFormat` - Default is null
- `excludedTypeNames` - Default is empty

## MSBuild
Expand Down Expand Up @@ -427,15 +432,14 @@ The MSBuild package includes a custom `.target` file which executes the `Refitte

The `RefitterGenerateTask` task will scan the project folder for `.refitter` files and executes them all. By default, telemetry collection is enabled, and to opt-out of it you must specify `<RefitterNoLogging>true</RefitterNoLogging>` in the `.csproj` `<PropertyGroup>`


# Using the generated code

Here's an example generated output from the [Swagger Petstore example](https://petstore3.swagger.io) using the default settings

**CLI Tool**

```bash
$ refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode"
refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode"
```

**Source Generator ***.refitter*** file**
Expand All @@ -451,7 +455,6 @@ $ refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode"

Full output is available [here](docs/DefaultOutput.cs)


```cs
using Refit;
using System.Collections.Generic;
Expand Down Expand Up @@ -502,7 +505,7 @@ Here's an example generated output from the [Swagger Petstore example](https://p
**CLI Tool**

```bash
$ refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --use-api-response
refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --use-api-response
```

**Source Generator ***.refitter*** file**
Expand Down Expand Up @@ -572,7 +575,7 @@ Here's an example generated output from the [Swagger Petstore example](https://p
**CLI Tool**

```bash
$ refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --multiple-interfaces ByEndpoint
refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --multiple-interfaces ByEndpoint
```

**Source Generator ***.refitter*** file**
Expand Down Expand Up @@ -630,7 +633,7 @@ Here's an example generated output from the [Swagger Petstore example](https://p
**CLI Tool**

```bash
$ refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --use-dynamic-querystring-parameters
refitter ./openapi.json --namespace "Your.Namespace.Of.Choice.GeneratedCode" --use-dynamic-querystring-parameters
```

**Output (Snippet)**
Expand Down Expand Up @@ -769,15 +772,16 @@ app.UseSwagger();
app.Run();
```


.NET Core supports registering the generated `ISwaggerPetstore` interface via `HttpClientFactory`

The following request to the API above

```shell
$ curl -X 'GET' 'https://localhost:5001/pet/1' -H 'accept: application/json'
curl -X 'GET' 'https://localhost:5001/pet/1' -H 'accept: application/json'
```

Returns a response that looks something like this:

```json
{
"id": 1,
Expand Down Expand Up @@ -926,12 +930,14 @@ Personally, they I use Refitter is to generate an interface per endpoint, so whe
Refitter supports generating Apizr formatted Refit interfaces that can be managed then by Apizr (v6+).

You can enable Apizr formatted Refit interface generation either:

- With the `--use-apizr` command line argument
- By setting the `apizrSettings` section in the `.refitter` settings file

Note that `--use-apizr` uses default Apizr settings with `withRequestOptions` set to `true` as recommended, while the `.refitter` settings file allows you to configure it deeper.

In both cases, it will format the generated Refit interfaces to be Apizr ready by:

- Adding a final IApizrRequestOptions options parameter to all generated methods (if `withRequestOptions` is set to `true`)
- Providing cancellation tokens by Apizr request options instead of a dedicated parameter (if `withRequestOptions` is set to `true`)
- Using method overloads instead of optional parameters (note that setting `useDynamicQuerystringParameters` to `true` improve overloading experience)
Expand Down Expand Up @@ -1188,6 +1194,7 @@ var result = await petstoreManager.ExecuteAsync((api, opt) => api.GetPetById(1,
Please head to the [Apizr documentation](https://www.apizr.net) to get more.

## System requirements

.NET 8.0

## Contributors
Expand Down
120 changes: 112 additions & 8 deletions docs/docfx_project/articles/refitter-file-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ The following is an example `.refitter` file
"dependencyInjectionSettings": { // Optional
"baseUrl": "https://petstore3.swagger.io/api/v3", // Optional. Leave this blank to set the base address manually
"httpMessageHandlers": [ // Optional
"AuthorizationMessageHandler",
"TelemetryMessageHandler"
"AuthorizationMessageHandler",
"TelemetryMessageHandler"
],
"usePolly": true, // DEPRECATED - Use "transientErrorHandler": "None|Polly|HttpResilience" instead
"transientErrorHandler": "HttpResilience", // Optional. Set this to configure transient error handling with a retry policy that uses a jittered backoff. May be one of None, Polly, HttpResilience
Expand Down Expand Up @@ -113,6 +113,8 @@ The following is an example `.refitter` file
"generateNativeRecords": false,
"generateDefaultValues": true,
"inlineNamedAny": false,
"dateFormat": "string",
"dateTimeFormat": "string",
"excludedTypeNames": [
"ExcludedTypeFoo",
"ExcludedTypeBar"
Expand Down Expand Up @@ -153,19 +155,19 @@ The following is an example `.refitter` file
- `keepSchemaPatterns`: A collection of regular expressions to force to keep matching schema. This is used together with `trimUnusedSchema`
- `includeInheritanceHierarchy`: Set to true to keep all possible type-instances of inheritance/union types. If this is false only directly referenced types will be kept. This works in conjunction with `trimUnusedSchema`
- `generateDefaultAdditionalProperties`: Set to `false` to skip default additional properties. Default is `true`
- `operationNameGenerator`: The NSwag `IOperationNameGenerator` implementation to use. See https://refitter.github.io/api/Refitter.Core.OperationNameGeneratorTypes.html
- `operationNameGenerator`: The NSwag `IOperationNameGenerator` implementation to use. See <https://refitter.github.io/api/Refitter.Core.OperationNameGeneratorTypes.html>
- `immutableRecords`: Set to `true` to generate contracts as immutable records instead of classes. Default is `false`
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping). See https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters for more information.
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping). See <https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters> for more information.
- `usePolymorphicSerialization`: Set to `true` to use `System.Text.Json` polymorphic serialization.
- `generateMultipleFiles`: Set to `true` to generate multiple files. This is automatically set to `true` when `ContractsOutputFolder` is specified. Refit interface(s) are written to a file called `RefitInterfaces.cs`, Contracts are written to a file called `Contracts.cs`, and Dependency Injection is written to a file called `DependencyInjection.cs`
- `dependencyInjectionSettings` - Setting this will generated extension methods to `IServiceCollection` for configuring Refit clients
- `baseUrl` - Used as the HttpClient base address. Leave this blank to manually set the base URL
- `httpMessageHandlers` - A collection of `HttpMessageHandler` that is added to the HttpClient pipeline
- `usePolly` - Set this to `true` to configure the HttpClient to use Polly using a retry policy with a jittered backoff. This is **DEPRECATED**, use `transientErrorHandler` instead
- `transientErrorHandler`: Set this to configure transient error handling with a retry policy that uses a jittered backoff. See https://refitter.github.io/api/Refitter.Core.TransientErrorHandler.html
- `transientErrorHandler`: Set this to configure transient error handling with a retry policy that uses a jittered backoff. See <https://refitter.github.io/api/Refitter.Core.TransientErrorHandler.html>
- `maxRetryCount` - This is the max retry count used in the Polly retry policy. Default is 6
- `firstBackoffRetryInSeconds` - This is the duration of the initial retry backoff. Default is 1 second
- `apizrSettings` - Setting this will format Refit interface to be managed by Apizr. See https://www.apizr.net for more information
- `apizrSettings` - Setting this will format Refit interface to be managed by Apizr. See <https://www.apizr.net> for more information
- `withRequestOptions` - Tells if the Refit interface methods should have a final IApizrRequestOptions options parameter
- `withRegistrationHelper` - Tells if Refitter should generate Apizr registration helpers (extended with dependencyInjectionSettings set, otherwise static)
- `withCacheProvider` - Set the cache provider to be used
Expand Down Expand Up @@ -204,6 +206,8 @@ The following is an example `.refitter` file
- `generateDefaultValues` - Default is true
- `inlineNamedAny` - Default is false
- `excludedTypeNames` - Default is empty
- `dateFormat` - Default is null
- `dateTimeFormat` - Default is null

### JSON Schema

Expand Down Expand Up @@ -253,6 +257,10 @@ The following is an example `.refitter` file
"type": "boolean",
"description": "Indicates whether to add accept headers."
},
"addContentTypeHeaders": {
"type": "boolean",
"description": "Indicates whether to add content-type headers."
},
"returnIApiResponse": {
"type": "boolean",
"description": "Indicates whether to return IApiResponse."
Expand Down Expand Up @@ -461,6 +469,7 @@ The following is an example `.refitter` file
},
"codeGeneratorSettings": {
"type": "object",
"description": "Settings for the code generator."
"properties": {
"requiredPropertiesMustBeDefined": {
"type": "boolean",
Expand All @@ -473,10 +482,105 @@ The following is an example `.refitter` file
"anyType": {
"type": "string",
"description": "The type used for 'any' in the code generator settings."
},
"dateType": {
"type": "string"
},
"dateTimeType": {
"type": "string"
},
"timeType": {
"type": "string"
},
"timeSpanType": {
"type": "string"
},
"arrayType": {
"type": "string"
},
"dictionaryType": {
"type": "string"
},
"arrayInstanceType": {
"type": "string"
},
"dictionaryInstanceType": {
"type": "string"
},
"arrayBaseType": {
"type": "string"
},
"dictionaryBaseType": {
"type": "string"
},
"propertySetterAccessModifier": {
"type": "string"
},
"jsonConverters": {
"type": "array",
"items": {
"type": "string"
}
},
"generateImmutableArrayProperties": {
"type": "boolean"
},
"generateImmutableDictionaryProperties": {
"type": "boolean"
},
"handleReferences": {
"type": "boolean"
},
"jsonSerializerSettingsTransformationMethod": {
"type": "string"
},
"generateJsonMethods": {
"type": "boolean"
},
"enforceFlagEnums": {
"type": "boolean"
},
"inlineNamedDictionaries": {
"type": "boolean"
},
"inlineNamedTuples": {
"type": "boolean"
},
"inlineNamedArrays": {
"type": "boolean"
},
"generateOptionalPropertiesAsNullable": {
"type": "boolean"
},
"generateNullableReferenceTypes": {
"type": "boolean"
},
"generateNativeRecords": {
"type": "boolean"
},
"generateDefaultValues": {
"type": "boolean"
},
"inlineNamedAny": {
"type": "boolean"
},
"excludedTypeNames": {
"type": "array",
"items": {
"type": "string"
}
},
"dateFormat": {
"type": "string"
},
"dateTimeFormat": {
"type": "string"
},
"propertyNameGenerator": {
"type": "object"
}
},
"description": "Settings for the code generator."
}
}
}
```
```
Loading

0 comments on commit fb51de7

Please sign in to comment.