Example #1
0
        private void AppendSelectionSet(StringBuilder builder, GraphQLField field, Func <GraphQLField, bool> filter, IReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments)
        {
            // Append selectionSet
            if ((field.SelectionSet?.Any() ?? false) || (field.TargetTypes?.Any() ?? false))
            {
                if (field.SelectionSet?.Any() ?? false)
                {
                    builder.Append("{");
                    // SelectionSet
                    FilterAndAppendSelectionSet(builder, field.SelectionSet, filter, arguments);
                }

                // Get other possible subTypes
                if (field.TargetTypes?.Any() ?? false)
                {
                    foreach (var possibleType in field.TargetTypes)
                    {
                        builder.Append($" ... on {possibleType.Key}");
                        builder.Append("{");
                        FilterAndAppendSelectionSet(builder, possibleType.Value.SelectionSet, filter, arguments);
                        builder.Append("}");
                    }
                }

                if (field.SelectionSet?.Any() ?? false)
                {
                    builder.Append("}");
                }
            }
        }
Example #2
0
        private void AppendDirectives(StringBuilder builder, GraphQLField field, IReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments)
        {
            // Append directives
            // Format: @directive(argumentName:$VariableName argumentName:$VariableName)
            if (field.Directives?.Any() ?? false)
            {
                foreach (var directive in field.Directives)
                {
                    builder.Append($" @{directive.DirectiveName}");

                    var directiveArguments = directive.Arguments?.ToDictionary(argument => argument,
                                                                               argument => arguments.FirstOrDefault(e => e.Key == argument).Value).Where(e => e.Value != null);

                    if (directiveArguments?.Any() ?? false)
                    {
                        builder.Append("(");
                        builder.Append(string.Join(" ",
                                                   directiveArguments.Select(
                                                       argument => argument.Key.ArgumentName + ":" +
                                                       (ShouldInlineArgument(argument)
                                                ? GetArgumentValue(argument.Value.ArgumentValue)
                                                : "$" + argument.Key.VariableName))));
                        builder.Append(")");
                    }
                }
            }
        }
        public void Test_Single_Other_Possible_Type_With_Extra_Field()
        {
            var fields = new GraphQLField[]
            {
                new GraphQLField("alias", "field", null, null, null,
                                 new Dictionary <string, GraphQLTargetType>
                {
                    {
                        "interfaceConcreteType",
                        new GraphQLTargetType
                        (
                            typeof(string),
                            new List <GraphQLField>
                        {
                            new GraphQLField("alias", "field", null, null),
                            new GraphQLField("alias2", "field2", null, null)
                        }
                        )
                    }
                }),
            };
            var queryGenerator = new GraphQLQueryGeneratorFromFields();
            var expected       = "{\"query\":\"query{alias:field ... on interfaceConcreteType{alias:field alias2:field2}}\"}";

            var actual = queryGenerator.GenerateQuery(GraphQLOperationType.Query, fields);

            Assert.Equal(expected, actual);
        }
Example #4
0
        public static double?GetImpactFromArgs(GraphQLField node)  //TODO: variables support
        {
            double?newImpact = null;

            if (node.Arguments != null)
            {
                if (node.Arguments.ValueFor("id") != null)
                {
                    newImpact = 1;
                }
                else
                {
                    if (node.Arguments.ValueFor("first") is GraphQLIntValue firstValue)
                    {
                        newImpact = Int.Parse(firstValue.Value);
                    }
                    else
                    {
                        if (node.Arguments.ValueFor("last") is GraphQLIntValue lastValue)
                        {
                            newImpact = Int.Parse(lastValue.Value);
                        }
                    }
                }
            }

            return(newImpact);
        }
 internal ValidationError(string path, ValidationType validationType, GraphQLField field, string expected, string actual)
 {
     this.Path           = path;
     this.ValidationType = validationType;
     this.Field          = field;
     this.Expected       = expected;
     this.Actual         = actual;
 }
Example #6
0
        /// <summary>
        /// Initializes an instance of <see cref="ExecutionNode"/> with the specified values
        /// </summary>
        /// <param name="parent">The parent node, or <see langword="null"/> if this is the root node</param>
        /// <param name="graphType">The graph type of this node, unwrapped if it is a <see cref="NonNullGraphType"/>. Array nodes will be a <see cref="ListGraphType"/> instance.</param>
        /// <param name="field">The AST field of this node</param>
        /// <param name="fieldDefinition">The graph's field type of this node</param>
        /// <param name="indexInParentNode">For child array item nodes of a <see cref="ListGraphType"/>, the index of this array item within the field; otherwise, <see langword="null"/></param>
        protected ExecutionNode(ExecutionNode parent, IGraphType graphType, GraphQLField field, FieldType fieldDefinition, int?indexInParentNode)
        {
            Debug.Assert(field?.Name == fieldDefinition?.Name); // ? for RootExecutionNode

            Parent            = parent;
            GraphType         = graphType;
            Field             = field !;
            FieldDefinition   = fieldDefinition !;
            IndexInParentNode = indexInParentNode;
        }
