diff --git a/src/NSwag.CodeGeneration.CSharp.Tests/CSharpClientSettingsTests.cs b/src/NSwag.CodeGeneration.CSharp.Tests/CSharpClientSettingsTests.cs index 20cb28966..d2083b6e6 100644 --- a/src/NSwag.CodeGeneration.CSharp.Tests/CSharpClientSettingsTests.cs +++ b/src/NSwag.CodeGeneration.CSharp.Tests/CSharpClientSettingsTests.cs @@ -9,6 +9,7 @@ public class CSharpClientSettingsTests { public class FooController : Controller { + [Obsolete("Testing generation of obsolete endpoints")] public object GetPerson(bool @override = false) { return null; @@ -104,6 +105,7 @@ public async Task When_parameter_name_is_reserved_keyword_then_it_is_appended_wi // Assert Assert.Contains("Task GetPersonAsync(bool? @override, ", code); + Assert.Contains("Obsolete", code); } [Fact] @@ -247,5 +249,53 @@ public async Task When_client_interface_generation_is_enabled_and_suppressed_the Assert.DoesNotContain("public partial interface IFooClient", code); Assert.Contains("public partial class FooClient : IFooClient", code); } + + [Fact] + public async Task When_regex_is_set_to_excluded_endpoints_the_client_will_not_generate_these_endpoint() + { + // Arrange + var swaggerGenerator = new WebApiOpenApiDocumentGenerator(new WebApiOpenApiDocumentGeneratorSettings + { + SchemaSettings = new NewtonsoftJsonSchemaGeneratorSettings() + }); + + var document = await swaggerGenerator.GenerateForControllerAsync(); + string firstPath = document.Paths.Keys.First(); + var generator = new CSharpClientGenerator(document, new CSharpClientGeneratorSettings + { + GenerateClientClasses = true, + ExcludeByPathRegex = firstPath.Replace("/", "\\/").TrimStart('/') // path: "/api/Foo" so corresponding regex is "api\/Foo" + }); + + // Act + var code = generator.GenerateFile(); + + // Assert + Assert.DoesNotContain("GetPerson", code); + } + + [Fact] + public async Task When_depreacted_endpoints_are_excluded_the_client_will_not_generate_these_endpoint() + { + // Arrange + var swaggerGenerator = new WebApiOpenApiDocumentGenerator(new WebApiOpenApiDocumentGeneratorSettings + { + SchemaSettings = new NewtonsoftJsonSchemaGeneratorSettings() + }); + + var document = await swaggerGenerator.GenerateForControllerAsync(); + var generator = new CSharpClientGenerator(document, new CSharpClientGeneratorSettings + { + GenerateClientClasses = true, + ExcludeDeprecated = true + }); + + // Act + var code = generator.GenerateFile(); + + // Assert + Assert.DoesNotContain("GetPerson", code); + Assert.DoesNotContain("Obsolete", code); + } } } \ No newline at end of file diff --git a/src/NSwag.CodeGeneration.TypeScript.Tests/TypeScriptClientSettingTests.cs b/src/NSwag.CodeGeneration.TypeScript.Tests/TypeScriptClientSettingTests.cs new file mode 100644 index 000000000..812ace8a2 --- /dev/null +++ b/src/NSwag.CodeGeneration.TypeScript.Tests/TypeScriptClientSettingTests.cs @@ -0,0 +1,80 @@ +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using NJsonSchema.CodeGeneration.TypeScript; +using NSwag.Generation.WebApi; +using System.Runtime.Serialization; +using Xunit; +using NJsonSchema.NewtonsoftJson.Converters; +using NJsonSchema; +using NJsonSchema.NewtonsoftJson.Generation; +using static NSwag.CodeGeneration.TypeScript.Tests.OperationParameterTests; + +namespace NSwag.CodeGeneration.TypeScript.Tests +{ + public class TypeScriptClientSettingTests + { + public class FooController + { + [Route("test")] + public string Test(int a, int? b) + { + return null; + } + + [Obsolete("Obsolete endpoint for testing")] + [Route("obsoleteEndpoint")] + public string ObsoleteEndpoint(int a, int? b) + { + return null; + } + } + + [Fact] + public async Task When_depreacted_endpoints_are_excluded_the_client_will_not_generate_these_endpoint() + { + // Arrange + var swaggerGenerator = new WebApiOpenApiDocumentGenerator(new WebApiOpenApiDocumentGeneratorSettings + { + SchemaSettings = new NewtonsoftJsonSchemaGeneratorSettings() + }); + + var document = await swaggerGenerator.GenerateForControllerAsync(); + var generator = new TypeScriptClientGenerator(document, new TypeScriptClientGeneratorSettings + { + ExcludeDeprecated = true + }); + + // Act + var code = generator.GenerateFile(); + + // Assert + Assert.DoesNotContain("obsoleteEndpoint", code); + Assert.DoesNotContain("deprecated", code); + Assert.Contains("test", code); // contains other endpoint + } + + [Fact] + public async Task When_regex_is_set_to_excluded_endpoints_the_client_will_not_generate_these_endpoint() + { + // Arrange + var swaggerGenerator = new WebApiOpenApiDocumentGenerator(new WebApiOpenApiDocumentGeneratorSettings + { + SchemaSettings = new NewtonsoftJsonSchemaGeneratorSettings() + }); + + var document = await swaggerGenerator.GenerateForControllerAsync(); + var generator = new TypeScriptClientGenerator(document, new TypeScriptClientGeneratorSettings + { + ExcludeByPathRegex = "test" + }); + + // Act + var code = generator.GenerateFile(); + + // Assert + Assert.DoesNotContain("foo", code); + Assert.Contains("obsoleteEndpoint", code); // contains other endpoint + Assert.Contains("deprecated", code); + } + } +} diff --git a/src/NSwag.CodeGeneration/ClientGeneratorBase.cs b/src/NSwag.CodeGeneration/ClientGeneratorBase.cs index eccc67c2d..83da754b6 100644 --- a/src/NSwag.CodeGeneration/ClientGeneratorBase.cs +++ b/src/NSwag.CodeGeneration/ClientGeneratorBase.cs @@ -9,6 +9,7 @@ using NJsonSchema; using NJsonSchema.CodeGeneration; using NSwag.CodeGeneration.Models; +using System.Text.RegularExpressions; namespace NSwag.CodeGeneration { @@ -162,6 +163,17 @@ private List GetOperations(OpenApiDocument document) var httpMethod = p.Key; var operation = p.Value; + if (this.BaseSettings.ExcludeDeprecated && operation.IsDeprecated) + { + continue; + } + + if (!string.IsNullOrWhiteSpace(this.BaseSettings.ExcludeByPathRegex) && Regex.IsMatch(pair.Key, this.BaseSettings.ExcludeByPathRegex)) + { + continue; + } + + var operationName = BaseSettings.OperationNameGenerator.GetOperationName(document, path, httpMethod, operation); @@ -181,7 +193,6 @@ private List GetOperations(OpenApiDocument document) operationModel.Path = path; operationModel.HttpMethod = httpMethod; operationModel.OperationName = operationName; - result.Add(operationModel); } } diff --git a/src/NSwag.CodeGeneration/ClientGeneratorBaseSettings.cs b/src/NSwag.CodeGeneration/ClientGeneratorBaseSettings.cs index 88d40e258..2e2c26a92 100644 --- a/src/NSwag.CodeGeneration/ClientGeneratorBaseSettings.cs +++ b/src/NSwag.CodeGeneration/ClientGeneratorBaseSettings.cs @@ -85,5 +85,11 @@ public virtual string GenerateControllerName(string controllerName) /// Gets or sets the name of the response class (supports the '{controller}' placeholder). public string ResponseClass { get; set; } + + /// Gets or sets the value indicating if deprecated endpoints shall be rendered + public bool ExcludeDeprecated { get; set; } + + /// Gets or sets the regular expression to indicate for which path's client code should be generated (null/empty means all) + public string ExcludeByPathRegex { get; set; } } } \ No newline at end of file diff --git a/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs b/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs index 4b6a24801..5b0084288 100644 --- a/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs +++ b/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToCSharpClientCommand.cs @@ -261,6 +261,20 @@ public string QueryNullValue set => Settings.QueryNullValue = value; } + [Argument(Name = "ExcludeDeprecated", IsRequired = false, Description = "Specifies if deprecated endpoints should be generated")] + public bool ExcludeDeprecated + { + get { return Settings.ExcludeDeprecated; } + set { Settings.ExcludeDeprecated = value; } + } + + [Argument(Name = "ExcludeByPathRegex", IsRequired = false, Description = "The regex which defines endpoints should not be genereated (regex is applied to path)")] + public string ExcludeByPathRegex + { + get { return Settings.ExcludeByPathRegex; } + set { Settings.ExcludeByPathRegex = value; } + } + public override async Task RunAsync(CommandLineProcessor processor, IConsoleHost host) { var result = await RunAsync(); diff --git a/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToTypeScriptClientCommand.cs b/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToTypeScriptClientCommand.cs index 01d96e013..f32c28196 100644 --- a/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToTypeScriptClientCommand.cs +++ b/src/NSwag.Commands/Commands/CodeGeneration/OpenApiToTypeScriptClientCommand.cs @@ -392,6 +392,20 @@ public bool IncludeHttpContext set => Settings.IncludeHttpContext = value; } + [Argument(Name = "ExcludeDeprecated", IsRequired = false, Description = "Specifies if deprecated endpoints should be generated")] + public bool ExcludeDeprecated + { + get { return Settings.ExcludeDeprecated; } + set { Settings.ExcludeDeprecated = value; } + } + + [Argument(Name = "ExcludeByPathRegex", IsRequired = false, Description = "The regex which defines endpoints should not be genereated (regex is applied to path)")] + public string ExcludeByPathRegex + { + get { return Settings.ExcludeByPathRegex; } + set { Settings.ExcludeByPathRegex = value; } + } + public override async Task RunAsync(CommandLineProcessor processor, IConsoleHost host) { var code = await RunAsync(); diff --git a/src/NSwag.Sample.NET80Minimal/nswag.json b/src/NSwag.Sample.NET80Minimal/nswag.json index 3c1f7acba..1d6ff9ff2 100644 --- a/src/NSwag.Sample.NET80Minimal/nswag.json +++ b/src/NSwag.Sample.NET80Minimal/nswag.json @@ -73,6 +73,8 @@ "inlineNamedDictionaries": false, "inlineNamedAny": false, "includeHttpContext": false, + "excludeDeprecated": false, + "excludeByPathRegex": null, "templateDirectory": null, "serviceHost": null, "serviceSchemes": null, @@ -114,6 +116,8 @@ "useRequestAndResponseSerializationSettings": false, "serializeTypeInformation": false, "queryNullValue": "", + "excludeDeprecated": false, + "excludeByPathRegex": null, "className": "{controller}Client", "operationGenerationMode": "MultipleClientsFromOperationId", "additionalNamespaceUsages": [], diff --git a/src/NSwag.Sample.NET90Minimal/nswag.json b/src/NSwag.Sample.NET90Minimal/nswag.json index 720f576a3..de153f33f 100644 --- a/src/NSwag.Sample.NET90Minimal/nswag.json +++ b/src/NSwag.Sample.NET90Minimal/nswag.json @@ -73,6 +73,8 @@ "inlineNamedDictionaries": false, "inlineNamedAny": false, "includeHttpContext": false, + "excludeDeprecated": false, + "excludeByPathRegex": null, "templateDirectory": null, "serviceHost": null, "serviceSchemes": null, @@ -114,6 +116,8 @@ "useRequestAndResponseSerializationSettings": false, "serializeTypeInformation": false, "queryNullValue": "", + "excludeDeprecated": false, + "excludeByPathRegex": null, "className": "{controller}Client", "operationGenerationMode": "MultipleClientsFromOperationId", "additionalNamespaceUsages": [], diff --git a/src/NSwagStudio/Views/CodeGenerators/SwaggerToCSharpClientGeneratorView.xaml b/src/NSwagStudio/Views/CodeGenerators/SwaggerToCSharpClientGeneratorView.xaml index 4de29841a..2b3388032 100644 --- a/src/NSwagStudio/Views/CodeGenerators/SwaggerToCSharpClientGeneratorView.xaml +++ b/src/NSwagStudio/Views/CodeGenerators/SwaggerToCSharpClientGeneratorView.xaml @@ -44,15 +44,15 @@ ToolTip="AdditionalNamespaceUsages" Margin="0,0,0,12" /> - - + + + + + + + + + + + + +