コード例 #1
0
        private static EventDescription CreateEvent(
            IExecutionContext executionContext)
        {
            IReadOnlyCollection <FieldSelection> selections = executionContext
                                                              .CollectFields(
                executionContext.Operation.RootType,
                executionContext.Operation.Definition.SelectionSet,
                null);

            if (selections.Count == 1)
            {
                FieldSelection           selection = selections.Single();
                var                      arguments = new List <ArgumentNode>();
                IVariableValueCollection variables = executionContext.Variables;

                foreach (ArgumentNode argument in selection.Selection.Arguments)
                {
                    if (argument.Value is VariableNode v)
                    {
                        IValueNode value = variables.GetVariable <IValueNode>(v.Name.Value);
                        arguments.Add(argument.WithValue(value));
                    }
                    else
                    {
                        arguments.Add(argument);
                    }
                }

                return(new EventDescription(selection.Field.Name, arguments));
            }
            else
            {
                throw new QueryException(CoreResources.Subscriptions_SingleRootField);
            }
        }
コード例 #2
0
        private ResolverTask(
            ResolverTask parent,
            FieldSelection fieldSelection,
            Path path,
            IImmutableStack <object> source,
            IDictionary <string, object> result,
            Action propagateNonNullViolation)
        {
            _parent           = parent;
            _executionContext = parent._executionContext;
            Source            = source;
            ObjectType        = fieldSelection.Field.DeclaringType;
            FieldSelection    = fieldSelection;
            FieldType         = fieldSelection.Field.Type;
            Path                       = path;
            _result                    = result;
            ScopedContextData          = parent.ScopedContextData;
            _propagateNonNullViolation = propagateNonNullViolation;

            ResolverContext = new ResolverContext(
                parent._executionContext, this,
                parent._executionContext.RequestAborted);

            FieldDelegate = parent._executionContext.FieldHelper
                            .CreateMiddleware(fieldSelection);
        }
コード例 #3
0
        private EventDescription CreateEvent(
            IExecutionContext executionContext)
        {
            IReadOnlyCollection <FieldSelection> selections = executionContext
                                                              .FieldHelper.CollectFields(
                executionContext.Operation.RootType,
                executionContext.Operation.Definition.SelectionSet);

            if (selections.Count == 1)
            {
                FieldSelection selection = selections.Single();
                Dictionary <string, ArgumentValue> argumentValues = selection
                                                                    .CoerceArgumentValues(executionContext.Variables);
                var arguments = new List <ArgumentNode>();

                foreach (KeyValuePair <string, ArgumentValue> argumentValue in
                         argumentValues)
                {
                    IInputType argumentType = argumentValue.Value.Type;
                    object     value        = argumentValue.Value.Value;

                    arguments.Add(new ArgumentNode(
                                      argumentValue.Key,
                                      argumentType.ParseValue(value)));
                }

                return(new EventDescription(selection.Field.Name, arguments));
            }
            else
            {
                // TODO : Error message
                throw new QueryException();
            }
        }
コード例 #4
0
        private bool TryCompleteObjectValue(
            ExecutionContext executionContext,
            IResolverContext resolverContext,
            ImmutableStack <object> source,
            FieldSelection fieldSelection,
            IType fieldType,
            Path path,
            object fieldValue,
            Action <object> setValue)
        {
            ObjectType objectType = ResolveObjectType(
                resolverContext, fieldType, fieldValue);
            OrderedDictionary objectResult = new OrderedDictionary();

            IReadOnlyCollection <FieldSelection> fields = executionContext
                                                          .FieldResolver.CollectFields(
                objectType, fieldSelection.Node.SelectionSet,
                executionContext.Errors.Add);

            foreach (FieldSelection field in fields)
            {
                executionContext.NextBatch.Add(new FieldResolverTask(
                                                   source.Push(fieldValue), objectType, field,
                                                   path.Append(field.ResponseName), objectResult));
            }

            setValue(objectResult);
            return(true);
        }
