Skip to content
Merged
4 changes: 1 addition & 3 deletions .github/workflows/smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ on:
- "!.github/workflows/template-url.yml"
- "!.github/workflows/smoke-tests.yml"
- "!test/smoke-tests.ps1"
branches:
- "main"
pull_request:
paths-ignore:
- "**/*"
Expand All @@ -32,7 +30,7 @@ on:
- "!.github/workflows/smoke-tests.yml"
- "!test/**/*"
branches:
- "*"
- "main"

jobs:

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ OPTIONS:
--tag Only include Endpoints that contain this tag. May be set multiple times and result in OR'ed evaluation
--skip-validation Skip validation of the OpenAPI specification
--no-deprecated-operations Don't generate deprecated operations
--operation-name-template Generate operation names using pattern. When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface
--operation-name-template Generate operation names using pattern. When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
--optional-nullable-parameters Generate nullable parameters as optional parameters
--trim-unused-schema Removes unreferenced components schema to keep the generated output to a minimum
--keep-schema Force to keep matching schema, uses regular expressions. Use together with "--trim-unused-schema". Can be set multiple times
Expand Down Expand Up @@ -223,7 +223,7 @@ The following is an example `.refitter` file
"useIsoDateFormat": false, // Optional. Default=false
"multipleInterfaces": "ByEndpoint", // Optional. May be one of "ByEndpoint" or "ByTag"
"generateDeprecatedOperations": false, // Optional. Default=true
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName} when multipleInterfaces != ByEndpoint
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName}. When multipleInterfaces == "ByEndpoint", this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
"optionalParameters": false, // Optional. Default=false
"outputFolder": "../CustomOutput" // Optional. Default=./Generated
"outputFilename": "RefitInterface.cs", // Optional. Default=Output.cs for CLI tool
Expand Down Expand Up @@ -337,7 +337,7 @@ The following is an example `.refitter` file
- `includeTags` - A collection of tags to use a filter for including endpoints that contain this tag.
- `includePathMatches` - A collection of regular expressions used to filter paths.
- `generateDeprecatedOperations` - a boolean indicating whether deprecated operations should be generated or skipped. Default is `true`
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using multiple interfaces with `ByEndpoint`, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
- `optionalParameters` - Generate non-required parameters as nullable optional parameters
- `trimUnusedSchema` - Removes unreferenced components schema to keep the generated output to a minimum
- `keepSchemaPatterns`: A collection of regular expressions to force to keep matching schema. This is used together with `trimUnusedSchema`
Expand Down
2 changes: 1 addition & 1 deletion docs/docfx_project/articles/cli-tool.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ OPTIONS:
--tag Only include Endpoints that contain this tag. May be set multiple times and result in OR'ed evaluation
--skip-validation Skip validation of the OpenAPI specification
--no-deprecated-operations Don't generate deprecated operations
--operation-name-template Generate operation names using pattern. When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface
--operation-name-template Generate operation names using pattern. When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
--optional-nullable-parameters Generate nullable parameters as optional parameters
--trim-unused-schema Removes unreferenced components schema to keep the generated output to a minimum
--keep-schema Force to keep matching schema, uses regular expressions. Use together with "--trim-unused-schema". Can be set multiple times
Expand Down
4 changes: 2 additions & 2 deletions docs/docfx_project/articles/refitter-file-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The following is an example `.refitter` file
"useIsoDateFormat": false, // Optional. Default=false
"multipleInterfaces": "ByEndpoint", // Optional. May be one of "ByEndpoint" or "ByTag"
"generateDeprecatedOperations": false, // Optional. Default=true
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName} when multipleInterfaces != ByEndpoint
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName}. When multipleInterfaces == "ByEndpoint", this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
"optionalParameters": false, // Optional. Default=false
"outputFolder": "../CustomOutput", // Optional. Default=./Generated
"outputFilename": "RefitInterface.cs", // Optional. Default=Output.cs for CLI tool
Expand Down Expand Up @@ -150,7 +150,7 @@ The following is an example `.refitter` file
- `includeTags` - A collection of tags to use a filter for including endpoints that contain this tag.
- `includePathMatches` - A collection of regular expressions used to filter paths.
- `generateDeprecatedOperations` - a boolean indicating whether deprecated operations should be generated or skipped. Default is `true`
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using multiple interfaces with `ByEndpoint`, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
- `optionalParameters` - Generate non-required parameters as nullable optional parameters
- `trimUnusedSchema` - Removes unreferenced components schema to keep the generated output to a minimum
- `keepSchemaPatterns`: A collection of regular expressions to force to keep matching schema. This is used together with `trimUnusedSchema`
Expand Down
2 changes: 1 addition & 1 deletion docs/json-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@
"type": "boolean"
},
"operationNameTemplate": {
"description": "Generate operation names using pattern. When using --multiple-interfaces ByEndpoint,\r\nthis is name of the Execute() method in the interface.",
"description": "Generate operation names using pattern. When using multiple interfaces ByEndpoint,\r\nthis is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'.",
"type": "string"
},
"optionalParameters": {
Expand Down
4 changes: 3 additions & 1 deletion src/Refitter.Core/RefitMultipleInterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public override IEnumerable<GeneratedCode> GenerateCode()

var returnType = GetTypeName(operation);
var verb = operations.Key.CapitalizeFirstCharacter();
var methodName = settings.OperationNameTemplate ?? "Execute";
var methodName = !string.IsNullOrWhiteSpace(settings.OperationNameTemplate)
? settings.OperationNameTemplate!.Replace("{operationName}", "Execute")
: "Execute";
var code = new StringBuilder();

this.docGenerator.AppendInterfaceDocumentation(operation, code);
Expand Down
4 changes: 2 additions & 2 deletions src/Refitter.Core/Settings/MultipleInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ public enum MultipleInterfaces

/// <summary>
/// Generate a Refit interface for each endpoint with a single Execute() method.
/// The method name can be customized using the <see cref="RefitGeneratorSettings.OperationNameTemplate"/> setting.
/// The method name can be customized using <see cref="RefitGeneratorSettings.OperationNameTemplate"/>, where this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'.
/// </summary>
[Description(
"""
Generate a Refit interface for each endpoint with a single Execute() method.
The method name can be customized using the OperationNameTemplate setting.
The method name can be customized using OperationNameTemplate, where this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'.
"""
)]
ByEndpoint,
Expand Down
4 changes: 2 additions & 2 deletions src/Refitter.MSBuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The following is an example `.refitter` file
"useIsoDateFormat": false, // Optional. Default=false
"multipleInterfaces": "ByEndpoint", // Optional. May be one of "ByEndpoint" or "ByTag"
"generateDeprecatedOperations": false, // Optional. Default=true
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName} when multipleInterfaces != ByEndpoint
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName}. When multipleInterfaces == "ByEndpoint", this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
"optionalParameters": false, // Optional. Default=false
"outputFolder": "../CustomOutput" // Optional. Default=./Generated
"outputFilename": "RefitInterface.cs", // Optional. Default=Output.cs for CLI tool
Expand Down Expand Up @@ -148,7 +148,7 @@ The following is an example `.refitter` file
- `includeTags` - A collection of tags to use a filter for including endpoints that contain this tag.
- `includePathMatches` - A collection of regular expressions used to filter paths.
- `generateDeprecatedOperations` - a boolean indicating whether deprecated operations should be generated or skipped. Default is `true`
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using `"multipleIinterfaces": "ByEndpoint"`, This is name of the Execute() method in the interface
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using multiple interfaces with `ByEndpoint`, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
- `optionalParameters` - Generate non-required parameters as nullable optional parameters
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping).
- `dependencyInjectionSettings` - Setting this will generated extension methods to `IServiceCollection` for configuring Refit clients. See https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters for more information.
Expand Down
4 changes: 2 additions & 2 deletions src/Refitter.SourceGenerator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The following is an example `.refitter` file
"useIsoDateFormat": false, // Optional. Default=false
"multipleInterfaces": "ByEndpoint", // Optional. May be one of "ByEndpoint" or "ByTag"
"generateDeprecatedOperations": false, // Optional. Default=true
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName} when multipleInterfaces != ByEndpoint
"operationNameTemplate": "{operationName}Async", // Optional. Must contain {operationName}. When multipleInterfaces == "ByEndpoint", this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
"optionalParameters": false, // Optional. Default=false
"outputFolder": "../CustomOutput" // Optional. Default=./Generated
"outputFilename": "RefitInterface.cs", // Optional. Default=Output.cs for CLI tool
Expand Down Expand Up @@ -147,7 +147,7 @@ The following is an example `.refitter` file
- `includeTags` - A collection of tags to use a filter for including endpoints that contain this tag.
- `includePathMatches` - A collection of regular expressions used to filter paths.
- `generateDeprecatedOperations` - a boolean indicating whether deprecated operations should be generated or skipped. Default is `true`
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using `"multipleIinterfaces": "ByEndpoint"`, This is name of the Execute() method in the interface
- `operationNameTemplate` - Generate operation names using pattern. This must contain the string {operationName}. An example usage of this could be `{operationName}Async` to suffix all method names with Async. When using multiple interfaces with `ByEndpoint`, this is name of the Execute() method in the interface where all instances of the string '{operationName}' is replaced with 'Execute'
- `optionalParameters` - Generate non-required parameters as nullable optional parameters
- `useDynamicQuerystringParameters`: Set to `true` to wrap multiple query parameters into a single complex one. Default is `false` (no wrapping).
- `dependencyInjectionSettings` - Setting this will generated extension methods to `IServiceCollection` for configuring Refit clients. See <https://github.com/reactiveui/refit?tab=readme-ov-file#dynamic-querystring-parameters> for more information.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
using FluentAssertions;
using Refitter.Tests.TestUtilities;
using Refitter.Core;
using Refitter.Tests.Build;
using Xunit;