Example #7
0
        public void Test_QueryGenerator_Alias_Null()
        {
            var field = new GraphQLField(alias: null, field: "Field1", fields: null, arguments: null);

            var expected = "{\"query\":\"query{Field1}\"}";

            var actual = _queryGenerator.GetQuery(new[] { field });

            Assert.Equal(expected, actual);
        }
Example #8
0
        public void Test_QueryGenerator_Argument_Default_Value()
        {
            var field = new GraphQLField(alias: null, field: "field1", fields: null, arguments: new List <GraphQLFieldArguments>()
            {
                new GraphQLFieldArguments("argumentName", "argumentType", "variableName", true, true, "DefaultValue")
            });

            var expected = "{\"query\":\"query{field1(argumentName:\\\"DefaultValue\\\")}\"}";

            var actual = _queryGenerator.GetQuery(new[] { field });

            Assert.Equal(expected, actual);
        }
Example #9
0
 private void AppendFieldName(StringBuilder builder, GraphQLField field)
 {
     // Append alias and field
     // Format: alias:field or field
     if (field.Alias == null || field.Alias.Equals(field.Field, StringComparison.OrdinalIgnoreCase))
     {
         builder.Append(field.Field);
     }
     else
     {
         builder.Append(field.Alias + ":" + field.Field);
     }
 }
Example #10
0
        protected override async ValueTask VisitFieldAsync(GraphQLField field, AnalysisContext context)
        {
            context.AssertRecursion();

            var prevCurrentSubSelectionImpact = context.CurrentSubSelectionImpact;
            var prevCurrentEndNodeImpact      = context.CurrentEndNodeImpact;

            if (context.FragmentMapAlreadyBuilt)
            {
                if (field.SelectionSet == null) // leaf field
                {
                    context.RecordFieldComplexity(field, context.CurrentEndNodeImpact);
                }
                else
                {
                    context.Result.TotalQueryDepth++;

                    double?impactFromArgs = AnalysisContext.GetImpactFromArgs(field);
                    context.CurrentEndNodeImpact = impactFromArgs == null
                        ? context.CurrentSubSelectionImpact
                        : impactFromArgs.Value / context.AvgImpact * context.CurrentSubSelectionImpact;

                    context.RecordFieldComplexity(field, context.CurrentEndNodeImpact);
                    context.CurrentSubSelectionImpact *= impactFromArgs ?? context.AvgImpact;
                }
            }
            else
            {
                if (field.SelectionSet == null) // leaf field
                {
                    context.CurrentFragmentComplexity.Complexity += context.CurrentEndNodeImpact;
                }
                else
                {
                    context.CurrentFragmentComplexity.Depth++;

                    double?impactFromArgs = AnalysisContext.GetImpactFromArgs(field);
                    context.CurrentEndNodeImpact = impactFromArgs == null
                        ? context.CurrentSubSelectionImpact
                        : impactFromArgs.Value / context.AvgImpact * context.CurrentSubSelectionImpact;

                    context.CurrentFragmentComplexity.Complexity += context.CurrentEndNodeImpact;
                    context.CurrentSubSelectionImpact            *= impactFromArgs ?? context.AvgImpact;
                }
            }

            await base.VisitFieldAsync(field, context).ConfigureAwait(false);

            context.CurrentSubSelectionImpact = prevCurrentSubSelectionImpact;
            context.CurrentEndNodeImpact      = prevCurrentEndNodeImpact;
        }
Example #11
0
        public void Filter_Root()
        {
            // Arrange
            var includedField    = new GraphQLField(field: "includedField", alias: null, fields: null, arguments: null);
            var notIncludedField = new GraphQLField(field: "notIncludedField", alias: null, fields: null, arguments: null);

            var expected = "{\"query\":\"query{includedField}\"}";

            // Act
            var actual = _queryGenerator.GenerateQuery(GraphQLOperationType.Query, new[] { includedField, notIncludedField }, filter: field => field.Field == "includedField");

            // Assert
            Assert.Equal(expected, actual);
        }
