상속: AbstractNode, ISelection, IHaveSelectionSet
        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 = ResolveFieldFromData(context, rootType, source, fieldType, field, path);

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

                if (result.Skip)
                {
                    return;
                }

                data.TryAdd(name, result.Value);
            }
        }
        private bool CanResolveFromData(Field field, FieldType type)
        {
            if (field == null || type == null)
            {
                return(false);
            }

            if (type.Arguments != null &&
                type.Arguments.Any())
            {
                return(false);
            }

            if (!(type.ResolvedType is ScalarGraphType))
            {
                return(false);
            }

            if (type.ResolvedType is NonNullGraphType)
            {
                return(false);
            }

            return(true);
        }
        /// <summary>
        ///     Resolve simple fields in a performant manor
        /// </summary>
        private static object ResolveFieldFromData(ExecutionContext context, IObjectGraphType rootType, object source,
                                                   FieldType fieldType, Field field, IEnumerable <string> path)
        {
            object result = null;

            try
            {
                if (fieldType.Resolver != null)
                {
                    var rfc = new ResolveFieldContext(context, field, fieldType, source, rootType, null, path);

                    result = fieldType.Resolver.Resolve(rfc);
                }
                else
                {
                    result = NameFieldResolver.Resolve(source, field.Name);
                }

                if (result != null)
                {
                    var scalarType = fieldType.ResolvedType as ScalarGraphType;

                    result = scalarType?.Serialize(result);
                }
            }
            catch (Exception exc)
            {
                var error = new ExecutionError($"Error trying to resolve {field.Name}.", exc);
                error.AddLocation(field, context.Document);
                error.Path = path.ToList();
                context.Errors.Add(error);
            }

            return(result);
        }
예제 #4
0
 public static void AddLocation(this ExecutionError error, Field field)
 {
     if (field != null)
     {
         error.AddLocation(field.SourceLocation.Line, field.SourceLocation.Column);
     }
 }
예제 #5
0
        private ResolveFieldResult <object> GenerateError(
            ResolveFieldResult <object> resolveResult,
            Field field,
            ExecutionContext context,
            Exception exc,
            IEnumerable <string> path)
        {
            var error = new ExecutionError("Error trying to resolve {0}.".ToFormat(field.Name), exc);

            error.AddLocation(field, context.Document);
            error.Path = path;
            context.Errors.Add(error);
            resolveResult.Skip = false;
            return(resolveResult);
        }
예제 #6
0
        private void Field(IGraphType type, Field field, ValidationContext context)
        {
            if (type == null)
            {
                return;
            }

            if (type.IsLeafType())
            {
                if (field.SelectionSet != null && field.SelectionSet.Selections.Any())
                {
                    var error = new ValidationError(context.OriginalQuery, "5.2.3", NoSubselectionAllowedMessage(field.Name, context.Print(type)), field.SelectionSet);
                    context.ReportError(error);
                }
            }
            else if(field.SelectionSet == null || !field.SelectionSet.Selections.Any())
            {
                var error = new ValidationError(context.OriginalQuery, "5.2.3", RequiredSubselectionMessage(field.Name, context.Print(type)), field);
                context.ReportError(error);
            }
        }
예제 #7
0
        private IDictionary <string, Field> SubFieldsFor(ExecutionContext context, IGraphType fieldType, Field field)
        {
            if (!(fieldType is IObjectGraphType) || !field.SelectionSet.Selections.Any())
            {
                return(null);
            }

            var subFields        = new Dictionary <string, Field>();
            var visitedFragments = new List <string>();
            var fields           = CollectFields(context, fieldType, field.SelectionSet, subFields, visitedFragments);

            return(fields);
        }
예제 #8
0
        public async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var fieldPath = path?.ToList() ?? new List <string>();

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

            var fieldDefinition = GetFieldDefinition(context.Document, 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;
                resolveContext.Errors            = context.Errors;
                resolveContext.Path = fieldPath;

                var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field);
                resolveContext.SubFields = subFields;

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

                if (result is Task)
                {
                    var task = result as Task;
                    if (task.IsFaulted)
                    {
                        var aggregateException = task.Exception;
                        var exception          = aggregateException.InnerExceptions.Count == 1
                            ? aggregateException.InnerException
                            : aggregateException;
                        return(GenerateError(resolveResult, field, context, exception, fieldPath));
                    }
                    await task.ConfigureAwait(false);

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

                resolveResult.Value =
                    await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath).ConfigureAwait(false);

                return(resolveResult);
            }
            catch (Exception exc)
            {
                return(GenerateError(resolveResult, field, context, exc, path));
            }
        }
예제 #9
0
        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));
        }
예제 #10
0
        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);
        }
예제 #11
0
 protected bool Equals(Field other)
 {
     return string.Equals(Name, other.Name) && string.Equals(Alias, other.Alias);
 }
