From 11ff97724b7d15317fe13bded807a29ce844a0f9 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 17 Dec 2022 19:06:59 +0100 Subject: [PATCH] Fix OpenAPI type mapping. --- .../Reflection/AssemblyTypeProvider.cs | 2 +- .../Reflection/TypeConfig.cs | 14 ++++++++++++-- .../Api/Config/OpenApi/DiscriminatorProcessor.cs | 5 +++-- .../src/Squidex/Areas/Api/Views/Shared/Docs.cshtml | 5 ++++- .../Reflection/TypeRegistryTests.cs | 12 ++++++++++++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/backend/src/Squidex.Infrastructure/Reflection/AssemblyTypeProvider.cs b/backend/src/Squidex.Infrastructure/Reflection/AssemblyTypeProvider.cs index c4dd0a326..6f0f290ea 100644 --- a/backend/src/Squidex.Infrastructure/Reflection/AssemblyTypeProvider.cs +++ b/backend/src/Squidex.Infrastructure/Reflection/AssemblyTypeProvider.cs @@ -31,7 +31,7 @@ public sealed class AssemblyTypeProvider : ITypeProvider where T : class public void Map(TypeRegistry typeRegistry) { - var baseType = typeof(T); + var baseType = typeof(T); foreach (var derivedType in assembly.GetTypes()) { diff --git a/backend/src/Squidex.Infrastructure/Reflection/TypeConfig.cs b/backend/src/Squidex.Infrastructure/Reflection/TypeConfig.cs index 860a88552..682096334 100644 --- a/backend/src/Squidex.Infrastructure/Reflection/TypeConfig.cs +++ b/backend/src/Squidex.Infrastructure/Reflection/TypeConfig.cs @@ -17,9 +17,9 @@ public sealed class TypeConfig public string? DiscriminatorProperty { get; set; } - public IReadOnlyList<(Type DerivedType, string TypeName)> DerivedTypes + public bool IsEmpty { - get => derivedTypes; + get => derivedTypes.Count == 0; } internal void Add(Type derivedType, string typeName) @@ -43,6 +43,14 @@ public sealed class TypeConfig mapByType = null; } + public IEnumerable<(Type DerivedType, string TypeName)> DerivedTypes() + { + var map = mapByType ??= BuildMapByType(); + + // The mapping can have multiple names per type, but the last is the default. + return map.Select(x => (x.Key, x.Value)); + } + public bool TryGetType(string typeName, [MaybeNullWhen(false)] out Type derivedType) { var map = mapByName ??= BuildMapByName(); @@ -61,6 +69,7 @@ public sealed class TypeConfig { var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + // Ensure that the last registration wins and becomes the default. foreach (var (derivedType, typeName) in derivedTypes) { result[typeName] = derivedType; @@ -73,6 +82,7 @@ public sealed class TypeConfig { var result = new Dictionary(); + // Ensure that the last registration wins and becomes the default. foreach (var (derivedType, typeName) in derivedTypes) { result[derivedType] = typeName; diff --git a/backend/src/Squidex/Areas/Api/Config/OpenApi/DiscriminatorProcessor.cs b/backend/src/Squidex/Areas/Api/Config/OpenApi/DiscriminatorProcessor.cs index 5f63842f4..fc6436d96 100644 --- a/backend/src/Squidex/Areas/Api/Config/OpenApi/DiscriminatorProcessor.cs +++ b/backend/src/Squidex/Areas/Api/Config/OpenApi/DiscriminatorProcessor.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using GraphQL.Utilities; using NJsonSchema; using NJsonSchema.Generation; using Squidex.Infrastructure.Reflection; @@ -28,7 +29,7 @@ public sealed class DiscriminatorProcessor : ISchemaProcessor } if (!typeRegistry.TryGetConfig(context.ContextualType.Type, out var config) || - config.DerivedTypes.Count <= 0 || + config.IsEmpty || config.DiscriminatorProperty == null) { return; @@ -42,7 +43,7 @@ public sealed class DiscriminatorProcessor : ISchemaProcessor var schema = context.Schema; - foreach (var (derivedType, typeName) in config.DerivedTypes) + foreach (var (derivedType, typeName) in config.DerivedTypes().OrderBy(x => x.TypeName)) { var derivedSchema = context.Generator.Generate(derivedType, context.Resolver); diff --git a/backend/src/Squidex/Areas/Api/Views/Shared/Docs.cshtml b/backend/src/Squidex/Areas/Api/Views/Shared/Docs.cshtml index 681c0b681..b1d5af700 100644 --- a/backend/src/Squidex/Areas/Api/Views/Shared/Docs.cshtml +++ b/backend/src/Squidex/Areas/Api/Views/Shared/Docs.cshtml @@ -35,7 +35,7 @@
- + diff --git a/backend/tests/Squidex.Infrastructure.Tests/Reflection/TypeRegistryTests.cs b/backend/tests/Squidex.Infrastructure.Tests/Reflection/TypeRegistryTests.cs index deb0caf05..dba1a83e0 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Reflection/TypeRegistryTests.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Reflection/TypeRegistryTests.cs @@ -112,6 +112,18 @@ public class TypeRegistryTests Assert.Equal(typeof(DerivedEvent), sut.GetType("DerivedEventV2")); } + [Fact] + public void Should_provide_last_registration_for_list() + { + sut.Add(typeof(DerivedCustom), "Custom1"); + sut.Add(typeof(DerivedCustom), "Custom2"); + sut.Add(typeof(DerivedBase), "Base"); + + sut.TryGetConfig(out var config); + + Assert.Equal(new[] { (typeof(DerivedCustom), "Custom2"), (typeof(DerivedBase), "Base") }, config?.DerivedTypes().ToArray()); + } + [Fact] public void Should_throw_exception_if_type_name_not_found() {