Skip to content

Commit

Permalink
Translation to component ref
Browse files Browse the repository at this point in the history
  • Loading branch information
yurvon-screamo committed Jul 29, 2024
1 parent 2c952f9 commit f0c2bf5
Show file tree
Hide file tree
Showing 20 changed files with 434 additions and 218 deletions.
30 changes: 30 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**
242 changes: 168 additions & 74 deletions src/Saunter/AttributeProvider/AttributeDocumentProvider.cs

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion src/Saunter/DocumentMiddleware/AsyncApiMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using System.Net;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using LEGO.AsyncAPI;
using LEGO.AsyncAPI.Models;
using LEGO.AsyncAPI.Writers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Saunter.Options;
Expand Down
3 changes: 2 additions & 1 deletion src/Saunter/Options/AsyncApiOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Reflection;
using LEGO.AsyncAPI.Models;
using Microsoft.Extensions.Options;
using Saunter.Options.Filters;

namespace Saunter.Options
Expand Down Expand Up @@ -77,6 +78,6 @@ public void AddOperationFilter<T>() where T : IOperationFilter
/// </summary>
public AsyncApiMiddlewareOptions Middleware { get; } = new AsyncApiMiddlewareOptions();

public ConcurrentDictionary<string, AsyncApiDocument> NamedApis { get; set; } = new();
public ConcurrentDictionary<string, AsyncApiDocument> NamedApis { get; private set; } = new();
}
}
1 change: 1 addition & 0 deletions src/Saunter/Options/Filters/IOperationFilter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using LEGO.AsyncAPI.Models;
using Saunter.Options.Filters;

public interface IOperationFilter
{
Expand Down
17 changes: 10 additions & 7 deletions src/Saunter/Options/Filters/OperationFilterContext.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using System.Reflection;
using Saunter.AttributeProvider.Attributes;

public class OperationFilterContext
namespace Saunter.Options.Filters
{
public OperationFilterContext(MethodInfo method, OperationAttribute operation)
public class OperationFilterContext
{
Method = method;
Operation = operation;
}
public OperationFilterContext(MethodInfo method, OperationAttribute operation)
{
Method = method;
Operation = operation;
}

public MethodInfo Method { get; }
public MethodInfo Method { get; }

public OperationAttribute Operation { get; }
public OperationAttribute Operation { get; }
}
}
2 changes: 2 additions & 0 deletions src/Saunter/SharedKernel/AsyncApiDocumentSerializeCloner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public AsyncApiDocument CloneProtype(AsyncApiDocument prototype)
}
}

cloned.Components ??= new();

return cloned;
}
}
Expand Down
63 changes: 43 additions & 20 deletions src/Saunter/SharedKernel/AsyncApiSchemaGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using LEGO.AsyncAPI.Bindings;
using LEGO.AsyncAPI.Models;
using Saunter.SharedKernel.Interfaces;

