-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #740 from leancodepl/feature/openapi
OpenAPI in .NET 9
- Loading branch information
Showing
14 changed files
with
281 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/CQRS/LeanCode.CQRS.AspNetCore/Registration/ApiDescriptionTags.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using LeanCode.CQRS.Execution; | ||
using Microsoft.AspNetCore.Routing; | ||
|
||
namespace LeanCode.CQRS.AspNetCore.Registration; | ||
|
||
public static class ApiDescriptionTags | ||
{ | ||
public static IReadOnlyList<string> FullNamespace(RouteEndpoint _, CQRSObjectMetadata m) | ||
{ | ||
return [(m.ObjectType.Namespace ?? "").Replace(".", " - ", StringComparison.InvariantCulture)]; | ||
} | ||
|
||
public static Func<RouteEndpoint, CQRSObjectMetadata, IReadOnlyList<string>> SkipNamespacePrefix(int skipFirst) | ||
{ | ||
return (_, m) => | ||
{ | ||
var parts = (m.ObjectType.Namespace ?? "").Split('.').Skip(skipFirst); | ||
return [string.Join(" - ", parts)]; | ||
}; | ||
} | ||
} |
16 changes: 8 additions & 8 deletions
16
src/CQRS/LeanCode.CQRS.AspNetCore/Registration/CQRSApiDescriptionConfiguration.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
using System.Collections.Frozen; | ||
using LeanCode.CQRS.Execution; | ||
using Microsoft.AspNetCore.Routing; | ||
|
||
namespace LeanCode.CQRS.AspNetCore.Registration; | ||
|
||
public class CQRSApiDescriptionConfiguration | ||
{ | ||
// Required by Swagger (Swashbuckle) | ||
public static readonly FrozenDictionary<string, string?> DefaultRouteValues = new Dictionary<string, string?> | ||
{ | ||
["controller"] = "CQRS", | ||
}.ToFrozenDictionary(); | ||
public Func<RouteEndpoint, CQRSObjectMetadata, IReadOnlyList<string>> TagsMapping { get; init; } = | ||
ApiDescriptionTags.FullNamespace; | ||
|
||
public Func<RouteEndpoint, IDictionary<string, string?>> RouteValuesMapping { get; init; } = | ||
_ => DefaultRouteValues; | ||
public Func<RouteEndpoint, CQRSObjectMetadata, string> SummaryMapping { get; init; } = | ||
static (_, m) => m.ObjectType.FullName ?? ""; | ||
|
||
public Func<RouteEndpoint, CQRSObjectMetadata, string> DescriptionMapping { get; init; } = | ||
static (_, m) => $"Executed by {m.HandlerType.FullName ?? "unknown handler"}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/CQRS/LeanCode.CQRS.AspNetCore/Registration/EndpointMetadata.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using Microsoft.AspNetCore.Http.Metadata; | ||
|
||
namespace LeanCode.CQRS.AspNetCore.Registration; | ||
|
||
internal class EndpointTags(IReadOnlyList<string> tags) : ITagsMetadata | ||
{ | ||
public IReadOnlyList<string> Tags => tags; | ||
} | ||
|
||
internal class EndpointSummary(string summary) : IEndpointSummaryMetadata | ||
{ | ||
public string Summary => summary; | ||
} | ||
|
||
internal class EndpointDescription(string description) : IEndpointDescriptionMetadata | ||
{ | ||
public string Description => description; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System.ComponentModel; | ||
using FluentValidation; | ||
using LeanCode.Contracts; | ||
using LeanCode.Contracts.Security; | ||
using LeanCode.CQRS.Execution; | ||
using LeanCode.CQRS.Validation.Fluent; | ||
using Serilog; | ||
using ILogger = Serilog.ILogger; | ||
|
||
namespace LeanCode.TestBed.Api; | ||
|
||
[AllowUnauthorized] | ||
public class TestCommand : ICommand | ||
{ | ||
public required bool TriggerCode1 { get; set; } | ||
public required bool TriggerCode2 { get; set; } | ||
public required string OtherParameter { get; set; } | ||
|
||
public static class ErrorCodes | ||
{ | ||
public const int Code1 = 1; | ||
public const int Code2 = 2; | ||
} | ||
} | ||
|
||
public class TestCommandCV : AbstractValidator<TestCommand> | ||
{ | ||
public TestCommandCV() | ||
{ | ||
RuleFor(e => e.TriggerCode1).Equal(false).WithCode(TestCommand.ErrorCodes.Code1); | ||
RuleFor(e => e.TriggerCode2).Equal(false).WithCode(TestCommand.ErrorCodes.Code2); | ||
} | ||
} | ||
|
||
public class TestCommandCH : ICommandHandler<TestCommand> | ||
{ | ||
private readonly ILogger logger = Log.ForContext<TestCommandCH>(); | ||
|
||
public Task ExecuteAsync(HttpContext context, TestCommand command) | ||
{ | ||
logger.Information("Executing command {Command}", command); | ||
return Task.CompletedTask; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using LeanCode.Contracts; | ||
using LeanCode.CQRS.Execution; | ||
|
||
namespace LeanCode.TestBed.Api; | ||
|
||
[Obsolete] | ||
public class TestQuery : IQuery<TestQueryResult> { } | ||
|
||
public class TestQueryResult | ||
{ | ||
public Guid Id { get; set; } | ||
public string Property1 { get; set; } | ||
public TestQueryResult? Inner { get; set; } | ||
} | ||
|
||
public class TestQueryQH : IQueryHandler<TestQuery, TestQueryResult> | ||
{ | ||
public Task<TestQueryResult> ExecuteAsync(HttpContext context, TestQuery query) | ||
{ | ||
return Task.FromResult( | ||
new TestQueryResult | ||
{ | ||
Id = Guid.NewGuid(), | ||
Property1 = "Some value", | ||
Inner = new() { Id = Guid.NewGuid(), Property1 = "Other value" }, | ||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net9.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="LeanCode.Contracts" /> | ||
|
||
<PackageReference Include="Serilog" /> | ||
<PackageReference Include="Serilog.Extensions.Logging" /> | ||
|
||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" /> | ||
<PackageReference Include="Swashbuckle.AspNetCore.ReDoc" /> | ||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" /> | ||
|
||
<ProjectReference Include="../src/Core/LeanCode.Components/LeanCode.Components.csproj" /> | ||
|
||
<ProjectReference Include="../src/CQRS/LeanCode.CQRS.AspNetCore/LeanCode.CQRS.AspNetCore.csproj" /> | ||
<ProjectReference Include="../src/CQRS/LeanCode.CQRS.Validation/LeanCode.CQRS.Validation.csproj" /> | ||
<ProjectReference Include="../src/CQRS/LeanCode.CQRS.Validation.Fluent/LeanCode.CQRS.Validation.Fluent.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using LeanCode.Components; | ||
using LeanCode.CQRS.AspNetCore; | ||
using LeanCode.CQRS.Validation.Fluent; | ||
using LeanCode.TestBed.Api; | ||
using Serilog; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
|
||
builder.Logging.AddSerilog(); | ||
builder.Services.AddFluentValidation(TypesCatalog.Of<TestCommandCH>()); | ||
builder.Services.AddCQRS(TypesCatalog.Of<TestCommand>(), TypesCatalog.Of<TestCommandCH>()); | ||
builder.Services.AddCQRSApiExplorer(); | ||
builder.Services.AddOpenApi(); | ||
|
||
var app = builder.Build(); | ||
|
||
app.MapOpenApi(); | ||
app.MapRemoteCQRS( | ||
"/", | ||
c => | ||
{ | ||
c.Commands = p => p.Secure().Validate(); | ||
c.Queries = p => p.Secure(); | ||
} | ||
); | ||
app.UseReDoc(opt => | ||
{ | ||
opt.SpecUrl("/openapi/v1.json"); | ||
opt.RoutePrefix = "redoc"; | ||
}); | ||
app.UseSwaggerUI(opt => | ||
{ | ||
opt.SwaggerEndpoint("/openapi/v1.json", "Test API"); | ||
opt.RoutePrefix = "swagger"; | ||
}); | ||
|
||
app.Run(); |
36 changes: 36 additions & 0 deletions
36
test/CQRS/LeanCode.CQRS.AspNetCore.Tests/Registration/ApiDescriptionTagsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using FluentAssertions; | ||
using LeanCode.CQRS.AspNetCore.Registration; | ||
using LeanCode.CQRS.Execution; | ||
using Xunit; | ||
|
||
namespace LeanCode.CQRS.AspNetCore.Tests.Registration; | ||
|
||
public class ApiDescriptionTagsTests | ||
{ | ||
private static readonly CQRSObjectMetadata Metadata = new CQRSObjectMetadata( | ||
CQRSObjectKind.Command, | ||
typeof(ApiDescriptionTagsTests), | ||
typeof(ApiDescriptionTagsTests), | ||
typeof(ApiDescriptionTagsTests), | ||
(_, _) => Task.FromResult<object?>(null) | ||
); | ||
|
||
[Fact] | ||
public void FullNamespace_returns_full_namespace_with_dot_replaced() | ||
{ | ||
var tags = ApiDescriptionTags.FullNamespace(null!, Metadata); | ||
|
||
tags.Should().BeEquivalentTo("LeanCode - CQRS - AspNetCore - Tests - Registration"); | ||
} | ||
|
||
[Fact] | ||
public void SkipNamespacePrefix_skips_initial_namespace_parts() | ||
{ | ||
Tag(skip: 0).Should().BeEquivalentTo("LeanCode - CQRS - AspNetCore - Tests - Registration"); | ||
Tag(skip: 1).Should().BeEquivalentTo("CQRS - AspNetCore - Tests - Registration"); | ||
Tag(skip: 2).Should().BeEquivalentTo("AspNetCore - Tests - Registration"); | ||
Tag(skip: 10).Should().BeEquivalentTo(""); | ||
|
||
IReadOnlyList<string> Tag(int skip) => ApiDescriptionTags.SkipNamespacePrefix(skip)(null!, Metadata); | ||
} | ||
} |
Oops, something went wrong.