Skip to content
This repository has been archived by the owner on Feb 12, 2023. It is now read-only.

Commit

Permalink
feat(Introspection): field descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Ivora committed Jun 26, 2017
1 parent b3c3a07 commit eabd886
Show file tree
Hide file tree
Showing 28 changed files with 235 additions and 133 deletions.
3 changes: 2 additions & 1 deletion examples/GraphQLCore.GraphiQLExample/Models/Human.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace GraphQLCore.GraphiQLExample.Models
{
using System;
using System.Collections.Generic;
using Type.Scalar;

Expand All @@ -10,6 +11,6 @@ public class Human : ICharacter
public string HomePlanet { get; set; }
public ID Id { get; set; }
public string Name { get; set; }
public string SecretBackstory { get; set; }
public string SecretBackstory { get { throw new Exception("secretBackstory is secret."); } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ public class GraphQLCharacterInterface : GraphQLInterfaceType<ICharacter>
public GraphQLCharacterInterface()
: base("Character", "A character in the Star Wars Trilogy")
{
this.Field("id", e => e.Id);
this.Field("name", e => e.Name);
this.Field("friends", e => e.Friends);
this.Field("appearsIn", e => e.AppearsIn);
this.Field("id", e => e.Id).WithDescription(
"The id of the character.");

this.Field("name", e => e.Name).WithDescription(
"The name of the character.");

this.Field("friends", e => e.Friends).WithDescription(
"The friends of the character, or an empty list if they " +
"have none.");

this.Field("appearsIn", e => e.AppearsIn).WithDescription(
"Which movies they appear in.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ public class GraphQLDroidObject : GraphQLObjectType<Droid>
public GraphQLDroidObject()
: base("Droid", "A character in the Star Wars Trilogy")
{
this.Field("id", e => e.Id);
this.Field("name", e => e.Name);
this.Field("friends", e => e.Friends);
this.Field("appearsIn", e => e.AppearsIn);
this.Field("primaryFunction", e => e.PrimaryFunction);
this.Field("id", e => e.Id).WithDescription("The id of the droid.");
this.Field("name", e => e.Name).WithDescription("The name of the droid.");
this.Field("friends", e => e.Friends).WithDescription("The friends of the droid, or an empty list if they have none.");
this.Field("appearsIn", e => e.AppearsIn).WithDescription("Which movies they appear in.");
this.Field("primaryFunction", e => e.PrimaryFunction).WithDescription("The primary function of the droid.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ public class GraphQLHumanObject : GraphQLObjectType<Human>
public GraphQLHumanObject()
: base("Human", "A humanoid creature in the Star Wars universe.")
{
this.Field("id", e => e.Id);
this.Field("name", e => e.Name);
this.Field("friends", e => e.Friends);
this.Field("appearsIn", e => e.AppearsIn);
this.Field("secretBackstory", e => e.SecretBackstory);
this.Field("homePlanet", e => e.HomePlanet);
this.Field("id", e => e.Id).WithDescription("The id of the human.");
this.Field("name", e => e.Name).WithDescription("The name of the human.");
this.Field("friends", e => e.Friends).WithDescription("The friends of the human, or an empty list if they have none.");
this.Field("appearsIn", e => e.AppearsIn).WithDescription("Which movies they appear in.");
this.Field("secretBackstory", e => e.SecretBackstory).WithDescription("Where are they from and how they came to be who they are.");
this.Field("homePlanet", e => e.HomePlanet).WithDescription("The home planet of the human, or null if unknown.");
}
}
}
2 changes: 1 addition & 1 deletion src/GraphQLCore/Execution/ExecutionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ private GraphQLComplexType GetOperationRootType()

return await scope.CompleteValue(
value,
value.GetType(),
value?.GetType(),
field,
field.Arguments.ToList());
}
Expand Down
17 changes: 17 additions & 0 deletions src/GraphQLCore/Type/Complex/Builders/FieldDefinitionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace GraphQLCore.Type.Complex
{
public class FieldDefinitionBuilder : FieldDefinitionBuilder<FieldDefinitionBuilder, GraphQLObjectTypeFieldInfo>
{
public FieldDefinitionBuilder(GraphQLObjectTypeFieldInfo fieldInfo)
: base(fieldInfo)
{
}

public FieldDefinitionBuilder OnChannel(string channelName)
{
this.FieldInfo.Channel = channelName;

return this;
}
}
}
29 changes: 29 additions & 0 deletions src/GraphQLCore/Type/Complex/Builders/FieldDefinitionBuilder`2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace GraphQLCore.Type.Complex
{
public abstract class FieldDefinitionBuilder<TDefinitionBuilder, TFieldInfo>
where TFieldInfo : GraphQLFieldInfo
where TDefinitionBuilder : FieldDefinitionBuilder<TDefinitionBuilder, TFieldInfo>
{
protected TFieldInfo FieldInfo { get; }

protected FieldDefinitionBuilder(TFieldInfo fieldInfo)
{
this.FieldInfo = fieldInfo;
}

public TDefinitionBuilder ResolveWithUnion<TUnionType>()
where TUnionType : GraphQLUnionType
{
this.FieldInfo.SystemType = typeof(TUnionType);

return (TDefinitionBuilder)this;
}

public TDefinitionBuilder WithDescription(string description)
{
this.FieldInfo.Description = description;

return (TDefinitionBuilder)this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace GraphQLCore.Type.Complex
{
public class InputFieldDefinitionBuilder : FieldDefinitionBuilder<InputFieldDefinitionBuilder, GraphQLInputObjectTypeFieldInfo>
{
public InputFieldDefinitionBuilder(GraphQLInputObjectTypeFieldInfo fieldInfo)
: base(fieldInfo)
{
}
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace GraphQLCore.Type.Complex
namespace GraphQLCore.Type.Complex
{
public class SubscriptionFieldDefinitionBuilder<TEntityType> : FieldDefinitionBuilder
{
private GraphQLSubscriptionTypeFieldInfo fieldInfo;
using System;
using System.Linq.Expressions;

public class SubscriptionFieldDefinitionBuilder<TEntityType>
: FieldDefinitionBuilder<SubscriptionFieldDefinitionBuilder<TEntityType>, GraphQLSubscriptionTypeFieldInfo>
{
public SubscriptionFieldDefinitionBuilder(GraphQLSubscriptionTypeFieldInfo fieldInfo) : base(fieldInfo)
{
this.fieldInfo = fieldInfo;
}

public SubscriptionFieldDefinitionBuilder<TEntityType> WithSubscriptionFilter(Expression<Func<TEntityType, bool>> filter)
{
this.fieldInfo.Filter = filter;
this.FieldInfo.Filter = filter;

return this;
}

public SubscriptionFieldDefinitionBuilder<TEntityType> WithSubscriptionFilter(LambdaExpression filter)
{
this.fieldInfo.Filter = filter;
this.FieldInfo.Filter = filter;

return this;
}

public new SubscriptionFieldDefinitionBuilder<TEntityType> OnChannel(string channelName)
public SubscriptionFieldDefinitionBuilder<TEntityType> OnChannel(string channelName)
{
this.fieldInfo.Channel = channelName;
this.FieldInfo.Channel = channelName;

return this;
}
Expand Down
31 changes: 0 additions & 31 deletions src/GraphQLCore/Type/Complex/FieldDefinitionBuilder.cs

This file was deleted.

7 changes: 4 additions & 3 deletions src/GraphQLCore/Type/Complex/GraphQLComplexType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public GraphQLObjectTypeFieldInfo GetFieldInfo(string fieldName)
if (fieldName == "__typename")
{
Expression<Func<string>> lambda = () => this.Name;
return GraphQLObjectTypeFieldInfo.CreateResolverFieldInfo("__typename", lambda);
return GraphQLObjectTypeFieldInfo.CreateResolverFieldInfo("__typename", lambda,
"The name of the current Object type at runtime.");
}

if (!this.ContainsField(fieldName))
Expand Down Expand Up @@ -85,9 +86,9 @@ public override IntrospectedType Introspect(ISchemaRepository schemaRepository)
return introspectedType;
}

protected GraphQLObjectTypeFieldInfo CreateFieldInfo<T, TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor)
protected GraphQLObjectTypeFieldInfo CreateFieldInfo<T, TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor, string description)
{
return GraphQLObjectTypeFieldInfo.CreateAccessorFieldInfo(fieldName, accessor);
return GraphQLObjectTypeFieldInfo.CreateAccessorFieldInfo(fieldName, accessor, description);
}
}
}
1 change: 1 addition & 0 deletions src/GraphQLCore/Type/Complex/GraphQLFieldInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
public abstract class GraphQLFieldInfo
{
public string Name { get; set; }
public string Description { get; set; }

public IDictionary<string, GraphQLObjectTypeArgumentInfo> Arguments { get; set; }
public abstract Type SystemType { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ public class GraphQLInputObjectTypeFieldInfo : GraphQLFieldInfo
public LambdaExpression Lambda { get; set; }
public override Type SystemType { get; set; }

public static GraphQLInputObjectTypeFieldInfo CreateAccessorFieldInfo(string fieldName, LambdaExpression accessor)
public static GraphQLInputObjectTypeFieldInfo CreateAccessorFieldInfo(string fieldName, LambdaExpression accessor, string description)
{
return new GraphQLInputObjectTypeFieldInfo()
{
Name = fieldName,
Arguments = new Dictionary<string, GraphQLObjectTypeArgumentInfo>(),
Lambda = accessor,
SystemType = ReflectionUtilities.GetReturnValueFromLambdaExpression(accessor)
SystemType = ReflectionUtilities.GetReturnValueFromLambdaExpression(accessor),
Description = description
};
}

Expand Down
7 changes: 5 additions & 2 deletions src/GraphQLCore/Type/Complex/GraphQLInputObjectType`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public GraphQLInputObjectType(string name, string description) : base(name, desc
this.SystemType = typeof(T);
}

public void Field<TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor)
public InputFieldDefinitionBuilder Field<TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor, string description = null)
{
if (this.ContainsField(fieldName))
throw new GraphQLException("Can't insert two fields with the same name.");
Expand All @@ -30,7 +30,10 @@ public void Field<TProperty>(string fieldName, Expression<Func<T, TProperty>> ac
if (this.IsInterfaceOrCollectionOfInterfaces(returnType))
throw new GraphQLException("Can't set accessor to interface based field");

this.Fields.Add(fieldName, GraphQLInputObjectTypeFieldInfo.CreateAccessorFieldInfo(fieldName, accessor));
var fieldInfo = GraphQLInputObjectTypeFieldInfo.CreateAccessorFieldInfo(fieldName, accessor, description);
this.Fields.Add(fieldName, fieldInfo);

return new InputFieldDefinitionBuilder(fieldInfo);
}

public override Result GetValueFromAst(GraphQLValue astValue, ISchemaRepository schemaRepository)
Expand Down
8 changes: 6 additions & 2 deletions src/GraphQLCore/Type/Complex/GraphQLInterfaceType`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Exceptions;
using System;
using System.Linq.Expressions;
using Complex;

public abstract class GraphQLInterfaceType<T> : GraphQLInterfaceType
where T : class
Expand All @@ -14,12 +15,15 @@ public GraphQLInterfaceType(string name, string description) : base(name, descri
this.SystemType = typeof(T);
}

public void Field<TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor)
public FieldDefinitionBuilder Field<TProperty>(string fieldName, Expression<Func<T, TProperty>> accessor, string description = null)
{
if (this.ContainsField(fieldName))
throw new GraphQLException("Can't insert two fields with the same name.");

this.Fields.Add(fieldName, this.CreateFieldInfo(fieldName, accessor));
var fieldInfo = this.CreateFieldInfo(fieldName, accessor, description);
this.Fields.Add(fieldName, fieldInfo);

return new FieldDefinitionBuilder(fieldInfo);
}
}
}
12 changes: 6 additions & 6 deletions src/GraphQLCore/Type/Complex/GraphQLObjectType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@ public GraphQLObjectType(string name, string description) : base(name, descripti
this.SystemType = this.GetType();
}

public FieldDefinitionBuilder Field(string fieldName, LambdaExpression fieldLambda)
public FieldDefinitionBuilder Field(string fieldName, LambdaExpression fieldLambda, string description)
{
return this.AddField(fieldName, fieldLambda);
return this.AddField(fieldName, fieldLambda, description);
}

protected virtual FieldDefinitionBuilder AddField(string fieldName, LambdaExpression resolver)
protected virtual FieldDefinitionBuilder AddField(string fieldName, LambdaExpression resolver, string description)
{
if (this.ContainsField(fieldName))
throw new GraphQLException("Can't insert two fields with the same name.");

this.ValidateResolver(resolver);

var fieldInfo = this.CreateResolverFieldInfo(fieldName, resolver);
var fieldInfo = this.CreateResolverFieldInfo(fieldName, resolver, description);

this.Fields.Add(fieldName, fieldInfo);

return new FieldDefinitionBuilder(fieldInfo);
}

private GraphQLObjectTypeFieldInfo CreateResolverFieldInfo(string fieldName, LambdaExpression resolver)
private GraphQLObjectTypeFieldInfo CreateResolverFieldInfo(string fieldName, LambdaExpression resolver, string description)
{
return GraphQLObjectTypeFieldInfo.CreateResolverFieldInfo(fieldName, resolver);
return GraphQLObjectTypeFieldInfo.CreateResolverFieldInfo(fieldName, resolver, description);
}
}
}
20 changes: 10 additions & 10 deletions src/GraphQLCore/Type/Complex/GraphQLObjectTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ namespace GraphQLCore.Type
{
public static class GraphQLObjectTypeExtensions
{
public static FieldDefinitionBuilder Field<T1>(this GraphQLObjectType @this, string name, Expression<Func<T1>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1>(this GraphQLObjectType @this, string name, Expression<Func<T1>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8, T9>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8, T9>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9>> resolver, string description = null) => @this.Field(name, resolver, description);

public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>> resolver) => @this.Field(name, resolver);
public static FieldDefinitionBuilder Field<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(this GraphQLObjectType @this, string name, Expression<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>> resolver, string description = null) => @this.Field(name, resolver, description);
}
}
Loading

0 comments on commit eabd886

Please sign in to comment.