Browse Source

GraphQL fixed

pull/297/head
HII 8 years ago
parent
commit
5df6cb75fb
  1. 2
      src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs
  2. 3
      src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs
  3. 14
      src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs
  4. 15
      src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedObjectGraphType.cs
  5. 63
      src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs
  6. 22
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  7. 16
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

2
src/Squidex.Domain.Apps.Entities/Contents/GraphQL/GraphQLModel.cs

@ -135,7 +135,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
return partitionResolver(key); return partitionResolver(key);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) GetGraphType(ISchemaEntity schema, IField field) public (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field)
{ {
return field.Accept(new QueryGraphTypeVisitor(schema, GetContentType, this, assetListType)); return field.Accept(new QueryGraphTypeVisitor(schema, GetContentType, this, assetListType));
} }

3
src/Squidex.Domain.Apps.Entities/Contents/GraphQL/IGraphModel.cs

@ -10,6 +10,7 @@ using GraphQL.Resolvers;
using GraphQL.Types; using GraphQL.Types;
using Squidex.Domain.Apps.Core; using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Contents.GraphQL.Types;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
@ -36,6 +37,6 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
IGraphType GetInputGraphType(IField field); IGraphType GetInputGraphType(IField field);
(IGraphType ResolveType, IFieldResolver Resolver) GetGraphType(ISchemaEntity schema, IField field); (IGraphType ResolveType, ValueResolver Resolver) GetGraphType(ISchemaEntity schema, IField field);
} }
} }

14
src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/ContentDataGraphType.cs

@ -43,10 +43,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
foreach (var partitionItem in partition) foreach (var partitionItem in partition)
{ {
var resolver = new FuncFieldResolver<object>(c =>
{
if (((ContentFieldData)c.Source).TryGetValue(c.FieldName, out var value))
{
return fieldInfo.Resolver(value, c);
}
else
{
return fieldInfo;
}
});
fieldGraphType.AddField(new FieldType fieldGraphType.AddField(new FieldType
{ {
Name = partitionItem.Key, Name = partitionItem.Key,
Resolver = fieldInfo.Resolver, Resolver = resolver,
ResolvedType = fieldInfo.ResolveType, ResolvedType = fieldInfo.ResolveType,
Description = field.RawProperties.Hints Description = field.RawProperties.Hints
}); });

15
src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/NestedObjectGraphType.cs

@ -6,6 +6,7 @@
// ========================================================================== // ==========================================================================
using System.Linq; using System.Linq;
using GraphQL.Resolvers;
using GraphQL.Types; using GraphQL.Types;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
@ -32,10 +33,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
if (fieldInfo.ResolveType != null) if (fieldInfo.ResolveType != null)
{ {
var resolver = new FuncFieldResolver<object>(c =>
{
if (((JObject)c.Source).TryGetValue(nestedField.Name, out var value))
{
return fieldInfo.Resolver(value, c);
}
else
{
return fieldInfo;
}
});
AddField(new FieldType AddField(new FieldType
{ {
Name = nestedField.Name.ToCamelCase(), Name = nestedField.Name.ToCamelCase(),
Resolver = fieldInfo.Resolver, Resolver = resolver,
ResolvedType = fieldInfo.ResolveType, ResolvedType = fieldInfo.ResolveType,
Description = $"The {fieldName}/{nestedField.DisplayName()} nested field." Description = $"The {fieldName}/{nestedField.DisplayName()} nested field."
}); });

63
src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/QueryGraphTypeVisitor.cs

@ -6,18 +6,18 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Collections.Generic;
using GraphQL.Resolvers;
using GraphQL.Types; using GraphQL.Types;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Schemas; using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
{ {
public sealed class QueryGraphTypeVisitor : IFieldVisitor<(IGraphType ResolveType, IFieldResolver Resolver)> public delegate object ValueResolver(JToken value, ResolveFieldContext context);
public sealed class QueryGraphTypeVisitor : IFieldVisitor<(IGraphType ResolveType, ValueResolver Resolver)>
{ {
private static readonly ValueResolver NoopResolver = new ValueResolver((value, c) => value);
private readonly ISchemaEntity schema; private readonly ISchemaEntity schema;
private readonly Func<Guid, IGraphType> schemaResolver; private readonly Func<Guid, IGraphType> schemaResolver;
private readonly IGraphModel model; private readonly IGraphModel model;
@ -31,87 +31,81 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
this.schemaResolver = schemaResolver; this.schemaResolver = schemaResolver;
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IArrayField field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IArrayField field)
{ {
return ResolveNested(field); return ResolveNested(field);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<AssetsFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<AssetsFieldProperties> field)
{ {
return ResolveAssets(assetListType); return ResolveAssets(assetListType);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<BooleanFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<BooleanFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopBoolean); return ResolveDefault(AllTypes.NoopBoolean);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<DateTimeFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<DateTimeFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopDate); return ResolveDefault(AllTypes.NoopDate);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<GeolocationFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<GeolocationFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopGeolocation); return ResolveDefault(AllTypes.NoopGeolocation);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<JsonFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<JsonFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopJson); return ResolveDefault(AllTypes.NoopJson);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<NumberFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<NumberFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopFloat); return ResolveDefault(AllTypes.NoopFloat);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<ReferencesFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<ReferencesFieldProperties> field)
{ {
return ResolveReferences(field); return ResolveReferences(field);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<StringFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<StringFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopString); return ResolveDefault(AllTypes.NoopString);
} }
public (IGraphType ResolveType, IFieldResolver Resolver) Visit(IField<TagsFieldProperties> field) public (IGraphType ResolveType, ValueResolver Resolver) Visit(IField<TagsFieldProperties> field)
{ {
return ResolveDefault(AllTypes.NoopTags); return ResolveDefault(AllTypes.NoopTags);
} }
private static (IGraphType ResolveType, IFieldResolver Resolver) ResolveDefault(IGraphType type) private static (IGraphType ResolveType, ValueResolver Resolver) ResolveDefault(IGraphType type)
{ {
return (type, new FuncFieldResolver<IReadOnlyDictionary<string, JToken>, object>(c => c.Source.GetOrDefault(c.FieldName))); return (type, NoopResolver);
} }
private static ValueTuple<IGraphType, IFieldResolver> ResolveAssets(IGraphType assetListType) private (IGraphType ResolveType, ValueResolver Resolver) ResolveNested(IArrayField field)
{ {
var resolver = new FuncFieldResolver<IReadOnlyDictionary<string, JToken>, object>(c => var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedObjectGraphType(model, schema, field)));
{
var context = (GraphQLExecutionContext)c.UserContext;
var contentIds = c.Source.GetOrDefault(c.FieldName);
return context.GetReferencedAssetsAsync(contentIds);
});
return (assetListType, resolver); return (schemaFieldType, NoopResolver);
} }
private ValueTuple<IGraphType, IFieldResolver> ResolveNested(IArrayField field) private (IGraphType ResolveType, ValueResolver Resolver) ResolveAssets(IGraphType assetListType)
{ {
var resolver = new FuncFieldResolver<IReadOnlyDictionary<string, JToken>, object>(c => var resolver = new ValueResolver((value, c) =>
{ {
return c.Source.GetOrDefault(c.FieldName); var context = (GraphQLExecutionContext)c.UserContext;
});
var schemaFieldType = new ListGraphType(new NonNullGraphType(new NestedObjectGraphType(model, schema, field))); return context.GetReferencedAssetsAsync(value);
});
return (schemaFieldType, resolver); return (assetListType, resolver);
} }
private ValueTuple<IGraphType, IFieldResolver> ResolveReferences(IField field) private (IGraphType ResolveType, ValueResolver Resolver) ResolveReferences(IField field)
{ {
var schemaId = ((ReferencesFieldProperties)field.RawProperties).SchemaId; var schemaId = ((ReferencesFieldProperties)field.RawProperties).SchemaId;
@ -122,12 +116,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types
return (null, null); return (null, null);
} }
var resolver = new FuncFieldResolver<IReadOnlyDictionary<string, JToken>, object>(c => var resolver = new ValueResolver((value, c) =>
{ {
var context = (GraphQLExecutionContext)c.UserContext; var context = (GraphQLExecutionContext)c.UserContext;
var contentIds = c.Source.GetOrDefault(c.FieldName);
return context.GetReferencedContentsAsync(schemaId, contentIds); return context.GetReferencedContentsAsync(schemaId, value);
}); });
var schemaFieldType = new ListGraphType(new NonNullGraphType(contentType)); var schemaFieldType = new ListGraphType(new NonNullGraphType(contentType));

22
tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs

@ -273,6 +273,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
myTags { myTags {
iv iv
} }
myArray {
iv {
nestedNumber
nestedBoolean
}
}
} }
} }
}"; }";
@ -342,6 +348,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
"tag1", "tag1",
"tag2" "tag2"
} }
},
myArray = new
{
iv = new[]
{
new
{
nestedNumber = 1,
nestedBoolean = true
},
new
{
nestedNumber = 2,
nestedBoolean = false
}
}
} }
} }
} }

