diff --git a/src/Microsoft.OpenApi.Hidi/CsdlFilter.xslt b/src/Microsoft.OpenApi.Hidi/CsdlFilter.xslt new file mode 100644 index 000000000..ee3bf0d40 --- /dev/null +++ b/src/Microsoft.OpenApi.Hidi/CsdlFilter.xslt @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index d9a958db9..98def8818 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -31,6 +31,14 @@ true + + + + + + + + diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index f96928d1e..feb62042b 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -24,6 +24,10 @@ using Microsoft.OpenApi.Writers; using static Microsoft.OpenApi.Hidi.OpenApiSpecVersionHelper; using System.Threading; +using System.Xml.Xsl; +using System.Xml; +using System.Runtime.CompilerServices; +using System.Reflection; namespace Microsoft.OpenApi.Hidi { @@ -35,6 +39,7 @@ public class OpenApiService public static async Task TransformOpenApiDocument( string openapi, string csdl, + string csdlFilter, FileInfo output, bool cleanoutput, string? version, @@ -85,6 +90,13 @@ CancellationToken cancellationToken openApiVersion = version != null ? TryParseOpenApiSpecVersion(version) : OpenApiSpecVersion.OpenApi3_0; stream = await GetStream(csdl, logger, cancellationToken); + + if (!string.IsNullOrEmpty(csdlFilter)) + { + XslCompiledTransform transform = GetFilterTransform(); + stream = ApplyFilter(csdl, csdlFilter, transform); + stream.Position = 0; + } document = await ConvertCsdlToOpenApi(stream); stopwatch.Stop(); logger.LogTrace("{timestamp}ms: Generated OpenAPI with {paths} paths.", stopwatch.ElapsedMilliseconds, document.Paths.Count); @@ -212,6 +224,31 @@ CancellationToken cancellationToken } } + private static XslCompiledTransform GetFilterTransform() + { + XslCompiledTransform transform = new(); + Assembly assembly = typeof(OpenApiService).GetTypeInfo().Assembly; + Stream xslt = assembly.GetManifestResourceStream("Microsoft.OpenApi.Hidi.CsdlFilter.xslt"); + transform.Load(new XmlTextReader(new StreamReader(xslt))); + return transform; + } + + private static Stream ApplyFilter(string csdl, string entitySetOrSingleton, XslCompiledTransform transform) + { + Stream stream; + StreamReader inputReader = new(csdl); + XmlReader inputXmlReader = XmlReader.Create(inputReader); + MemoryStream filteredStream = new(); + StreamWriter writer = new(filteredStream); + XsltArgumentList args = new(); + args.AddParam("entitySetOrSingleton", "", entitySetOrSingleton); + transform.Transform(inputXmlReader, args, writer); + stream = filteredStream; + return stream; + } + + + /// /// Implementation of the validate command /// @@ -308,8 +345,8 @@ public static async Task ConvertCsdlToOpenApi(Stream csdl) EnableDiscriminatorValue = false, EnableDerivedTypesReferencesForRequestBody = false, EnableDerivedTypesReferencesForResponses = false, - ShowRootPath = true, - ShowLinks = true + ShowRootPath = false, + ShowLinks = false }; OpenApiDocument document = edmModel.ConvertToOpenApi(settings); diff --git a/src/Microsoft.OpenApi.Hidi/Program.cs b/src/Microsoft.OpenApi.Hidi/Program.cs index 985c8751c..8b466913c 100644 --- a/src/Microsoft.OpenApi.Hidi/Program.cs +++ b/src/Microsoft.OpenApi.Hidi/Program.cs @@ -24,6 +24,9 @@ static async Task Main(string[] args) var csdlOption = new Option("--csdl", "Input CSDL file path or URL"); csdlOption.AddAlias("-cs"); + var csdlFilterOption = new Option("--csdl-filter", "Comma delimited list of EntitySets or Singletons to filter CSDL on. e.g. tasks,accounts"); + csdlFilterOption.AddAlias("-csf"); + var outputOption = new Option("--output", () => new FileInfo("./output"), "The output directory path for the generated file.") { Arity = ArgumentArity.ZeroOrOne }; outputOption.AddAlias("-o"); @@ -39,13 +42,13 @@ static async Task Main(string[] args) var logLevelOption = new Option("--loglevel", () => LogLevel.Information, "The log level to use when logging messages to the main output."); logLevelOption.AddAlias("-ll"); - var filterByOperationIdsOption = new Option("--filter-by-operationids", "Filters OpenApiDocument by OperationId(s) provided"); + var filterByOperationIdsOption = new Option("--filter-by-operationids", "Filters OpenApiDocument by comma delimited list of OperationId(s) provided"); filterByOperationIdsOption.AddAlias("-op"); - var filterByTagsOption = new Option("--filter-by-tags", "Filters OpenApiDocument by Tag(s) provided"); + var filterByTagsOption = new Option("--filter-by-tags", "Filters OpenApiDocument by comma delimited list of Tag(s) provided. Also accepts a single regex."); filterByTagsOption.AddAlias("-t"); - var filterByCollectionOption = new Option("--filter-by-collection", "Filters OpenApiDocument by Postman collection provided"); + var filterByCollectionOption = new Option("--filter-by-collection", "Filters OpenApiDocument by Postman collection provided. Provide path to collection file."); filterByCollectionOption.AddAlias("-c"); var inlineLocalOption = new Option("--inlineLocal", "Inline local $ref instances"); @@ -66,6 +69,7 @@ static async Task Main(string[] args) { descriptionOption, csdlOption, + csdlFilterOption, outputOption, cleanOutputOption, versionOption, @@ -78,8 +82,8 @@ static async Task Main(string[] args) inlineExternalOption }; - transformCommand.SetHandler ( - OpenApiService.TransformOpenApiDocument, descriptionOption, csdlOption, outputOption, cleanOutputOption, versionOption, formatOption, logLevelOption, inlineLocalOption, inlineExternalOption, filterByOperationIdsOption, filterByTagsOption, filterByCollectionOption); + transformCommand.SetHandler ( + OpenApiService.TransformOpenApiDocument, descriptionOption, csdlOption, csdlFilterOption, outputOption, cleanOutputOption, versionOption, formatOption, logLevelOption, inlineLocalOption, inlineExternalOption, filterByOperationIdsOption, filterByTagsOption, filterByCollectionOption); rootCommand.Add(transformCommand); rootCommand.Add(validateCommand); diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 066d20658..5ae43a371 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -20,8 +20,8 @@ - - + + all diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiServiceTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiServiceTests.cs index 1c9fd003b..af5437aa1 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiServiceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiServiceTests.cs @@ -22,7 +22,7 @@ public async Task ReturnConvertedCSDLFile() // Act var openApiDoc = await OpenApiService.ConvertCsdlToOpenApi(csdlStream); - var expectedPathCount = 6; + var expectedPathCount = 5; // Assert Assert.NotNull(openApiDoc);