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("}"); } } }
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); }
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; }
/// <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; }
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); }
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); }
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); } }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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) { }
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; }
/// <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}") });