コード例 #5
0
        public void Coerce_InputObject_NonNullFieldIsNull()
        {
            // arrange
            DocumentNode document =
                Utf8GraphQLParser.Parse("{ foo(a: {  a: { } }) }");
            OperationDefinitionNode operation = document.Definitions
                                                .OfType <OperationDefinitionNode>().First();

            ISchema schema    = CreateSchema();
            var     fragments = new FragmentCollection(
                schema,
                document);

            var variables = new VariableCollection(
                TypeConversion.Default,
                new Dictionary <string, object>());

            var collector = new FieldCollector(fragments, (f, s) => null);
            IReadOnlyCollection <FieldSelection> selections =
                collector.CollectFields(schema.QueryType,
                                        operation.SelectionSet, null);
            FieldSelection selection = selections.First();

            // act
            Action action = () => selection.CoerceArguments(variables);

            // assert
            Assert.Throws <QueryException>(action).Errors.MatchSnapshot();
        }
コード例 #6
0
        public static Dictionary <string, ArgumentValue> CoerceArgumentValues(
            this FieldSelection fieldSelection,
            IVariableCollection variables,
            Path path)
        {
            Dictionary <string, ArgumentValue> coercedArgumentValues =
                new Dictionary <string, ArgumentValue>();

            Dictionary <string, IValueNode> argumentValues =
                fieldSelection.Selection.Arguments
                .Where(t => t.Value != null)
                .ToDictionary(t => t.Name.Value, t => t.Value);

            foreach (InputField argument in fieldSelection.Field.Arguments)
            {
                coercedArgumentValues[argument.Name] = CreateArgumentValue(
                    argument, argumentValues, variables,
                    message => QueryError.CreateArgumentError(
                        message,
                        path,
                        fieldSelection.Nodes.First(),
                        argument.Name));
            }

            return(coercedArgumentValues);
        }
コード例 #7
0
        private static EventDescription CreateEvent(
            IExecutionContext executionContext)
        {
            IReadOnlyCollection <FieldSelection> selections = executionContext
                                                              .CollectFields(
                executionContext.Operation.RootType,
                executionContext.Operation.Definition.SelectionSet,
                null);

            if (selections.Count == 1)
            {
                FieldSelection selection = selections.Single();
                IReadOnlyDictionary <NameString, ArgumentValue> argumentValues =
                    selection.CoerceArguments(executionContext.Variables);
                var arguments = new List <ArgumentNode>();

                foreach (KeyValuePair <NameString, ArgumentValue> argValue in
                         argumentValues)
                {
                    IInputType argumentType = argValue.Value.Type;
                    object     value        = argValue.Value.Value;

                    arguments.Add(new ArgumentNode(
                                      argValue.Key,
                                      argumentType.ParseValue(value)));
                }

                return(new EventDescription(selection.Field.Name, arguments));
            }
            else
            {
                throw new QueryException(
                          CoreResources.Subscriptions_SingleRootField);
            }
        }
コード例 #8
0
        private void Initialize(
            IExecutionContext executionContext,
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            IDictionary <string, object> serializedResult)
        {
            _executionContext = executionContext;
            _serializedResult = serializedResult;
            _fieldSelection   = fieldSelection;

            IsRoot            = true;
            Path              = Path.New(fieldSelection.ResponseName);
            Source            = source;
            SourceObject      = executionContext.Operation.RootValue;
            ScopedContextData = ImmutableDictionary <string, object> .Empty;

            _arguments = fieldSelection.CoerceArguments(
                executionContext.Variables,
                executionContext.Converter);

            string responseName = fieldSelection.ResponseName;

            PropagateNonNullViolation = () =>
            {
                serializedResult[responseName] = null;
            };
        }