namespace Saunter.SharedKernel
{
internal class AsyncApiSchemaGenerator : IAsyncApiSchemaGenerator
{
public AsyncApiSchema? Generate(Type? type)
public GeneratedSchemas? Generate(Type? type)
{
return GenerateBranch(type, new());
}

private static AsyncApiSchema? GenerateBranch(Type? type, HashSet<Type> parents)
private static GeneratedSchemas? GenerateBranch(Type? type, HashSet<Type> parents)
{
if (type is null)
{
Expand All @@ -28,6 +29,11 @@ internal class AsyncApiSchemaGenerator : IAsyncApiSchemaGenerator
Nullable = !typeInfo.IsValueType,
};

var nestedShemas = new List<AsyncApiSchema>()
{
schema
};

if (typeInfo.IsGenericType)
{
var nullableType = typeof(Nullable<>).MakeGenericType(typeInfo.GenericTypeArguments);
Expand All @@ -41,17 +47,6 @@ internal class AsyncApiSchemaGenerator : IAsyncApiSchemaGenerator

var name = ToNameCase(typeInfo.Name);

if (!parents.Add(type))
{
schema.Reference = new()
{
Id = name,
Type = ReferenceType.Schema,
};

return schema;
}

schema.Title = name;
schema.Type = MapJsonTypeToSchemaType(typeInfo);

Expand All @@ -70,17 +65,45 @@ internal class AsyncApiSchemaGenerator : IAsyncApiSchemaGenerator
schema.Format = schema.Title;
}

return schema;
return new(schema, nestedShemas);
}

schema.Properties = typeInfo
if (!parents.Add(type))
{
schema = new()
{
Title = name,
Reference = new()
{
Id = name,
Type = ReferenceType.Schema,
}
};

// No new types have been created, so empty
return new(schema, Array.Empty<AsyncApiSchema>());
}

var properties = typeInfo
.DeclaredProperties
.Where(p => p.GetMethod is not null && !p.GetMethod.IsStatic)
.ToDictionary(
prop => ToNameCase(prop.Name),
prop => GenerateBranch(prop.PropertyType.GetTypeInfo(), parents.ToHashSet()));
.Where(p => p.GetMethod is not null && !p.GetMethod.IsStatic);

foreach (var prop in properties)
{
var generatedSchemas = GenerateBranch(prop.PropertyType.GetTypeInfo(), parents);
if (generatedSchemas is null)
{
continue;
}

var key = ToNameCase(prop.Name);

schema.Properties[key] = generatedSchemas.Value.Root;

nestedShemas.AddRange(generatedSchemas.Value.All);
}

return schema;
return new(schema, nestedShemas.DistinctBy(n => n.Title).ToArray());
}

private static string ToNameCase(string name)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
using LEGO.AsyncAPI.Models;

namespace Saunter.SharedKernel.Interfaces
{
public interface IAsyncApiSchemaGenerator
{
AsyncApiSchema? Generate(Type? type);
GeneratedSchemas? Generate(Type? type);
}

public readonly record struct GeneratedSchemas(AsyncApiSchema Root, IReadOnlyCollection<AsyncApiSchema> All);
}
28 changes: 22 additions & 6 deletions test/Saunter.IntegrationTests.ReverseProxy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
FROM mcr.microsoft.com/dotnet/aspnet:6.0
# Run "dotnet publish -c Release" before building this image
COPY bin/Release/net6.0/publish/ App/
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

WORKDIR /App
EXPOSE 5000
ENTRYPOINT ["dotnet", "Saunter.IntegrationTests.ReverseProxy.dll"]
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["test/Saunter.IntegrationTests.ReverseProxy/Saunter.IntegrationTests.ReverseProxy.csproj", "test/Saunter.IntegrationTests.ReverseProxy/"]
COPY ["src/Saunter/Saunter.csproj", "src/Saunter/"]
RUN dotnet restore "./test/Saunter.IntegrationTests.ReverseProxy/Saunter.IntegrationTests.ReverseProxy.csproj"
COPY . .
WORKDIR "/src/test/Saunter.IntegrationTests.ReverseProxy"
RUN dotnet build "./Saunter.IntegrationTests.ReverseProxy.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Saunter.IntegrationTests.ReverseProxy.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Saunter.IntegrationTests.ReverseProxy.dll"]
5 changes: 2 additions & 3 deletions test/Saunter.IntegrationTests.ReverseProxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ public void ConfigureServices(IServiceCollection services)
Info = new AsyncApiInfo
{
Title = Environment.GetEnvironmentVariable("PATH_BASE"),
Version = "1.0.0"
}
Version = "1.0.0",
},
};
});

Expand Down Expand Up @@ -93,7 +93,6 @@ public void Configure(IApplicationBuilder app)
}
}


public class LightMeasuredEvent
{
public int Id { get; set; }
Expand Down
7 changes: 3 additions & 4 deletions test/Saunter.IntegrationTests.ReverseProxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ The [docker-compose.yml](./docker-compose.yml) file sets up 3 containers
2. service-b
3. nginx reverse proxy

Running the test (from root project location):

Running the test:
```
$ dotnet publish -c Release
$ docker-compose up
```bash
docker-compose --file ./test/Saunter.IntegrationTests.ReverseProxy/docker-compose.yml up --build
```

You should be able to access both services UI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<UserSecretsId>cf516cef-fd3c-4a50-b81e-b2b390ecc9f7</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.20.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Saunter\Saunter.csproj" />
</ItemGroup>
Expand Down
9 changes: 4 additions & 5 deletions test/Saunter.IntegrationTests.ReverseProxy/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
version: '3.7'

services:
service-a:
service-a: &service
build:
context: .
context: ../..
dockerfile: test/Saunter.IntegrationTests.ReverseProxy/Dockerfile
restart: always
environment:
- PATH_BASE=/service-a

service-b:
build:
context: .
restart: always
<<: *service
environment:
- PATH_BASE=/service-b

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using LEGO.AsyncAPI.Models;
using Shouldly;

namespace Saunter.Tests.AttributeProvider.DocumentGenerationTests
{
internal static class AssertAsyncApiDocumentHelper
{
public static AsyncApiChannel AssertAndGetChannel(this AsyncApiDocument document, string key, string description)
{
document.Channels.Count.ShouldBe(1);
document.Channels.ShouldContainKey(key);

var channel = document.Channels[key];
channel.ShouldNotBeNull();
channel.Description.ShouldBe(description);

return channel;
}

public static void AssertByMessage(this AsyncApiDocument document, AsyncApiOperation operation, params string[] messageIds)
{
operation.Message.Count.ShouldBe(messageIds.Length);
operation.Message.ShouldAllBe(c => c.Reference.Type == ReferenceType.Message);

foreach (var messageId in messageIds)
{
operation.Message.ShouldContain(m => m.Reference.Id == messageId);
document.Components.Messages.ShouldContainKey(messageId);

var message = document.Components.Messages[messageId];
document.Components.Schemas.ContainsKey(message.Payload.Reference.Id);
}
}
}
}
Loading

0 comments on commit f0c2bf5

Please sign in to comment.