Beispiel #1
0
        public FieldType AddSingleField <TReturn>(
            IObjectGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, object>, IQueryable <TReturn> > resolve,
            Func <ResolveEfFieldContext <TDbContext, object>, TReturn, Task>?mutate = null,
            Type?graphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            bool nullable      = false,
            string?description = null)
            where TReturn : class
        {
            var field = BuildSingleField(name, resolve, mutate, arguments, graphType, nullable, description);

            return(graph.AddField(field));
        }
        public static ExecutionNode BuildExecutionNode(ExecutionNode parent, IGraphType graphType, Field field, FieldType fieldDefinition, int?indexInParentNode = null)
        {
            if (graphType is NonNullGraphType nonNullFieldType)
            {
                graphType = nonNullFieldType.ResolvedType;
            }

            return(graphType switch
            {
                ListGraphType _ => new ArrayExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode),
                IObjectGraphType _ => new ObjectExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode),
                IAbstractGraphType _ => new ObjectExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode),
                ScalarGraphType _ => new ValueExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode),
                _ => throw new InvalidOperationException($"Unexpected type: {graphType}")
            });
        /// <summary>
        /// Builds an execution node with the specified parameters.
        /// </summary>
        protected ExecutionNode BuildSubscriptionExecutionNode(ExecutionNode parent, IGraphType graphType, Field field, FieldType fieldDefinition, int?indexInParentNode, object source)
        {
            if (graphType is NonNullGraphType nonNullFieldType)
            {
                graphType = nonNullFieldType.ResolvedType;
            }

            return(graphType switch
            {
                ListGraphType _ => new SubscriptionArrayExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode, source),
                IObjectGraphType _ => new SubscriptionObjectExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode, source),
                IAbstractGraphType _ => new SubscriptionObjectExecutionNode(parent, graphType, field, fieldDefinition, indexInParentNode, source),
                ScalarGraphType scalarGraphType => new SubscriptionValueExecutionNode(parent, scalarGraphType, field, fieldDefinition, indexInParentNode, source),
                _ => throw new InvalidOperationException($"Unexpected type: {graphType}")
            });
    public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphType type, ISchema schema)
    {
        var applied = field.FindAppliedDirective("upper");

        if (applied != null)
        {
            var inner = field.Resolver ?? NameFieldResolver.Instance;
            field.Resolver = new FuncFieldResolver <object>(async context =>
            {
                object result = await inner.ResolveAsync(context).ConfigureAwait(false);

                return(result is string str ? str.ToUpperInvariant() : result);
            });
        }
    }
        public string PrintType(IGraphType type)
        {
            Schema?.Initialize();

            return(type switch
            {
                EnumerationGraphType graphType => PrintEnum(graphType),
                ScalarGraphType scalarGraphType => PrintScalar(scalarGraphType),
                IObjectGraphType objectGraphType => PrintObject(objectGraphType),
                IInterfaceGraphType interfaceGraphType => PrintInterface(interfaceGraphType),
                UnionGraphType unionGraphType => PrintUnion(unionGraphType),
                DirectiveGraphType directiveGraphType => PrintDirective(directiveGraphType),  //TODO: DirectiveGraphType does not inherit IGraphType
                IInputObjectGraphType input => PrintInputObject(input),
                _ => throw new InvalidOperationException($"Unknown GraphType '{type.GetType().Name}' with name '{type.Name}'")
            });
Beispiel #6
0
        public override string PrintObject(IObjectGraphType type)
        {
            var isExtension = type.IsExtensionType();

            var interfaces            = type.ResolvedInterfaces.Select(x => x.Name).ToList();
            var delimiter             = " & ";
            var implementedInterfaces = interfaces.Count > 0
                ? " implements {0}".ToFormat(string.Join(delimiter, interfaces))
                : "";

            var federatedDirectives = PrintFederatedDirectives(type);

            var extended = isExtension ? "extend " : "";

            return(FormatDescription(type.Description) + "{1}type {2}{3}{4} {{{0}{5}{0}}}".ToFormat(Environment.NewLine, extended, type.Name, implementedInterfaces, federatedDirectives, PrintFields(type)));
        }
Beispiel #7
0
 public static void AddFieldToQuery <TFrom, TTo>(
     this IGraphQLQueryResolver resolver,
     IObjectGraphType query,
     string name,
     string methodName)
     where TFrom : ObjectGraphType <TTo>
 {
     (query as ObjectGraphType)
     .FieldAsync <ListGraphType <TFrom> >(
         name,
         arguments: resolver.GetQueryArguments(methodName),
         resolve: async context =>
     {
         return(await resolver.InvokeAsync <IEnumerable <TTo> >(context, methodName));
     });
 }
        public static void Field(
            this IObjectGraphType obj,
            string name,
            IGraphType type,
            string description       = null,
            QueryArguments arguments = null,
            Func <ResolveFieldContext, object> resolve = null)
        {
            var field = new FieldType();

            field.Name         = name;
            field.Description  = description;
            field.Arguments    = arguments;
            field.ResolvedType = type;
            field.Resolver     = resolve != null ? new FuncFieldResolver <object>(resolve) : null;
            obj.AddField(field);
        }
        public static ExecutionNode BuildExecutionNode(ExecutionNode parent, IGraphType graphType, Field field, FieldType fieldDefinition, string[] path = null)
        {
            path ??= AppendPath(parent.Path, field.Name);

            if (graphType is NonNullGraphType nonNullFieldType)
            {
                graphType = nonNullFieldType.ResolvedType;
            }

            return(graphType switch
            {
                ListGraphType _ => new ArrayExecutionNode(parent, graphType, field, fieldDefinition, path),
                IObjectGraphType _ => new ObjectExecutionNode(parent, graphType, field, fieldDefinition, path),
                IAbstractGraphType _ => new ObjectExecutionNode(parent, graphType, field, fieldDefinition, path),
                ScalarGraphType _ => new ValueExecutionNode(parent, graphType, field, fieldDefinition, path),
                _ => throw new InvalidOperationException($"Unexpected type: {graphType}")
            });
        public FieldType GetFieldDefinition(ISchema schema, IObjectGraphType parentType, Field field)
        {
            if (field.Name == SchemaIntrospection.SchemaMeta.Name && schema.Query == parentType)
            {
                return(SchemaIntrospection.SchemaMeta);
            }
            if (field.Name == SchemaIntrospection.TypeMeta.Name && schema.Query == parentType)
            {
                return(SchemaIntrospection.TypeMeta);
            }
            if (field.Name == SchemaIntrospection.TypeNameMeta.Name)
            {
                return(SchemaIntrospection.TypeNameMeta);
            }

            return(parentType.Fields.FirstOrDefault(f => f.Name == field.Name));
        }
Beispiel #11
0
        public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphType type, ISchema schema)
        {
            var applied = field.FindAppliedDirective(AuthorizeDirective.DirectiveName);

            if (applied == null)
            {
                return;
            }

            var isAuthenticated = _contextAccessor.HttpContext?.User.Identity?.IsAuthenticated;

            if (isAuthenticated == true)
            {
                return;
            }

            field.Resolver = new AsyncFieldResolver <object>(async context => { throw new NotAuthenticatedException(); });
        }
        public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphType type, ISchema schema)
        {
            var applied = field.FindAppliedDirective("upper");

            if (applied != null)
            {
                var inner = field.Resolver ?? NameFieldResolver.Instance;
                field.Resolver = new FuncFieldResolver <object>(context =>
                {
                    object result = inner.Resolve(context);

                    return(result switch
                    {
                        string str => str?.ToUpperInvariant(),
                        Task <string> task => Task.FromResult(task.GetAwaiter().GetResult()?.ToUpperInvariant()),
                        _ => result
                    });
                });
        public static void FieldAsync(
            this IObjectGraphType obj,
            string name,
            IGraphType type,
            string description       = null,
            QueryArguments arguments = null,
            Func <IResolveFieldContext, Task <object> > resolve = null)
        {
            var field = new FieldType
            {
                Name         = name,
                Description  = description,
                Arguments    = arguments,
                ResolvedType = type,
                Resolver     = resolve != null ? new AsyncFieldResolver <object>(resolve) : null
            };

            obj.AddField(field);
        }
        /// <summary>
        /// Iterates the given <see cref="ControllerActionGraphFieldTemplate" /> and adds
        /// all found types to the type system for this <see cref="ISchema" />. Generates
        /// a field reference on the provided parent with a resolver pointing to the provided graph action.
        /// </summary>
        /// <param name="parentType">The parent which will own the generated action field.</param>
        /// <param name="action">The action.</param>
        private void AddActionAsField(IObjectGraphType parentType, IGraphTypeFieldTemplate action)
        {
            // apend the action as a field on the parent
            var maker       = GraphQLProviders.GraphTypeMakerProvider.CreateFieldMaker(this.Schema);
            var fieldResult = maker.CreateField(action);

            if (fieldResult != null)
            {
                if (parentType.Fields.ContainsKey(fieldResult.Field.Name))
                {
                    throw new GraphTypeDeclarationException(
                              $"The '{parentType.Kind}' graph type '{parentType.Name}' already contains a field named '{fieldResult.Field.Name}'. " +
                              $"The action method '{action.InternalFullName}' cannot be added to the graph type with the same name.");
                }

                parentType.Extend(fieldResult.Field);
                this.EnsureDependents(fieldResult);
            }
        }
Beispiel #15
0
        /// <summary>
        /// Adds a field with the specified properties to a specified output graph type.
        /// </summary>
        /// <param name="obj">The graph type to add a field to.</param>
        /// <param name="name">The name of the field.</param>
        /// <param name="type">The graph type of this field.</param>
        /// <param name="description">The description of the field.</param>
        /// <param name="arguments">A list of arguments for the field.</param>
        /// <param name="resolve">A field resolver delegate. If not specified, <see cref="NameFieldResolver"/> will be used.</param>
        public static void Field( //TODO: v5 - change void to T where T : IObjectGraphType
            this IObjectGraphType obj,
            string name,
            IGraphType type,
            string description       = null,
            QueryArguments arguments = null,
            Func <IResolveFieldContext, object> resolve = null)
        {
            var field = new FieldType
            {
                Name         = name,
                Description  = description,
                Arguments    = arguments,
                ResolvedType = type,
                Resolver     = resolve != null ? new FuncFieldResolver <object>(resolve) : null
            };

            obj.AddField(field);
        }
        public void AddQueryConnectionField <TSource, TReturn>(
            IObjectGraphType graph,
            string name,
            Func <ResolveEfFieldContext <TDbContext, TSource>, IQueryable <TReturn> > resolve,
            Type?itemGraphType = null,
            IEnumerable <QueryArgument>?arguments = null,
            int pageSize       = 10,
            string?description = null)
            where TReturn : class
        {
            Guard.AgainstNull(nameof(graph), graph);
            Guard.AgainstNull(nameof(resolve), resolve);

            var connection = BuildQueryConnectionField(name, resolve, pageSize, itemGraphType, description);

            var field = graph.AddField(connection.FieldType);

            field.AddWhereArgument(arguments);
        }
Beispiel #17
0
 public static FieldType FieldAsync <TGraphType, TSourceType>(
     this IObjectGraphType obj,
     string name,
     string description       = null,
     QueryArguments arguments = null,
     Func <ResolveFieldContext <TSourceType>, Task <object> > resolve = null,
     string deprecationReason = null)
     where TGraphType : IGraphType
 {
     return(obj.AddField(new FieldType
     {
         Name = name,
         Description = description,
         DeprecationReason = deprecationReason,
         Type = typeof(TGraphType),
         Arguments = arguments,
         Resolver = resolve != null
             ? new AsyncFieldResolver <TSourceType, object>(resolve)
             : null,
     }));
 }
        public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphType type, ISchema schema)
        {
            var permission = field.GetAppliedPermission();

            if (permission == null)
            {
                return;
            }

            var isAuthorized = _contextAccessor
                               .HttpContext
                               ?.User
                               .HasClaim(x => x.Type == "Permission" && x.Value == permission);

            if (isAuthorized == true)
            {
                return;
            }

            field.Resolver = new AsyncFieldResolver <object>(async context => throw new NotAuthorizedException());
        }
Beispiel #19
0
        /// <inheritdoc/>
        public override void VisitObjectFieldDefinition(FieldType field, IObjectGraphType type, ISchema schema)
        {
            // 2.2
            if (field.Name.StartsWith("__"))
            {
                throw new InvalidOperationException($"The field '{field.Name}' of an Object type '{type.Name}' must not have a name which begins with the __ (two underscores).");
            }

            if (field.ResolvedType == null)
            {
                throw new InvalidOperationException($"The field '{field.Name}' of an Object type '{type.Name}' must have non-null '{nameof(IFieldType.ResolvedType)}' property.");
            }

            // 2.3
            if (!field.ResolvedType.IsOutputType())
            {
                throw new InvalidOperationException($"The field '{field.Name}' of an Object type '{type.Name}' must be an output type.");
            }

            ValidateArgumentsUniqueness(field, type);
        }
        /// <summary>
        /// Ensures the object graph type is tracked against all its implemented interfaces and queued
        /// to be added to the interfaces it declares that are not known to this instance.
        /// </summary>
        /// <param name="objectGraphType">The object graph type to watch.</param>
        private void EnsureObjectTypeIsTracked(IObjectGraphType objectGraphType)
        {
            _allKnownTypes.Add(objectGraphType);
            foreach (var interfaceName in objectGraphType.InterfaceNames)
            {
                if (_interfacesByName.TryGetValue(interfaceName, out var interfaceType))
                {
                    _graphTypesByInterface[interfaceType].Add(objectGraphType);
                    this.ApplyAllFields(interfaceType, objectGraphType);
                }
                else
                {
                    if (!_queuedTypesByInterfaceName.TryGetValue(interfaceName, out var _))
                    {
                        _queuedTypesByInterfaceName.TryAdd(interfaceName, new HashSet <IObjectGraphType>());
                    }

                    _queuedTypesByInterfaceName[interfaceName].Add(objectGraphType);
                }
            }
        }
Beispiel #21
0
        public override string PrintObject(IObjectGraphType type)
        {
            // Do not return an empty query type: "Query { }" as it is not valid as part of the sdl.
            if (type != null && string.Equals(type.Name, "Query", StringComparison.Ordinal) && !type.Fields.Any(x => !IsFederatedType(x.ResolvedType.GetNamedType().Name)))
            {
                return(string.Empty);
            }

            var isExtension = type.IsExtensionType();

            var interfaces            = type.ResolvedInterfaces.List.Select(x => x.Name).ToList();
            var delimiter             = " & ";
            var implementedInterfaces = interfaces.Count > 0
                ? " implements {0}".ToFormat(string.Join(delimiter, interfaces))
                : "";

            var federatedDirectives = PrintFederatedDirectives(type);

            var extended = isExtension ? "extend " : "";

            return(FormatDescription(type.Description) + "{1}type {2}{3}{4} {{{0}{5}{0}}}".ToFormat(Environment.NewLine, extended, type.Name, implementedInterfaces, federatedDirectives, PrintFields(type)));
        }
Beispiel #22
0
        /// <summary>
        /// Performs an out-of-band append of a new graph field to a parent. Accounts for type updates in this schema ONLY.
        /// </summary>
        /// <param name="parentType">the parent type to add the new field to.</param>
        /// <param name="fieldName">Name of the field.</param>
        /// <param name="path">The path segment to represent the new field.</param>
        /// <param name="definition">The definition item from which graph attributes should be used, if any. Attributes will be set to an empty string if not supplied.</param>
        /// <returns>The type associated with the field added to the parent type.</returns>
        private IObjectGraphType CreateVirtualFieldOnParent(
            IObjectGraphType parentType,
            string fieldName,
            GraphFieldPath path,
            IGraphItemTemplate definition = null)
        {
            var childField = new VirtualGraphField(
                fieldName,
                path,
                this.MakeSafeTypeNameFromRoutePath(path))
            {
                IsDepreciated      = false,
                DepreciationReason = string.Empty,
                Description        = definition?.Description ?? string.Empty,
            };

            parentType.Extend(childField);
            this.Schema.KnownTypes.EnsureGraphType(childField.AssociatedGraphType);
            this.EnsureDependents(childField);

            return(childField.AssociatedGraphType);
        }
        /// <summary>
        /// Returns a <see cref="FieldType"/> for the specified AST <see cref="Field"/> within a specified parent
        /// output graph type within a given schema. For meta-fields, returns the proper meta-field field type.
        /// </summary>
        public static FieldType GetFieldDefinition(ISchema schema, IObjectGraphType parentType, Field field)
        {
            if (field.Name == schema.SchemaMetaFieldType.Name && schema.Query == parentType)
            {
                return(schema.SchemaMetaFieldType);
            }
            if (field.Name == schema.TypeMetaFieldType.Name && schema.Query == parentType)
            {
                return(schema.TypeMetaFieldType);
            }
            if (field.Name == schema.TypeNameMetaFieldType.Name)
            {
                return(schema.TypeNameMetaFieldType);
            }

            if (parentType == null)
            {
                throw new ArgumentNullException(nameof(parentType), $"Schema is not configured correctly to fetch field '{field.Name}'. Are you missing a root type?");
            }

            return(parentType.GetField(field.Name));
        }
Beispiel #24
0
        /// <summary>
        /// Generates the list of used end-types
        /// </summary>
        /// <param name="providers">The list of defined api providers</param>
        /// <param name="types">The list of merged types</param>
        /// <param name="nodeInterface">The node interface (for relay compliance)</param>
        /// <param name="allInterfaces">The list of defined type interfaces</param>
        /// <param name="api">The api root element</param>
        /// <param name="mutationType">The type containing all mutation methods</param>
        /// <returns>The list of defined types</returns>
        private static Dictionary <string, IGraphType> GenerateApiTypes(
            List <ApiProvider> providers,
            List <MergedType> types,
            NodeInterface nodeInterface,
            Dictionary <string, IGraphType> allInterfaces,
            MergedApiRoot api,
            out IObjectGraphType mutationType)
        {
            var graphTypes = types.ToDictionary(
                type => type.ComplexTypeName,
                type => type.GenerateGraphType(nodeInterface, GetTypeInterfaces(type, providers, allInterfaces)));

            mutationType = api.GenerateMutationType();
            graphTypes[mutationType.Name] = mutationType;
            graphTypes.Values.OfType <IComplexGraphType>().SelectMany(a => a.Fields).ForEach(
                f =>
            {
                var fieldDescription = f.GetMetadata <MergedField>(MergedType.MetaDataTypeKey);
                if (fieldDescription == null)
                {
                    return;
                }

                SetFieldArguments(f, fieldDescription, graphTypes);
                f.ResolvedType = GetTypeForField(fieldDescription, graphTypes);

                if (f.Resolver == null)
                {
                    f.Resolver = fieldDescription.Resolver ?? fieldDescription.Type;
                }

                if (!string.IsNullOrWhiteSpace(fieldDescription.Description))
                {
                    f.Description = fieldDescription.Description;
                }
            });
            return(graphTypes);
        }
Beispiel #25
0
        public GraphQLModel(IAppEntity app,
                            IEnumerable <ISchemaEntity> schemas,
                            int pageSizeContents,
                            int pageSizeAssets,
                            IUrlGenerator urlGenerator)
        {
            partitionResolver = app.PartitionResolver();

            CanGenerateAssetSourceUrl = urlGenerator.CanGenerateAssetSourceUrl;

            assetType     = new AssetGraphType(this);
            assetListType = new ListGraphType(new NonNullGraphType(assetType));

            var allSchemas = schemas.Where(x => x.SchemaDef.IsPublished).ToList();

            BuildSchemas(allSchemas);

            graphQLSchema = BuildSchema(this, pageSizeContents, pageSizeAssets, allSchemas);
            graphQLSchema.RegisterValueConverter(JsonConverter.Instance);
            graphQLSchema.RegisterValueConverter(InstantConverter.Instance);

            InitializeContentTypes();
        }
        // See 'Type Validation' section in https://spec.graphql.org/June2018/#sec-Objects
        // Object types have the potential to be invalid if incorrectly defined.
        // This set of rules must be adhered to by every Object type in a GraphQL schema.
        /// <inheritdoc/>
        public override void VisitObject(IObjectGraphType type, ISchema schema)
        {
            // 1
            if (type.Fields.Count == 0)
            {
                throw new InvalidOperationException($"An Object type '{type.Name}' must define one or more fields.");
            }

            // 2.1
            foreach (var item in type.Fields.List.ToLookup(f => f.Name))
            {
                if (item.Count() > 1)
                {
                    throw new InvalidOperationException($"The field '{item.Key}' must have a unique name within Object type '{type.Name}'; no two fields may share the same name.");
                }
            }

            // 3
            // TODO: ? An object type may declare that it implements one or more unique interfaces.

            // 4
            // TODO: An object type must be a super‐set of all interfaces it implements
        }
        private async Task ExtractFieldAsync(ExecutionContext context, IObjectGraphType rootType, object source,
                                             Field field, FieldType fieldType, ConcurrentDictionary <string, object> data, IEnumerable <string> path)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var name = field.Alias ?? field.Name;

            if (data.ContainsKey(name))
            {
                return;
            }

            if (!ShouldIncludeNode(context, field.Directives))
            {
                return;
            }

            if (CanResolveFromData(field, fieldType))
            {
                var result = await ResolveFieldFromDataAsync(context, rootType, source, fieldType, field, path)
                             .ConfigureAwait(false);

                data.TryAdd(name, result);
            }
            else
            {
                var result = await ResolveFieldAsync(context, rootType, source, field, path)
                             .ConfigureAwait(false);

                if (result.Skip)
                {
                    return;
                }

                data.TryAdd(name, result.Value);
            }
        }