コード例 #9
0
        private static void ResolveFieldSelection(
            ObjectType type,
            FieldNode fieldSelection,
            Action <QueryError> reportError,
            Dictionary <string, FieldSelection> fields)
        {
            NameString fieldName = fieldSelection.Name.Value;

            if (type.Fields.TryGetField(fieldName, out ObjectField field))
            {
                string name = fieldSelection.Alias == null
                    ? fieldSelection.Name.Value
                    : fieldSelection.Alias.Value;

                if (fields.TryGetValue(name, out FieldSelection selection))
                {
                    fields[name] = selection.Merge(fieldSelection);
                }
                else
                {
                    fields.Add(name, FieldSelection.Create(
                                   fieldSelection, field, name));
                }
            }
            else
            {
                reportError(QueryError.CreateFieldError(
                                "Could not resolve the specified field.",
                                fieldSelection));
            }
        }
コード例 #10
0
        public ResolverTask(
            IExecutionContext executionContext,
            ObjectType objectType,
            FieldSelection fieldSelection,
            Path path,
            ImmutableStack <object> source,
            OrderedDictionary result)
        {
            _executionContext = executionContext;

            Source         = source;
            ObjectType     = objectType;
            FieldSelection = fieldSelection;
            FieldType      = fieldSelection.Field.Type;
            Path           = path;
            Result         = result;

            ResolverContext = new ResolverContext(
                executionContext, this,
                executionContext.CancellationToken);

            Options = executionContext.Options;

            ExecuteMiddleware = executionContext.GetMiddleware(
                objectType, fieldSelection.Selection);
            HasMiddleware = ExecuteMiddleware != null;
        }
コード例 #11
0
        public void Coerce_NonNullString_ToAbc()
        {
            // arrange
            DocumentNode document =
                Utf8GraphQLParser.Parse("{ bar (a: \"abc\") }");
            OperationDefinitionNode operation = document.Definitions
                                                .OfType <OperationDefinitionNode>().First();

            ISchema schema    = CreateSchema();
            var     fragments = new FragmentCollection(
                schema,
                document);

            var variables = new VariableCollection(
                TypeConversion.Default,
                new Dictionary <string, object>());

            var collector = new FieldCollector(fragments, (f, s) => null);
            IReadOnlyCollection <FieldSelection> selections =
                collector.CollectFields(schema.QueryType,
                                        operation.SelectionSet, Path.New("bar"));
            FieldSelection selection = selections.First();
            var            path      = Path.New("bar");

            // act
            IReadOnlyDictionary <NameString, ArgumentValue> arguments =
                selection.CoerceArguments(variables);

            // assert
            MatchSnapshot(arguments);
        }
コード例 #12
0
        private async Task ExecuteFieldResolverBatchAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, IResolverContext context, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, IResolverContext, object)>();

            foreach (FieldResolverTask task in batch)
            {
                IResolverContext resolverContext = new ResolverContext(
                    executionContext, task);
                object resolverResult = task.FieldSelection.Field.Resolver(
                    resolverContext, cancellationToken);
                runningTasks.Add((task, resolverContext, resolverResult));
            }

            foreach (var runningTask in runningTasks)
            {
                FieldSelection fieldSelection = runningTask.task.FieldSelection;
                object         fieldValue     = await CompleteFieldValueAsync(
                    runningTask.resolverResult);

                TryCompleteValue(executionContext, runningTask.context,
                                 runningTask.task.Source,
                                 fieldSelection, fieldSelection.Field.Type,
                                 runningTask.task.Path, fieldValue,
                                 runningTask.task.SetValue);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
コード例 #13
0
        public IReadOnlyList <FieldSelection> CollectFields(
            ObjectType type,
            SelectionSetNode selectionSet,
            Path path)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (selectionSet == null)
            {
                throw new ArgumentNullException(nameof(selectionSet));
            }

            var fields = new OrderedDictionary <string, FieldInfo>();

            CollectFields(type, selectionSet, path, null, fields);

            int i = 0;
            var fieldSelections = new FieldSelection[fields.Count];

            foreach (FieldInfo field in fields.Values)
            {
                field.Middleware     = _factory(field.Field, field.Selection);
                fieldSelections[i++] = new FieldSelection(field);
            }
            return(fieldSelections);
        }