Example #12
0
        public void Check_Simple_Mutation_Single_Field()
        {
            var fields = new GraphQLField[]
            {
                new GraphQLField("alias", "field", null, null),
            };
            var fieldBuilder   = new FieldBuilderMock(fields);
            var queryGenerator = new GraphQLQueryGeneratorFromFields();
            var expected       = "{\"query\":\"mutation{alias:field}\"}";

            var actual = queryGenerator.GetMutation <string>(fieldBuilder); // Type parameter is ignored since it just returns the fields

            Assert.Equal(expected, actual);
        }
Example #13
0
        public void Filter_Scalars_SelectionSet_Included()
        {
            // Arrange
            var includedField = new GraphQLField(field: "includedField", alias: null, arguments: null,
                                                 fields: new[] {
                new GraphQLField(field: "subfield", alias: null, fields: null, arguments: null)
            });

            var expected = "{\"query\":\"query{includedField{subfield}}\"}";

            // Act
            var actual = _queryGenerator.GenerateQuery(GraphQLOperationType.Query, new[] { includedField }, filter: field => field.Field == "includedField");

            // Assert
            Assert.Equal(expected, actual);
        }
Example #14
0
 public SchemaField(ISchemaQueryType <Info> declaringType, GraphQLField field, Schema schema)
 {
     DeclaringType = declaringType;
     _field        = field;
     _schema       = schema;
     if (_field.Type.IsScalar)
     {
         var varType = _schema.GraphQLSchema.VariableTypes.VariableTypeOf(_field.Type.CLRType);
         FieldType = SchemaFieldType <Info> .NewValueField(varType);
     }
     else
     {
         FieldType = SchemaFieldType <Info> .NewQueryField(_schema.OfType(_field.Type));;
     }
     Arguments = _field.Arguments.ToDictionary(a => a.ArgumentName);
 }
Example #15
0
        private void AppendField(StringBuilder builder, GraphQLField field, Func <GraphQLField, bool> filter, IReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments)
        {
            // Append alias and field
            // Format: alias:field or field
            AppendFieldName(builder, field);

            // Append arguments
            // Format: (argumentName:$VariableName argumentName:$VariableName)
            AppendArguments(builder, field, arguments);

            // Append directives
            // Format: @directive(argumentName:$VariableName argumentName:$VariableName)
            AppendDirectives(builder, field, arguments);

            // Append selectionSet
            // Format: {field field}
            AppendSelectionSet(builder, field, filter, arguments);
        }
Example #16
0
        private static Type GetSpecificType(GraphQLField selection, bool isListType)
        {
            var type = selection.BaseType;

            if (isListType)
            {
                type = GetIEnumerableType(type);
            }

            var isNullable = IsNullableType(type);

            if (isNullable)
            {
                type = type.GenericTypeArguments.First();
            }

            return(type);
        }
Example #17
0
 public SchemaField(ISchemaQueryType <Info> declaringType, GraphQLField field, Schema schema)
 {
     DeclaringType = declaringType;
     _field        = field;
     _schema       = schema;
     if (_field.Type.TypeKind == TypeKind.SCALAR)
     {
         var varType = _schema.GraphQLSchema.VariableTypes.VariableTypeOf(_field.Type.CLRType);
         if (varType?.Type == null)
         {
             throw new Exception("Field has unknown return type. " + declaringType.TypeName + "." + _field.Name);
         }
         FieldType = SchemaFieldType <Info> .NewValueField(varType);
     }
     else
     {
         FieldType = SchemaFieldType <Info> .NewQueryField(_schema.OfType(_field.Type));;
     }
     Arguments = _field.Arguments.ToDictionary(a => a.ArgumentName);
 }