예제 #12
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 async Task <ResolveFieldResult <object> > ResolveFieldAsync(ExecutionContext context, IObjectGraphType parentType, object source, Field field, IEnumerable <string> path)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var fieldPath = path?.ToList() ?? new List <string>();

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

            var fieldDefinition = GetFieldDefinition(context.Document, 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
                {
                    FieldName         = field.Name,
                    FieldAst          = field,
                    FieldDefinition   = fieldDefinition,
                    ReturnType        = fieldDefinition.ResolvedType,
                    ParentType        = parentType,
                    Arguments         = arguments,
                    Source            = source,
                    Schema            = context.Schema,
                    Document          = context.Document,
                    Fragments         = context.Fragments,
                    RootValue         = context.RootValue,
                    UserContext       = context.UserContext,
                    Operation         = context.Operation,
                    Variables         = context.Variables,
                    CancellationToken = context.CancellationToken,
                    Metrics           = context.Metrics,
                    Errors            = context.Errors,
                    Path = fieldPath
                };

                var subFields = SubFieldsFor(context, fieldDefinition.ResolvedType, field);
                resolveContext.SubFields = subFields;

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

                result = await UnwrapResultAsync(result)
                         .ConfigureAwait(false);

                resolveResult.Value = await CompleteValueAsync(context, parentType, fieldDefinition.ResolvedType, field, result, fieldPath)
                                      .ConfigureAwait(false);

                return(resolveResult);
            }
            catch (Exception exc)
            {
                return(GenerateError(resolveResult, field, context, exc, path));
            }
        }
        /// <summary>
        ///     Resolve simple fields in a performant manor
        /// </summary>
        private static async Task <object> ResolveFieldFromDataAsync(ExecutionContext context, IObjectGraphType rootType, object source,
                                                                     FieldType fieldType, Field field, IEnumerable <string> path)
        {
            object result = null;

            try
            {
                if (fieldType.Resolver != null)
                {
                    var rfc = new ResolveFieldContext(context, field, fieldType, source, rootType, null, path);

                    result = fieldType.Resolver.Resolve(rfc);

                    result = await UnwrapResultAsync(result)
                             .ConfigureAwait(false);
                }
                else
                {
                    result = NameFieldResolver.Resolve(source, field.Name);
                }

                if (result != null)
                {
                    var scalarType = fieldType.ResolvedType as ScalarGraphType;

                    result = scalarType?.Serialize(result);
                }
            }
            catch (Exception exc)
            {
                var error = new ExecutionError($"Error trying to resolve {field.Name}.", exc);
                error.AddLocation(field, context.Document);
                error.Path = path.ToList();
                context.Errors.Add(error);

                // If there was an exception, the value of result cannot be trusted
                result = null;
            }

            return(result);
        }
예제 #15
0
        private ResolveEventStreamResult ResolveEventStream(
            ExecutionContext context,
            IObjectGraphType parentType,
            object source,
            Field field,
            IEnumerable <string> path)
        {
            context.CancellationToken.ThrowIfCancellationRequested();

            var fieldPath = path?.ToList() ?? new List <string>();

            var resolveResult = new ResolveEventStreamResult
            {
                Skip = false
            };

            if (!(GetFieldDefinition(context.Document, context.Schema, parentType, field) is EventStreamFieldType fieldDefinition))
            {
                resolveResult.Skip = true;
                return(resolveResult);
            }

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

            try
            {
                var resolveContext = new ResolveEventStreamContext();
                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;
                resolveContext.Errors            = context.Errors;
                resolveContext.Path = fieldPath;

                if (fieldDefinition.Subscriber == null)
                {
                    return(GenerateError(resolveResult, field, context,
                                         new InvalidOperationException($"Subscriber not set for field {field.Name}"),
                                         fieldPath));
                }

                var result = fieldDefinition.Subscriber.Subscribe(resolveContext);

                var valueTransformer = result
                                       .SelectMany(async value =>
                {
                    var fieldResolveResult = await ResolveFieldAsync(context, parentType, value, field, fieldPath);
                    return(new ExecutionResult
                    {
                        Data = fieldResolveResult.Value
                    });
                })
                                       .Catch <ExecutionResult, Exception>(exception =>
                                                                           Observable.Return(
                                                                               new ExecutionResult
                {
                    Errors = new ExecutionErrors
                    {
                        new ExecutionError(
                            $"Could not subscribe to field '{field.Name}' in query '{context.Document.OriginalQuery}'",
                            exception)
                        {
                            Path = path
                        }
                    }
                }));

                resolveResult.Value = valueTransformer;
                return(resolveResult);
            }
            catch (Exception exc)
            {
                return(GenerateError(resolveResult, field, context, exc, path));
            }
        }
 private ResolveFieldResult<object> GenerateError(ResolveFieldResult<object> resolveResult, Field field, ExecutionContext context, 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;
 }
