Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0dc267c
Add a mock OpenApiDocument
MaggieKimani1 Oct 12, 2021
0ecca08
Add tests for filtering validation
MaggieKimani1 Oct 12, 2021
2f4a1c8
Add an OpenApi filtering service for filtering an OpenApiDocument bas…
MaggieKimani1 Oct 12, 2021
8e45f8b
Add necessary packages
MaggieKimani1 Oct 12, 2021
f270b90
Simplify using statement and switch condition
MaggieKimani1 Oct 12, 2021
9cda4fb
Use static class reference
MaggieKimani1 Oct 18, 2021
af61c14
Add --filterbyOperationId command option
MaggieKimani1 Oct 18, 2021
d24442d
Add filterByOperationId param and logic
MaggieKimani1 Oct 18, 2021
501e88c
Add static modifier
MaggieKimani1 Oct 18, 2021
d5b1b5e
Clean up and add xml comments
MaggieKimani1 Oct 18, 2021
4016ba1
Add a class that visits the OpenApi operations and returns the search…
MaggieKimani1 Oct 18, 2021
73bef22
Add a search result object model
MaggieKimani1 Oct 18, 2021
a1d46e5
Copies OpenApiOperation references to the new subset document
MaggieKimani1 Oct 18, 2021
b3c79eb
Copy OpenApiInfo and components from the source document to the new s…
MaggieKimani1 Oct 20, 2021
cd5f3fa
Add an info object to the mock document
MaggieKimani1 Oct 20, 2021
3c43ea1
Clean up: Remove unnecessary params
MaggieKimani1 Oct 20, 2021
43f48ec
Remove package reference
MaggieKimani1 Oct 21, 2021
8ba33cd
Revert "Remove package reference"
MaggieKimani1 Oct 21, 2021
2397e9d
Update the Public API interface text file
MaggieKimani1 Oct 26, 2021
d13dcf4
Remove unnecessary package dependency
MaggieKimani1 Oct 26, 2021
00dd9c4
Allow filtering for multiple operationIds
MaggieKimani1 Nov 1, 2021
3f3dae0
Add check for writing to an already existing file
MaggieKimani1 Nov 1, 2021
27ab7f7
Copy over all Info properties
MaggieKimani1 Nov 2, 2021
c3c0abc
Add license header
MaggieKimani1 Nov 2, 2021
dbd8d92
Clean up and add XML documentations for public methods
MaggieKimani1 Nov 2, 2021
a689c36
Copy over extensions object to new document
MaggieKimani1 Nov 2, 2021
deaa2fe
Move declaration closer to first reference point
MaggieKimani1 Nov 3, 2021
015b3cd
Code cleanup
MaggieKimani1 Nov 4, 2021
ac94489
Merge branch 'vnext' into mk/add-filter-commandOption
darrelmiller Nov 5, 2021
d259cc1
Remove [Fact] attribute
MaggieKimani1 Nov 5, 2021
f2102cc
Merge remote-tracking branch 'origin/mk/add-filter-commandOption' int…
MaggieKimani1 Nov 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 41 additions & 42 deletions src/Microsoft.OpenApi.Tool/OpenApiService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System;
using System.IO;
using System.Linq;
using System.Net;
Expand All @@ -21,29 +23,44 @@ public static void ProcessOpenApiDocument(
FileInfo output,
OpenApiSpecVersion version,
OpenApiFormat format,
string filterByOperationIds,
bool inline,
bool resolveExternal)
{
if (input == null)
if (string.IsNullOrEmpty(input))
{
throw new ArgumentNullException("input");
throw new ArgumentNullException(nameof(input));
}
if(output == null)
{
throw new ArgumentException(nameof(output));
}
if (output.Exists)
{
throw new IOException("The file you're writing to already exists. Please input a new output path.");
}

var stream = GetStream(input);

OpenApiDocument document;

var result = new OpenApiStreamReader(new OpenApiReaderSettings
{
ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
ReferenceResolution = resolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
}
).ReadAsync(stream).GetAwaiter().GetResult();

OpenApiDocument document;
document = result.OpenApiDocument;

// Check if filter options are provided, then execute
if (!string.IsNullOrEmpty(filterByOperationIds))
{
var predicate = OpenApiFilterService.CreatePredicate(filterByOperationIds);
document = OpenApiFilterService.CreateFilteredDocument(document, predicate);
}

var context = result.OpenApiDiagnostic;

if (context.Errors.Count != 0)
if (context.Errors.Count > 0)
{
var errorReport = new StringBuilder();

Expand All @@ -52,43 +69,26 @@ public static void ProcessOpenApiDocument(
errorReport.AppendLine(error.ToString());
}

throw new ArgumentException(String.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray()));
throw new ArgumentException(string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray()));
}

using (var outputStream = output?.Create())
{
TextWriter textWriter;

if (outputStream != null)
{
textWriter = new StreamWriter(outputStream);
}
else
{
textWriter = Console.Out;
}
using var outputStream = output?.Create();

var settings = new OpenApiWriterSettings()
{
ReferenceInline = inline == true ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences
};
IOpenApiWriter writer;
switch (format)
{
case OpenApiFormat.Json:
writer = new OpenApiJsonWriter(textWriter, settings);
break;
case OpenApiFormat.Yaml:
writer = new OpenApiYamlWriter(textWriter, settings);
break;
default:
throw new ArgumentException("Unknown format");
}
var textWriter = outputStream != null ? new StreamWriter(outputStream) : Console.Out;

document.Serialize(writer, version);
var settings = new OpenApiWriterSettings()
{
ReferenceInline = inline ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences
};
IOpenApiWriter writer = format switch
{
OpenApiFormat.Json => new OpenApiJsonWriter(textWriter, settings),
OpenApiFormat.Yaml => new OpenApiYamlWriter(textWriter, settings),
_ => throw new ArgumentException("Unknown format"),
};
document.Serialize(writer, version);

textWriter.Flush();
}
textWriter.Flush();
}