Beispiel #28
0
        public async Task <IActionResult> Post([FromBody] GraphQlQuery query)
        {
            IObjectGraphType currentObjectGraphType = null;

            switch (query.OperationName)
            {
            case "GetBlogData":
                currentObjectGraphType = new BlogQuery(blogService);
                break;

            case "GetAuthors":
                currentObjectGraphType = new AuthorsQuery(blogService);
                break;

            default:
                currentObjectGraphType = new BlogQuery(blogService);
                break;
            }

            var schema = new Schema {
                Query = currentObjectGraphType
            };

            var result = await new DocumentExecuter().ExecuteAsync(x =>
            {
                x.Schema = schema;
                x.Query  = query.Query;
                x.Inputs = query.Variables;
            });

            if (result.Errors?.Count > 0)
            {
                return(BadRequest());
            }

            return(Ok(result));
        }
Beispiel #29
0
        /// <summary>
        /// Inspects the root and ensures that any intermediate, virtual fields
        /// are accounted for and returns a reference to the immediate parent this action should be added to.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns>IGraphField.</returns>
        private IObjectGraphType AddOrRetrieveRoutePath(IGraphTypeFieldTemplate action)
        {
            var pathSegments = action.Route.GenerateParentPathSegments();

            // loop through all parent path parts of this action
            // creating virtual fields as necessary or using existing ones and adding on to them
            IObjectGraphType parentType = this.Schema.OperationTypes[action.Route.RootCollection];

            for (var i = 0; i < pathSegments.Count; i++)
            {
                var segment       = pathSegments[i];
                var formattedName = _formatter.FormatFieldName(segment.Name);
                if (parentType.Fields.ContainsKey(formattedName))
                {
                    var field     = parentType[formattedName];
                    var foundType = Schema.KnownTypes.FindGraphType(field.TypeExpression.TypeName);
                    if (foundType is IObjectGraphType ogt)
                    {
                        parentType = ogt;
                        continue;
                    }

                    throw new GraphTypeDeclarationException(
                              $"The action '{action.Name}' attempted to nest itself under the grpah type '{foundType?.Name}' but the graph type " +
                              "does not exist or does not accept fields.");
                }

                var fieldType = this.CreateVirtualFieldOnParent(
                    parentType,
                    formattedName,
                    segment,
                    i == 0 ? action.Parent : null);
                parentType = fieldType;
            }

            return(parentType);
        }
