Пример #1
0
        /// <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));
        }
Пример #2
0
 // 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));
 }
Пример #3
0
 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}'.")
     });
Пример #4
0
        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?
            }
        }
Пример #5
0
        /// <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");
        }
Пример #6
0
        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);
        }
Пример #7
0
 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;
 }
Пример #8
0
        /// <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));
        }
Пример #9
0
        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);
        }
Пример #11
0
 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[]>();
 }
Пример #12
0
 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)
 {
 }
Пример #13
0
 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);
        }
Пример #16
0
 /// <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);
        }
Пример #20
0
 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()));
 }
Пример #22
0
        /// <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));
        }
Пример #23
0
        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));
        }
Пример #24
0
        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);
        }
Пример #25
0
 /// <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));
 }
Пример #26
0
        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));
        }