private static Stream GetStream(string input)
Expand Down Expand Up @@ -127,7 +127,6 @@ internal static void ValidateOpenApiDocument(string input)

document = new OpenApiStreamReader(new OpenApiReaderSettings
{
//ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
}
).Read(stream, out var context);
Expand Down
32 changes: 7 additions & 25 deletions src/Microsoft.OpenApi.Tool/Program.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,15 @@
using System;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Threading.Tasks;
using Microsoft.OpenApi;

namespace Microsoft.OpenApi.Tool
{
class Program
static class Program
{
static async Task<int> OldMain(string[] args)
{

var command = new RootCommand
{
new Option("--input", "Input OpenAPI description file path or URL", typeof(string) ),
new Option("--output","Output OpenAPI description file", typeof(FileInfo), arity: ArgumentArity.ZeroOrOne),
new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)),
new Option("--format", "File format",typeof(OpenApiFormat) ),
new Option("--inline", "Inline $ref instances", typeof(bool) ),
new Option("--resolveExternal","Resolve external $refs", typeof(bool))
};

command.Handler = CommandHandler.Create<string,FileInfo,OpenApiSpecVersion,OpenApiFormat,bool, bool>(
OpenApiService.ProcessOpenApiDocument);

// Parse the incoming args and invoke the handler
return await command.InvokeAsync(args);
}

static async Task<int> Main(string[] args)
{
var rootCommand = new RootCommand() {
Expand All @@ -47,9 +28,10 @@ static async Task<int> Main(string[] args)
new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)),
new Option("--format", "File format",typeof(OpenApiFormat) ),
new Option("--inline", "Inline $ref instances", typeof(bool) ),
new Option("--resolveExternal","Resolve external $refs", typeof(bool))
new Option("--resolveExternal","Resolve external $refs", typeof(bool)),
new Option("--filterByOperationIds", "Filters by OperationId provided", typeof(string))
};
transformCommand.Handler = CommandHandler.Create<string, FileInfo, OpenApiSpecVersion, OpenApiFormat, bool, bool>(
transformCommand.Handler = CommandHandler.Create<string, FileInfo, OpenApiSpecVersion, OpenApiFormat, string, bool, bool>(
OpenApiService.ProcessOpenApiDocument);

rootCommand.Add(transformCommand);
Expand Down
3 changes: 2 additions & 1 deletion src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageIconUrl>http://go.microsoft.com/fwlink/?LinkID=288890</PackageIconUrl>
<PackageProjectUrl>https://github.com/Microsoft/OpenAPI.NET</PackageProjectUrl>
Expand Down Expand Up @@ -36,7 +37,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
Expand Down
112 changes: 112 additions & 0 deletions src/Microsoft.OpenApi/Services/CopyReferences.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Collections.Generic;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;

namespace Microsoft.OpenApi.Services
{
internal class CopyReferences : OpenApiVisitorBase
{
private readonly OpenApiDocument _target;
public OpenApiComponents Components = new();

public CopyReferences(OpenApiDocument target)
{
_target = target;
}

/// <summary>
/// Visits IOpenApiReferenceable instances that are references and not in components.
/// </summary>
/// <param name="referenceable"> An IOpenApiReferenceable object.</param>
public override void Visit(IOpenApiReferenceable referenceable)
{
switch (referenceable)
{
case OpenApiSchema schema:
EnsureComponentsExists();
EnsureSchemasExists();
if (!Components.Schemas.ContainsKey(schema.Reference.Id))
{
Components.Schemas.Add(schema.Reference.Id, schema);
}
break;

case OpenApiParameter parameter:
EnsureComponentsExists();
EnsureParametersExists();
if (!Components.Parameters.ContainsKey(parameter.Reference.Id))
{
Components.Parameters.Add(parameter.Reference.Id, parameter);
}
break;

case OpenApiResponse response:
EnsureComponentsExists();
EnsureResponsesExists();
if (!Components.Responses.ContainsKey(response.Reference.Id))
{
Components.Responses.Add(response.Reference.Id, response);
}
break;

default:
break;
}
base.Visit(referenceable);
}

/// <summary>
/// Visits <see cref="OpenApiSchema"/>
/// </summary>
/// <param name="schema">The OpenApiSchema to be visited.</param>
public override void Visit(OpenApiSchema schema)
{
// This is needed to handle schemas used in Responses in components
if (schema.Reference != null)
{
EnsureComponentsExists();
EnsureSchemasExists();
if (!Components.Schemas.ContainsKey(schema.Reference.Id))
{
Components.Schemas.Add(schema.Reference.Id, schema);
}
}
base.Visit(schema);
}

private void EnsureComponentsExists()
{
if (_target.Components == null)
{
_target.Components = new OpenApiComponents();
}
}

private void EnsureSchemasExists()
{
if (_target.Components.Schemas == null)
{
_target.Components.Schemas = new Dictionary<string, OpenApiSchema>();
}
}

private void EnsureParametersExists()
{
if (_target.Components.Parameters == null)
{
_target.Components.Parameters = new Dictionary<string, OpenApiParameter>();
}
}

private void EnsureResponsesExists()
{
if (_target.Components.Responses == null)
{
_target.Components.Responses = new Dictionary<string, OpenApiResponse>();
}
}
}
}
Loading