namespace Refitter.Tests.Examples;

public class MultipleInterfacesByEndpointWithOperationNameTests
{
private const string OpenApiSpec = @"
openapi: '3.0.0'
paths:
/foo/{id}:
get:
tags:
- 'Foo'
operationId: 'Get foo details'
description: 'Get the details of the specified foo'
parameters:
- in: 'path'
name: 'id'
description: 'Foo ID'
required: true
schema:
type: 'string'
- in: 'query'
name: 'Title'
description: 'Job title'
nullable: true
schema:
type: 'string'
- in: 'query'
name: 'Description'
description: 'Job description'
optional: true
schema:
type: 'string'
- in: 'query'
name: 'Contact'
description: 'Contact Person'
schema:
type: 'string'
responses:
'200':
description: 'successful operation'
/foo:
get:
tags:
- 'Foo'
operationId: 'Get all foos'
description: 'Get all foos'
parameters:
- in: 'query'
name: 'Title'
description: 'Foo title'
nullable: true
schema:
type: 'string'
responses:
'200':
description: 'successful operation'
/bar:
get:
tags:
- 'Bar'
operationId: 'Get all bars'
description: 'Get all bars'
responses:
'200':
description: 'successful operation'
/bar/{id}:
get:
tags:
- 'Bar'
operationId: 'Get bar details'
description: 'Get the details of the specified bar'
parameters:
- in: 'path'
name: 'id'
description: 'Bar ID'
required: true
schema:
type: 'string'
- in: 'query'
name: 'Title'
description: 'Bar title'
nullable: true
schema:
type: 'string'
- in: 'query'
name: 'Description'
description: 'Bar description'
optional: true
schema:
type: 'string'
- in: 'query'
name: 'Contact'
description: 'Contact Person'
schema:
type: 'string'
responses:
'200':
description: 'successful operation'
";

[Fact]
public async Task Can_Generate_Code()
{
string generatedCode = await GenerateCode();
generatedCode.Should().NotBeNullOrWhiteSpace();
}

[Fact]
public async Task Generates_IGetAllFooEndpoint()
{
string generatedCode = await GenerateCode();
generatedCode.Should().Contain("partial interface IGetAllFoosEndpoint");
}

[Fact]
public async Task Generates_IGetFooDetailsEndpoint()
{
string generatedCode = await GenerateCode();
generatedCode.Should().Contain("partial interface IGetFooDetailsEndpoint");
}

[Fact]
public async Task Generates_IGetAllBarEndpoint()
{
string generatedCode = await GenerateCode();
generatedCode.Should().Contain("partial interface IGetAllBarsEndpoint");
}

[Fact]
public async Task Generates_IGetBarDetailsEndpoint()
{
string generatedCode = await GenerateCode();
generatedCode.Should().Contain("partial interface IGetBarDetailsEndpoint");
}

[Fact]
public async Task Generates_Dynamic_Querystring_Parameters()
{
string generatedCode = await GenerateCode(true);
generatedCode.Should().Contain("GetFooDetailsQueryParams");
generatedCode.Should().NotContain("GetAllFoosQueryParams");
generatedCode.Should().Contain("GetBarDetailsQueryParams");
}

[Fact]
public async Task Methods_Name_ExecuteAsync()
{
string generatedCode = await GenerateCode();
generatedCode.Should().Contain("ExecuteAsync");
}

[Fact]
public async Task Can_Build_Generated_Code()
{
string generatedCode = await GenerateCode();
BuildHelper
.BuildCSharp(generatedCode)
.Should()
.BeTrue();
}

private static async Task<string> GenerateCode(bool useDynamicQuerystringParameters = false)
{
var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec);
var settings = new RefitGeneratorSettings
{
OpenApiPath = swaggerFile,
MultipleInterfaces = MultipleInterfaces.ByEndpoint,
UseDynamicQuerystringParameters = useDynamicQuerystringParameters,
OperationNameTemplate = "{operationName}Async",
ImmutableRecords = true
};

var sut = await RefitGenerator.CreateAsync(settings);
var generatedCode = sut.Generate();
return generatedCode;
}

}
2 changes: 1 addition & 1 deletion src/Refitter.Tests/Examples/OpenApiUrlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ public async Task Can_Build_Generated_Code_From_OpenApi_v3_Url_Yaml(string url)
.Should()
.BeTrue(url);
}
#endif
}
#endif
Loading
Loading