Example #18
0
        private void AppendArguments(StringBuilder builder, GraphQLField field, IReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments)
        {
            // Append arguments
            // Format: (argumentName:$VariableName argumentName:$VariableName)
            var fieldArguments = field.Arguments?.ToDictionary(argument => argument,
                                                               argument => arguments.FirstOrDefault(e => e.Key == argument).Value).Where(e => e.Value != null);

            if (fieldArguments?.Any() ?? false)
            {
                builder.Append("(");

                builder.Append(string.Join(" ",
                                           fieldArguments.Select(
                                               argument => argument.Key.ArgumentName + ":" +
                                               (ShouldInlineArgument(argument)
                                        ? GetArgumentValue(argument.Value.ArgumentValue)
                                        : "$" + argument.Key.VariableName))));

                builder.Append(")");
            }
        }
        public void QueryGenerator_Generates_Directive_Variable()
        {
            // Arrange
            var field =
                new GraphQLField(alias: null, field: "field1", fields: null, type: typeof(string), targetTypes: null, arguments: new List <GraphQLFieldArguments>()
            {
            }, directives: new List <GraphQLFieldDirective>
            {
                new GraphQLFieldDirective("if", new List <GraphQLFieldArguments>
                {
                    new GraphQLFieldArguments("if", "Boolean", "ifvariable", isRequired: true, inlineArgument: false, defaultValue: "DefaultValue")
                })
            });

            var expected = "{\"query\":\"query($ifvariable:Boolean){field1 @if(if:$ifvariable)}\",\"variables\":{\"ifvariable\":\"DefaultValue\"}}";

            // Act
            var actual = _queryGenerator.GenerateQuery(GraphQLOperationType.Query, new[] { field });

            // Assert
            Assert.Equal(expected, actual);
        }
        /// <summary>
        /// Returns a dictionary of directives with their arguments values for a field.
        /// Values will be retrieved from literals or variables as specified by the document.
        /// </summary>
        public static IDictionary <string, DirectiveInfo>?GetDirectives(GraphQLField field, Variables?variables, ISchema schema)
        {
            if (field.Directives == null || field.Directives.Count == 0)
            {
                return(null);
            }

            Dictionary <string, DirectiveInfo>?directives = null;

            foreach (var dir in field.Directives.Items)
            {
                var dirDefinition = schema.Directives.Find(dir.Name);

                // KnownDirectivesInAllowedLocations validation rule should handle unknown directives, so
                // if someone purposely removed the validation rule, it would ignore unknown directives
                // while executing the request
                if (dirDefinition == null)
                {
                    continue;
                }

                (directives ??= new())[dirDefinition.Name] = new DirectiveInfo(dirDefinition, GetArguments(dirDefinition.Arguments, dir.Arguments, variables) ?? _emptyDirectiveArguments);
        public void QueryGenerator_Should_Throw_If_Required_Argument_Is_Not_Filled()
        {
            // Arrange
            var field =
                new GraphQLField(alias: null, field: "field1", fields: null, type: typeof(string), targetTypes: null, arguments: new List <GraphQLFieldArguments>()
            {
            }, directives: new List <GraphQLFieldDirective>
            {
                new GraphQLFieldDirective("if", new List <GraphQLFieldArguments>
                {
                    new GraphQLFieldArguments("if", "Boolean", "ifvariable", isRequired: true, inlineArgument: true)
                })
            });

            // Act / Assert
            var exception = Assert.Throws <GraphQLArgumentsRequiredException>(() =>
                                                                              _queryGenerator.GenerateQuery(GraphQLOperationType.Query, new[] { field }));

            Assert.Single(exception.Arguments);
            Assert.Equal("ifvariable", exception.Arguments.First().VariableName);
            Assert.Equal("if", exception.Arguments.First().ArgumentName);
        }
Example #22
0
    public RepeatedSubfieldsTests()
    {
        FirstInnerField = new GraphQLField {
            Name = new GraphQLName("first")
        };
        FirstFieldSelection = new GraphQLSelectionSet
        {
            Selections = new List <ASTNode>
            {
                FirstInnerField
            }
        };
        SecondInnerField = new GraphQLField {
            Name = new GraphQLName("second")
        };
        SecondFieldSelection = new GraphQLSelectionSet
        {
            Selections = new List <ASTNode>
            {
                SecondInnerField
            }
        };
        FirstTestField = new GraphQLField {
            Name = new GraphQLName("test")
        };
        SecondTestField = new GraphQLField {
            Name = new GraphQLName("test")
        };
        AliasedTestField = new GraphQLField {
            Alias = new GraphQLAlias {
                Name = new GraphQLName("alias")
            }, Name = new GraphQLName("test")
        };

        FirstTestField.SelectionSet   = FirstFieldSelection;
        SecondTestField.SelectionSet  = SecondFieldSelection;
        AliasedTestField.SelectionSet = SecondFieldSelection;
    }
Example #23
0
        public void Check_Simple_Query_Multiple_Nested_Field()
        {
            var fields = new GraphQLField[]
            {
                new GraphQLField(
                    alias: "alias",
                    field: "field",
                    fields: new []
                {
                    new GraphQLField(
                        alias: "alias2",
                        field: "field2",
                        fields: null,
                        arguments: null
                        ),
                    new GraphQLField(
                        alias: "alias3",
                        field: "field3",
                        fields: null,
                        arguments: null
                        ),
                },
                    arguments: null),
                new GraphQLField(
                    alias: "alias4",
                    field: "field4",
                    fields: null,
                    arguments: null
                    )
            };
            var fieldBuilder   = new FieldBuilderMock(fields);
            var queryGenerator = new GraphQLQueryGeneratorFromFields();
            var expected       = "{\"query\":\"query{alias:field{alias2:field2 alias3:field3} alias4:field4}\"}";

            var actual = queryGenerator.GetQuery <string>(fieldBuilder); // Type parameter is ignored since it just returns the fields

            Assert.Equal(expected, actual);
        }
 /// <summary>
 /// Initializes an instance of <see cref="ValueExecutionNode"/> with the specified values.
 /// </summary>
 public ValueExecutionNode(ExecutionNode parent, ScalarGraphType graphType, GraphQLField field, FieldType fieldDefinition, int?indexInParentNode)
     : base(parent, graphType, field, fieldDefinition, indexInParentNode)
 {
 }
Example #25
0
 public Info(GraphQLField field)
 {
     Field = field;
 }
        private string GenerateQueryForField(GraphQLField field, IReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments)
        {
            StringBuilder builder = new StringBuilder();

            // Append alias and field
            if (field.Alias == null || field.Alias.Equals(field.Field, StringComparison.OrdinalIgnoreCase))
            {
                builder.Append(field.Field);
            }
            else
            {
                builder.Append(field.Alias + ":" + field.Field);
            }

            // Append arguments
            // Format: (argumentName:$VariableName argumentName:$VariableName)
            var fieldArguments = field.Arguments?.ToDictionary(argument => argument,
                                                               argument => arguments.FirstOrDefault(e => e.Key == argument).Value).Where(e => e.Value != null);

            if (fieldArguments?.Any() ?? false)
            {
                builder.Append("(");

                builder.Append(string.Join(" ",
                                           fieldArguments.Select(
                                               argument => argument.Key.ArgumentName + ":" +
                                               (ShouldInlineArgument(argument)
                                        ? JsonConvert.SerializeObject(argument.Value.ArgumentValue)
                                        : "$" + argument.Key.VariableName))));

                builder.Append(")");
            }

            // Append subquery
            if ((field.SelectionSet?.Any() ?? false) || (field.TargetTypes?.Any() ?? false))
            {
                if (field.SelectionSet?.Any() ?? false)
                {
                    builder.Append("{");
                    // SelectionSet
                    builder.Append(string.Join(" ", field.SelectionSet.Select(e => GenerateQueryForField(e, arguments))));
                }

                // Get other possible subTypes
                if (field.TargetTypes?.Any() ?? false)
                {
                    foreach (var possibleType in field.TargetTypes)
                    {
                        builder.Append($" ... on {possibleType.Key}");
                        builder.Append("{");
                        builder.Append(string.Join(" ", possibleType.Value.SelectionSet.Select(e => GenerateQueryForField(e, arguments))));
                        builder.Append("}");

                        // Append subquery
                        //builder.Append(
                        //    $" ... on {possibleType.Key}{GenerateQueryForFields(possibleType.Value.SelectionSet, arguments)}");
                    }
                }

                if (field.SelectionSet?.Any() ?? false)
                {
                    builder.Append("}");
                }
            }

            return(builder.ToString());
        }
 internal ValidationError(string path, ValidationType validationType, GraphQLField field)
 {
     this.Path           = path;
     this.ValidationType = validationType;
     this.Field          = field;
 }
 public GraphQLFieldConverter(GraphQLField graphQLField)
 {
     this.graphQLField = graphQLField;
 }
 public GraphQLFieldWithOverridedAlias(string alias, GraphQLField field)
     : base(alias, field: field.Field, fields: field.Fields,
            arguments: field.Arguments)
 {
     Inner = field;
 }
Example #30
0
 /// <summary>
 /// Initializes an <see cref="SubscriptionArrayExecutionNode"/> instance with the specified values.
 /// </summary>
 public SubscriptionArrayExecutionNode(ExecutionNode parent, IGraphType graphType, GraphQLField field, FieldType fieldDefinition, int?indexInParentNode, object source)
     : base(parent, graphType, field, fieldDefinition, indexInParentNode)
 {
     Source = source;
 }
        /// <summary>
        /// Builds an execution node with the specified parameters.
        /// </summary>
        protected virtual ExecutionNode BuildExecutionNode(ExecutionNode parent, IGraphType graphType, GraphQLField 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 scalarGraphType => new ValueExecutionNode(parent, scalarGraphType, field, fieldDefinition, indexInParentNode),
                _ => throw new InvalidOperationException($"Unexpected type: {graphType}")
            });