private static IEnumerable <Delegation.VariableValue> ResolveUsedRequestVariables(
            ISchema schema,
            NameString schemaName,
            ExtractedField extractedField,
            IReadOnlyDictionary <string, IValueNode> requestVariables,
            ExtractFieldQuerySyntaxRewriter rewriter)
        {
            foreach (VariableDefinitionNode variable in extractedField.Variables)
            {
                string          name      = variable.Variable.Name.Value;
                INamedInputType namedType = schema.GetType <INamedInputType>(
                    variable.Type.NamedType().Name.Value);

                if (!requestVariables.TryGetValue(name, out IValueNode value))
                {
                    value = NullValueNode.Default;
                }

                value = rewriter.RewriteValueNode(
                    schemaName,
                    (IInputType)variable.Type.ToType(namedType),
                    value);

                yield return(new Delegation.VariableValue
                             (
                                 name,
                                 variable.Type,
                                 value,
                                 variable.DefaultValue
                             ));
            }
        }
        private static void ResolveScopedVariableArguments(
            IResolverContext context,
            NameString schemaName,
            SelectionPathComponent component,
            IOutputField field,
            ICollection <Delegation.VariableValue> variables,
            ExtractFieldQuerySyntaxRewriter rewriter)
        {
            foreach (ArgumentNode argument in component.Arguments)
            {
                if (!field.Arguments.TryGetField(argument.Name.Value, out IInputField arg))
                {
                    throw new QueryException(
                              ErrorBuilder.New()
                              .SetMessage(
                                  StitchingResources.DelegationMiddleware_ArgumentNotFound,
                                  argument.Name.Value)
                              .SetExtension("argument", argument.Name.Value)
                              .SetCode(ErrorCodes.ArgumentNotFound)
                              .Build());
                }

                if (argument.Value is ScopedVariableNode sv)
                {
                    Delegation.VariableValue variable =
                        _resolvers.Resolve(context, sv, arg.Type);
                    IValueNode value = rewriter.RewriteValueNode(
                        schemaName, arg.Type, variable.Value);
                    variables.Add(variable.WithValue(value));
                }
            }
        }
        private static IReadOnlyCollection <Delegation.VariableValue> CreateVariableValues(
            IMiddlewareContext context,
            NameString schemaName,
            IEnumerable <Delegation.VariableValue> scopedVariables,
            ExtractedField extractedField,
            ExtractFieldQuerySyntaxRewriter rewriter)
        {
            var values = new Dictionary <string, Delegation.VariableValue>();

            foreach (Delegation.VariableValue value in scopedVariables)
            {
                values[value.Name] = value;
            }

            IReadOnlyDictionary <string, IValueNode> requestVariables = context.GetVariables();

            foreach (Delegation.VariableValue value in ResolveUsedRequestVariables(
                         context.Schema, schemaName, extractedField,
                         requestVariables, rewriter))
            {
                values[value.Name] = value;
            }

            return(values.Values);
        }
        private static IReadOnlyList <Delegation.VariableValue> ResolveScopedVariables(
            IResolverContext context,
            NameString schemaName,
            OperationType operationType,
            IEnumerable <SelectionPathComponent> components,
            ExtractFieldQuerySyntaxRewriter rewriter)
        {
            var variables = new List <Delegation.VariableValue>();

            IStitchingContext  stitchingContext = context.Service <IStitchingContext>();
            ISchema            remoteSchema     = stitchingContext.GetRemoteSchema(schemaName);
            IComplexOutputType type             = remoteSchema.GetOperationType(operationType);

            SelectionPathComponent[] comps = components.Reverse().ToArray();

            for (int i = 0; i < comps.Length; i++)
            {
                SelectionPathComponent component = comps[i];

                if (!type.Fields.TryGetField(component.Name.Value, out IOutputField field))
                {
                    throw new QueryException(new Error
                    {
                        Message = string.Format(
                            CultureInfo.InvariantCulture,
                            StitchingResources.DelegationMiddleware_PathElementInvalid,
                            component.Name.Value,
                            type.Name)
                    });
                }

                ResolveScopedVariableArguments(
                    context, schemaName, component,
                    field, variables, rewriter);

                if (i + 1 < comps.Length)
                {
                    if (!field.Type.IsComplexType())
                    {
                        throw new QueryException(new Error
                        {
                            Message = StitchingResources
                                      .DelegationMiddleware_PathElementTypeUnexpected
                        });
                    }
                    type = (IComplexOutputType)field.Type.NamedType();
                }
            }

            return(variables);
        }
