Browse Source

Graphql enums. (#848)

* Graphql enums.

* Build fix.
pull/849/head
Sebastian Stehle 4 years ago
committed by GitHub
parent
commit
23521282dc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Builder.cs
  2. 46
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldEnumType.cs
  3. 25
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldInputVisitor.cs
  4. 29
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/FieldVisitor.cs
  5. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/Contents/SchemaInfo.cs
  6. 2
      backend/src/Squidex.Infrastructure/EventSourcing/EnvelopeExtensions.cs
  7. 35
      backend/src/Squidex.Web/GraphQL/BufferingDocumentWriter.cs
  8. 1
      backend/src/Squidex.Web/Squidex.Web.csproj
  9. 5
      backend/src/Squidex/Config/Domain/SerializationServices.cs
  10. 26
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/TestSchemas.cs

6
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<SchemaInfo, ComponentGraphType> componentTypes = new Dictionary<SchemaInfo, ComponentGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<SchemaInfo, ContentGraphType> contentTypes = new Dictionary<SchemaInfo, ContentGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<SchemaInfo, ContentResultGraphType> contentResultTypes = new Dictionary<SchemaInfo, ContentResultGraphType>(ReferenceEqualityComparer.Instance);
private readonly Dictionary<string, EnumerationGraphType> enumTypes = new Dictionary<string, EnumerationGraphType>();
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<T>(string name, string prefix, IEnumerable<T> values)
{
return enumTypes.GetOrAdd(name, x => new FieldEnumType<T>(name, prefix, values));
}
public IEnumerable<KeyValuePair<SchemaInfo, ContentGraphType>> GetAllContentTypes()
{
return contentTypes;

46
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<T> : EnumerationGraphType
{
public FieldEnumType(string name, string prefix, IEnumerable<T> 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;
}
}
}

25
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<NumberFieldProperties> field, FieldInfo args)
public IGraphType? Visit(IField<ReferencesFieldProperties> field, FieldInfo args)
{
return AllTypes.Float;
return AllTypes.Strings;
}
public IGraphType? Visit(IField<ReferencesFieldProperties> field, FieldInfo args)
public IGraphType? Visit(IField<NumberFieldProperties> 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<StringFieldProperties> 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<TagsFieldProperties> 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;
}

29
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<NumberFieldProperties> 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<StringFieldProperties> 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<TagsFieldProperties> 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<ReferencesFieldProperties> field, FieldInfo args)

5
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"];

2
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;
}

35
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<JsonSerializerSettings> action)
{
documentWriter = new DocumentWriter(action);
}
public async Task WriteAsync<T>(Stream stream, T value,
CancellationToken cancellationToken = default)
{
await using (var bufferStream = new FileBufferingWriteStream())
{
await documentWriter.WriteAsync(bufferStream, value, cancellationToken);
await bufferStream.DrainBufferAsync(stream, cancellationToken);
}
}
}
}

1
backend/src/Squidex.Web/Squidex.Web.csproj

@ -17,6 +17,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="GraphQL.NewtonsoftJson" Version="4.7.1" />
<PackageReference Include="GraphQL.Server.Transports.AspNetCore" Version="5.2.0" />
<PackageReference Include="Lazy.Fody" Version="1.11.0" PrivateAssets="all" />
<PackageReference Include="Meziantou.Analyzer" Version="1.0.694">

5
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<IErrorInfoProvider>();
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());

26
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())

Loading…
Cancel
Save