コード例 #14
0
        public FieldDelegate GetOrCreateMiddleware(
            FieldSelection fieldSelection,
            Func <FieldDelegate> fieldPipeline)
        {
            if (fieldSelection == null)
            {
                throw new ArgumentNullException(nameof(fieldSelection));
            }

            if (!_cache.TryGetValue(fieldSelection,
                                    out FieldDelegate directivePipeline))
            {
                directivePipeline = fieldPipeline.Invoke();

                IReadOnlyList <IDirective> directives =
                    CollectDirectives(fieldSelection);

                if (directives.Any())
                {
                    directivePipeline = Compile(
                        directivePipeline,
                        directives);
                }

                _cache.TryAdd(fieldSelection, directivePipeline);
            }

            return(directivePipeline);
        }
コード例 #15
0
        private bool TryCompleteScalarValue(
            ExecutionContext executionContext,
            IResolverContext resolverContext,
            ImmutableStack <object> source,
            FieldSelection fieldSelection,
            IType fieldType,
            Path path,
            object fieldValue,
            Action <object> setValue)
        {
            try
            {
                setValue(((ISerializableType)fieldType).Serialize(fieldValue));
                return(true);
            }
            catch (ArgumentException ex)
            {
                executionContext.Errors.Add(new FieldError(
                                                ex.Message, fieldSelection.Node));
            }
            catch (Exception)
            {
                executionContext.Errors.Add(new FieldError(
                                                "Undefined field serialization error.",
                                                fieldSelection.Node));
            }

            setValue(null);
            return(false);
        }
コード例 #16
0
        public Dictionary <string, ArgumentValue> CoerceArgumentValues(
            ObjectType objectType,
            FieldSelection fieldSelection,
            VariableCollection variables)
        {
            Dictionary <string, ArgumentValue> coercedArgumentValues =
                new Dictionary <string, ArgumentValue>();

            Dictionary <string, IValueNode> argumentValues =
                fieldSelection.Node.Arguments
                .Where(t => t.Value != null)
                .ToDictionary(t => t.Name.Value, t => t.Value);

            foreach (InputField argument in fieldSelection.Field.Arguments.Values)
            {
                string     argumentName  = argument.Name;
                IInputType argumentType  = argument.Type;
                IValueNode defaultValue  = argument.DefaultValue;
                object     argumentValue = CoerceArgumentValue(
                    argumentName, argumentType, defaultValue,
                    variables, argumentValues);

                if (argumentType is NonNullType && argumentValue == null)
                {
                    throw new QueryException(new ArgumentError(
                                                 $"The argument type of '{argumentName}' is a non-null type.",
                                                 argumentName, fieldSelection.Node));
                }

                coercedArgumentValues[argumentName] = new ArgumentValue(
                    argumentType, argumentType.NativeType, argumentValue);
            }

            return(coercedArgumentValues);
        }