예제 #17
0
        public async Task <object> CompleteValueAsync(ExecutionContext context, IObjectGraphType parentType, IGraphType fieldType, Field field, object result, IEnumerable <string> path)
        {
            var fieldName = field?.Name;

            var nonNullType = fieldType as NonNullGraphType;

            if (nonNullType != null)
            {
                var type      = nonNullType.ResolvedType;
                var completed = await CompleteValueAsync(context, parentType, type, field, result, path).ConfigureAwait(false);

                if (completed == null)
                {
                    var error = new ExecutionError("Cannot return null for non-null type. Field: {0}, Type: {1}!."
                                                   .ToFormat(fieldName, type.Name));
                    error.AddLocation(field, context.Document);
                    throw error;
                }

                return(completed);
            }

            if (result == null)
            {
                return(null);
            }

            if (fieldType is ScalarGraphType)
            {
                var scalarType   = fieldType as ScalarGraphType;
                var coercedValue = scalarType.Serialize(result);
                return(coercedValue);
            }

            if (fieldType is ListGraphType)
            {
                var list = result as IEnumerable;

                if (list == null)
                {
                    var error = new ExecutionError("User error: expected an IEnumerable list though did not find one.");
                    error.AddLocation(field, context.Document);
                    throw error;
                }

                var listType = fieldType as ListGraphType;
                var itemType = listType.ResolvedType;

                var results = await list
                              .MapAsync(async (index, item) =>
                                        await CompleteValueAsync(context, parentType, itemType, field, item, path.Concat(new[] { $"{index}" })).ConfigureAwait(false))
                              .ConfigureAwait(false);

                return(results);
            }

            var objectType = fieldType as IObjectGraphType;

            if (fieldType is IAbstractGraphType)
            {
                var abstractType = fieldType as IAbstractGraphType;
                objectType = abstractType.GetObjectType(result);

                if (objectType == null)
                {
                    var error = new ExecutionError(
                        $"Abstract type {abstractType.Name} must resolve to an Object type at " +
                        $"runtime for field {parentType.Name}.{fieldName} " +
                        $"with value {result}, received 'null'.");
                    error.AddLocation(field, context.Document);
                    throw error;
                }

                if (!abstractType.IsPossibleType(objectType))
                {
                    var error = new ExecutionError(
                        "Runtime Object type \"{0}\" is not a possible type for \"{1}\""
                        .ToFormat(objectType, abstractType));
                    error.AddLocation(field, context.Document);
                    throw error;
                }
            }

            if (objectType == null)
            {
                return(null);
            }

            if (objectType.IsTypeOf != null && !objectType.IsTypeOf(result))
            {
                var error = new ExecutionError(
                    "Expected value of type \"{0}\" but got: {1}."
                    .ToFormat(objectType, result));
                error.AddLocation(field, context.Document);
                throw error;
            }

            var subFields        = new Dictionary <string, Field>();
            var visitedFragments = new List <string>();

            subFields = CollectFields(context, objectType, field?.SelectionSet, subFields, visitedFragments);

            return(await ExecuteFieldsAsync(context, objectType, result, subFields, path).ConfigureAwait(false));
        }
        /// <summary>
        ///     Resolve lists in a performant manor
        /// </summary>
        private async Task <List <object> > ResolveListFromData(ExecutionContext context, object source, IObjectGraphType parentType,
                                                                IGraphType graphType, Field field, IEnumerable <string> path)
        {
            var result           = new List <object>();
            var listInfo         = graphType as ListGraphType;
            var subType          = listInfo?.ResolvedType as IObjectGraphType;
            var data             = source as IEnumerable;
            var visitedFragments = new List <string>();
            var subFields        = CollectFields(context, subType, field.SelectionSet, null, visitedFragments);

            if (data == null)
            {
                var error = new ExecutionError("User error: expected an IEnumerable list though did not find one.");
                error.AddLocation(field, context.Document);
                throw error;
            }

            var index = 0;

            foreach (var node in data)
            {
                var currentPath = path.Concat(new[] { $"{index++}" });

                if (subType != null)
                {
                    var nodeResult = await ExecuteFieldsAsync(context, subType, node, subFields, currentPath);

                    result.Add(nodeResult);
                }
                else
                {
                    var nodeResult = await CompleteValueAsync(context, parentType, listInfo?.ResolvedType, field, node, currentPath).ConfigureAwait(false);

                    result.Add(nodeResult);
                }
            }

            return(result);
        }
예제 #19
0
        private FieldType GetFieldDef(ISchema schema, GraphType parentType, Field field)
        {
            var name = field.Name;

            if (name == SchemaIntrospection.SchemaMeta.Name
                && Equals(schema.Query, parentType))
            {
                return SchemaIntrospection.SchemaMeta;
            }

            if (name == SchemaIntrospection.TypeMeta.Name
                && Equals(schema.Query, parentType))
            {
                return SchemaIntrospection.TypeMeta;
            }

            if (name == SchemaIntrospection.TypeNameMeta.Name
                && (parentType is ObjectGraphType
                    || parentType is InterfaceGraphType
                    || parentType is UnionGraphType))
            {
                return SchemaIntrospection.TypeNameMeta;
            }

            if (parentType is ObjectGraphType || parentType is InterfaceGraphType)
            {
                return parentType.Fields.FirstOrDefault(x => x.Name == field.Name);
            }

            return null;
        }
예제 #20
0
 protected bool Equals(Field other)
 {
     return(string.Equals(Name, other.Name, StringComparison.InvariantCulture) && string.Equals(Alias, other.Alias, StringComparison.InvariantCulture));
 }