16
tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTestBase.cs

@ -72,7 +72,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
.AddGeolocation(10, "my-geolocation", Partitioning.Invariant, .AddGeolocation(10, "my-geolocation", Partitioning.Invariant,
new GeolocationFieldProperties()) new GeolocationFieldProperties())
.AddTags(11, "my-tags", Partitioning.Invariant, .AddTags(11, "my-tags", Partitioning.Invariant,
new TagsFieldProperties()); new TagsFieldProperties())
.AddArray(12, "my-array", Partitioning.Invariant, f => f
.AddBoolean(121, "nested-boolean")
.AddNumber(122, "nested-number"));
A.CallTo(() => app.Id).Returns(appId); A.CallTo(() => app.Id).Returns(appId);
A.CallTo(() => app.Name).Returns(appName); A.CallTo(() => app.Name).Returns(appName);
@ -122,7 +125,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
.AddValue("iv", JToken.FromObject(new[] { refId }))) .AddValue("iv", JToken.FromObject(new[] { refId })))
.AddField("my-geolocation", .AddField("my-geolocation",
new ContentFieldData() new ContentFieldData()
.AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 }))); .AddValue("iv", JToken.FromObject(new { latitude = 10, longitude = 20 })))
.AddField("my-array",
new ContentFieldData()
.AddValue("iv", new JArray(
new JObject(
new JProperty("nested-boolean", true),
new JProperty("nested-number", 1)),
new JObject(
new JProperty("nested-boolean", false),
new JProperty("nested-number", 2)))));
if (!noJson) if (!noJson)
{ {

Loading…
Cancel
Save