Beispiel #30
0
        public FieldType GetFieldDefinition(Document document, ISchema schema, IObjectGraphType parentType, Field field)
        {
            if (field.Name == SchemaIntrospection.SchemaMeta.Name && schema.Query == parentType)
            {
                return(SchemaIntrospection.SchemaMeta);
            }
            if (field.Name == SchemaIntrospection.TypeMeta.Name && schema.Query == parentType)
            {
                return(SchemaIntrospection.TypeMeta);
            }
            if (field.Name == SchemaIntrospection.TypeNameMeta.Name)
            {
                return(SchemaIntrospection.TypeNameMeta);
            }

            if (parentType == null)
            {
                var error = new ExecutionError($"Schema is not configured correctly to fetch {field.Name}.  Are you missing a root type?");
                error.AddLocation(field, document);
                throw error;
            }

            return(parentType.Fields.FirstOrDefault(f => f.Name == field.Name));
        }
        public FieldType GetFieldDefinition(ISchema schema, IObjectGraphType parentType, Field field)
        {
            if (field.Name == SchemaIntrospection.SchemaMeta.Name && schema.Query == parentType)
            {
                return SchemaIntrospection.SchemaMeta;
            }
            if (field.Name == SchemaIntrospection.TypeMeta.Name && schema.Query == parentType)
            {
                return SchemaIntrospection.TypeMeta;
            }
            if (field.Name == SchemaIntrospection.TypeNameMeta.Name)
            {
                return SchemaIntrospection.TypeNameMeta;
            }

            return parentType.Fields.FirstOrDefault(f => f.Name == field.Name);
        }
        public async Task<ResolveFieldResult<object>> ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Fields fields)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var resolveResult = new ResolveFieldResult<object>
            {
                Skip = false
            };

            var field = fields.First();

            var fieldDefinition = GetFieldDefinition(context.Schema, parentType, field);
            if (fieldDefinition == null)
            {
                resolveResult.Skip = true;
                return resolveResult;
            }

            var arguments = GetArgumentValues(context.Schema, fieldDefinition.Arguments, field.Arguments, context.Variables);

            try
            {
                var resolveContext = new ResolveFieldContext();
                resolveContext.FieldName = field.Name;
                resolveContext.FieldAst = field;
                resolveContext.FieldDefinition = fieldDefinition;
                resolveContext.ReturnType = fieldDefinition.ResolvedType;
                resolveContext.ParentType = parentType;
                resolveContext.Arguments = arguments;
                resolveContext.Source = source;
                resolveContext.Schema = context.Schema;
                resolveContext.Document = context.Document;
                resolveContext.Fragments = context.Fragments;
                resolveContext.RootValue = context.RootValue;
                resolveContext.UserContext = context.UserContext;
                resolveContext.Operation = context.Operation;
                resolveContext.Variables = context.Variables;
                resolveContext.CancellationToken = context.CancellationToken;
                resolveContext.Metrics = context.Metrics;

                var resolver = fieldDefinition.Resolver ?? new NameFieldResolver();
                var result = resolver.Resolve(resolveContext);

                if (result is Task)
                {
                    var task = result as Task;
                    await task.ConfigureAwait(false);

                    result = task.GetProperyValue("Result");
                }

                resolveResult.Value =
                    await CompleteValueAsync(context, fieldDefinition.ResolvedType, fields, result).ConfigureAwait(false);
                return resolveResult;
            }
            catch (Exception exc)
            {
                var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc);
                error.AddLocation(field, context.Document);
                context.Errors.Add(error);
                resolveResult.Skip = false;
                return resolveResult;
            }
        }
 public Task<Dictionary<string, object>> ExecuteFieldsAsync(ExecutionContext context, IObjectGraphType rootType, object source, Dictionary<string, Fields> fields)
 {
     return fields.ToDictionaryAsync<KeyValuePair<string, Fields>, string, ResolveFieldResult<object>, object>(
         pair => pair.Key,
         pair => ResolveFieldAsync(context, rootType, source, pair.Value));
 }