Skip to content

Commit 7637861

Browse files
Merge pull request #1064 from microsoft/feature/csdlsettings
Enable Hidi users configure CSDL to OpenAPI conversion settings
2 parents ab9bafb + ec05eca commit 7637861

File tree

7 files changed

+92
-8
lines changed

7 files changed

+92
-8
lines changed

src/Microsoft.OpenApi.Hidi/Handlers/TransformCommandHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal class TransformCommandHandler : ICommandHandler
2121
public Option<string?> VersionOption { get; set; }
2222
public Option<OpenApiFormat?> FormatOption { get; set; }
2323
public Option<bool> TerseOutputOption { get; set; }
24+
public Option<string> SettingsFileOption { get; set; }
2425
public Option<LogLevel> LogLevelOption { get; set; }
2526
public Option<string> FilterByOperationIdsOption { get; set; }
2627
public Option<string> FilterByTagsOption { get; set; }
@@ -42,6 +43,7 @@ public async Task<int> InvokeAsync(InvocationContext context)
4243
string? version = context.ParseResult.GetValueForOption(VersionOption);
4344
OpenApiFormat? format = context.ParseResult.GetValueForOption(FormatOption);
4445
bool terseOutput = context.ParseResult.GetValueForOption(TerseOutputOption);
46+
string settingsFile = context.ParseResult.GetValueForOption(SettingsFileOption);
4547
LogLevel logLevel = context.ParseResult.GetValueForOption(LogLevelOption);
4648
bool inlineLocal = context.ParseResult.GetValueForOption(InlineLocalOption);
4749
bool inlineExternal = context.ParseResult.GetValueForOption(InlineExternalOption);
@@ -54,7 +56,7 @@ public async Task<int> InvokeAsync(InvocationContext context)
5456
var logger = loggerFactory.CreateLogger<OpenApiService>();
5557
try
5658
{
57-
await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken);
59+
await OpenApiService.TransformOpenApiDocument(openapi, csdl, csdlFilter, output, cleanOutput, version, format, terseOutput, settingsFile, logLevel, inlineLocal, inlineExternal, filterbyoperationids, filterbytags, filterbycollection, cancellationToken);
5860

5961
return 0;
6062
}

src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,20 @@
4444
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
4545
<PackageReference Include="Microsoft.OData.Edm" Version="7.12.5" />
4646
<PackageReference Include="Microsoft.OpenApi.OData" Version="1.2.0-preview6" />
47+
<PackageReference Include="System.CommandLine.Hosting" Version="0.4.0-alpha.22114.1" />
4748
</ItemGroup>
4849

4950
<ItemGroup>
5051
<ProjectReference Include="..\Microsoft.OpenApi.Readers\Microsoft.OpenApi.Readers.csproj" />
5152
<ProjectReference Include="..\Microsoft.OpenApi\Microsoft.OpenApi.csproj" />
5253
</ItemGroup>
5354

55+
<!-- Make internals available for Unit Testing -->
56+
<ItemGroup>
57+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
58+
<_Parameter1>Microsoft.OpenApi.Hidi.Tests</_Parameter1>
59+
</AssemblyAttribute>
60+
</ItemGroup>
61+
<!-- End Unit test Internals -->
62+
5463
</Project>

src/Microsoft.OpenApi.Hidi/OpenApiService.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
using System.Xml.Xsl;
2828
using System.Xml;
2929
using System.Reflection;
30+
using Microsoft.Extensions.Configuration;
31+
using System.Runtime.CompilerServices;
3032

3133
namespace Microsoft.OpenApi.Hidi
3234
{
@@ -44,6 +46,7 @@ public static async Task TransformOpenApiDocument(
4446
string? version,
4547
OpenApiFormat? format,
4648
bool terseOutput,
49+
string settingsFile,
4750
LogLevel logLevel,
4851
bool inlineLocal,
4952
bool inlineExternal,
@@ -98,7 +101,8 @@ CancellationToken cancellationToken
98101
stream = ApplyFilter(csdl, csdlFilter, transform);
99102
stream.Position = 0;
100103
}
101-
document = await ConvertCsdlToOpenApi(stream);
104+
105+
document = await ConvertCsdlToOpenApi(stream, settingsFile);
102106
stopwatch.Stop();
103107
logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count);
104108
}
@@ -304,25 +308,37 @@ public static async Task ValidateOpenApiDocument(
304308
}
305309
}
306310

