29
29
using Microsoft . OpenApi . Hidi . Utilities ;
30
30
using Microsoft . OpenApi . Models ;
31
31
using Microsoft . OpenApi . OData ;
32
+ using Microsoft . OpenApi . Reader ;
32
33
using Microsoft . OpenApi . Readers ;
33
34
using Microsoft . OpenApi . Services ;
34
35
using Microsoft . OpenApi . Writers ;
@@ -38,6 +39,12 @@ namespace Microsoft.OpenApi.Hidi
38
39
{
39
40
internal static class OpenApiService
40
41
{
42
+ static OpenApiService ( )
43
+ {
44
+ OpenApiReaderRegistry . RegisterReader ( OpenApiConstants . Yaml , new OpenApiYamlReader ( ) ) ;
45
+ OpenApiReaderRegistry . RegisterReader ( OpenApiConstants . Yml , new OpenApiYamlReader ( ) ) ;
46
+ }
47
+
41
48
/// <summary>
42
49
/// Implementation of the transform command
43
50
/// </summary>
@@ -52,7 +59,12 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
52
59
{
53
60
if ( options . Output == null )
54
61
{
55
- var inputExtension = GetInputPathExtension ( options . OpenApi , options . Csdl ) ;
62
+ #pragma warning disable CA1308 // Normalize strings to uppercase
63
+ var extension = options . OpenApiFormat ? . GetDisplayName ( ) . ToLowerInvariant ( ) ;
64
+ var inputExtension = ! string . IsNullOrEmpty ( extension ) ? string . Concat ( "." , extension )
65
+ : GetInputPathExtension ( options . OpenApi , options . Csdl ) ;
66
+
67
+ #pragma warning restore CA1308 // Normalize strings to uppercase
56
68
options . Output = new ( $ "./output{ inputExtension } ") ;
57
69
} ;
58
70
@@ -67,7 +79,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
67
79
68
80
// Default to yaml and OpenApiVersion 3 during csdl to OpenApi conversion
69
81
var openApiFormat = options . OpenApiFormat ?? ( ! string . IsNullOrEmpty ( options . OpenApi ) ? GetOpenApiFormat ( options . OpenApi , logger ) : OpenApiFormat . Yaml ) ;
70
- var openApiVersion = options . Version != null ? TryParseOpenApiSpecVersion ( options . Version ) : OpenApiSpecVersion . OpenApi3_0 ;
82
+ var openApiVersion = options . Version != null ? TryParseOpenApiSpecVersion ( options . Version ) : OpenApiSpecVersion . OpenApi3_1 ;
71
83
72
84
// If ApiManifest is provided, set the referenced OpenAPI document
73
85
var apiDependency = await FindApiDependencyAsync ( options . FilterOptions . FilterByApiManifest , logger , cancellationToken ) . ConfigureAwait ( false ) ;
@@ -85,7 +97,8 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
85
97
}
86
98
87
99
// Load OpenAPI document
88
- var document = await GetOpenApiAsync ( options , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
100
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
101
+ var document = await GetOpenApiAsync ( options , format , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
89
102
90
103
if ( options . FilterOptions != null )
91
104
{
@@ -212,7 +225,7 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma
212
225
}
213
226
214
227
// Get OpenAPI document either from OpenAPI or CSDL
215
- private static async Task < OpenApiDocument > GetOpenApiAsync ( HidiOptions options , ILogger logger , string ? metadataVersion = null , CancellationToken cancellationToken = default )
228
+ private static async Task < OpenApiDocument > GetOpenApiAsync ( HidiOptions options , string format , ILogger logger , string ? metadataVersion = null , CancellationToken cancellationToken = default )
216
229
{
217
230
OpenApiDocument document ;
218
231
Stream stream ;
@@ -233,7 +246,7 @@ private static async Task<OpenApiDocument> GetOpenApiAsync(HidiOptions options,
233
246
await stream . DisposeAsync ( ) . ConfigureAwait ( false ) ;
234
247
}
235
248
236
- document = await ConvertCsdlToOpenApiAsync ( filteredStream ?? stream , metadataVersion , options . SettingsConfig , cancellationToken ) . ConfigureAwait ( false ) ;
249
+ document = await ConvertCsdlToOpenApiAsync ( filteredStream ?? stream , format , metadataVersion , options . SettingsConfig , cancellationToken ) . ConfigureAwait ( false ) ;
237
250
stopwatch . Stop ( ) ;
238
251
logger . LogTrace ( "{Timestamp}ms: Generated OpenAPI with {Paths} paths." , stopwatch . ElapsedMilliseconds , document . Paths . Count ) ;
239
252
}
@@ -375,14 +388,16 @@ private static async Task<ReadResult> ParseOpenApiAsync(string openApiFile, bool
375
388
{
376
389
stopwatch . Start ( ) ;
377
390
378
- result = await new OpenApiStreamReader ( new ( )
379
- {
391
+ var settings = new OpenApiReaderSettings
392
+ {
380
393
LoadExternalRefs = inlineExternal ,
381
394
BaseUrl = openApiFile . StartsWith ( "http" , StringComparison . OrdinalIgnoreCase ) ?
382
395
new ( openApiFile ) :
383
396
new Uri ( "file://" + new FileInfo ( openApiFile ) . DirectoryName + Path . DirectorySeparatorChar )
384
- }
385
- ) . ReadAsync ( stream , cancellationToken ) . ConfigureAwait ( false ) ;
397
+ } ;
398
+
399
+ var format = OpenApiModelFactory . GetFormat ( openApiFile ) ;
400
+ result = await OpenApiDocument . LoadAsync ( stream , format , settings , cancellationToken ) . ConfigureAwait ( false ) ;
386
401
387
402
logger . LogTrace ( "{Timestamp}ms: Completed parsing." , stopwatch . ElapsedMilliseconds ) ;
388
403
@@ -398,15 +413,15 @@ private static async Task<ReadResult> ParseOpenApiAsync(string openApiFile, bool
398
413
/// </summary>
399
414
/// <param name="csdl">The CSDL stream.</param>
400
415
/// <returns>An OpenAPI document.</returns>
401
- public static async Task < OpenApiDocument > ConvertCsdlToOpenApiAsync ( Stream csdl , string ? metadataVersion = null , IConfiguration ? settings = null , CancellationToken token = default )
416
+ public static async Task < OpenApiDocument > ConvertCsdlToOpenApiAsync ( Stream csdl , string format , string ? metadataVersion = null , IConfiguration ? settings = null , CancellationToken token = default )
402
417
{
403
418
using var reader = new StreamReader ( csdl ) ;
404
419
var csdlText = await reader . ReadToEndAsync ( token ) . ConfigureAwait ( false ) ;
405
420
var edmModel = CsdlReader . Parse ( XElement . Parse ( csdlText ) . CreateReader ( ) ) ;
406
421
settings ??= SettingsUtilities . GetConfiguration ( ) ;
407
422
408
423
var document = edmModel . ConvertToOpenApi ( SettingsUtilities . GetOpenApiConvertSettings ( settings , metadataVersion ) ) ;
409
- document = FixReferences ( document ) ;
424
+ document = FixReferences ( document , format ) ;
410
425
411
426
return document ;
412
427
}
@@ -416,14 +431,15 @@ public static async Task<OpenApiDocument> ConvertCsdlToOpenApiAsync(Stream csdl,
416
431
/// </summary>
417
432
/// <param name="document"> The converted OpenApiDocument.</param>
418
433
/// <returns> A valid OpenApiDocument instance.</returns>
419
- public static OpenApiDocument FixReferences ( OpenApiDocument document )
434
+ public static OpenApiDocument FixReferences ( OpenApiDocument document , string format )
420
435
{
421
436
// This method is only needed because the output of ConvertToOpenApi isn't quite a valid OpenApiDocument instance.
422
437
// So we write it out, and read it back in again to fix it up.
423
438
424
439
var sb = new StringBuilder ( ) ;
425
440
document . SerializeAsV3 ( new OpenApiYamlWriter ( new StringWriter ( sb ) ) ) ;
426
- var doc = new OpenApiStringReader ( ) . Read ( sb . ToString ( ) , out _ ) ;
441
+
442
+ var doc = OpenApiDocument . Parse ( sb . ToString ( ) , format ) . OpenApiDocument ;
427
443
428
444
return doc ;
429
445
}
@@ -571,7 +587,8 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl
571
587
throw new ArgumentException ( "Please input a file path or URL" ) ;
572
588
}
573
589
574
- var document = await GetOpenApiAsync ( options , logger , null , cancellationToken ) . ConfigureAwait ( false ) ;
590
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
591
+ var document = await GetOpenApiAsync ( options , format , logger , null , cancellationToken ) . ConfigureAwait ( false ) ;
575
592
576
593
using ( logger . BeginScope ( "Creating diagram" ) )
577
594
{
@@ -732,7 +749,8 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
732
749
}
733
750
734
751
// Load OpenAPI document
735
- var document = await GetOpenApiAsync ( options , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
752
+ var format = OpenApiModelFactory . GetFormat ( options . OpenApi ) ;
753
+ var document = await GetOpenApiAsync ( options , format , logger , options . MetadataVersion , cancellationToken ) . ConfigureAwait ( false ) ;
736
754
737
755
cancellationToken . ThrowIfCancellationRequested ( ) ;
738
756
@@ -750,7 +768,7 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
750
768
// Write OpenAPI to Output folder
751
769
options . Output = new ( Path . Combine ( options . OutputFolder , "openapi.json" ) ) ;
752
770
options . TerseOutput = true ;
753
- WriteOpenApi ( options , OpenApiFormat . Json , OpenApiSpecVersion . OpenApi3_0 , document , logger ) ;
771
+ WriteOpenApi ( options , OpenApiFormat . Json , OpenApiSpecVersion . OpenApi3_1 , document , logger ) ;
754
772
755
773
// Create OpenAIPluginManifest from ApiDependency and OpenAPI document
756
774
var manifest = new OpenAIPluginManifest
0 commit comments