コード例 #17
0
        private async Task ExecuteFieldResolverBatchSeriallyAsync(
            ExecutionContext executionContext,
            List <FieldResolverTask> batch,
            CancellationToken cancellationToken)
        {
            List <(FieldResolverTask task, object resolverResult)> runningTasks =
                new List <(FieldResolverTask, object)>();

            foreach (FieldResolverTask task in batch)
            {
                // execute resolver
                IResolverContext resolverContext = new ResolverContext(
                    executionContext, task);
                object resolverResult = task.FieldSelection.Field.Resolver(
                    resolverContext, cancellationToken);

                // complete resolver value
                FieldSelection fieldSelection = task.FieldSelection;
                object         fieldValue     = await CompleteFieldValueAsync(
                    resolverResult);

                TryCompleteValue(executionContext, resolverContext, task.Source,
                                 fieldSelection, fieldSelection.Field.Type,
                                 task.Path, fieldValue,
                                 task.SetValue);

                // execute sub-selection fields normally
                await ExecuteFieldResolversAsync(executionContext, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
            }
        }
コード例 #18
0
        private static ArgumentValue CreateArgumentValue(
            FieldSelection fieldSelection,
            InputField argument,
            Dictionary <string, IValueNode> argumentValues,
            IVariableCollection variables,
            Path path)
        {
            object argumentValue = null;

            try
            {
                argumentValue = CoerceArgumentValue(
                    argument, variables, argumentValues);
            }
            catch (ScalarSerializationException ex)
            {
                throw new QueryException(QueryError.CreateArgumentError(
                                             ex.Message,
                                             path,
                                             fieldSelection.Nodes.First(),
                                             argument.Name));
            }

            if (argument.Type is NonNullType && argumentValue == null)
            {
                throw new QueryException(QueryError.CreateArgumentError(
                                             $"The argument type of '{argument.Name}' is a " +
                                             "non-null type.",
                                             path,
                                             fieldSelection.Nodes.First(),
                                             argument.Name));
            }

            return(new ArgumentValue(argument.Type, argumentValue));
        }
コード例 #19
0
 public override int GetHashCode()
 {
     unchecked
     {
         int hash = (FieldSelection?.GetHashCode() ?? 0) * 397;
         hash = hash ^ ((Type?.GetHashCode() ?? 0) * 7);
         return(hash);
     }
 }
コード例 #20
0
        public FieldDelegate CreateMiddleware(
            FieldSelection fieldSelection)
        {
            if (fieldSelection == null)
            {
                throw new ArgumentNullException(nameof(fieldSelection));
            }

            return(_middlewareRes.Invoke(fieldSelection));
        }
コード例 #21
0
 public FieldResolverTask(ImmutableStack <object> source,
                          ObjectType objectType, FieldSelection fieldSelection,
                          Path path, OrderedDictionary result)
 {
     Source         = source;
     ObjectType     = objectType;
     FieldSelection = fieldSelection;
     FieldType      = fieldSelection.Field.Type;
     Path           = path;
     Result         = result;
 }
コード例 #22
0
        // TODO : refactor this
        private bool TryCompleteValue(
            ExecutionContext executionContext,
            IResolverContext resolverContext,
            ImmutableStack <object> source,
            FieldSelection fieldSelection,
            IType fieldType,
            Path path,
            object fieldValue,
            Action <object> setValue)
        {
            object completedValue = fieldValue;

            if (fieldType.IsNonNullType())
            {
                IType innerType = fieldType.InnerType();
                if (!TryCompleteValue(
                        executionContext, resolverContext, source, fieldSelection,
                        innerType, path, completedValue, setValue))
                {
                    executionContext.Errors.Add(new FieldError(
                                                    "Cannot return null for non-nullable field.",
                                                    fieldSelection.Node));
                    return(false);
                }
                return(true);
            }

            if (completedValue == null)
            {
                setValue(null);
                return(false);
            }

            if (fieldType.IsListType())
            {
                return(TryCompleteListValue(executionContext, resolverContext,
                                            source, fieldSelection, fieldType, path, completedValue,
                                            setValue));
            }

            if (fieldType.IsScalarType() ||
                fieldType.IsEnumType())
            {
                return(TryCompleteScalarValue(executionContext, resolverContext,
                                              source, fieldSelection, fieldType, path, completedValue,
                                              setValue));
            }

            return(TryCompleteObjectValue(executionContext, resolverContext,
                                          source, fieldSelection, fieldType, path, completedValue,
                                          setValue));
        }
コード例 #23
0
        private FieldSelection(FieldSelection field, int responseIndex)
        {
            _args              = field._args;
            _vars              = field._vars;
            _visibility        = field._visibility;
            _path              = field._path;
            _hasArgumentErrors = field._hasArgumentErrors;

            ResponseName = field.ResponseName;
            Field        = field.Field;
            Selection    = field.Selection;

            Middleware    = field.Middleware;
            ResponseIndex = responseIndex;
        }
コード例 #24
0
        public static ResolverContext Rent(
            IExecutionContext executionContext,
            FieldSelection fieldSelection,
            IImmutableStack <object> source,
            IDictionary <string, object> serializedResult)
        {
            var context = new ResolverContext();

            context.Initialize(
                executionContext,
                fieldSelection,
                source,
                serializedResult);
            return(context);
        }
コード例 #25
0
 protected static void EnsureRootValueNonNullState(
     IQueryResult result,
     IEnumerable <ResolverTask> rootResolverTasks)
 {
     foreach (ResolverTask resolverTask in rootResolverTasks)
     {
         FieldSelection selection = resolverTask.FieldSelection;
         if (resolverTask.FieldType.IsNonNullType() &&
             result.Data[selection.ResponseName] == null)
         {
             result.Data.Clear();
             break;
         }
     }
 }
コード例 #26
0
 private IEnumerable <IDirective> GetFieldSelectionDirectives(
     FieldSelection fieldSelection)
 {
     foreach (DirectiveNode directive in fieldSelection.Nodes
              .SelectMany(t => t.Directives))
     {
         if (_schema.TryGetDirectiveType(directive.Name.Value,
                                         out DirectiveType directiveType) &&
             directiveType.IsExecutable)
         {
             yield return(new Directive(
                              directiveType, directive, fieldSelection));
         }
     }
 }
コード例 #27
0
 public ResolverTask Branch(
     FieldSelection fieldSelection,
     Path path,
     IImmutableStack <object> source,
     IDictionary <string, object> result,
     Action propagateNonNullViolation)
 {
     return(new ResolverTask(
                this,
                fieldSelection,
                path,
                source,
                result,
                propagateNonNullViolation));
 }
コード例 #28
0
        private IReadOnlyList <IDirective> CollectDirectives(
            FieldSelection fieldSelection)
        {
            var processed  = new HashSet <string>();
            var directives = new List <IDirective>();

            CollectTypeSystemDirectives(
                processed, directives,
                fieldSelection.Field);

            CollectQueryDirectives(
                processed, directives,
                fieldSelection);

            return(directives.AsReadOnly());
        }
コード例 #29
0
 public ResolverTask(
     IExecutionContext executionContext,
     ObjectType objectType,
     FieldSelection fieldSelection,
     Path path,
     ImmutableStack <object> source,
     OrderedDictionary result)
 {
     Source          = source;
     ObjectType      = objectType;
     FieldSelection  = fieldSelection;
     FieldType       = fieldSelection.Field.Type;
     Path            = path;
     Result          = result;
     ResolverContext = new ResolverContext(executionContext, this);
 }
コード例 #30
0
        private async Task <IExecutionResult> ExecuteInternalAsync(
            IExecutionContext executionContext)
        {
            object rootValue = executionContext.Operation.RootValue;

            FieldSelection fieldSelection = executionContext.CollectFields(
                executionContext.Schema.SubscriptionType,
                executionContext.Operation.Definition.SelectionSet,
                null)
                                            .Single();

            ImmutableStack <object> source = ImmutableStack.Create(rootValue);

            var subscribeContext = ResolverContext.Rent(
                executionContext,
                fieldSelection,
                source,
                new FieldData(1));

            SubscribeResolverDelegate subscribeResolver =
                fieldSelection.Field.SubscribeResolver
                ?? DefaultSubscribeResolverAsync;

            try
            {
                IAsyncEnumerable <object> sourceStream =
                    await subscribeResolver(subscribeContext)
                    .ConfigureAwait(false);

                return(new SubscriptionResult(
                           sourceStream,
                           message =>
                {
                    IExecutionContext cloned = executionContext.Clone();
                    cloned.ContextData[WellKnownContextData.EventMessage] = message;
                    return cloned;
                },
                           ExecuteSubscriptionQueryAsync,
                           executionContext.ServiceScope,
                           executionContext.RequestAborted));
            }
            finally
            {
                ResolverContext.Return(subscribeContext);
            }
        }