diff --git a/README.md b/README.md index 1ac4aa093..d66a08536 100644 --- a/README.md +++ b/README.md @@ -211,8 +211,11 @@ OPTIONS: --disableCodingRules Disable ATC-Coding-Rules --useProblemDetailsAsDefaultResponseBody Use ProblemDetails as default responsen body --endpointsLocation [ENDPOINTSLOCATION] If endpoints-localtion is provided, generated files will be placed here instead of the Endpoints folder + --endpointsNamespace [ENDPOINTSNAMESPACE] If endpoints-namespace is provided, generated files will be placed here instead of the Endpoints namespace --contractsLocation [CONTRACTSLOCATION] If contracts-localtion is provided, generated files will be placed here instead of the Contracts folder + --contractsNamespace [CONTRACTSNAMESPACE] If contracts-namespace is provided, generated files will be placed here instead of the Contracts namespace --handlersLocation [HANDLERSLOCATION] If handlers-localtion is provided, generated files will be placed here instead of the Handlers folder + --handlersNamespace [HANDLERSNAMESPACE] If handlers-namespace is provided, generated files will be placed here instead of the Handlers namespace --usePartialClassForContracts Use Partial-Class for contracts --usePartialClassForEndpoints Use Partial-Class for endpoints --removeNamespaceGroupSeparatorInGlobalUsings Remove space between namespace groups in GlobalUsing.cs @@ -256,8 +259,11 @@ COMMANDS: "projectName": "", "projectSuffixName": "", "contractsLocation": "Contracts.[[apiGroupName]]", + "contractsNamespace": "Contracts.[[apiGroupName]]", "endpointsLocation": "Endpoints.[[apiGroupName]]", + "endpointsNamespace": "Endpoints.[[apiGroupName]]", "handlersLocation": "Handlers.[[apiGroupName]]", + "handlersNamespace": "Handlers.[[apiGroupName]]", "usePartialClassForContracts": false, "usePartialClassForEndpoints": false, "removeNamespaceGroupSeparatorInGlobalUsings": false, @@ -288,8 +294,11 @@ COMMANDS: "projectName": "", "projectSuffixName": "", "contractsLocation": "Contracts.[[apiGroupName]]", + "contractsNamespace": "Contracts.[[apiGroupName]]", "endpointsLocation": "Endpoints.[[apiGroupName]]", + "endpointsNamespace": "Endpoints.[[apiGroupName]]", "handlersLocation": "Handlers.[[apiGroupName]]", + "handlersNamespace": "Handlers.[[apiGroupName]]", "usePartialClassForContracts": false, "usePartialClassForEndpoints": false, "removeNamespaceGroupSeparatorInGlobalUsings": false, @@ -346,7 +355,7 @@ You can use specific syntax to define and customize the output file structure. ##### Syntax -For options like `contractsLocation`, `endpointsLocation`, and `handlersLocation`, +For options like `contractsLocation`, `contractsNamespace`, `endpointsLocation`, `endpointsNamespace`, `handlersLocation`, `handlersNamespace`, you can define paths using placeholders and custom directory names. The syntax is flexible and allows you to organize files based on grouping or specific requirements. @@ -355,13 +364,20 @@ The syntax is flexible and allows you to organize files based on grouping or spe | Option-Name | Option-Value | Example-file | Generated-output | |-------------|--------------|--------------|------------------| -| contractsLocation | Contracts | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | -| contractsLocation | Contracts.[[apiGroupName]] | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | -| contractsLocation | Contracts-[[apiGroupName]] | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | -| contractsLocation | [[apiGroupName]].MyContracts | Account.cs | [Project-root]\Accounts\MyContracts\Account.cs | -| contractsLocation | [[apiGroupName]]-MyContracts | Account.cs | [Project-root]\Accounts\MyContracts\Account.cs | -| contractsLocation | [[apiGroupName]] | Account.cs | [Project-root]\Accounts\Account.cs | -| contractsLocation | . | Account.cs | [Project-root]\Account.cs | +| contractsLocation | Contracts | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | +| contractsLocation | Contracts.[[apiGroupName]] | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | +| contractsLocation | Contracts-[[apiGroupName]] | Account.cs | [Project-root]\Contracts\Accounts\Account.cs | +| contractsLocation | [[apiGroupName]].MyContracts | Account.cs | [Project-root]\Accounts\MyContracts\Account.cs | +| contractsLocation | [[apiGroupName]]-MyContracts | Account.cs | [Project-root]\Accounts\MyContracts\Account.cs | +| contractsLocation | [[apiGroupName]] | Account.cs | [Project-root]\Accounts\Account.cs | +| contractsLocation | . | Account.cs | [Project-root]\Account.cs | +| contractsNamespace | Contracts | Account.cs | [Project-root].Contracts.Accounts.Account.cs | +| contractsNamespace | Contracts.[[apiGroupName]] | Account.cs | [Project-root].Contracts.Accounts.Account.cs | +| contractsNamespace | Contracts-[[apiGroupName]] | Account.cs | [Project-root].Contracts.Accounts.Account.cs | +| contractsNamespace | [[apiGroupName]].MyContracts | Account.cs | [Project-root].Accounts.MyContracts.Account.cs | +| contractsNamespace | [[apiGroupName]]-MyContracts | Account.cs | [Project-root].Accounts.MyContracts.Account.cs | +| contractsNamespace | [[apiGroupName]] | Account.cs | [Project-root].Accounts.Account.cs | +| contractsNamespace | . | Account.cs | [Project-root].Account.cs | > Placeholder Explanation: > diff --git a/src/Atc.Rest.ApiGenerator.CLI/ApiOptionsHelper.cs b/src/Atc.Rest.ApiGenerator.CLI/ApiOptionsHelper.cs index d9d09ac63..f441f92ea 100644 --- a/src/Atc.Rest.ApiGenerator.CLI/ApiOptionsHelper.cs +++ b/src/Atc.Rest.ApiGenerator.CLI/ApiOptionsHelper.cs @@ -154,16 +154,28 @@ private static void ApplyGeneratorOverrides( apiOptions.Generator.ProjectName = serverCommandSettings.ProjectPrefixName; } + if (serverCommandSettings.EndpointsLocation is not null && + serverCommandSettings.EndpointsLocation.IsSet) + { + apiOptions.Generator.EndpointsLocation = serverCommandSettings.EndpointsLocation.Value; + } + + if (serverCommandSettings.EndpointsNamespace is not null && + serverCommandSettings.EndpointsNamespace.IsSet) + { + apiOptions.Generator.EndpointsNamespace = serverCommandSettings.EndpointsNamespace.Value; + } + if (serverCommandSettings.ContractsLocation is not null && serverCommandSettings.ContractsLocation.IsSet) { apiOptions.Generator.ContractsLocation = serverCommandSettings.ContractsLocation.Value; } - if (serverCommandSettings.EndpointsLocation is not null && - serverCommandSettings.EndpointsLocation.IsSet) + if (serverCommandSettings.ContractsNamespace is not null && + serverCommandSettings.ContractsNamespace.IsSet) { - apiOptions.Generator.EndpointsLocation = serverCommandSettings.EndpointsLocation.Value; + apiOptions.Generator.ContractsNamespace = serverCommandSettings.ContractsNamespace.Value; } if (serverCommandSettings.HandlersLocation is not null && @@ -172,6 +184,12 @@ private static void ApplyGeneratorOverrides( apiOptions.Generator.HandlersLocation = serverCommandSettings.HandlersLocation.Value; } + if (serverCommandSettings.HandlersNamespace is not null && + serverCommandSettings.HandlersNamespace.IsSet) + { + apiOptions.Generator.HandlersNamespace = serverCommandSettings.HandlersNamespace.Value; + } + if (serverCommandSettings.UsePartialClassForContracts) { apiOptions.Generator.UsePartialClassForContracts = serverCommandSettings.UsePartialClassForContracts; @@ -212,16 +230,28 @@ private static void ApplyGeneratorOverrides( apiOptions.Generator.ProjectSuffixName = $"{ContentGeneratorConstants.DefaultHttpClientName}.Generated"; } + if (clientApiCommandSettings.EndpointsLocation is not null && + clientApiCommandSettings.EndpointsLocation.IsSet) + { + apiOptions.Generator.EndpointsLocation = clientApiCommandSettings.EndpointsLocation.Value; + } + + if (clientApiCommandSettings.EndpointsNamespace is not null && + clientApiCommandSettings.EndpointsNamespace.IsSet) + { + apiOptions.Generator.EndpointsNamespace = clientApiCommandSettings.EndpointsNamespace.Value; + } + if (clientApiCommandSettings.ContractsLocation is not null && clientApiCommandSettings.ContractsLocation.IsSet) { apiOptions.Generator.ContractsLocation = clientApiCommandSettings.ContractsLocation.Value; } - if (clientApiCommandSettings.EndpointsLocation is not null && - clientApiCommandSettings.EndpointsLocation.IsSet) + if (clientApiCommandSettings.ContractsNamespace is not null && + clientApiCommandSettings.ContractsNamespace.IsSet) { - apiOptions.Generator.EndpointsLocation = clientApiCommandSettings.EndpointsLocation.Value; + apiOptions.Generator.ContractsNamespace = clientApiCommandSettings.ContractsNamespace.Value; } if (clientApiCommandSettings.UsePartialClassForContracts) diff --git a/src/Atc.Rest.ApiGenerator.CLI/Commands/ArgumentCommandConstants.cs b/src/Atc.Rest.ApiGenerator.CLI/Commands/ArgumentCommandConstants.cs index cb385698f..ba492c320 100644 --- a/src/Atc.Rest.ApiGenerator.CLI/Commands/ArgumentCommandConstants.cs +++ b/src/Atc.Rest.ApiGenerator.CLI/Commands/ArgumentCommandConstants.cs @@ -21,8 +21,11 @@ public static class ArgumentCommandConstants public const string LongConfigurationValidateModelPropertyNameCasingStyle = "--validate-modelPropertyNameCasingStyle"; public const string LongEndpointsLocation = "--endpointsLocation"; + public const string LongEndpointsNamespace = "--endpointsNamespace"; public const string LongContractsLocation = "--contractsLocation"; + public const string LongContractsNamespace = "--contractsNamespace"; public const string LongHandlersLocation = "--handlersLocation"; + public const string LongHandlersNamespace = "--handlersNamespace"; public const string LongClientHttpClientName = "--httpClientName"; public const string LongExcludeEndpointGeneration = "--excludeEndpointGeneration"; diff --git a/src/Atc.Rest.ApiGenerator.CLI/Commands/Settings/BaseGenerateCommandSettings.cs b/src/Atc.Rest.ApiGenerator.CLI/Commands/Settings/BaseGenerateCommandSettings.cs index 1234d1990..c1892a948 100644 --- a/src/Atc.Rest.ApiGenerator.CLI/Commands/Settings/BaseGenerateCommandSettings.cs +++ b/src/Atc.Rest.ApiGenerator.CLI/Commands/Settings/BaseGenerateCommandSettings.cs @@ -18,14 +18,26 @@ public class BaseGenerateCommandSettings : BaseConfigurationCommandSettings [Description($"If endpoints-localtion is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Endpoints} folder.")] public FlagValue? EndpointsLocation { get; init; } + [CommandOption($"{ArgumentCommandConstants.LongEndpointsNamespace} [ENDPOINTSNAMESPACE]")] + [Description($"If endpoints-namespace is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Endpoints} namespace.")] + public FlagValue? EndpointsNamespace { get; init; } + [CommandOption($"{ArgumentCommandConstants.LongContractsLocation} [CONTRACTSLOCATION]")] [Description($"If contracts-localtion is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Contracts} folder.")] public FlagValue? ContractsLocation { get; init; } + [CommandOption($"{ArgumentCommandConstants.LongContractsNamespace} [CONTRACTSNAMESPACE]")] + [Description($"If contracts-namespace is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Contracts} namespace.")] + public FlagValue? ContractsNamespace { get; init; } + [CommandOption($"{ArgumentCommandConstants.LongHandlersLocation} [HANDLERSLOCATION]")] [Description($"If handlers-localtion is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Handlers} folder.")] public FlagValue? HandlersLocation { get; init; } + [CommandOption($"{ArgumentCommandConstants.LongHandlersNamespace} [HANDLERSNAMESPACE]")] + [Description($"If handlers-namespace is provided, generated files will be placed here instead of the {ContentGeneratorConstants.Handlers} namespace.")] + public FlagValue? HandlersNamespace { get; init; } + [CommandOption(ArgumentCommandConstants.LongUsePartialClassForContracts)] [Description("Use Partial-Class for contracts")] public bool UsePartialClassForContracts { get; init; } diff --git a/src/Atc.Rest.ApiGenerator.Client.CSharp/ProjectGenerator/ClientCSharpApiGenerator.cs b/src/Atc.Rest.ApiGenerator.Client.CSharp/ProjectGenerator/ClientCSharpApiGenerator.cs index 91c45ca92..54c7d9173 100644 --- a/src/Atc.Rest.ApiGenerator.Client.CSharp/ProjectGenerator/ClientCSharpApiGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Client.CSharp/ProjectGenerator/ClientCSharpApiGenerator.cs @@ -128,9 +128,13 @@ public void GenerateParameters() { var apiGroupName = openApiPath.GetApiGroupName(); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractNamespaceWithoutApiGroupName = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -148,7 +152,8 @@ public void GenerateParameters() var parameterParameters = ContentGeneratorClientParameterParametersFactory.Create( fullNamespace, openApiOperation.Value, - openApiPath.Value.Parameters); + openApiPath.Value.Parameters, + contractNamespaceWithoutApiGroupName); var contentGenerator = new ContentGeneratorClientParameter( new GeneratedCodeHeaderGenerator(new GeneratedCodeGeneratorParameters(settings.Version)), @@ -174,9 +179,11 @@ public void GenerateEndpointInterfaces() { var apiGroupName = openApiPath.GetApiGroupName(); - var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation) + $".{ContentGeneratorConstants.Interfaces}"; + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace) + $".{ContentGeneratorConstants.Interfaces}"; + + var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -216,10 +223,12 @@ public void GenerateEndpoints() { var apiGroupName = openApiPath.GetApiGroupName(); - var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace); + + var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -232,7 +241,7 @@ public void GenerateEndpoints() settings.ProjectName, apiGroupName, fullNamespace, - contractsLocation, + contractsNamespace, openApiPath.Value, openApiOperation.Key, openApiOperation.Value, @@ -266,10 +275,12 @@ public void GenerateEndpointResultInterfaces() { var apiGroupName = openApiPath.GetApiGroupName(); - var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation) + $".{ContentGeneratorConstants.Interfaces}"; + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace) + $".{ContentGeneratorConstants.Interfaces}"; + + var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -282,7 +293,7 @@ public void GenerateEndpointResultInterfaces() settings.ProjectName, apiGroupName, fullNamespace, - contractsLocation, + contractsNamespace, openApiPath.Value, openApiOperation.Value, settings.UsePartialClassForContracts); @@ -312,10 +323,12 @@ public void GenerateEndpointResults() { var apiGroupName = openApiPath.GetApiGroupName(); - var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation); + var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -328,7 +341,7 @@ public void GenerateEndpointResults() settings.ProjectName, apiGroupName, fullNamespace, - contractsLocation, + contractsNamespace, openApiPath.Value, openApiOperation.Value, settings.UsePartialClassForContracts); @@ -397,7 +410,7 @@ public void MaintainGlobalUsings( if (operationSchemaMappings.Any(apiOperation => apiOperation.Model.IsShared)) { - requiredUsings.Add(NamespaceFactory.Create(settings.ProjectName, LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation))); + requiredUsings.Add(NamespaceFactory.Create(settings.ProjectName, NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace))); } var apiGroupNames = openApiDocument.GetApiGroupNames(); @@ -405,7 +418,7 @@ public void MaintainGlobalUsings( { var apiGroupName = openApiPath.GetApiGroupName(); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -420,7 +433,7 @@ public void MaintainGlobalUsings( continue; } - var requiredUsing = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var requiredUsing = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); if (!requiredUsings.Contains(requiredUsing, StringComparer.CurrentCulture)) { requiredUsings.Add(requiredUsing); @@ -436,7 +449,7 @@ public void MaintainGlobalUsings( var apiOperationModels = GetDistinctApiOperationModels(apiOperations); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); foreach (var apiOperationModel in apiOperationModels) { @@ -451,7 +464,7 @@ public void MaintainGlobalUsings( continue; } - var requiredUsing = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var requiredUsing = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); if (!requiredUsings.Contains(requiredUsing, StringComparer.CurrentCulture)) { requiredUsings.Add(requiredUsing); @@ -459,7 +472,7 @@ public void MaintainGlobalUsings( } } - requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, LocationFactory.CreateWithApiGroupName(x, settings.EndpointsLocation), ContentGeneratorConstants.Interfaces))); + requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, NamespaceFactory.CreateWithApiGroupName(x, settings.EndpointsNamespace), ContentGeneratorConstants.Interfaces))); GlobalUsingsHelper.CreateOrUpdate( logger, @@ -473,9 +486,11 @@ private void GenerateEnumerationType( string enumerationName, OpenApiSchema openApiSchemaEnumeration) { - var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); var enumParameters = ContentGeneratorServerClientEnumParametersFactory.Create( codeGeneratorContentHeader, @@ -504,12 +519,16 @@ private void GenerateModel( string apiGroupName, bool isSharedContract) { + var contractsNamespace = isSharedContract + ? NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace) + : NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = isSharedContract ? LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation) : LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); - var parameters = ContentGeneratorServerClientModelParametersFactory.CreateForClass( codeGeneratorContentHeader, fullNamespace, @@ -543,9 +562,11 @@ private void GenerateCustomErrorResponseModel() return; } - var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); var parameters = ContentGeneratorServerClientModelParametersFactory.CreateForCustomErrorResponseModel( codeGeneratorContentHeader, diff --git a/src/Atc.Rest.ApiGenerator.Framework.Minimal/Factories/ContentGeneratorServerHandlerParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework.Minimal/Factories/ContentGeneratorServerHandlerParametersFactory.cs index 85faf73a2..982eb098b 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Minimal/Factories/ContentGeneratorServerHandlerParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Minimal/Factories/ContentGeneratorServerHandlerParametersFactory.cs @@ -4,12 +4,9 @@ public static class ContentGeneratorServerHandlerParametersFactory { public static ClassParameters Create( string @namespace, - string contractNamespace, OpenApiPathItem openApiPath, OpenApiOperation openApiOperation) { - ArgumentNullException.ThrowIfNull(openApiOperation); - var operationName = openApiOperation.GetOperationName(); var hasParameters = openApiPath.HasParameters() || diff --git a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerApiGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerApiGenerator.cs index a5a3f94bf..cf4e89847 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerApiGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerApiGenerator.cs @@ -150,9 +150,13 @@ public void GenerateParameters() { var apiGroupName = openApiPath.GetApiGroupName(); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractNamespaceWithoutApiGroupName = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -170,7 +174,8 @@ public void GenerateParameters() var parameterParameters = ContentGeneratorServerParameterParametersFactory.CreateForRecord( fullNamespace, openApiOperation.Value, - openApiPath.Value.Parameters); + openApiPath.Value.Parameters, + contractNamespaceWithoutApiGroupName); var contentGenerator = new ContentGenerators.ContentGeneratorServerParameter( new GeneratedCodeHeaderGenerator(new GeneratedCodeGeneratorParameters(settings.Version)), @@ -196,9 +201,11 @@ public void GenerateResults() { var apiGroupName = openApiPath.GetApiGroupName(); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -236,9 +243,11 @@ public void GenerateInterfaces() { var apiGroupName = openApiPath.GetApiGroupName(); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -274,9 +283,11 @@ public void GenerateEndpoints() { foreach (var apiGroupName in openApiDocument.GetApiGroupNames()) { - var endpointsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace); + + var endpointsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsLocation); var endpointParameters = ContentGeneratorServerEndpointParametersFactory.Create( operationSchemaMappings, @@ -352,7 +363,7 @@ public void MaintainGlobalUsings( { var requiredUsing = NamespaceFactory.Create( settings.ProjectName, - LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation)); + LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace)); if (!requiredUsings.Contains(requiredUsing, StringComparer.CurrentCulture)) { @@ -362,7 +373,7 @@ public void MaintainGlobalUsings( var apiGroupNames = openApiDocument.GetApiGroupNames(); - requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, LocationFactory.CreateWithApiGroupName(x, settings.ContractsLocation)))); + requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, NamespaceFactory.CreateWithApiGroupName(x, settings.ContractsNamespace)))); GlobalUsingsHelper.CreateOrUpdate( logger, @@ -378,7 +389,11 @@ private string GetRouteByApiGroupName( var (key, _) = openApiDocument.Paths.FirstOrDefault(x => x.IsPathStartingSegmentName(apiGroupName)); if (key is null) { - throw new NotSupportedException($"{nameof(apiGroupName)} was not found in any route."); + (key, _) = openApiDocument.Paths.FirstOrDefault(x => x.IsPathStartingApiGroupName(apiGroupName)); + if (key is null) + { + throw new NotSupportedException($"{nameof(apiGroupName)} was not found in any route."); + } } var routeSuffix = key @@ -392,9 +407,11 @@ private void GenerateEnumerationType( string enumerationName, OpenApiSchema openApiSchemaEnumeration) { - var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + + var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); var enumParameters = ContentGeneratorServerClientEnumParametersFactory.Create( codeGeneratorContentHeader, @@ -423,12 +440,16 @@ private void GenerateModel( string apiGroupName, bool isSharedContract) { + var contractsNamespace = isSharedContract + ? NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace) + : NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = isSharedContract ? LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation) : LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); - var parameters = ContentGeneratorServerClientModelParametersFactory.CreateForRecord( codeGeneratorContentHeader, fullNamespace, diff --git a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerDomainGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerDomainGenerator.cs index 12030a56d..2c5c626d1 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerDomainGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerDomainGenerator.cs @@ -108,15 +108,18 @@ public void ScaffoldHandlers() var apiGroupName = urlPath.GetApiGroupName(); var handlersLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.HandlersLocation); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); var fullNamespace = NamespaceFactory.Create(settings.ProjectName, handlersLocation); foreach (var openApiOperation in urlPath.Value.Operations) { + if (openApiOperation.Value.Deprecated && !settings.IncludeDeprecatedOperations) + { + continue; + } + var classParameters = ContentGeneratorServerHandlerParametersFactory.Create( fullNamespace, - $"Api.Generated.{contractsLocation}", // TODO: Fix this urlPath.Value, openApiOperation.Value); @@ -257,7 +260,7 @@ public void MaintainGlobalUsings( var apiGroupNames = openApiDocument.GetApiGroupNames(); - requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithApiGroupName(x, settings.ContractsLocation)))); + requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithApiGroupName(x, settings.ContractsNamespace)))); GlobalUsingsHelper.CreateOrUpdate( logger, diff --git a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerHostTestGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerHostTestGenerator.cs index 8a3f277db..4ab5cdce5 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerHostTestGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerHostTestGenerator.cs @@ -275,7 +275,7 @@ public void MaintainGlobalUsings( if (operationSchemaMappings.Any(apiOperation => apiOperation.Model.IsShared)) { - requiredUsings.Add(NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation))); + requiredUsings.Add(NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace))); } var apiGroupNames = openApiDocument.GetApiGroupNames(); @@ -287,7 +287,7 @@ public void MaintainGlobalUsings( continue; } - requiredUsings.Add(NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation))); + requiredUsings.Add(NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace))); } GlobalUsingsHelper.CreateOrUpdate( diff --git a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerApiGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerApiGenerator.cs index e0d6f125f..35f09a7e3 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerApiGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerApiGenerator.cs @@ -166,9 +166,13 @@ public void GenerateParameters() { var apiGroupName = openApiPath.GetApiGroupName(); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractNamespaceWithoutApiGroupName = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -186,7 +190,8 @@ public void GenerateParameters() var parameterParameters = ContentGeneratorServerParameterParametersFactory.CreateForClass( fullNamespace, openApiOperation.Value, - openApiPath.Value.Parameters); + openApiPath.Value.Parameters, + contractNamespaceWithoutApiGroupName); var contentGenerator = new ContentGenerators.ContentGeneratorServerParameter( new GeneratedCodeHeaderGenerator(new GeneratedCodeGeneratorParameters(settings.Version)), @@ -212,9 +217,11 @@ public void GenerateResults() { var apiGroupName = openApiPath.GetApiGroupName(); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -252,9 +259,11 @@ public void GenerateInterfaces() { var apiGroupName = openApiPath.GetApiGroupName(); - var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var contractsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); foreach (var openApiOperation in openApiPath.Value.Operations) { @@ -290,9 +299,11 @@ public void GenerateEndpoints() { foreach (var apiGroupName in openApiDocument.GetApiGroupNames()) { - var endpointsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsLocation); + var endpointsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace); + + var endpointsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.EndpointsLocation); var controllerParameters = ContentGeneratorServerEndpointParametersFactory.Create( operationSchemaMappings, @@ -364,7 +375,7 @@ public void MaintainGlobalUsings( { var requiredUsing = NamespaceFactory.Create( settings.ProjectName, - LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation)); + LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace)); if (!requiredUsings.Contains(requiredUsing, StringComparer.CurrentCulture)) { @@ -374,7 +385,7 @@ public void MaintainGlobalUsings( var apiGroupNames = openApiDocument.GetApiGroupNames(); - requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, LocationFactory.CreateWithApiGroupName(x, settings.ContractsLocation)))); + requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(settings.ProjectName, NamespaceFactory.CreateWithApiGroupName(x, settings.ContractsNamespace)))); GlobalUsingsHelper.CreateOrUpdate( logger, @@ -390,7 +401,11 @@ private string GetRouteByApiGroupName( var (key, _) = openApiDocument.Paths.FirstOrDefault(x => x.IsPathStartingSegmentName(apiGroupName)); if (key is null) { - throw new NotSupportedException($"{nameof(apiGroupName)} was not found in any route."); + (key, _) = openApiDocument.Paths.FirstOrDefault(x => x.IsPathStartingApiGroupName(apiGroupName)); + if (key is null) + { + throw new NotSupportedException($"{nameof(apiGroupName)} was not found in any route."); + } } var routeSuffix = key @@ -404,9 +419,11 @@ private void GenerateEnumerationType( string enumerationName, OpenApiSchema openApiSchemaEnumeration) { - var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); + var contractsNamespace = NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + + var contractsLocation = LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation); var enumParameters = ContentGeneratorServerClientEnumParametersFactory.Create( codeGeneratorContentHeader, @@ -435,12 +452,16 @@ private void GenerateModel( string apiGroupName, bool isSharedContract) { + var contractsNamespace = isSharedContract + ? NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace) + : NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace); + + var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsNamespace); + var contractsLocation = isSharedContract ? LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation) : LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation); - var fullNamespace = NamespaceFactory.Create(settings.ProjectName, contractsLocation); - var parameters = ContentGeneratorServerClientModelParametersFactory.CreateForClass( codeGeneratorContentHeader, fullNamespace, diff --git a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerDomainGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerDomainGenerator.cs index 284189913..f64ca605a 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerDomainGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerDomainGenerator.cs @@ -97,6 +97,11 @@ public void ScaffoldHandlers() foreach (var openApiOperation in urlPath.Value.Operations) { + if (openApiOperation.Value.Deprecated && !settings.IncludeDeprecatedOperations) + { + continue; + } + var classParameters = ContentGeneratorServerHandlerParametersFactory.Create( fullNamespace, urlPath.Value, @@ -154,7 +159,7 @@ public void MaintainGlobalUsings( var apiGroupNames = openApiDocument.GetApiGroupNames(); - requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithApiGroupName(x, settings.ContractsLocation)))); + requiredUsings.AddRange(apiGroupNames.Select(x => NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithApiGroupName(x, settings.ContractsNamespace)))); GlobalUsingsHelper.CreateOrUpdate( logger, diff --git a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerHostTestGenerator.cs b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerHostTestGenerator.cs index 5fda32d74..5a3525c4f 100644 --- a/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerHostTestGenerator.cs +++ b/src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerHostTestGenerator.cs @@ -277,7 +277,7 @@ public void MaintainGlobalUsings( if (operationSchemaMappings.Any(apiOperation => apiOperation.Model.IsShared)) { - requiredUsings.Add(NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsLocation))); + requiredUsings.Add(NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithoutTemplateForApiGroupName(settings.ContractsNamespace))); } requiredUsings.Add("AutoFixture"); @@ -292,7 +292,7 @@ public void MaintainGlobalUsings( continue; } - requiredUsings.Add(NamespaceFactory.Create(apiProjectName, LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsLocation))); + requiredUsings.Add(NamespaceFactory.Create(apiProjectName, NamespaceFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace))); } GlobalUsingsHelper.CreateOrUpdate( diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/NamespaceFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/NamespaceFactory.cs index da0e302fd..f12b9b922 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/NamespaceFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/NamespaceFactory.cs @@ -21,4 +21,13 @@ public static string Create( return fullNamespace; } + + public static string CreateWithApiGroupName( + string apiGroupName, + string value) + => LocationFactory.CreateWithApiGroupName(apiGroupName, value); + + public static string CreateWithoutTemplateForApiGroupName( + string value) + => LocationFactory.CreateWithoutTemplateForApiGroupName(value); } \ No newline at end of file diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointParametersFactory.cs index 9573dbf70..f56b3584c 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointParametersFactory.cs @@ -6,7 +6,7 @@ public static ContentGeneratorClientEndpointParameters Create( string projectName, string apiGroupName, string @namespace, - string contractsLocation, + string contractsNamespace, OpenApiPathItem openApiPath, OperationType httpMethod, OpenApiOperation openApiOperation, @@ -23,7 +23,7 @@ public static ContentGeneratorClientEndpointParameters Create( AppendParameters(parameters, openApiOperation.Parameters); AppendParametersFromBody(parameters, openApiOperation.RequestBody); - var modelNamespace = NamespaceFactory.Create(projectName, contractsLocation); + var modelNamespace = NamespaceFactory.Create(projectName, contractsNamespace); var operationName = openApiOperation.GetOperationName(); var controllerAuthorization = openApiPath.ExtractApiPathAuthorization(); var endpointAuthorization = openApiOperation.ExtractApiOperationAuthorization(openApiPath); diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultInterfaceParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultInterfaceParametersFactory.cs index 5d55ad825..e97862e66 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultInterfaceParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultInterfaceParametersFactory.cs @@ -6,7 +6,7 @@ public static ContentGeneratorClientEndpointResultInterfaceParameters Create( string projectName, string apiGroupName, string @namespace, - string contractsLocation, + string contractsNamespace, OpenApiPathItem openApiPath, OpenApiOperation openApiOperation, bool usePartialClass) @@ -20,7 +20,7 @@ public static ContentGeneratorClientEndpointResultInterfaceParameters Create( AppendParameters(parameters, openApiOperation.Parameters); AppendParametersFromBody(parameters, openApiOperation.RequestBody); - var modelNamespace = NamespaceFactory.Create(projectName, contractsLocation); + var modelNamespace = NamespaceFactory.Create(projectName, contractsNamespace); var operationName = openApiOperation.GetOperationName(); var controllerAuthorization = openApiPath.ExtractApiPathAuthorization(); var endpointAuthorization = openApiOperation.ExtractApiOperationAuthorization(openApiPath); diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultParametersFactory.cs index 3d58d197a..8a591f569 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientEndpointResultParametersFactory.cs @@ -6,7 +6,7 @@ public static ContentGeneratorClientEndpointResultParameters Create( string projectName, string apiGroupName, string @namespace, - string contractsLocation, + string contractsNamespace, OpenApiPathItem openApiPath, OpenApiOperation openApiOperation, bool usePartialClass) @@ -20,7 +20,7 @@ public static ContentGeneratorClientEndpointResultParameters Create( AppendParameters(parameters, openApiOperation.Parameters); AppendParametersFromBody(parameters, openApiOperation.RequestBody); - var modelNamespace = NamespaceFactory.Create(projectName, contractsLocation); + var modelNamespace = NamespaceFactory.Create(projectName, contractsNamespace); var operationName = openApiOperation.GetOperationName(); var controllerAuthorization = openApiPath.ExtractApiPathAuthorization(); var endpointAuthorization = openApiOperation.ExtractApiOperationAuthorization(openApiPath); diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientParameterParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientParameterParametersFactory.cs index 2732baf9d..9110f4385 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientParameterParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Client/ContentGeneratorClientParameterParametersFactory.cs @@ -8,7 +8,8 @@ public static class ContentGeneratorClientParameterParametersFactory public static ContentGeneratorClientParameterParameters Create( string @namespace, OpenApiOperation openApiOperation, - IList globalPathParameters) + IList globalPathParameters, + string contractNamespaceWithoutApiGroupName) { ArgumentNullException.ThrowIfNull(openApiOperation); ArgumentNullException.ThrowIfNull(globalPathParameters); @@ -17,8 +18,8 @@ public static ContentGeneratorClientParameterParameters Create( var parameters = new List(); - AppendParameters(parameters, globalPathParameters); - AppendParameters(parameters, openApiOperation.Parameters); + AppendParameters(parameters, globalPathParameters, contractNamespaceWithoutApiGroupName); + AppendParameters(parameters, openApiOperation.Parameters, contractNamespaceWithoutApiGroupName); AppendParametersFromBody(parameters, openApiOperation.RequestBody); return new ContentGeneratorClientParameterParameters( @@ -32,14 +33,13 @@ public static ContentGeneratorClientParameterParameters Create( private static void AppendParameters( ICollection parameters, - IEnumerable openApiParameters) + IEnumerable openApiParameters, + string contractNamespaceWithoutApiGroupName) { foreach (var openApiParameter in openApiParameters) { var useListForDataType = openApiParameter.Schema.IsTypeArray(); - var parameterName = openApiParameter.Name.EnsureValidFormattedPropertyName(); - var dataType = useListForDataType ? openApiParameter.Schema.Items.GetDataType() : openApiParameter.Schema.GetDataType(); @@ -50,19 +50,11 @@ private static void AppendParameters( if (parameters.FirstOrDefault(x => x.Name == openApiParameter.Name) is null) { - var defaultValueInitializer = openApiParameter.Schema.GetDefaultValueAsString(); - - if (!string.IsNullOrEmpty(defaultValueInitializer) && - openApiParameter.ContainsEnumInSchemaOrProperties()) - { - defaultValueInitializer = dataType.Equals(parameterName, StringComparison.Ordinal) - ? $"{ContentGeneratorConstants.Contracts}.{dataType}.{defaultValueInitializer.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true)}" - : $"{dataType}.{defaultValueInitializer.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true)}"; - } + var defaultValueInitializer = openApiParameter.GetDefaultValueInitializer(contractNamespaceWithoutApiGroupName); parameters.Add(new ContentGeneratorClientParameterParametersProperty( openApiParameter.Name, - parameterName, + openApiParameter.Name.EnsureValidFormattedPropertyName(), openApiParameter.ExtractDocumentationTags(), dataType, isSimpleType, diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Server/ContentGeneratorServerParameterParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Server/ContentGeneratorServerParameterParametersFactory.cs index 01de34df2..fe7e63a08 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Server/ContentGeneratorServerParameterParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/Server/ContentGeneratorServerParameterParametersFactory.cs @@ -8,7 +8,8 @@ public static class ContentGeneratorServerParameterParametersFactory public static ContentGeneratorServerParameterParameters CreateForClass( string @namespace, OpenApiOperation openApiOperation, - IList globalPathParameters) + IList globalPathParameters, + string contractNamespaceWithoutApiGroupName) { ArgumentNullException.ThrowIfNull(openApiOperation); ArgumentNullException.ThrowIfNull(globalPathParameters); @@ -17,8 +18,8 @@ public static ContentGeneratorServerParameterParameters CreateForClass( var parameters = new List(); - AppendParameters(parameters, globalPathParameters); - AppendParameters(parameters, openApiOperation.Parameters); + AppendParameters(parameters, globalPathParameters, contractNamespaceWithoutApiGroupName); + AppendParameters(parameters, openApiOperation.Parameters, contractNamespaceWithoutApiGroupName); AppendParametersFromBody(parameters, openApiOperation.RequestBody); return new ContentGeneratorServerParameterParameters( @@ -33,7 +34,8 @@ public static ContentGeneratorServerParameterParameters CreateForClass( public static ContentGeneratorServerParameterParameters CreateForRecord( string @namespace, OpenApiOperation openApiOperation, - IList globalPathParameters) + IList globalPathParameters, + string contractNamespaceWithoutApiGroupName) { ArgumentNullException.ThrowIfNull(openApiOperation); ArgumentNullException.ThrowIfNull(globalPathParameters); @@ -42,8 +44,8 @@ public static ContentGeneratorServerParameterParameters CreateForRecord( var parameters = new List(); - AppendParameters(parameters, globalPathParameters); - AppendParameters(parameters, openApiOperation.Parameters); + AppendParameters(parameters, globalPathParameters, contractNamespaceWithoutApiGroupName); + AppendParameters(parameters, openApiOperation.Parameters, contractNamespaceWithoutApiGroupName); AppendParametersFromBody(parameters, openApiOperation.RequestBody); return new ContentGeneratorServerParameterParameters( @@ -57,7 +59,8 @@ public static ContentGeneratorServerParameterParameters CreateForRecord( private static void AppendParameters( ICollection parameters, - IEnumerable openApiParameters) + IEnumerable openApiParameters, + string contractNamespaceWithoutApiGroupName) { foreach (var openApiParameter in openApiParameters) { @@ -73,6 +76,8 @@ private static void AppendParameters( if (parameters.FirstOrDefault(x => x.Name == openApiParameter.Name) is null) { + var defaultValueInitializer = openApiParameter.GetDefaultValueInitializer(contractNamespaceWithoutApiGroupName); + parameters.Add(new ContentGeneratorServerParameterParametersProperty( openApiParameter.Name, openApiParameter.Name.EnsureValidFormattedPropertyName(), @@ -84,7 +89,7 @@ private static void AppendParameters( GetIsNullable(openApiParameter), openApiParameter.Required, GetAdditionalValidationAttributes(openApiParameter), - openApiParameter.Schema.GetDefaultValueAsString())); + defaultValueInitializer)); } } } @@ -134,7 +139,7 @@ private static void AppendParametersFromBody( var requestBodyType = "string?"; if (requestSchema.Reference is not null) { - requestBodyType = requestSchema.Reference.Id.EnsureFirstCharacterToUpper(); + requestBodyType = requestSchema.Reference.Id.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true); } else if (isFormatTypeOfBinary) { @@ -146,7 +151,7 @@ private static void AppendParametersFromBody( } else if (requestSchema.Items is not null) { - requestBodyType = requestSchema.Items.Reference.Id.EnsureFirstCharacterToUpper(); + requestBodyType = requestSchema.Items.Reference.Id.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true); } parameters.Add(new ContentGeneratorServerParameterParametersProperty( diff --git a/src/Atc.Rest.ApiGenerator.Framework/Providers/NugetPackageReferenceProvider.cs b/src/Atc.Rest.ApiGenerator.Framework/Providers/NugetPackageReferenceProvider.cs index 511c7dbf1..e50b9e7b4 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Providers/NugetPackageReferenceProvider.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Providers/NugetPackageReferenceProvider.cs @@ -11,7 +11,7 @@ public class NugetPackageReferenceProvider( { "Atc", "2.0.525" }, { "Atc.Azure.Options", "3.0.31" }, { "Atc.Rest", "2.0.525" }, - { "Atc.Rest.Client", "1.0.36" }, + { "Atc.Rest.Client", "1.0.84" }, { "Atc.Rest.Extended", "2.0.525" }, { "Atc.Rest.FluentAssertions", "2.0.525" }, { "Atc.Rest.MinimalApi", "1.0.87" }, @@ -19,18 +19,18 @@ public class NugetPackageReferenceProvider( { "AutoFixture", "4.18.1" }, { "AutoFixture.AutoNSubstitute", "4.18.1" }, { "AutoFixture.Xunit2", "4.18.1" }, - { "FluentAssertions", "6.12.0" }, + { "FluentAssertions", "7.0.0" }, { "FluentValidation.AspNetCore", "11.3.0" }, { "Microsoft.ApplicationInsights.AspNetCore", "2.22.0" }, { "Microsoft.AspNetCore.Authentication.JwtBearer", "8.0.4" }, { "Microsoft.AspNetCore.OpenApi", "8.0.6" }, { "Microsoft.AspNetCore.Mvc.Testing", "8.0.6" }, { "Microsoft.NETCore.Platforms", "7.0.4" }, - { "Microsoft.NET.Test.Sdk", "17.10.0" }, - { "NSubstitute", "5.1.0" }, + { "Microsoft.NET.Test.Sdk", "17.12.0" }, + { "NSubstitute", "5.3.0" }, { "Swashbuckle.AspNetCore", "7.0.0" }, - { "xunit", "2.9.2" }, - { "xunit.runner.visualstudio", "2.8.1" }, + { "xunit", "2.9.3" }, + { "xunit.runner.visualstudio", "3.0.1" }, }; public async Task GetAtcApiGeneratorVersion() diff --git a/src/Atc.Rest.ApiGenerator.Framework/Settings/GeneratorSettings.cs b/src/Atc.Rest.ApiGenerator.Framework/Settings/GeneratorSettings.cs index b71b4f525..b3a026771 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Settings/GeneratorSettings.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Settings/GeneratorSettings.cs @@ -13,10 +13,16 @@ public class GeneratorSettings( public string EndpointsLocation { get; set; } = ContentGeneratorConstants.Endpoints; + public string EndpointsNamespace { get; set; } = ContentGeneratorConstants.Endpoints; + public string ContractsLocation { get; set; } = ContentGeneratorConstants.Contracts; + public string ContractsNamespace { get; set; } = ContentGeneratorConstants.Contracts; + public string HandlersLocation { get; set; } = ContentGeneratorConstants.Handlers; + public string HandlersNamespace { get; set; } = ContentGeneratorConstants.Handlers; + public bool UsePartialClassForContracts { get; set; } public bool UsePartialClassForEndpoints { get; set; } diff --git a/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiParameterExtensions.cs b/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiParameterExtensions.cs index 0543afc80..1beac4a9f 100644 --- a/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiParameterExtensions.cs +++ b/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiParameterExtensions.cs @@ -32,6 +32,31 @@ public static bool ContainsEnumInSchemaOrProperties( apiParameter.Schema.OneOf.Any(oneOfSchema => oneOfSchema.IsSchemaEnumOrPropertyEnum()) || apiParameter.Schema.AnyOf.Any(anyOfSchema => anyOfSchema.IsSchemaEnumOrPropertyEnum()); + public static string? GetDefaultValueInitializer( + this OpenApiParameter openApiParameter, + string contractNamespaceWithoutApiGroupName) + { + var parameterName = openApiParameter.Name.EnsureValidFormattedPropertyName(); + + var useListForDataType = openApiParameter.Schema.IsTypeArray(); + + var dataType = useListForDataType + ? openApiParameter.Schema.Items.GetDataType() + : openApiParameter.Schema.GetDataType(); + + var defaultValueInitializer = openApiParameter.Schema.GetDefaultValueAsString(); + + if (!string.IsNullOrEmpty(defaultValueInitializer) && + openApiParameter.ContainsEnumInSchemaOrProperties()) + { + defaultValueInitializer = dataType.Equals(parameterName, StringComparison.Ordinal) + ? $"{contractNamespaceWithoutApiGroupName}.{dataType}.{defaultValueInitializer.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true)}" + : $"{dataType}.{defaultValueInitializer.PascalCase(ApiOperationExtractor.ModelNameSeparators, removeSeparators: true)}"; + } + + return defaultValueInitializer; + } + public static CodeDocumentationTags ExtractDocumentationTags( this OpenApiParameter apiParameter) { diff --git a/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiPathItemExtensions.cs b/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiPathItemExtensions.cs index 6f5f9fb53..db404866e 100644 --- a/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiPathItemExtensions.cs +++ b/src/Atc.Rest.ApiGenerator.OpenApi/Extensions/OpenApiPathItemExtensions.cs @@ -16,6 +16,31 @@ public static string GetApiGroupName( }; } + public static bool IsPathStartingApiGroupName( + this KeyValuePair urlPath, string segmentName) + { + if (segmentName is null) + { + throw new ArgumentNullException(nameof(segmentName)); + } + + var sa = urlPath.Key.Split('/', StringSplitOptions.RemoveEmptyEntries); + if (string.IsNullOrEmpty(segmentName) && sa.Length == 0) + { + return true; + } + + if (sa.Length == 0) + { + return false; + } + + var apiGroupName = urlPath.GetApiGroupName(); + + return segmentName.Equals(apiGroupName, StringComparison.OrdinalIgnoreCase) || + segmentName.Equals(apiGroupName.EnsureSingular(), StringComparison.OrdinalIgnoreCase); + } + public static ApiAuthorizeModel? ExtractApiPathAuthorization( this OpenApiPathItem apiPath) { diff --git a/src/Atc.Rest.ApiGenerator.OpenApi/GlobalUsings.cs b/src/Atc.Rest.ApiGenerator.OpenApi/GlobalUsings.cs index 2689646de..3f0215b44 100644 --- a/src/Atc.Rest.ApiGenerator.OpenApi/GlobalUsings.cs +++ b/src/Atc.Rest.ApiGenerator.OpenApi/GlobalUsings.cs @@ -6,6 +6,7 @@ global using System.Text; global using Atc.CodeDocumentation.CodeComment; +global using Atc.CodeGeneration.CSharp.Extensions; global using Atc.Data.Models; global using Atc.Rest.ApiGenerator.Contracts; global using Atc.Rest.ApiGenerator.Contracts.ContentGeneratorsParameters.Server; diff --git a/src/Atc.Rest.ApiGenerator/Factories/GeneratorSettingsFactory.cs b/src/Atc.Rest.ApiGenerator/Factories/GeneratorSettingsFactory.cs index eb2fee70b..1227de821 100644 --- a/src/Atc.Rest.ApiGenerator/Factories/GeneratorSettingsFactory.cs +++ b/src/Atc.Rest.ApiGenerator/Factories/GeneratorSettingsFactory.cs @@ -27,16 +27,31 @@ public static GeneratorSettings Create( generatorSettings.EndpointsLocation = apiOptionsGenerator.EndpointsLocation; } + if (!string.IsNullOrEmpty(apiOptionsGenerator.EndpointsNamespace)) + { + generatorSettings.EndpointsNamespace = apiOptionsGenerator.EndpointsNamespace; + } + if (!string.IsNullOrEmpty(apiOptionsGenerator.ContractsLocation)) { generatorSettings.ContractsLocation = apiOptionsGenerator.ContractsLocation; } + if (!string.IsNullOrEmpty(apiOptionsGenerator.ContractsNamespace)) + { + generatorSettings.ContractsNamespace = apiOptionsGenerator.ContractsNamespace; + } + if (!string.IsNullOrEmpty(apiOptionsGenerator.HandlersLocation)) { generatorSettings.HandlersLocation = apiOptionsGenerator.HandlersLocation; } + if (!string.IsNullOrEmpty(apiOptionsGenerator.HandlersNamespace)) + { + generatorSettings.HandlersNamespace = apiOptionsGenerator.HandlersNamespace; + } + return generatorSettings; } } \ No newline at end of file diff --git a/src/Atc.Rest.ApiGenerator/Options/ApiOptionsGenerator.cs b/src/Atc.Rest.ApiGenerator/Options/ApiOptionsGenerator.cs index 94db2e280..72b05c0a3 100644 --- a/src/Atc.Rest.ApiGenerator/Options/ApiOptionsGenerator.cs +++ b/src/Atc.Rest.ApiGenerator/Options/ApiOptionsGenerator.cs @@ -14,10 +14,16 @@ public class ApiOptionsGenerator public string ContractsLocation { get; set; } = ContentGeneratorConstants.Contracts + ".[[apiGroupName]]"; + public string ContractsNamespace { get; set; } = ContentGeneratorConstants.Contracts + ".[[apiGroupName]]"; + public string EndpointsLocation { get; set; } = ContentGeneratorConstants.Endpoints + ".[[apiGroupName]]"; + public string EndpointsNamespace { get; set; } = ContentGeneratorConstants.Endpoints + ".[[apiGroupName]]"; + public string HandlersLocation { get; set; } = ContentGeneratorConstants.Handlers + ".[[apiGroupName]]"; + public string HandlersNamespace { get; set; } = ContentGeneratorConstants.Handlers + ".[[apiGroupName]]"; + public bool UsePartialClassForContracts { get; set; } public bool UsePartialClassForEndpoints { get; set; } diff --git a/test/Atc.Rest.ApiGenerator.CLI.Tests/ScenariosTests.cs b/test/Atc.Rest.ApiGenerator.CLI.Tests/ScenariosTests.cs index 98c5b2f88..f1fc39452 100644 --- a/test/Atc.Rest.ApiGenerator.CLI.Tests/ScenariosTests.cs +++ b/test/Atc.Rest.ApiGenerator.CLI.Tests/ScenariosTests.cs @@ -53,33 +53,36 @@ public async Task ValidateYamlSpecificationByScenario( } [Theory] - [InlineData("DemoSample", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("DemoSample", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("ExAllResponseTypes", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("ExAllResponseTypes", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("ExAsyncEnumerable", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("ExAsyncEnumerable", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("ExAsyncEnumerable", AspNetOutputType.MinimalApi, false, null, null, null)] - [InlineData("ExAsyncEnumerable", AspNetOutputType.MinimalApi, true, null, null, null)] - [InlineData("ExGenericPagination", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("ExGenericPagination", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("ExNsWithTask", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("ExNsWithTask", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("ExUsers", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("ExUsers", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("PetStore", AspNetOutputType.Mvc, false, null, null, null)] - [InlineData("PetStore", AspNetOutputType.Mvc, true, null, null, null)] - [InlineData("Structure1", AspNetOutputType.Mvc, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers")] - [InlineData("Structure1", AspNetOutputType.Mvc, true, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers")] - [InlineData("Structure1", AspNetOutputType.MinimalApi, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers")] - [InlineData("Structure1", AspNetOutputType.MinimalApi, true, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers")] + [InlineData("DemoSample", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("DemoSample", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("ExAllResponseTypes", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("ExAllResponseTypes", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("ExAsyncEnumerable", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("ExAsyncEnumerable", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("ExAsyncEnumerable", AspNetOutputType.MinimalApi, false, null, null, null, null, null, null)] + [InlineData("ExAsyncEnumerable", AspNetOutputType.MinimalApi, true, null, null, null, null, null, null)] + [InlineData("ExGenericPagination", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("ExGenericPagination", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("ExNsWithTask", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("ExNsWithTask", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("ExUsers", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("ExUsers", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("PetStore", AspNetOutputType.Mvc, false, null, null, null, null, null, null)] + [InlineData("PetStore", AspNetOutputType.Mvc, true, null, null, null, null, null, null)] + [InlineData("Structure1", AspNetOutputType.Mvc, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers", "[[apiGroupName]].MyHandlers")] + [InlineData("Structure1", AspNetOutputType.Mvc, true, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers", "[[apiGroupName]].MyHandlers")] + [InlineData("Structure1", AspNetOutputType.MinimalApi, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers", "[[apiGroupName]].MyHandlers")] + [InlineData("Structure1", AspNetOutputType.MinimalApi, true, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyHandlers", "[[apiGroupName]].MyHandlers")] public async Task GenerateVerifyAndBuildForServerAllByScenario( string scenarioName, AspNetOutputType aspNetOutputType, bool useProblemDetailsAsDefaultResponseBody, string? contractsLocation, + string? contractsNamespace, string? endpointsLocation, - string? handlersLocation) + string? endpointsNamespace, + string? handlersLocation, + string? handlersNamespace) { // Arrange var scenarioPath = CollectScenarioPaths().First(x => x.Name == scenarioName); @@ -93,35 +96,50 @@ public async Task GenerateVerifyAndBuildForServerAllByScenario( } // Act & Assert - await AssertGenerateForServerAll(outputPath, scenarioPath, specificationFile, aspNetOutputType, useProblemDetailsAsDefaultResponseBody, contractsLocation, endpointsLocation, handlersLocation); + await AssertGenerateForServerAll( + outputPath, + scenarioPath, + specificationFile, + aspNetOutputType, + useProblemDetailsAsDefaultResponseBody, + contractsLocation, + contractsNamespace, + endpointsLocation, + endpointsNamespace, + handlersLocation, + handlersNamespace); + await AssertVerifyCsFilesForServerAll(outputPath, scenarioPath, aspNetOutputType, useProblemDetailsAsDefaultResponseBody); + await AssertBuildForServerAll(outputPath, scenarioPath); } [Theory] - [InlineData("DemoSample", false, false, null, null)] - [InlineData("DemoSample", true, false, null, null)] - [InlineData("ExAllResponseTypes", false, false, null, null)] - [InlineData("ExAllResponseTypes", true, false, null, null)] - [InlineData("ExAsyncEnumerable", false, false, null, null)] - [InlineData("ExAsyncEnumerable", true, false, null, null)] - [InlineData("ExGenericPagination", false, false, null, null)] - [InlineData("ExGenericPagination", true, false, null, null)] - [InlineData("ExNsWithTask", false, false, null, null)] - [InlineData("ExNsWithTask", true, false, null, null)] - [InlineData("ExUsers", false, false, null, null)] - [InlineData("ExUsers", true, false, null, null)] - [InlineData("PetStore", false, false, null, null)] - [InlineData("PetStore", true, false, null, null)] - [InlineData("Monta", false, true, null, null)] - [InlineData("Structure1", false, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints")] - [InlineData("Structure1", true, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints")] + [InlineData("DemoSample", false, false, null, null, null, null)] + [InlineData("DemoSample", true, false, null, null, null, null)] + [InlineData("ExAllResponseTypes", false, false, null, null, null, null)] + [InlineData("ExAllResponseTypes", true, false, null, null, null, null)] + [InlineData("ExAsyncEnumerable", false, false, null, null, null, null)] + [InlineData("ExAsyncEnumerable", true, false, null, null, null, null)] + [InlineData("ExGenericPagination", false, false, null, null, null, null)] + [InlineData("ExGenericPagination", true, false, null, null, null, null)] + [InlineData("ExNsWithTask", false, false, null, null, null, null)] + [InlineData("ExNsWithTask", true, false, null, null, null, null)] + [InlineData("ExUsers", false, false, null, null, null, null)] + [InlineData("ExUsers", true, false, null, null, null, null)] + [InlineData("PetStore", false, false, null, null, null, null)] + [InlineData("PetStore", true, false, null, null, null, null)] + [InlineData("Monta", false, true, null, null, null, null)] + [InlineData("Structure1", false, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints")] + [InlineData("Structure1", true, false, "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyContracts", "[[apiGroupName]].MyEndpoints", "[[apiGroupName]].MyEndpoints")] public async Task GenerateVerifyAndBuildForClientCSharpByScenario( string scenarioName, bool useProblemDetailsAsDefaultResponseBody, bool useCustomErrorResponseModel, string? contractsLocation, - string? endpointsLocation) + string? contractsNamespace, + string? endpointsLocation, + string? endpointsNamespace) { // Arrange var scenarioPath = CollectScenarioPaths().First(x => x.Name == scenarioName); @@ -136,7 +154,18 @@ public async Task GenerateVerifyAndBuildForClientCSharpByScenario( } // Act & Assert - await AssertGenerateForClientCSharp(outputPath, scenarioPath, specificationFile, optionsFile, useProblemDetailsAsDefaultResponseBody, useCustomErrorResponseModel, contractsLocation, endpointsLocation); + await AssertGenerateForClientCSharp( + outputPath, + scenarioPath, + specificationFile, + optionsFile, + useProblemDetailsAsDefaultResponseBody, + useCustomErrorResponseModel, + contractsLocation, + contractsNamespace, + endpointsLocation, + endpointsNamespace); + await AssertVerifyCsFilesForClientCSharp(outputPath, scenarioPath, useProblemDetailsAsDefaultResponseBody, useCustomErrorResponseModel); } @@ -261,8 +290,11 @@ private static async Task AssertGenerateForServerAll( AspNetOutputType aspNetOutputType, bool useProblemDetailsAsDefaultResponseBody, string? contractsLocation, + string? contractsNamespace, string? endpointsLocation, - string? handlersLocation) + string? endpointsNamespace, + string? handlersLocation, + string? handlersNamespace) { var sbCommands = new StringBuilder(); sbCommands.Append("generate server all"); @@ -289,18 +321,36 @@ private static async Task AssertGenerateForServerAll( sbCommands.Append(contractsLocation); } + if (contractsNamespace is not null) + { + sbCommands.Append(" --contractsNamespace "); + sbCommands.Append(contractsNamespace); + } + if (endpointsLocation is not null) { sbCommands.Append(" --endpointsLocation "); sbCommands.Append(endpointsLocation); } + if (endpointsNamespace is not null) + { + sbCommands.Append(" --endpointsNamespace "); + sbCommands.Append(endpointsNamespace); + } + if (handlersLocation is not null) { sbCommands.Append(" --handlersLocation "); sbCommands.Append(handlersLocation); } + if (handlersNamespace is not null) + { + sbCommands.Append(" --handlersNamespace "); + sbCommands.Append(handlersNamespace); + } + sbCommands.Append(" --verbose"); var (isSuccessful, output) = await ProcessHelper.Execute(cliExeFile!, sbCommands.ToString()); @@ -396,7 +446,9 @@ private static async Task AssertGenerateForClientCSharp( bool useProblemDetailsAsDefaultResponseBody, bool useCustomErrorResponseModel, string? contractsLocation, - string? endpointsLocation) + string? contractsNamespace, + string? endpointsLocation, + string? endpointsNamespace) { var sbCommands = new StringBuilder(); sbCommands.Append("generate client csharp"); @@ -424,12 +476,24 @@ private static async Task AssertGenerateForClientCSharp( sbCommands.Append(contractsLocation); } + if (contractsNamespace is not null) + { + sbCommands.Append(" --contractsNamespace "); + sbCommands.Append(contractsNamespace); + } + if (endpointsLocation is not null) { sbCommands.Append(" --endpointsLocation "); sbCommands.Append(endpointsLocation); } + if (endpointsNamespace is not null) + { + sbCommands.Append(" --endpointsNamespace "); + sbCommands.Append(endpointsNamespace); + } + sbCommands.Append(" --verbose"); var (isSuccessful, output) = await ProcessHelper.Execute(cliExeFile!, sbCommands.ToString());