From e268e6e4b63ed3c016ead5cc4329b7af8276339c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 17 Feb 2022 20:00:14 +0100 Subject: [PATCH 1/4] Graphql enums. --- .../Contents/GraphQL/Types/Builder.cs | 6 +++ .../GraphQL/Types/Contents/FieldEnumType.cs | 46 +++++++++++++++++++ .../Types/Contents/FieldInputVisitor.cs | 25 ++++++++-- .../GraphQL/Types/Contents/FieldVisitor.cs | 29 ++++++++++-- .../GraphQL/Types/Contents/SchemaInfo.cs | 5 +- .../GraphQL/BufferingDocumentWriter.cs | 35 ++++++++++++++ backend/src/Squidex.Web/Squidex.Web.csproj | 1 + .../Config/Domain/SerializationServices.cs | 5 +- .../Contents/GraphQL/TestSchemas.cs | 26 +++++++---- 9 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs create mode 100644 backend/src/Squidex.Web/GraphQL/BufferingDocumentWriter.cs diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs index 68f2c53d5..a3d9d12be 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs @@ -24,6 +24,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types private readonly Dictionary componentTypes = new Dictionary(ReferenceEqualityComparer.Instance); private readonly Dictionary contentTypes = new Dictionary(ReferenceEqualityComparer.Instance); private readonly Dictionary contentResultTypes = new Dictionary(ReferenceEqualityComparer.Instance); + private readonly Dictionary enumTypes = new Dictionary(); private readonly FieldVisitor fieldVisitor; private readonly FieldInputVisitor fieldInputVisitor; private readonly PartitionResolver partitionResolver; @@ -150,6 +151,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types return componentTypes.GetOrDefault(schema); } + public EnumerationGraphType GetEnumeration(string name, string prefix, IEnumerable values) + { + return enumTypes.GetOrAdd(name, x => new FieldEnumType(name, string prefix, values)); + } + public IEnumerable> GetAllContentTypes() { return contentTypes; diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs new file mode 100644 index 000000000..3ed6f0da3 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs @@ -0,0 +1,46 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using GraphQL.Types; +using Squidex.Text; + +namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents +{ + public sealed class FieldEnumType : EnumerationGraphType + { + public FieldEnumType(string name, string prefix, IEnumerable values) + { + Name = name; + + var index = 0; + + foreach (var value in values) + { + AddValue(BuildName(value, prefix, index), null, value); + + index++; + } + } + + private static string BuildName(T value, string prefix, int index) + { + var name = value!.ToString()!.Slugify().ToPascalCase(); + + if (string.IsNullOrEmpty(name)) + { + name = $"{prefix}_{index}"; + } + + if (!char.IsLetter(name[0])) + { + name = $"{prefix}_{name}"; + } + + return name; + } + } +} diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs index 91c542449..49f933377 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs @@ -69,23 +69,40 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents return AllTypes.Json; } - public IGraphType? Visit(IField field, FieldInfo args) + public IGraphType? Visit(IField field, FieldInfo args) { - return AllTypes.Float; + return AllTypes.Strings; } - public IGraphType? Visit(IField field, FieldInfo args) + public IGraphType? Visit(IField field, FieldInfo args) { - return AllTypes.Strings; + if (field.Properties?.AllowedValues?.Count > 0) + { + return builder.GetEnumeration(args.EnumName, "Number", field.Properties.AllowedValues); + } + + return AllTypes.Float; } public IGraphType? Visit(IField field, FieldInfo args) { + if (field.Properties?.AllowedValues?.Count > 0) + { + return builder.GetEnumeration(args.EnumName, "String", field.Properties.AllowedValues); + } + return AllTypes.String; } public IGraphType? Visit(IField field, FieldInfo args) { + if (field.Properties?.AllowedValues?.Count > 0) + { + var @enum = builder.GetEnumeration(args.EnumName, "Tag", field.Properties.AllowedValues); + + return new ListGraphType(new NonNullGraphType(@enum)); + } + return AllTypes.Strings; } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs index dd303dc26..698536671 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs @@ -164,17 +164,40 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) { - return (AllTypes.Float, JsonNumber, null); + var type = AllTypes.Float; + + if (field.Properties?.AllowedValues?.Count > 0) + { + type = builder.GetEnumeration(args.EnumName, "Number", field.Properties.AllowedValues); + } + + return (type, JsonNumber, null); } public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) { - return (AllTypes.String, JsonString, null); + var type = AllTypes.String; + + if (field.Properties?.AllowedValues?.Count > 0) + { + type = builder.GetEnumeration(args.EnumName, "String", field.Properties.AllowedValues); + } + + return (type, JsonString, null); } public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) { - return (AllTypes.Strings, JsonStrings, null); + var type = AllTypes.Strings; + + if (field.Properties?.AllowedValues?.Count > 0) + { + var @enum = builder.GetEnumeration(args.EnumName, "Tag", field.Properties.AllowedValues); + + type = new ListGraphType(new NonNullGraphType(@enum)); + } + + return (type, JsonStrings, null); } public (IGraphType?, IFieldResolver?, QueryArguments?) Visit(IField field, FieldInfo args) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs index 48098e28c..366a03571 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs @@ -92,6 +92,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents public string DisplayName { get; } + public string EnumName { get; } + public string LocalizedType { get; } public string LocalizedInputType { get; } @@ -116,8 +118,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents Fields = fields; FieldName = fieldName; FieldNameDynamic = names[$"{fieldName}__Dynamic"]; - LocalizedType = names[$"{typeName}Dto"]; + EnumName = names[$"{fieldName}Enum"]; LocalizedInputType = names[$"{typeName}InputDto"]; + LocalizedType = names[$"{typeName}Dto"]; NestedInputType = names[$"{typeName}ChildInputDto"]; NestedType = names[$"{typeName}ChildDto"]; ReferenceType = names[$"{typeName}UnionDto"]; diff --git a/backend/src/Squidex.Web/GraphQL/BufferingDocumentWriter.cs b/backend/src/Squidex.Web/GraphQL/BufferingDocumentWriter.cs new file mode 100644 index 000000000..7173ea0d9 --- /dev/null +++ b/backend/src/Squidex.Web/GraphQL/BufferingDocumentWriter.cs @@ -0,0 +1,35 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using GraphQL; +using GraphQL.NewtonsoftJson; +using Microsoft.AspNetCore.WebUtilities; +using Newtonsoft.Json; + +namespace Squidex.Web.GraphQL +{ + public sealed class BufferingDocumentWriter : IDocumentWriter + { + private readonly DocumentWriter documentWriter; + + public BufferingDocumentWriter(Action action) + { + documentWriter = new DocumentWriter(action); + } + + public async Task WriteAsync(Stream stream, T value, + CancellationToken cancellationToken = default) + { + await using (var bufferStream = new FileBufferingWriteStream()) + { + await documentWriter.WriteAsync(bufferStream, value, cancellationToken); + + await bufferStream.DrainBufferAsync(stream, cancellationToken); + } + } + } +} diff --git a/backend/src/Squidex.Web/Squidex.Web.csproj b/backend/src/Squidex.Web/Squidex.Web.csproj index 1f4a8fff5..8cb7249a1 100644 --- a/backend/src/Squidex.Web/Squidex.Web.csproj +++ b/backend/src/Squidex.Web/Squidex.Web.csproj @@ -17,6 +17,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/backend/src/Squidex/Config/Domain/SerializationServices.cs b/backend/src/Squidex/Config/Domain/SerializationServices.cs index 3a0bd7483..466563a38 100644 --- a/backend/src/Squidex/Config/Domain/SerializationServices.cs +++ b/backend/src/Squidex/Config/Domain/SerializationServices.cs @@ -30,6 +30,7 @@ using Squidex.Infrastructure.Json.Objects; using Squidex.Infrastructure.Queries; using Squidex.Infrastructure.Queries.Json; using Squidex.Infrastructure.Reflection; +using Squidex.Web.GraphQL; using IGraphQLBuilder = GraphQL.DI.IGraphQLBuilder; namespace Squidex.Config.Domain @@ -128,9 +129,9 @@ namespace Squidex.Config.Domain { var errorInfoProvider = c.GetRequiredService(); - return new DocumentWriter(options => + return new BufferingDocumentWriter(options => { - options.ContractResolver = new ExecutionResultContractResolver(new ErrorInfoProvider()); + options.ContractResolver = new ExecutionResultContractResolver(errorInfoProvider); options.Converters.Add(new JsonValueConverter()); options.Converters.Add(new WriteonlyGeoJsonConverter()); diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs index f612e7e9f..d4c95db47 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs @@ -45,26 +45,32 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL new StringFieldProperties()) .AddString(3, "my-localized-string", Partitioning.Language, new StringFieldProperties()) - .AddNumber(4, "my-number", Partitioning.Invariant, + .AddString(4, "my-string-enum", Partitioning.Invariant, + new StringFieldProperties { AllowedValues = ReadonlyList.Create("A", "B", "C") }) + .AddNumber(5, "my-number", Partitioning.Invariant, new NumberFieldProperties()) - .AddAssets(5, "my-assets", Partitioning.Invariant, + .AddNumber(6, "my-number-enum", Partitioning.Invariant, + new NumberFieldProperties { AllowedValues = ReadonlyList.Create(1.0, 2.0, 3.0) }) + .AddAssets(7, "my-assets", Partitioning.Invariant, new AssetsFieldProperties()) - .AddBoolean(6, "my-boolean", Partitioning.Invariant, + .AddBoolean(8, "my-boolean", Partitioning.Invariant, new BooleanFieldProperties()) - .AddDateTime(7, "my-datetime", Partitioning.Invariant, + .AddDateTime(9, "my-datetime", Partitioning.Invariant, new DateTimeFieldProperties()) - .AddReferences(8, "my-references", Partitioning.Invariant, + .AddReferences(10, "my-references", Partitioning.Invariant, new ReferencesFieldProperties { SchemaId = Ref1Id.Id }) - .AddReferences(9, "my-union", Partitioning.Invariant, + .AddReferences(11, "my-union", Partitioning.Invariant, new ReferencesFieldProperties()) - .AddGeolocation(10, "my-geolocation", Partitioning.Invariant, + .AddGeolocation(12, "my-geolocation", Partitioning.Invariant, new GeolocationFieldProperties()) - .AddComponent(11, "my-component", Partitioning.Invariant, + .AddComponent(13, "my-component", Partitioning.Invariant, new ComponentFieldProperties { SchemaId = Ref1Id.Id }) - .AddComponents(12, "my-components", Partitioning.Invariant, + .AddComponents(14, "my-components", Partitioning.Invariant, new ComponentsFieldProperties { SchemaIds = ReadonlyList.Create(Ref1.Id, Ref2.Id) }) - .AddTags(13, "my-tags", Partitioning.Invariant, + .AddTags(15, "my-tags", Partitioning.Invariant, new TagsFieldProperties()) + .AddTags(16, "my-tags-enum", Partitioning.Invariant, + new TagsFieldProperties { AllowedValues = ReadonlyList.Create("A", "B", "C") }) .AddArray(100, "my-array", Partitioning.Invariant, f => f .AddBoolean(121, "nested-boolean", new BooleanFieldProperties()) From 47ab5fa3b08e1e7d8a914dc59b0876c36d9a77a3 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 17 Feb 2022 21:34:26 +0100 Subject: [PATCH 2/4] Build fix. --- .../Contents/GraphQL/Types/Builder.cs | 2 +- .../Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs index a3d9d12be..7022aec95 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs @@ -153,7 +153,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types public EnumerationGraphType GetEnumeration(string name, string prefix, IEnumerable values) { - return enumTypes.GetOrAdd(name, x => new FieldEnumType(name, string prefix, values)); + return enumTypes.GetOrAdd(name, x => new FieldEnumType(name, prefix, values)); } public IEnumerable> GetAllContentTypes() diff --git a/backend/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs b/backend/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs index 0d83825cc..e6c03509c 100644 --- a/backend/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs +++ b/backend/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs @@ -117,7 +117,7 @@ namespace Squidex.Infrastructure.EventSourcing public static Guid GetGuid(this EnvelopeHeaders obj, string key) { - if (obj.TryGetValue(key, out var v) && v is JsonString s && Guid.TryParse(v.ToString(), out var guid)) + if (obj.TryGetValue(key, out var v) && v is JsonString s && Guid.TryParse(s.ToString(), out var guid)) { return guid; } From f9ba51e7f1d8a210fce28af33805a2e2b1889a1f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 19 Feb 2022 09:02:23 +0100 Subject: [PATCH 3/4] Name fixes --- .../Contents/GraphQL/Types/Builder.cs | 4 +- .../GraphQL/Types/Contents/FieldEnumType.cs | 28 ++------- .../Types/Contents/FieldInputVisitor.cs | 6 +- .../GraphQL/Types/Contents/FieldVisitor.cs | 6 +- .../Contents/GraphQL/Types/Contents/Names.cs | 58 +++++++++++++++++++ .../GraphQL/Types/Contents/SchemaInfo.cs | 50 ---------------- 6 files changed, 72 insertions(+), 80 deletions(-) create mode 100644 backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs index 7022aec95..c98b28bcb 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs @@ -151,9 +151,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types return componentTypes.GetOrDefault(schema); } - public EnumerationGraphType GetEnumeration(string name, string prefix, IEnumerable values) + public EnumerationGraphType GetEnumeration(string name, IEnumerable values) { - return enumTypes.GetOrAdd(name, x => new FieldEnumType(name, prefix, values)); + return enumTypes.GetOrAdd(name, x => new FieldEnumType(name, values)); } public IEnumerable> GetAllContentTypes() diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs index 3ed6f0da3..905538b56 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs @@ -12,35 +12,19 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { public sealed class FieldEnumType : EnumerationGraphType { - public FieldEnumType(string name, string prefix, IEnumerable values) + public FieldEnumType(string name, IEnumerable values) { Name = name; - var index = 0; + var names = new Names(); foreach (var value in values) { - AddValue(BuildName(value, prefix, index), null, value); - - index++; + if (!Equals(value, null)) + { + AddValue(names[value.ToString()!.Slugify().ToPascalCase()], null, value); + } } } - - private static string BuildName(T value, string prefix, int index) - { - var name = value!.ToString()!.Slugify().ToPascalCase(); - - if (string.IsNullOrEmpty(name)) - { - name = $"{prefix}_{index}"; - } - - if (!char.IsLetter(name[0])) - { - name = $"{prefix}_{name}"; - } - - return name; - } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs index 49f933377..9031739a2 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs @@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { if (field.Properties?.AllowedValues?.Count > 0) { - return builder.GetEnumeration(args.EnumName, "Number", field.Properties.AllowedValues); + return builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); } return AllTypes.Float; @@ -88,7 +88,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { if (field.Properties?.AllowedValues?.Count > 0) { - return builder.GetEnumeration(args.EnumName, "String", field.Properties.AllowedValues); + return builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); } return AllTypes.String; @@ -98,7 +98,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { if (field.Properties?.AllowedValues?.Count > 0) { - var @enum = builder.GetEnumeration(args.EnumName, "Tag", field.Properties.AllowedValues); + var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); return new ListGraphType(new NonNullGraphType(@enum)); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs index 698536671..272143811 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs @@ -168,7 +168,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents if (field.Properties?.AllowedValues?.Count > 0) { - type = builder.GetEnumeration(args.EnumName, "Number", field.Properties.AllowedValues); + type = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); } return (type, JsonNumber, null); @@ -180,7 +180,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents if (field.Properties?.AllowedValues?.Count > 0) { - type = builder.GetEnumeration(args.EnumName, "String", field.Properties.AllowedValues); + type = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); } return (type, JsonString, null); @@ -192,7 +192,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents if (field.Properties?.AllowedValues?.Count > 0) { - var @enum = builder.GetEnumeration(args.EnumName, "Tag", field.Properties.AllowedValues); + var @enum = builder.GetEnumeration(args.EnumName, field.Properties.AllowedValues); type = new ListGraphType(new NonNullGraphType(@enum)); } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs new file mode 100644 index 000000000..ea7fcd434 --- /dev/null +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs @@ -0,0 +1,58 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure; + +namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents +{ + internal sealed class Names + { + private static readonly HashSet ReservedNames = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Asset", + "AssetResultDto", + "Content", + "Component", + "EntityCreatedResultDto", + "EntitySavedResultDto", + "JsonScalar", + "JsonPrimitive", + "User" + }; + + private readonly Dictionary takenNames = new Dictionary(); + + public string this[string name, bool isEntity = true] + { + get => GetName(name, isEntity); + } + + private string GetName(string name, bool isEntity) + { + Guard.NotNullOrEmpty(name); + + if (!char.IsLetter(name[0])) + { + name = "gql_" + name; + } + else if (isEntity && ReservedNames.Contains(name)) + { + name = $"{name}Entity"; + } + + if (!takenNames.TryGetValue(name, out var offset)) + { + takenNames[name] = 0; + return name; + } + + takenNames[name] = ++offset; + + return $"{name}{offset + 1}"; + } + } +} diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs index 366a03571..f64b54f4e 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs @@ -7,7 +7,6 @@ using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Entities.Schemas; -using Squidex.Infrastructure; using Squidex.Text; #pragma warning disable MA0048 // File name must match type name @@ -155,53 +154,4 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents return new FieldInfo(rootField, typeName, names, parentNames, fieldInfos); } } - - internal sealed class Names - { - // Reserver names that are used for other GraphQL types. - private static readonly HashSet ReservedNames = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Asset", - "AssetResultDto", - "Content", - "Component", - "EntityCreatedResultDto", - "EntitySavedResultDto", - "JsonScalar", - "JsonPrimitive", - "User" - }; - private readonly Dictionary takenNames = new Dictionary(); - - public string this[string name, bool isEntity = true] - { - get => GetName(name, isEntity); - } - - private string GetName(string name, bool isEntity) - { - Guard.NotNullOrEmpty(name); - - if (!char.IsLetter(name[0])) - { - name = "gql_" + name; - } - else if (isEntity && ReservedNames.Contains(name)) - { - name = $"{name}Entity"; - } - - // Avoid duplicate names. - if (!takenNames.TryGetValue(name, out var offset)) - { - takenNames[name] = 0; - return name; - } - - takenNames[name] = ++offset; - - // Add + 1 to all offsets for backwards-compatibility. - return $"{name}{offset + 1}"; - } - } } From 41889b3f2b744c32eeb4aaab8f28f9e6f8496c53 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 19 Feb 2022 09:03:30 +0100 Subject: [PATCH 4/4] Comments --- .../Contents/GraphQL/Types/Contents/FieldEnumType.cs | 6 +++++- .../Contents/GraphQL/Types/Contents/Names.cs | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs index 905538b56..674668366 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs @@ -16,13 +16,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { Name = name; + // Avoid conflicts with duplicate names. var names = new Names(); foreach (var value in values) { if (!Equals(value, null)) { - AddValue(names[value.ToString()!.Slugify().ToPascalCase()], null, value); + // Get rid of special characters. + var valueName = value.ToString()!.Slugify().ToPascalCase(); + + AddValue(names[valueName], null, value); } } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs index ea7fcd434..04b6da64e 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/Names.cs @@ -11,6 +11,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents { internal sealed class Names { + // Reserver names that are used for other GraphQL types. private static readonly HashSet ReservedNames = new HashSet(StringComparer.OrdinalIgnoreCase) { "Asset", @@ -23,7 +24,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents "JsonPrimitive", "User" }; - private readonly Dictionary takenNames = new Dictionary(); public string this[string name, bool isEntity = true] @@ -44,6 +44,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents name = $"{name}Entity"; } + // Avoid duplicate names. if (!takenNames.TryGetValue(name, out var offset)) { takenNames[name] = 0; @@ -52,6 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types.Contents takenNames[name] = ++offset; + // Add + 1 to all offsets for backwards-compatibility. return $"{name}{offset + 1}"; } }