diff --git a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs index d0a49c209..e00cd7efa 100644 --- a/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs +++ b/src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs @@ -19,6 +19,7 @@ internal class TransformCommandHandler : ICommandHandler public Option OutputOption { get; set; } public Option CleanOutputOption { get; set; } public Option VersionOption { get; set; } + public Option MetadataVersionOption { get; set; } public Option FormatOption { get; set; } public Option TerseOutputOption { get; set; } public Option SettingsFileOption { get; set; } @@ -41,6 +42,7 @@ public async Task InvokeAsync(InvocationContext context) FileInfo output = context.ParseResult.GetValueForOption(OutputOption); bool cleanOutput = context.ParseResult.GetValueForOption(CleanOutputOption); string? version = context.ParseResult.GetValueForOption(VersionOption); + string metadataVersion = context.ParseResult.GetValueForOption(MetadataVersionOption); OpenApiFormat? format = context.ParseResult.GetValueForOption(FormatOption); bool terseOutput = context.ParseResult.GetValueForOption(TerseOutputOption); string settingsFile = context.ParseResult.GetValueForOption(SettingsFileOption); @@ -57,7 +59,7 @@ public async Task InvokeAsync(InvocationContext context) var logger = loggerFactory.CreateLogger(); try { - await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, settingsFile, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, logger, cancellationToken); + await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, metadataVersion, format, terseOutput, settingsFile, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, logger, cancellationToken); return 0; } diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index d21a07947..dc0c3a0cc 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -43,7 +43,7 @@ - + diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 4d535ee02..5d5ec95d4 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Net; using System.Net.Http; using System.Security; @@ -20,7 +19,6 @@ using Microsoft.OpenApi.OData; using Microsoft.OpenApi.Readers; using Microsoft.OpenApi.Services; -using Microsoft.OpenApi.Validations; using Microsoft.OpenApi.Writers; using static Microsoft.OpenApi.Hidi.OpenApiSpecVersionHelper; using System.Threading; @@ -43,6 +41,7 @@ public static async Task TransformOpenApiDocument( FileInfo output, bool cleanoutput, string? version, + string metadataVersion, OpenApiFormat? format, bool terseOutput, string settingsFile, @@ -81,7 +80,7 @@ CancellationToken cancellationToken OpenApiFormat openApiFormat = format ?? (!string.IsNullOrEmpty(openapi) ? GetOpenApiFormat(openapi, logger) : OpenApiFormat.Yaml); OpenApiSpecVersion openApiVersion = version != null ? TryParseOpenApiSpecVersion(version) : OpenApiSpecVersion.OpenApi3_0; - OpenApiDocument document = await GetOpenApi(openapi, csdl, csdlFilter, settingsFile, inlineExternal, logger, cancellationToken); + OpenApiDocument document = await GetOpenApi(openapi, csdl, csdlFilter, settingsFile, inlineExternal, logger, cancellationToken, metadataVersion); document = await FilterOpenApiDocument(filterbyoperationids, filterbytags, filterbycollection, document, logger, cancellationToken); WriteOpenApi(output, terseOutput, inlineLocal, inlineExternal, openApiFormat, openApiVersion, document, logger); } @@ -132,11 +131,11 @@ private static void WriteOpenApi(FileInfo output, bool terseOutput, bool inlineL } // Get OpenAPI document either from OpenAPI or CSDL - private static async Task GetOpenApi(string openapi, string csdl, string csdlFilter, string settingsFile, bool inlineExternal, ILogger logger, CancellationToken cancellationToken) + private static async Task GetOpenApi(string openapi, string csdl, string csdlFilter, string settingsFile, bool inlineExternal, ILogger logger, CancellationToken cancellationToken, string metadataVersion = null) { OpenApiDocument document; Stream stream; - + if (!string.IsNullOrEmpty(csdl)) { var stopwatch = new Stopwatch(); @@ -154,7 +153,7 @@ private static async Task GetOpenApi(string openapi, string csd stream = null; } - document = await ConvertCsdlToOpenApi(filteredStream ?? stream, settingsFile, cancellationToken); + document = await ConvertCsdlToOpenApi(filteredStream ?? stream, metadataVersion, settingsFile, cancellationToken); stopwatch.Stop(); logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); } @@ -317,7 +316,7 @@ internal static IConfiguration GetConfiguration(string settingsFile) /// /// The CSDL stream. /// An OpenAPI document. - public static async Task ConvertCsdlToOpenApi(Stream csdl, string settingsFile = null, CancellationToken token = default) + public static async Task ConvertCsdlToOpenApi(Stream csdl, string metadataVersion = null, string settingsFile = null, CancellationToken token = default) { using var reader = new StreamReader(csdl); var csdlText = await reader.ReadToEndAsync(token); @@ -325,6 +324,12 @@ public static async Task ConvertCsdlToOpenApi(Stream csdl, stri var config = GetConfiguration(settingsFile); var settings = new OpenApiConvertSettings(); + + if (!string.IsNullOrEmpty(metadataVersion)) + { + settings.SemVerVersion = metadataVersion; + } + config.GetSection("OpenApiConvertSettings").Bind(settings); OpenApiDocument document = edmModel.ConvertToOpenApi(settings); diff --git a/src/Microsoft.OpenApi.Hidi/Program.cs b/src/Microsoft.OpenApi.Hidi/Program.cs index 8d3cc3243..5c5bf691a 100644 --- a/src/Microsoft.OpenApi.Hidi/Program.cs +++ b/src/Microsoft.OpenApi.Hidi/Program.cs @@ -46,9 +46,12 @@ internal static RootCommand CreateRootCommand() var versionOption = new Option("--version", "OpenAPI specification version"); versionOption.AddAlias("-v"); + var metadataVersionOption = new Option("--metadata-version", "Graph metadata version to use."); + metadataVersionOption.AddAlias("--mv"); + var formatOption = new Option("--format", "File format"); formatOption.AddAlias("-f"); - + var terseOutputOption = new Option("--terse-output", "Produce terse json output"); terseOutputOption.AddAlias("--to"); @@ -93,6 +96,7 @@ internal static RootCommand CreateRootCommand() outputOption, cleanOutputOption, versionOption, + metadataVersionOption, formatOption, terseOutputOption, settingsFileOption, @@ -112,6 +116,7 @@ internal static RootCommand CreateRootCommand() OutputOption = outputOption, CleanOutputOption = cleanOutputOption, VersionOption = versionOption, + MetadataVersionOption = metadataVersionOption, FormatOption = formatOption, TerseOutputOption = terseOutputOption, SettingsFileOption = settingsFileOption, diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs index f95acd879..9081c49f5 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs @@ -38,9 +38,9 @@ public async Task ReturnConvertedCSDLFile() } [Theory] - [InlineData("Todos.Todo.UpdateTodo",null, 1)] + [InlineData("Todos.Todo.UpdateTodo", null, 1)] [InlineData("Todos.Todo.ListTodo", null, 1)] - [InlineData(null, "Todos.Todo", 4)] + [InlineData(null, "Todos.Todo", 5)] public async Task ReturnFilteredOpenApiDocBasedOnOperationIdsAndInputCsdlDocument(string operationIds, string tags, int expectedPathCount) { // Arrange @@ -190,7 +190,7 @@ public async Task TransformCommandConvertsOpenApi() { var fileinfo = new FileInfo("sample.json"); // create a dummy ILogger instance for testing - await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml",null, null, fileinfo, true, null, null,false,null,false,false,null,null,null,new Logger(new LoggerFactory()), new CancellationToken()); + await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml",null, null, fileinfo, true, null, null, null,false,null,false,false,null,null,null,new Logger(new LoggerFactory()), new CancellationToken()); var output = File.ReadAllText("sample.json"); Assert.NotEmpty(output); @@ -201,7 +201,7 @@ public async Task TransformCommandConvertsOpenApi() public async Task TransformCommandConvertsOpenApiWithDefaultOutputname() { // create a dummy ILogger instance for testing - await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml", null, null, null, true, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); + await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml", null, null, null, true, null, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); var output = File.ReadAllText("output.yml"); Assert.NotEmpty(output); @@ -211,7 +211,7 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputname() public async Task TransformCommandConvertsCsdlWithDefaultOutputname() { // create a dummy ILogger instance for testing - await OpenApiService.TransformOpenApiDocument(null, "UtilityFiles\\Todo.xml", null, null, true, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); + await OpenApiService.TransformOpenApiDocument(null, "UtilityFiles\\Todo.xml", null, null, true, null, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); var output = File.ReadAllText("output.yml"); Assert.NotEmpty(output); @@ -221,7 +221,7 @@ public async Task TransformCommandConvertsCsdlWithDefaultOutputname() public async Task TransformCommandConvertsOpenApiWithDefaultOutputnameAndSwitchFormat() { // create a dummy ILogger instance for testing - await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml", null, null, null, true, "3.0", OpenApiFormat.Yaml, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); + await OpenApiService.TransformOpenApiDocument("UtilityFiles\\SampleOpenApi.yml", null, null, null, true, "3.0", null, OpenApiFormat.Yaml, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken()); var output = File.ReadAllText("output.yml"); Assert.NotEmpty(output); @@ -231,7 +231,7 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputnameAndSwitchF public async Task ThrowTransformCommandIfOpenApiAndCsdlAreEmpty() { await Assert.ThrowsAsync(async () => - await OpenApiService.TransformOpenApiDocument(null, null, null, null, true, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken())); + await OpenApiService.TransformOpenApiDocument(null, null, null, null, true, null, null, null, false, null, false, false, null, null, null, new Logger(new LoggerFactory()), new CancellationToken())); }