예제 #5
0
        private static IReadOnlyQueryRequest CreateQuery(
            IMiddlewareContext context,
            NameString schemaName,
            IImmutableStack <SelectionPathComponent> path)
        {
            var fieldRewriter = new ExtractFieldQuerySyntaxRewriter(
                context.Schema,
                context.Service <IEnumerable <IQueryDelegationRewriter> >());

            OperationType operationType =
                context.Schema.IsRootType(context.ObjectType)
                    ? context.Operation.Operation
                    : OperationType.Query;

            ExtractedField extractedField = fieldRewriter.ExtractField(
                schemaName, context.Document, context.Operation,
                context.FieldSelection, context.ObjectType);

            IEnumerable <VariableValue> scopedVariables =
                ResolveScopedVariables(
                    context, schemaName, operationType, path);

            IReadOnlyCollection <VariableValue> variableValues =
                CreateVariableValues(
                    context, scopedVariables, extractedField);

            DocumentNode query = RemoteQueryBuilder.New()
                                 .SetOperation(operationType)
                                 .SetSelectionPath(path)
                                 .SetRequestField(extractedField.Field)
                                 .AddVariables(CreateVariableDefs(variableValues))
                                 .AddFragmentDefinitions(extractedField.Fragments)
                                 .Build();

            var requestBuilder = QueryRequestBuilder.New();

            AddVariables(context, schemaName,
                         requestBuilder, query, variableValues);

            requestBuilder.SetQuery(query);
            requestBuilder.AddProperty(
                WellKnownProperties.IsAutoGenerated,
                true);

            return(requestBuilder.Create());
        }
예제 #6
0
        public void ExtractField_WithCustomRewriters()
        {
            // arrange
            ISchema schema = Schema.Create(
                FileResource.Open("Stitching.graphql"),
                c =>
            {
                c.RegisterType <DateTimeType>();
                c.RegisterDirective <DelegateDirectiveType>();
                c.RegisterDirective <ComputedDirectiveType>();
                c.Use(next => context => Task.CompletedTask);
            });

            DocumentNode query = Utf8GraphQLParser.Parse(
                FileResource.Open("StitchingQuery.graphql"));

            OperationDefinitionNode operation = query.Definitions
                                                .OfType <OperationDefinitionNode>().Single();

            FieldNode selection = operation
                                  .SelectionSet.Selections
                                  .OfType <FieldNode>().First();

            var rewriters = new List <IQueryDelegationRewriter>
            {
                new DummyRewriter()
            };

            // act
            var rewriter = new ExtractFieldQuerySyntaxRewriter(
                schema, rewriters);

            ExtractedField extractedField = rewriter.ExtractField(
                "customer", query, operation, selection,
                schema.GetType <ObjectType>("Query"));

            // assert
            DocumentNode document = RemoteQueryBuilder.New()
                                    .SetRequestField(extractedField.Field)
                                    .AddFragmentDefinitions(extractedField.Fragments)
                                    .AddVariables(extractedField.Variables)
                                    .Build();

            QuerySyntaxSerializer.Serialize(document)
            .MatchSnapshot();
        }
        public void ExtractField(string schemaFile, string queryFile)
        {
            // arrange
            ISchema schema = Schema.Create(
                FileResource.Open(schemaFile),
                c =>
            {
                c.RegisterType <DateTimeType>();
                c.RegisterDirective <DelegateDirectiveType>();
                c.RegisterDirective <ComputedDirectiveType>();
                c.Use(next => context => Task.CompletedTask);
            });

            DocumentNode query = Parser.Default.Parse(
                FileResource.Open(queryFile));

            OperationDefinitionNode operation = query.Definitions
                                                .OfType <OperationDefinitionNode>().Single();

            FieldNode selection = operation
                                  .SelectionSet.Selections
                                  .OfType <FieldNode>().First();

            // act
            var rewriter = new ExtractFieldQuerySyntaxRewriter(schema,
                                                               Array.Empty <IQueryDelegationRewriter>());
            ExtractedField extractedField = rewriter.ExtractField(
                "customer", query, operation, selection,
                schema.GetType <ObjectType>("Query"));

            // assert
            DocumentNode document = RemoteQueryBuilder.New()
                                    .SetRequestField(extractedField.Field)
                                    .AddFragmentDefinitions(extractedField.Fragments)
                                    .AddVariables(extractedField.Variables)
                                    .Build();

            QuerySyntaxSerializer.Serialize(document)
            .MatchSnapshot(new SnapshotNameExtension(
                               schemaFile, queryFile));
        }