diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index e8d9431de..696837d3f 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -21,6 +21,7 @@ internal class TransformCommandHandler : ICommandHandler public Option VersionOption { get; set; } public Option FormatOption { get; set; } public Option TerseOutputOption { get; set; } + public Option SettingsFileOption { get; set; } public Option LogLevelOption { get; set; } public Option FilterByOperationIdsOption { get; set; } public Option FilterByTagsOption { get; set; } @@ -42,6 +43,7 @@ public async Task InvokeAsync(InvocationContext context) string? version = context.ParseResult.GetValueForOption(VersionOption); OpenApiFormat? format = context.ParseResult.GetValueForOption(FormatOption); bool terseOutput = context.ParseResult.GetValueForOption(TerseOutputOption); + string settingsFile = context.ParseResult.GetValueForOption(SettingsFileOption); LogLevel logLevel = context.ParseResult.GetValueForOption(LogLevelOption); bool inlineLocal = context.ParseResult.GetValueForOption(InlineLocalOption); bool inlineExternal = context.ParseResult.GetValueForOption(InlineExternalOption); @@ -54,7 +56,7 @@ public async Task InvokeAsync(InvocationContext context) var logger = loggerFactory.CreateLogger(); try { - await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken); + await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, settingsFile, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 6c9b54e04..f88e7ed63 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -44,6 +44,7 @@ + @@ -51,4 +52,12 @@ + + + + <_Parameter1>Microsoft.OpenApi.Hidi.Tests + + + + diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 034350f1a..0d9500682 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -27,6 +27,8 @@ using System.Xml.Xsl; using System.Xml; using System.Reflection; +using Microsoft.Extensions.Configuration; +using System.Runtime.CompilerServices; namespace Microsoft.OpenApi.Hidi { @@ -44,6 +46,7 @@ public static async Task TransformOpenApiDocument( string? version, OpenApiFormat? format, bool terseOutput, + string settingsFile, LogLevel logLevel, bool inlineLocal, bool inlineExternal, @@ -98,7 +101,8 @@ CancellationToken cancellationToken stream = ApplyFilter(csdl, csdlFilter, transform); stream.Position = 0; } - document = await ConvertCsdlToOpenApi(stream); + + document = await ConvertCsdlToOpenApi(stream, settingsFile); stopwatch.Stop(); logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); } @@ -304,17 +308,29 @@ public static async Task ValidateOpenApiDocument( } } + internal static IConfiguration GetConfiguration(string settingsFile) + { + settingsFile ??= "appsettings.json"; + + IConfiguration config = new ConfigurationBuilder() + .AddJsonFile(settingsFile, true) + .Build(); + + return config; + } + /// /// Converts CSDL to OpenAPI /// /// The CSDL stream. /// An OpenAPI document. - public static async Task ConvertCsdlToOpenApi(Stream csdl) + public static async Task ConvertCsdlToOpenApi(Stream csdl, string settingsFile = null) { using var reader = new StreamReader(csdl); var csdlText = await reader.ReadToEndAsync(); var edmModel = CsdlReader.Parse(XElement.Parse(csdlText).CreateReader()); - + + var config = GetConfiguration(settingsFile); var settings = new OpenApiConvertSettings() { AddSingleQuotesForStringParameters = true, @@ -322,7 +338,7 @@ public static async Task ConvertCsdlToOpenApi(Stream csdl) DeclarePathParametersOnPathItem = true, EnableKeyAsSegment = true, EnableOperationId = true, - ErrorResponsesAsDefault = false, + ErrorResponsesAsDefault = false, PrefixEntityTypeNameBeforeKey = true, TagDepth = 2, EnablePagination = true, @@ -335,6 +351,8 @@ public static async Task ConvertCsdlToOpenApi(Stream csdl) EnableCount = true, UseSuccessStatusCodeRange = true }; + config.GetSection("OpenApiConvertSettings").Bind(settings); + OpenApiDocument document = edmModel.ConvertToOpenApi(settings); document = FixReferences(document); diff --git a/src/Microsoft.OpenApi.Hidi/Program.cs b/src/Microsoft.OpenApi.Hidi/Program.cs index 926c58deb..71e9e0d00 100644 --- a/src/Microsoft.OpenApi.Hidi/Program.cs +++ b/src/Microsoft.OpenApi.Hidi/Program.cs @@ -2,8 +2,14 @@ // Licensed under the MIT license. using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Hosting; +using System.CommandLine.Parsing; + using System.IO; using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Hidi.Handlers; @@ -41,6 +47,9 @@ static async Task Main(string[] args) var terseOutputOption = new Option("--terse-output", "Produce terse json output"); terseOutputOption.AddAlias("--to"); + var settingsFileOption = new Option("--settings-path", "The configuration file with CSDL conversion settings."); + settingsFileOption.AddAlias("--sp"); + var logLevelOption = new Option("--log-level", () => LogLevel.Information, "The log level to use when logging messages to the main output."); logLevelOption.AddAlias("--ll"); @@ -81,6 +90,7 @@ static async Task Main(string[] args) versionOption, formatOption, terseOutputOption, + settingsFileOption, logLevelOption, filterByOperationIdsOption, filterByTagsOption, @@ -99,6 +109,7 @@ static async Task Main(string[] args) VersionOption = versionOption, FormatOption = formatOption, TerseOutputOption = terseOutputOption, + SettingsFileOption = settingsFileOption, LogLevelOption = logLevelOption, FilterByOperationIdsOption = filterByOperationIdsOption, FilterByTagsOption = filterByTagsOption, diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index f4c368024..d73d8af81 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -34,6 +34,9 @@ + + Always + Always diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs index af5437aa1..c2fb3798f 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs @@ -1,10 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using System; -using System.IO; -using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; using Microsoft.OpenApi.Hidi; +using Microsoft.OpenApi.OData; using Microsoft.OpenApi.Services; using Xunit; @@ -51,5 +50,26 @@ public async Task ReturnFilteredOpenApiDocBasedOnOperationIdsAndInputCsdlDocumen Assert.NotEmpty(subsetOpenApiDocument.Paths); Assert.Equal(expectedPathCount, subsetOpenApiDocument.Paths.Count); } + + [Theory] + [InlineData("UtilityFiles/appsettingstest.json")] + [InlineData(null)] + public void ReturnOpenApiConvertSettingsWhenSettingsFileIsProvided(string filePath) + { + // Arrange + var config = OpenApiService.GetConfiguration(filePath); + + // Act and Assert + var settings = config.GetSection("OpenApiConvertSettings").Get(); + + if (filePath == null) + { + Assert.Null(settings); + } + else + { + Assert.NotNull(settings); + } + } } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/appsettingstest.json b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/appsettingstest.json new file mode 100644 index 000000000..a71d0a9fa --- /dev/null +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/appsettingstest.json @@ -0,0 +1,21 @@ +{ + "OpenApiConvertSettings": { + "AddSingleQuotesForStringParameters": "true", + "AddEnumDescriptionExtension": "true", + "DeclarePathParametersOnPathItem": "true", + "EnableKeyAsSegment": "true", + "EnableOperationId": "true", + "ErrorResponsesAsDefault": "false", + "PrefixEntityTypeNameBeforeKey": "true", + "TagDepth": 2, + "EnablePagination": "true", + "EnableDiscriminatorValue": "true", + "EnableDerivedTypesReferencesForRequestBody": "false", + "EnableDerivedTypesReferencesForResponses": "false", + "ShowRootPath": "false", + "ShowLinks": "false", + "ExpandDerivedTypesNavigationProperties": "false", + "EnableCount": "true", + "UseSuccessStatusCodeRange": "true" + } +} \ No newline at end of file