/// <inheritdoc /> public Task <T> Execute <T>(GraphQLOperationType operationType, string url = null, HttpMethod httpMethod = null, IDictionary <string, string> headers = null, Expression <Func <T, T> > filter = null, string authorizationToken = null, string authorizationMethod = "Bearer", CancellationToken cancellationToken = default, params GraphQLQueryArgument[] arguments) where T : class { // Generate selectionSet var selectionSet = FieldBuilder.GenerateSelectionSet(typeof(T)); // Execute return(Execute <T>(operationType, selectionSet, arguments, url: url, httpMethod: httpMethod, headers: headers, filter: filter, authorizationMethod: authorizationMethod, authorizationToken: authorizationToken, cancellationToken: cancellationToken)); }
// ReSharper disable once InconsistentNaming private IGraphQLQuery <T> GetGraphQLQuery <T>(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, IDictionary <string, string> headers, Func <GraphQLField, bool> filter, string authorizationToken = null, string authorizationMethod = "Bearer") where T : class { return(new GraphQLQuery <T>(operationType, selectionSet, arguments, url, httpMethod, filter, authorizationToken, authorizationMethod, headers, QueryGenerator, HttpExecutor, Deserialization)); }
private static string Render(GraphQLOperationType type) { return(type switch { GraphQLOperationType.Mutation => "mutation", GraphQLOperationType.Query => "query", GraphQLOperationType.Subscription => "subscription", _ => throw new NotImplementedException($"Unknown query operation type '{type}'.") });
public GraphQLQueryOperation(GraphQLOperationType type, string name, ISelectionSet <T> selectionSet) { Type = type; Name = name; SelectionSet = selectionSet ?? throw new ArgumentNullException(nameof(selectionSet)); if (!selectionSet.Selections.Any()) { // TODO throw? } }
/// <inheritdoc /> public string GenerateQuery(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, Func <GraphQLField, bool> filter, params GraphQLQueryArgument[] arguments) { switch (operationType) { case GraphQLOperationType.Query: case GraphQLOperationType.Mutation: case GraphQLOperationType.Subscription: return(GetQuery(operationType, selectionSet.ToList(), filter, arguments)); } throw new NotImplementedException($"Operation {operationType} not implemented"); }
private string GetQuery(GraphQLOperationType operationType, ICollection <GraphQLField> selectionSet, Func <GraphQLField, bool> filter, params GraphQLQueryArgument[] queryArguments) { // Get arguments var readonlyArguments = GetArguments(selectionSet, filter, queryArguments); // Get query if (operationType == GraphQLOperationType.Subscription) { // Only support for one field for subscriptions if (selectionSet.Count > 1) { throw new NotSupportedException("Subscriptions does not support more than one selection"); } } // Get queryType string queryType; switch (operationType) { case GraphQLOperationType.Query: queryType = "query"; break; case GraphQLOperationType.Mutation: queryType = "mutation"; break; case GraphQLOperationType.Subscription: queryType = "subscription " + (string.IsNullOrWhiteSpace(selectionSet.First().Alias) ? selectionSet.First().Field : selectionSet.First().Alias); break; default: throw new NotImplementedException($"Querytype {operationType} not implemented"); } var queryBuilder = new StringBuilder(); AppendRootQueryType(queryBuilder, queryType); AppendRootArguments(queryBuilder, readonlyArguments); AppendRootSelectionSet(queryBuilder, selectionSet, filter, readonlyArguments); var request = GetQueryRequest(queryBuilder.ToString(), readonlyArguments); // Logging if (Logger != null && Logger.IsEnabled(LogLevel.Debug)) { Logger.LogDebug($"Generated the GraphQL query {request} from the fields:{Environment.NewLine + string.Join(Environment.NewLine, selectionSet)}"); } return(request); }
public GraphQLQuery(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, string authorizationToken, string authorizationMethod, IGraphQLQueryGeneratorFromFields queryGenerator, IGraphQLHttpExecutor executor, IGraphQLDeserialization deserilization) { _url = url ?? throw new ArgumentNullException(nameof(url)); _httpMethod = httpMethod ?? throw new ArgumentNullException(nameof(httpMethod)); _executor = executor ?? throw new ArgumentNullException(nameof(executor)); this._deserilization = deserilization; _authorizationMethod = authorizationMethod; this._queryGenerator = queryGenerator; _authorizationToken = authorizationToken; OperationType = operationType; SelectionSet = selectionSet; _arguments = arguments; }
/// <inheritdoc /> public Task <dynamic> Execute(GraphQLOperationType operationType, Action <IGraphQLBuilder> builder, string url = null, HttpMethod httpMethod = null, IDictionary <string, string> headers = null, string authorizationToken = null, string authorizationMethod = "Bearer", CancellationToken cancellationToken = default, params GraphQLQueryArgument[] arguments) { // Get builder var build = new GraphQLBuilder(); builder(build); // Get the fields and query var selectionSet = build.GetFields(); // Execute return(Execute <dynamic>(operationType, selectionSet, arguments, url: url, httpMethod: httpMethod, headers: headers, filter: null, authorizationMethod: authorizationMethod, authorizationToken: authorizationToken, cancellationToken: cancellationToken)); }
public async Task Validate_Hello_Query_Invalid_QueryType(GraphQLOperationType operationType) { // Arrange var graphQLClient = this.GraphQLHttpClient; // Act var introspectionQuery = await graphQLClient.CreateQuery <GraphQLIntrospectionQuery>("http://localhost/graphql").Execute(); var validationOutput = introspectionQuery.ValidateGraphQLType <TestHelloQuery>(operationType); // Assert Assert.Single(validationOutput); Assert.Equal(ValidationType.Operation_Type_Not_Found, validationOutput.First().ValidationType); }
public void Then_Field_Arguments_Are_Rendered( [Values] GraphQLOperationType operationType, [Values(null, "", " ", "MyQuery")] string operationName) { var phoneNumberSelectionSet = SelectionSetBuilder.For <PhoneNumber>() .AddScalarField(phone => phone.Number) .Build(); var phoneArguments = new ArgumentCollection { ArgumentBuilder.Build("areaCode", "231"), ArgumentBuilder.Build("foobar") }; var contactSelectionSet = SelectionSetBuilder.For <Contact>() .AddObjectCollectionField("michiganNumbers", contact => contact.PhoneNumbers, phoneArguments, phoneNumberSelectionSet) .Build(); var numberArguments = new ArgumentCollection { ArgumentBuilder.Build("isEven", true), ArgumentBuilder.Build("greaterThan", 22) }; var customerSelectionSet = SelectionSetBuilder.For <Customer>() .AddScalarCollectionField("favEvenNumbersGreaterThan22", customer => customer.FavoriteNumbers, numberArguments) .Build(); var customersArguments = new ArgumentCollection { ArgumentBuilder.Build("isActive", true), ArgumentBuilder.Build("lastName", "Smith"), ArgumentBuilder.Build("minRating", 3.2) }; var query = QueryOperationBuilder.ForSchema <SimpleSchema>(operationType, operationName) .AddObjectCollectionField(schema => schema.Customers, customersArguments, customerSelectionSet) .AddObjectCollectionField("foobar", schema => schema.Customers, customersArguments, customerSelectionSet) .AddObjectField(schema => schema.Administrator, contactSelectionSet) .Build(); var result = new QueryRenderer().Render(query); Snapshot.Match(result); }
public GraphQLBatchMerger(GraphQLOperationType graphQLOperationType, string url, HttpMethod httpMethod, IDictionary <string, string> headers, string authorizationToken, string authorizationMethod, IGraphQLHttpExecutor executor, IGraphQLFieldBuilder fieldBuilder, IGraphQLQueryGeneratorFromFields queryGenerator, IGraphQLDeserialization graphQLDeserialization) { _graphQLOperationType = graphQLOperationType; _url = url; _httpMethod = httpMethod; _headers = headers; _authorizationToken = authorizationToken; _authorizationMethod = authorizationMethod; _executor = executor; _fieldBuilder = fieldBuilder; _queryGenerator = queryGenerator; _graphQLDeserialization = graphQLDeserialization; _fields = new Dictionary <string, IEnumerable <GraphQLFieldWithOverridedAlias> >(); _arguments = new Dictionary <string, GraphQLQueryArgumentWithOverriddenVariable[]>(); }
public GraphQLQuery(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, string authorizationToken, string authorizationMethod, IDictionary <string, string> headers, IGraphQLQueryGeneratorFromFields queryGenerator, IGraphQLHttpExecutor executor, IGraphQLDeserialization deserilization) : this(operationType : operationType, selectionSet : selectionSet, arguments : arguments, url : url, httpMethod : httpMethod, filter : null, authorizationToken : authorizationToken, authorizationMethod : authorizationMethod, headers : headers, queryGenerator : queryGenerator, executor : executor, deserilization : deserilization) { }
public GraphQLQuery(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, Func <GraphQLField, bool> filter, string authorizationToken, string authorizationMethod, IDictionary <string, string> headers, IGraphQLQueryGeneratorFromFields queryGenerator, IGraphQLHttpExecutor executor, IGraphQLDeserialization deserilization) { this._url = url ?? throw new ArgumentNullException(nameof(url)); this._httpMethod = httpMethod; this._executor = executor ?? throw new ArgumentNullException(nameof(executor)); this._deserilization = deserilization; this._authorizationMethod = authorizationMethod; this._queryGenerator = queryGenerator; this._authorizationToken = authorizationToken; this.OperationType = operationType; this.SelectionSet = selectionSet; this._arguments = arguments; this._headers = headers; this._filter = filter; }
public void Then_Added_Fields_Are_Rendered( [Values] GraphQLOperationType operationType, [Values(null, "", " ", "MyQuery")] string operationName) { var addressSelectionSet = SelectionSetBuilder.For <Address>() .AddScalarField("line1", address => address.Street1) .AddScalarField("line2", address => address.Street2) .AddScalarField(address => address.City) .AddScalarField(address => address.State) .AddScalarField(address => address.ZipCode) .Build(); var phoneNumberSelectionSet = SelectionSetBuilder.For <PhoneNumber>() .AddScalarField(phone => phone.Number) .AddScalarField("ext", phone => phone.Extension) .Build(); var contactSelectionSet = SelectionSetBuilder.For <Contact>() .AddScalarField(contact => contact.FirstName) .AddScalarField("surname", contact => contact.LastName) .AddScalarCollectionField("names", contact => contact.Nicknames) .AddObjectField(contact => contact.Address, addressSelectionSet) .AddObjectCollectionField(contact => contact.PhoneNumbers, phoneNumberSelectionSet) .AddObjectCollectionField("foobar", contact => contact.PhoneNumbers, phoneNumberSelectionSet) .Build(); var customerSelectionSet = SelectionSetBuilder.For <Customer>() .AddScalarField(customer => customer.Id) .AddScalarField("acctNum", customer => customer.AccountNumber) .AddObjectField("contactInfo", customer => customer.CustomerContact, contactSelectionSet) .AddScalarCollectionField(customer => customer.FavoriteNumbers) .Build(); var queryOperation = QueryOperationBuilder.ForSchema <SimpleSchema>(operationType, operationName) .AddScalarField(schema => schema.Version) .AddScalarCollectionField("versions", schema => schema.PastVersions) .AddObjectCollectionField("users", schema => schema.Customers, customerSelectionSet) .AddObjectField("admin", schema => schema.Administrator, contactSelectionSet) .Build(); var result = new QueryRenderer().Render(queryOperation); Snapshot.Match(result); }
private async Task <GraphQLDataResult <T> > ExecuteQuery <T>(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, IDictionary <string, string> headers, string authorizationMethod, string authorizationToken) where T : class { // Generate query var requestQuery = QueryGenerator.GenerateQuery(operationType, selectionSet, arguments.ToArray()); // Get response GraphQLExecutorResponse response = await HttpExecutor.ExecuteQuery(requestQuery, url, httpMethod, headers : headers, authorizationToken : authorizationToken, authorizationMethod : authorizationMethod).ConfigureAwait(false); // Deserilize var result = Deserialization.DeserializeResult <T>(response.Response, selectionSet); if (result?.Errors?.Any() ?? false) { throw new GraphQLErrorException(query: requestQuery, errors: result.Errors); } // Set headers result.Headers = response.Headers; return(result); }
/// <inheritdoc /> public string GenerateQuery(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, params GraphQLQueryArgument[] arguments) { return(GenerateQuery(operationType, selectionSet, null, arguments)); }
public When_Building_A_Query_Operation(GraphQLOperationType operationType) : base(operationType) { }
public When_Adding_An_Object_Field(GraphQLOperationType operationType) : base(operationType) { }
private string GetQuery(GraphQLOperationType operationType, ICollection <GraphQLField> fields, params GraphQLQueryArgument[] queryArguments) { // Get all the arguments from the fields var fieldArguments = Helper.GetAllArgumentsFromFields(fields).ToList(); // Create list of argument variables which was not found var variablesNotFoundInFields = queryArguments.ToList(); // Create mapping for each argument field IDictionary <GraphQLFieldArguments, GraphQLQueryArgument> arguments = new Dictionary <GraphQLFieldArguments, GraphQLQueryArgument>(); ICollection <GraphQLFieldArguments> argumentsNotSet = new Collection <GraphQLFieldArguments>(); List <string> duplicateVariableNames = new List <string>(); foreach (var field in fieldArguments) { foreach (var fieldArgument in field.Value) { // Remove from variablesNotFoundInFields variablesNotFoundInFields.RemoveAll(argument => (argument.Field == null || argument.Field == field.Key) && // Match on field name argument.VariableName == fieldArgument.VariableName); // Find matching query arguments var queryArgument = queryArguments .Where(argument => (argument.Field == null || argument.Field == field.Key) && argument.VariableName == fieldArgument.VariableName) .Take(2) .ToList(); // Find match for argument switch (queryArgument.Count) { case 0: // Set default value if (fieldArgument.DefaultValue != null) { arguments.Add(fieldArgument, new GraphQLQueryArgument(fieldArgument.VariableName, fieldArgument.DefaultValue)); break; } // If no default was set we need to check if it was required if (fieldArgument.IsRequired) { argumentsNotSet.Add(fieldArgument); } break; case 1: arguments.Add(fieldArgument, queryArgument[0]); break; default: duplicateVariableNames.Add(queryArgument[0].VariableName); break; } } } // If any arguments was detected not set if (argumentsNotSet.Any()) { throw new GraphQLArgumentsRequiredException(argumentsNotSet); } // If duplicate variable names has been detected if (duplicateVariableNames.Any()) { throw new GraphQLDuplicateVariablesException(duplicateVariableNames); } // Check if any supplied arguments was not found in fields if (variablesNotFoundInFields.Any()) { throw new GraphQLArgumentVariableNotFoundException(variablesNotFoundInFields); } // Detect any variable collision var variableCollisions = arguments .Where(e => !ShouldInlineArgument(e)) // If argument is inlined it will not be a problem .GroupBy(e => e.Key.VariableName) .Where(e => e.Count() > 1) .ToList(); // Replace entire list with new arguments to prevent side effects if (variableCollisions.Any()) { arguments = arguments.ToDictionary( e => e.Key, e => (GraphQLQueryArgument) new GraphQLQueryArgumentWithOverriddenVariable(e.Value)); } // Update all variables foreach (var argumentVariableCollision in variableCollisions) { foreach (var item in argumentVariableCollision.Select((value, i) => new { i, value })) { var argumentWithCollision = item.value; var index = item.i; argumentWithCollision.Value.VariableName += "_" + index; } } // Get readonly arguments var readonlyArguments = new ReadOnlyDictionary <GraphQLFieldArguments, GraphQLQueryArgument>(arguments); // Get query if (operationType == GraphQLOperationType.Subscription) { // Only support for one field if (fields.Count > 1) { throw new NotSupportedException("Subscriptions does not support more than one selection"); } } // Get queryType string queryType; switch (operationType) { case GraphQLOperationType.Query: queryType = "query"; break; case GraphQLOperationType.Mutation: queryType = "mutation"; break; case GraphQLOperationType.Subscription: queryType = "subscription " + (string.IsNullOrWhiteSpace(fields.First().Alias) ? fields.First().Field : fields.First().Alias); break; default: throw new NotImplementedException($"Querytype {operationType} not implemented"); } var query = GetGraphQLQuery(queryType, GetArguments(readonlyArguments), GenerateQueryForFields(fields, readonlyArguments)); var request = GetQueryRequest(query, readonlyArguments); // Logging if (Logger != null && Logger.IsEnabled(LogLevel.Debug)) { Logger.LogDebug($"Generated the GraphQL query {request} from the fields:{Environment.NewLine + string.Join(Environment.NewLine, fields)}"); } return(request); }
internal ValidationError(ValidationType validationType, GraphQLOperationType operationType) { this.ValidationType = validationType; this.OperationType = operationType; }
/// <summary> /// Validate if the GraphQL query type <typeparamref name="T"/> is valid for the specified <paramref name="graphQLIntrospectionSchema"/> and <paramref name="operationType"/> /// </summary> /// <typeparam name="T">The GraphQL query type to validate against</typeparam> /// <param name="graphQLIntrospectionSchema">The introspectionSchema to validate against</param> /// <param name="operationType">The operationType to validate against</param> /// <returns>An empty list if no errors were found or a <see cref="ValidationError"/> for each error found</returns> public static IEnumerable <ValidationError> ValidateGraphQLType <T>(this GraphQLIntrospectionSchema graphQLIntrospectionSchema, GraphQLOperationType operationType) { return(ValidateGraphQLType <T>(graphQLIntrospectionSchema, operationType, new GraphQLFieldBuilder())); }
/// <summary> /// Validate if the GraphQL <paramref name="selectionSet"/> is valid for the specified <paramref name="graphQLIntrospectionSchema"/> and <paramref name="operationType"/> /// </summary> /// <param name="graphQLIntrospectionSchema">The introspectionSchema to validate against</param> /// <param name="operationType">The operationType to validate against</param> /// <param name="selectionSet">The selectionSet which should be validated</param> /// <returns>An empty list if no errors were found or a <see cref="ValidationError"/> for each error found</returns> public IEnumerable <ValidationError> ValidateGraphQLSelectionSet(GraphQLIntrospectionSchema graphQLIntrospectionSchema, GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet) { if (graphQLIntrospectionSchema is null) { throw new ArgumentNullException(nameof(graphQLIntrospectionSchema)); } if (selectionSet is null) { throw new ArgumentNullException(nameof(selectionSet)); } // Get implicit types var graphQLIntrospectionSchemaWithImplicitTypes = graphQLIntrospectionSchema.WithImplicitFields(); GraphQLIntrospectionFullType type = null; switch (operationType) { case GraphQLOperationType.Query: if (graphQLIntrospectionSchemaWithImplicitTypes.QueryType != null) { type = GetTypeByName(graphQLIntrospectionSchemaWithImplicitTypes, graphQLIntrospectionSchemaWithImplicitTypes.QueryType.Name); } break; case GraphQLOperationType.Mutation: if (graphQLIntrospectionSchemaWithImplicitTypes.MutationType != null) { type = GetTypeByName(graphQLIntrospectionSchemaWithImplicitTypes, graphQLIntrospectionSchemaWithImplicitTypes.MutationType.Name); } break; case GraphQLOperationType.Subscription: if (graphQLIntrospectionSchemaWithImplicitTypes.SubscriptionType != null) { type = GetTypeByName(graphQLIntrospectionSchemaWithImplicitTypes, graphQLIntrospectionSchemaWithImplicitTypes.SubscriptionType.Name); } break; default: throw new ArgumentOutOfRangeException(nameof(operationType), $"Operationtype {operationType} is not supported"); } if (type == null) { return(new List <ValidationError> { new ValidationError(ValidationType.Operation_Type_Not_Found, operationType) }); } return(ValidateSelectionSet(graphQLIntrospectionSchemaWithImplicitTypes, selectionSet, type, operationType, rootLevel: true)); }
private Task <GraphQLDataResult <T> > ExecuteQuery <T>(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, IDictionary <string, string> headers, Expression <Func <T, T> > filter, string authorizationMethod, string authorizationToken, CancellationToken cancellationToken) where T : class { var query = GetGraphQLQuery <T>(operationType, selectionSet, arguments, url, httpMethod, headers, GetQueryFilter <T>(filter), authorizationToken: authorizationToken, authorizationMethod: authorizationMethod); return(query.ExecuteDetailed(cancellationToken)); }
private async Task <T> Execute <T>(GraphQLOperationType operationType, IEnumerable <GraphQLField> selectionSet, GraphQLQueryArgument[] arguments, string url, HttpMethod httpMethod, IDictionary <string, string> headers, Expression <Func <T, T> > filter, string authorizationMethod, string authorizationToken, CancellationToken cancellationToken) where T : class { var result = await ExecuteQuery <T>(operationType, selectionSet, arguments, url, httpMethod, headers, filter, authorizationMethod : authorizationMethod, authorizationToken : authorizationToken, cancellationToken : cancellationToken).ConfigureAwait(false); return(result.Data); }
/// <inheritdoc /> public IGraphQLBatch CreateBatch(GraphQLOperationType operationType, string url = null, HttpMethod httpMethod = null, IDictionary <string, string> headers = null, string authorizationToken = null, string authorizationMethod = "Bearer") { return(new GraphQLBatch(operationType, url, httpMethod, headers, authorizationToken: authorizationToken, authorizationMethod: authorizationMethod, HttpExecutor, FieldBuilder, QueryGenerator, Deserialization)); }
private static IEnumerable <ValidationError> ValidateSelectionSet(GraphQLIntrospectionSchema graphQLIntrospectionSchema, IEnumerable <GraphQLField> selectionSet, GraphQLIntrospectionFullType graphQLIntrospectionType, GraphQLOperationType operationType, string fieldPath = null, bool rootLevel = false) { foreach (var selection in selectionSet) { // Get fieldPath var selectionFieldPath = fieldPath == null ? selection.Field : string.Join(".", fieldPath, selection.Field); // Get field from introspection var introspectionField = graphQLIntrospectionType.Fields.SingleOrDefault(e => e.Name == selection.Field); if (introspectionField == null) { yield return(new ValidationError(selectionFieldPath, ValidationType.Field_Not_Found, selection)); continue; } // IsDeprecated if (introspectionField.IsDeprecated) { yield return(new ValidationError(selectionFieldPath, ValidationType.Field_Deprecated, selection)); } // Validate arguments foreach (var argument in selection.Arguments) { // Get argument path var argumentPath = $"{selectionFieldPath}({argument.ArgumentName})"; // Get argument var introspectionArgument = introspectionField.Args.SingleOrDefault(arg => arg.Name == argument.ArgumentName); if (introspectionArgument == null) { yield return(new ValidationError(selectionFieldPath, ValidationType.Argument_Not_Found, selection)); continue; } // Validate type var typeName = GetTypeName(introspectionArgument.Type); if (!string.Equals(typeName, argument.ArgumentType, StringComparison.OrdinalIgnoreCase)) { yield return(new ValidationError(selectionFieldPath, ValidationType.Argument_Invalid_Type, selection, introspectionArgument.Type.Name, argument.ArgumentType)); } } // Switch on type kind (ignore __typename since union can only have __typename as selectionSet) var hasSelectionSet = selection.SelectionSet.Any(f => f.Field != "__typename"); // Get concrete type GraphQLIntrospectionFullType graphQLType = GetSubtype(graphQLIntrospectionSchema, introspectionField.Type); // Get kind switch (graphQLType.Kind) { case GraphQLTypeKind.Scalar: case GraphQLTypeKind.Union: case GraphQLTypeKind.Enum: // If Scalar/Union/Enum we cannot have selectionSet if (hasSelectionSet) { yield return(new ValidationError(selectionFieldPath, ValidationType.Field_Cannot_Have_SelectionSet, selection)); } break; case GraphQLTypeKind.Object: case GraphQLTypeKind.Interface: // Object/Interface should have selectionSet if (!hasSelectionSet) { yield return(new ValidationError(selectionFieldPath, ValidationType.Field_Should_Have_SelectionSet, selection)); } break; default: // Report error throw new NotImplementedException($"{nameof(GraphQLTypeKind)} {introspectionField.Type.Kind} not implemented for fields"); } // TODO: Validation should also validate type is correct for instance if GraphQLString is having the type String // Validate type if (selection.BaseType != null) { if (graphQLType.Kind == GraphQLTypeKind.Enum || graphQLType.Kind == GraphQLTypeKind.Scalar) { foreach (var error in ValidateNonNullScalar(selectionFieldPath, selection, IsListType(introspectionField.Type), IsNonNull(introspectionField.Type), graphQLType)) { yield return(error); } } switch (graphQLType.Kind) { case GraphQLTypeKind.Enum: foreach (var error in ValidateEnum(selectionFieldPath, selection, IsListType(introspectionField.Type), IsNonNull(introspectionField.Type), graphQLType)) { yield return(error); } break; case GraphQLTypeKind.Scalar: foreach (var error in ValidateScalar(selectionFieldPath, selection, IsListType(introspectionField.Type), IsNonNull(introspectionField.Type), graphQLType)) { yield return(error); } break; } } // Validate selectionSet if (hasSelectionSet) { // Validate selectionSet foreach (var result in ValidateSelectionSet(graphQLIntrospectionSchema, selection.SelectionSet, graphQLType, operationType, selectionFieldPath)) { yield return(result); } // Validate possible types foreach (var possibleType in selection.TargetTypes) { // Get fieldPath for possible type var possibleTypeFieldPath = $"{selectionFieldPath}[{possibleType.Key}]"; // Get type var introspectionPossibleType = GetTypeByName(graphQLIntrospectionSchema, possibleType.Key); if (introspectionPossibleType == null) { yield return(new ValidationError(possibleTypeFieldPath, ValidationType.PossibleType_Not_Found, selection)); continue; } // Validate selectionSet foreach (var result in ValidateSelectionSet(graphQLIntrospectionSchema, possibleType.Value.SelectionSet, introspectionPossibleType, operationType, possibleTypeFieldPath)) { yield return(result); } } } } }
private static IEnumerable <ValidationError> ValidateGraphQLType <T>(this GraphQLIntrospectionSchema graphQLIntrospectionSchema, GraphQLOperationType operationType, IGraphQLFieldBuilder fieldBuilder) { if (fieldBuilder is null) { throw new ArgumentNullException(nameof(fieldBuilder)); } var validator = new GraphQLValidation(); return(validator.ValidateGraphQLSelectionSet(graphQLIntrospectionSchema, operationType, fieldBuilder.GenerateSelectionSet(typeof(T)))); }
public static IQueryOperationBuilder <T> ForSchema <T>(GraphQLOperationType type, string name) where T : class { return(new QueryOperationBuilder <T>(type, name)); }
public When_Adding_A_Scalar_Collection_Field(GraphQLOperationType operationType) : base(operationType) { }
/// <summary> /// Validate if the GraphQL query type <typeparamref name="T"/> is valid for the specified <paramref name="graphQLIntrospectionQuery"/> and <paramref name="operationType"/> /// </summary> /// <typeparam name="T">The GraphQL query type to validate against</typeparam> /// <param name="graphQLIntrospectionQuery">The introspectionSchema to validate against</param> /// <param name="operationType">The operationType to validate against</param> /// <returns>An empty list if no errors were found or a <see cref="ValidationError"/> for each error found</returns> public static IEnumerable <ValidationError> ValidateGraphQLType <T>(this GraphQLIntrospectionQuery graphQLIntrospectionQuery, GraphQLOperationType operationType) { if (graphQLIntrospectionQuery is null) { throw new ArgumentNullException(nameof(graphQLIntrospectionQuery)); } return(ValidateGraphQLType <T>(graphQLIntrospectionQuery.Schema, operationType)); }