311+
internal static IConfiguration GetConfiguration(string settingsFile)
312+
{
313+
settingsFile ??= "appsettings.json";
314+
315+
IConfiguration config = new ConfigurationBuilder()
316+
.AddJsonFile(settingsFile, true)
317+
.Build();
318+
319+
return config;
320+
}
321+
307322
/// <summary>
308323
/// Converts CSDL to OpenAPI
309324
/// </summary>
310325
/// <param name="csdl">The CSDL stream.</param>
311326
/// <returns>An OpenAPI document.</returns>
312-
public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl)
327+
public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl, string settingsFile = null)
313328
{
314329
using var reader = new StreamReader(csdl);
315330
var csdlText = await reader.ReadToEndAsync();
316331
var edmModel = CsdlReader.Parse(XElement.Parse(csdlText).CreateReader());
317-
332+
333+
var config = GetConfiguration(settingsFile);
318334
var settings = new OpenApiConvertSettings()
319335
{
320336
AddSingleQuotesForStringParameters = true,
321337
AddEnumDescriptionExtension = true,
322338
DeclarePathParametersOnPathItem = true,
323339
EnableKeyAsSegment = true,
324340
EnableOperationId = true,
325-
ErrorResponsesAsDefault = false,
341+
ErrorResponsesAsDefault = false,
326342
PrefixEntityTypeNameBeforeKey = true,
327343
TagDepth = 2,
328344
EnablePagination = true,
@@ -335,6 +351,8 @@ public static async Task<OpenApiDocument> ConvertCsdlToOpenApi(Stream csdl)
335351
EnableCount = true,
336352
UseSuccessStatusCodeRange = true
337353
};
354+
config.GetSection("OpenApiConvertSettings").Bind(settings);
355+
338356
OpenApiDocument document = edmModel.ConvertToOpenApi(settings);
339357

340358
document = FixReferences(document);

src/Microsoft.OpenApi.Hidi/Program.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
// Licensed under the MIT license.
33

44
using System.CommandLine;
5+
using System.CommandLine.Builder;
6+
using System.CommandLine.Hosting;
7+
using System.CommandLine.Parsing;
8+
59
using System.IO;
610
using System.Threading.Tasks;
11+
using Microsoft.Extensions.Configuration;
12+
using Microsoft.Extensions.Hosting;
713
using Microsoft.Extensions.Logging;
814
using Microsoft.OpenApi.Hidi.Handlers;
915

@@ -41,6 +47,9 @@ static async Task Main(string[] args)
4147
var terseOutputOption = new Option<bool>("--terse-output", "Produce terse json output");
4248
terseOutputOption.AddAlias("--to");
4349

50+
var settingsFileOption = new Option<string>("--settings-path", "The configuration file with CSDL conversion settings.");
51+
settingsFileOption.AddAlias("--sp");
52+
4453
var logLevelOption = new Option<LogLevel>("--log-level", () => LogLevel.Information, "The log level to use when logging messages to the main output.");
4554
logLevelOption.AddAlias("--ll");
4655

@@ -81,6 +90,7 @@ static async Task Main(string[] args)
8190
versionOption,
8291
formatOption,
8392
terseOutputOption,
93+
settingsFileOption,
8494
logLevelOption,
8595
filterByOperationIdsOption,
8696
filterByTagsOption,
@@ -99,6 +109,7 @@ static async Task Main(string[] args)
99109
VersionOption = versionOption,
100110
FormatOption = formatOption,
101111
TerseOutputOption = terseOutputOption,
112+
SettingsFileOption = settingsFileOption,
102113
LogLevelOption = logLevelOption,
103114
FilterByOperationIdsOption = filterByOperationIdsOption,
104115
FilterByTagsOption = filterByTagsOption,

test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
</ItemGroup>
3535

3636
<ItemGroup>
37+
<None Update="UtilityFiles\appsettingstest.json">
38+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
39+
</None>
3740
<None Update="UtilityFiles\postmanCollection_ver1.json">
3841
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3942
</None>

test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
using System;
5-
using System.IO;
6-
using System.Threading.Tasks;
4+
using Microsoft.Extensions.Configuration;
75
using Microsoft.OpenApi.Hidi;
6+
using Microsoft.OpenApi.OData;
87
using Microsoft.OpenApi.Services;
98
using Xunit;
109

@@ -51,5 +50,26 @@ public async Task ReturnFilteredOpenApiDocBasedOnOperationIdsAndInputCsdlDocumen
5150
Assert.NotEmpty(subsetOpenApiDocument.Paths);
5251
Assert.Equal(expectedPathCount, subsetOpenApiDocument.Paths.Count);
5352
}
53+
54+
[Theory]
55+
[InlineData("UtilityFiles/appsettingstest.json")]
56+
[InlineData(null)]
57+
public void ReturnOpenApiConvertSettingsWhenSettingsFileIsProvided(string filePath)
58+
{
59+
// Arrange
60+
var config = OpenApiService.GetConfiguration(filePath);
61+
62+
// Act and Assert
63+
var settings = config.GetSection("OpenApiConvertSettings").Get<OpenApiConvertSettings>();
64+
65+
if (filePath == null)
66+
{
67+
Assert.Null(settings);
68+
}
69+
else
70+
{
71+
Assert.NotNull(settings);
72+
}
73+
}
5474
}
5575
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"OpenApiConvertSettings": {
3+
"AddSingleQuotesForStringParameters": "true",
4+
"AddEnumDescriptionExtension": "true",
5+
"DeclarePathParametersOnPathItem": "true",
6+
"EnableKeyAsSegment": "true",
7+
"EnableOperationId": "true",
8+
"ErrorResponsesAsDefault": "false",
9+
"PrefixEntityTypeNameBeforeKey": "true",
10+
"TagDepth": 2,
11+
"EnablePagination": "true",
12+
"EnableDiscriminatorValue": "true",
13+
"EnableDerivedTypesReferencesForRequestBody": "false",
14+
"EnableDerivedTypesReferencesForResponses": "false",
15+
"ShowRootPath": "false",
16+
"ShowLinks": "false",
17+
"ExpandDerivedTypesNavigationProperties": "false",
18+
"EnableCount": "true",
19+
"UseSuccessStatusCodeRange": "true"
20+
}
21+
}

0 commit comments

Comments
 (0)