예제 #1
0
        /// <summary>
        /// Add required services for GraphQL data loader support
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IGraphQLBuilder AddDataLoader(this IGraphQLBuilder builder)
        {
            builder.Services.TryAddSingleton <IDataLoaderContextAccessor, DataLoaderContextAccessor>();
            builder.Services.AddSingleton <IDocumentExecutionListener, DataLoaderDocumentListener>();

            return(builder);
        }
        private static void WithPayload(this IGraphQLBuilder builder, Func <string> payloadFactory, PayloadType payloadType)
        {
            builder.Advanced.WithConfiguration(innerBuilder =>
            {
                if (payloadFactory == null)
                {
                    throw new ArgumentNullException(nameof(payloadFactory));
                }

                innerBuilder.WithContentEncoding(Encoding.UTF8);
                innerBuilder.WithMediaType("application/json");

                innerBuilder.WithConfiguration(s =>
                {
                    s.WithDefiniteContentType(typeof(GraphQLPayload));

                    s.ContentFactory = () =>
                    {
                        var payload = (payloadFactory() ?? string.Empty).Trim().Replace(Environment.NewLine, "\n").Replace("\t", " ");

                        return(new GraphQLPayload
                        {
                            Query = payload,
                            Variables = s.Items[RelayVariablesKey] as IDictionary <string, object>
                        });
                    };
                });
            });
        }
        /// <summary>
        /// Set up a delegate to create the UserContext for each GraphQL request
        /// </summary>
        /// <typeparam name="TUserContext"></typeparam>
        /// <param name="builder">The GraphQL builder.</param>
        /// <param name="creator">A delegate used to create the user context from the <see cref="HttpContext"/>.</param>
        /// <returns>The GraphQL builder.</returns>
        public static IGraphQLBuilder AddUserContextBuilder <TUserContext>(this IGraphQLBuilder builder, Func <HttpContext, Task <TUserContext> > creator)
            where TUserContext : class, IDictionary <string, object>
        {
            builder.Services.AddSingleton <IUserContextBuilder>(new UserContextBuilder <TUserContext>(creator));

            return(builder);
        }
        public static IGraphQLBuilder AddEntityGraphQueryResolver(this IGraphQLBuilder builder)
        {
            #region ComparisonExpression
            builder.Services.AddSingleton <IComparisonExpressionBuilder, EqualComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, GreaterThanComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, GreaterThanOrEqualComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, LessThanComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, LessThanOrEqualComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, IsNullComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, NotEqualComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, PrefixLikeComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, LikeComparisonExpressionBuilder>();
            builder.Services.AddSingleton <IComparisonExpressionBuilder, SuffixLikeComparisonExpressionBuilder>();

            builder.Services.TryAddSingleton <IComparisonExpressionFactory, ComparisonExpressionFactory>();
            #endregion

            builder.Services.AddSingleton <IEntityGraphQueryMiddlewareBuilder, LimitGraphQueryMiddlewareBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryMiddlewareBuilder, OffsetGraphQueryMiddlewareBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryMiddlewareBuilder, OrderByGraphQueryMiddlewareBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryMiddlewareBuilder, PredicateGraphQueryMiddlewareBuilder>();

            builder.Services.TryAddScoped <IEntityGraphQueryBuilderFactory, EntityGraphQueryBuilderFactory>();
            builder.Services.TryAddScoped <IEntityGraphQueryResolver, EntityGraphQueryResolver>();

            return(builder);
        }
        /// <summary>
        /// Scans the specified assembly for classes that implement <see cref="IDIObjectGraphBase{TSource}"/> and
        /// registers clr type mappings on the schema between that <see cref="DIObjectGraphType{TDIGraph, TSource}"/>
        /// (constructed from that class and its source type), and the source type.
        /// Skips classes where the source type is <see cref="object"/>, or where the class is marked with
        /// the <see cref="DoNotMapClrTypeAttribute"/>, or where another graph type would be automatically mapped
        /// to the specified type, or where a graph type has already been registered to the specified clr type.
        /// </summary>
        public static IGraphQLBuilder AddDIClrTypeMappings(this IGraphQLBuilder builder, Assembly assembly)
        {
            var typesAlreadyMapped = new HashSet <Type>(
                assembly.GetDefaultClrTypeMappings()
                .Where(x => x.GraphType.IsOutputType())
                .Select(x => x.ClrType));

            var types = assembly.GetTypes()
                        .Where(x => x.IsClass && !x.IsAbstract && typeof(IDIObjectGraphBase).IsAssignableFrom(x))
                        .Select <Type, (Type DIGraphType, Type?SourceType)>(x => {
                var iface = x.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDIObjectGraphBase <>));
                return(x, iface?.GetGenericArguments()[0]);
            })
                        .Where(x => x.SourceType != null && x.SourceType != typeof(object) && !x.DIGraphType.IsDefined(typeof(DoNotMapClrTypeAttribute)) && !typesAlreadyMapped.Contains(x.SourceType))
                        .Select <(Type DIGraphType, Type?SourceType), (Type ClrType, Type GraphType)>(x => (x.SourceType !, typeof(DIObjectGraphType <,>).MakeGenericType(x.DIGraphType, x.SourceType !)))
                        .ToList();

            if (types.Count == 0)
            {
                return(builder);
            }

            builder.ConfigureSchema(schema => {
                var existingMappings = new HashSet <Type>(schema.TypeMappings.Where(x => x.graphType.IsOutputType()).Select(x => x.clrType));
                foreach (var type in types)
                {
                    if (!existingMappings.Contains(type.ClrType))
                    {
                        schema.RegisterTypeMapping(type.ClrType, type.GraphType);
                    }
                }
            });

            return(builder);
        }
        public static IGraphQLBuilder AddLibplanetExplorer <T>(this IGraphQLBuilder builder)
            where T : IAction, new()
        {
            builder.Services.AddLibplanetExplorer <T>();

            return(builder);
        }
예제 #7
0
        /// <summary>
        /// Adds the GraphQL authorization.
        /// </summary>
        /// <param name="builder">The GraphQL builder.</param>
        /// <param name="options">An action delegate to configure the provided <see cref="AuthorizationOptions"/>.</param>
        /// <returns>Reference to the passed <paramref name="builder"/>.</returns>
        public static IGraphQLBuilder AddGraphQLAuthorization(this IGraphQLBuilder builder, Action <AuthorizationOptions> options)
        {
            builder.Services
            .AddHttpContextAccessor()
            .AddTransient <IValidationRule, AuthorizationValidationRule>()
#if NETCOREAPP3_0
            .AddAuthorizationCore(options);
 /// <summary>
 /// Registers <see cref="AutoInputObjectGraphType{TSourceType}"/>, <see cref="DIObjectGraphType{TDIGraph}"/> and
 /// <see cref="DIObjectGraphType{TDIGraph, TSource}"/> as generic types.
 /// </summary>
 public static IGraphQLBuilder AddDIGraphTypes(this IGraphQLBuilder builder)
 {
     builder.TryRegister(typeof(AutoInputObjectGraphType <>), typeof(AutoInputObjectGraphType <>), ServiceLifetime.Transient);
     builder.TryRegister(typeof(DIObjectGraphType <>), typeof(DIObjectGraphType <>), ServiceLifetime.Transient);
     builder.TryRegister(typeof(DIObjectGraphType <,>), typeof(DIObjectGraphType <,>), ServiceLifetime.Transient);
     return(builder);
 }
        /// <summary>
        /// Adds an <see cref="IUserContextBuilder"/> as a singleton.
        /// </summary>
        /// <typeparam name="TUserContextBuilder">The type of the <see cref="IUserContextBuilder"/> implementation.</typeparam>
        /// <param name="builder">The GraphQL builder.</param>
        /// <returns>The GraphQL builder.</returns>
        public static IGraphQLBuilder AddUserContextBuilder <TUserContextBuilder>(this IGraphQLBuilder builder)
            where TUserContextBuilder : class, IUserContextBuilder
        {
            builder.Services.AddSingleton <IUserContextBuilder, TUserContextBuilder>();

            return(builder);
        }
 /// <inheritdoc cref="AddAutomaticPersistedQueries(IGraphQLBuilder, Action{AutomaticPersistedQueriesCacheOptions})"/>
 public static IGraphQLBuilder AddAutomaticPersistedQueries(this IGraphQLBuilder builder, Action <AutomaticPersistedQueriesCacheOptions, IServiceProvider>?action)
 {
     builder.Services
     .Configure(action)
     .TryRegister <IConfigureExecution, AutomaticPersistedQueriesExecution>(ServiceLifetime.Singleton, RegistrationCompareMode.ServiceTypeAndImplementationType);
     return(builder);
 }
 public static IGraphQLBuilder AddWebSocketsHttpMiddleware <TSchema, TMiddleware>(this IGraphQLBuilder builder)
     where TSchema : ISchema
     where TMiddleware : GraphQLWebSocketsMiddleware <TSchema>
 {
     builder.Services.Register <TMiddleware, TMiddleware>(ServiceLifetime.Singleton);
     return(builder);
 }
        /// <summary>
        /// Set up a delegate to create the UserContext for each GraphQL request
        /// </summary>
        /// <typeparam name="TUserContext"></typeparam>
        /// <param name="builder"></param>
        /// <param name="creator"></param>
        /// <returns></returns>
        public static IGraphQLBuilder AddUserContextBuilder <TUserContext>(this IGraphQLBuilder builder, Func <HttpContext, TUserContext> creator)
            where TUserContext : class
        {
            builder.Services.AddSingleton <IUserContextBuilder>(new UserContextBuilder <TUserContext>(creator));

            return(builder);
        }
예제 #13
0
        public static IGraphQLBuilder AddSelfActivatingSchema <TSchema>(this IGraphQLBuilder builder, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton)
            where TSchema : class, ISchema
        {
            if (serviceLifetime == ServiceLifetime.Transient && typeof(IDisposable).IsAssignableFrom(typeof(TSchema)))
            {
                // This scenario can cause a memory leak if the schema is requested from the root service provider.
                // If it was requested from a scoped provider, then there is no reason to register it as transient.
                // See following link:
                // https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#disposable-transient-services-captured-by-container
                throw new InvalidOperationException("A schema that implements IDisposable should not be registered as a transient service. " +
                                                    "See https://docs.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#disposable-transient-services-captured-by-container");
            }

            // Register the service with the DI provider as TSchema, overwriting any existing registration
            builder.Register(provider =>
            {
                var selfActivatingServices = new SelfActivatingServiceProvider(provider);
                var schema = ActivatorUtilities.CreateInstance <TSchema>(selfActivatingServices);
                return(schema);
            }, serviceLifetime);

            // Now register the service as ISchema if not already registered.
            builder.TryRegister <ISchema>(provider =>
            {
                var selfActivatingServices = new SelfActivatingServiceProvider(provider);
                var schema = ActivatorUtilities.CreateInstance <TSchema>(selfActivatingServices);
                return(schema);
            }, serviceLifetime);

            return(builder);
        }
예제 #14
0
        public GenericType(IGraphQLBuilder builder = null)
        {
            try
            {
                var typedClass = typeof(T);
                var props      = typedClass.GetProperties();
                foreach (var prop in props)
                {
                    Type propGraphQLType = null;

                    propGraphQLType = prop.PropertyType.TryConvertToGraphQLType();

                    if (propGraphQLType != null && GraphQLExtensions.IsExtendedGraphQLType(propGraphQLType))
                    {
                        var resolvedType = propGraphQLType;
                        builder
                        .GetType()
                        .GetInterface("IGraphQLBuilder")
                        .GetMethod("Type")
                        .MakeGenericMethod(resolvedType)
                        .Invoke(builder, null);
                    }
                    else if (propGraphQLType is null)
                    {
                        var resolvedType = propGraphQLType ?? prop.PropertyType;

                        builder
                        .GetType()
                        .GetInterface("IGraphQLBuilder")
                        .GetMethod("Type")
                        .MakeGenericMethod(resolvedType)
                        .Invoke(builder, null);

                        propGraphQLType = typeof(GenericType <>).MakeGenericType(resolvedType);

                        if (propGraphQLType is null)
                        {
                            throw new InvalidCastException(
                                      $"{prop.Name} was not automatically convertible into a GraphQL type. " +
                                      $"Try explicitly adding this Type through the GraphQL-Core middleware.");
                        }

                        propGraphQLType = GraphQLCoreTypeWrapperGenerator.GetDerivedGenericUserType(propGraphQLType);

                        if (propGraphQLType is null)
                        {
                            throw new NotSupportedException(
                                      $"{prop.Name} is a custom type but was not registered through builder. " +
                                      $"Try explicitly adding this Type through the Graph-Core middleware");
                        }
                    }

                    Field(propGraphQLType, prop.Name);
                }
            }
            catch (Exception e)
            {
                throw new GraphQLCoreTypeException($"An attempt to create a generic type for type {nameof(T)} failed. Refer to inner exception for details", e);
            }
        }
    /// <summary>
    /// Add required services for GraphQL web sockets
    /// </summary>
    public static IGraphQLBuilder AddWebSockets(this IGraphQLBuilder builder)
    {
        builder.Services
        .Register(typeof(IWebSocketConnectionFactory <>), typeof(WebSocketConnectionFactory <>), ServiceLifetime.Transient)
        .Register <IOperationMessageListener, LogMessagesListener>(ServiceLifetime.Transient)
        .Register <IOperationMessageListener, ProtocolMessageListener>(ServiceLifetime.Transient);

        return(builder);
    }
        /// <summary>
        /// Adds a <see cref="IGraphQLRequestDeserializer"/> and a <see cref="IDocumentWriter"/>
        /// to the service collection with the provided configuration/settings.
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configureDeserializerSettings">
        /// Action to further configure the request deserializer's settings.
        /// Affects reading of the JSON from the HTTP request the middleware processes.
        /// </param>
        /// <param name="configureSerializerSettings">
        /// Action to further configure the response serializer's settings.
        /// Affects JSON returned by the middleware.
        /// </param>
        /// <returns>GraphQL Builder.</returns>
        public static IGraphQLBuilder AddNewtonsoftJson(this IGraphQLBuilder builder,
                                                        Action <JsonSerializerSettings> configureDeserializerSettings = null,
                                                        Action <JsonSerializerSettings> configureSerializerSettings   = null)
        {
            builder.Services.AddSingleton <IGraphQLRequestDeserializer>(p => new GraphQLRequestDeserializer(configureDeserializerSettings ?? (_ => { })));
            builder.Services.Replace(ServiceDescriptor.Singleton <IDocumentWriter>(p => new DocumentWriter(configureSerializerSettings ?? (_ => { }), p.GetService <IErrorInfoProvider>() ?? new ErrorInfoProvider())));

            return(builder);
        }
        /// <summary>
        /// Add required services for GraphQL web sockets
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IGraphQLBuilder AddWebSockets(this IGraphQLBuilder builder)
        {
            builder.Services
            .AddTransient(typeof(IWebSocketConnectionFactory <>), typeof(WebSocketConnectionFactory <>))
            .AddTransient <IOperationMessageListener, LogMessagesListener>()
            .AddTransient <IOperationMessageListener, ProtocolMessageListener>();

            return(builder);
        }
예제 #18
0
        /// <summary>
        /// Provides the ability to configure <see cref="ErrorInfoProviderOptions"/> for the default <see cref="ErrorInfoProvider"/>.
        /// Also provides integration with Microsoft.Extensions.Options so the caller may use services.Configure{ErrorInfoProviderOptions}(...)
        /// </summary>
        /// <param name="builder">GraphQL builder used for GraphQL specific extension methods as 'this' argument.</param>
        /// <param name="configureOptions">Action to configure the <see cref="ErrorInfoProviderOptions"/>.</param>
        /// <returns>Reference to <paramref name="builder"/>.</returns>
        public static IGraphQLBuilder AddErrorInfoProvider(this IGraphQLBuilder builder, Action <ErrorInfoProviderOptions> configureOptions)
        {
            if (configureOptions == null)
            {
                throw new ArgumentNullException(nameof(configureOptions));
            }

            return(builder.AddErrorInfoProvider((opt, _) => configureOptions(opt)));
        }
예제 #19
0
 /// <summary>
 /// Adds the GraphQL Relay types <see cref="ConnectionType<>"/>, <see cref="EdgeType<>"/>
 /// and <see cref="PageInfoType"/>.
 /// </summary>
 /// <param name="builder">The application builder.</param>
 /// <returns>The application builder.</returns>
 public static IGraphQLBuilder AddRelayGraphTypes(this IGraphQLBuilder builder)
 {
     builder
     .Services
     .AddSingleton(typeof(ConnectionType <>))
     .AddSingleton(typeof(EdgeType <>))
     .AddSingleton <PageInfoType>();
     return(builder);
 }
예제 #20
0
 /// <summary>
 /// Adds the GraphQL authorization.
 /// </summary>
 /// <param name="builder">The GraphQL builder.</param>
 /// <param name="options">An action delegate to configure the provided <see cref="AuthorizationOptions"/>.</param>
 /// <returns>The GraphQL builder.</returns>
 public static IGraphQLBuilder AddGraphQLAuthorization(this IGraphQLBuilder builder, Action <AuthorizationOptions> options)
 {
     builder.Services.TryAddSingleton <IHttpContextAccessor, HttpContextAccessor>();
     builder
     .Services
     .AddTransient <IValidationRule, AuthorizationValidationRule>()
     .AddAuthorization(options);
     return(builder);
 }
        public static IServiceCollection AddXCMS(this IServiceCollection services, IGraphQLBuilder graphQlbuilder)
        {
            graphQlbuilder.AddGraphTypes(typeof(XCMSAnchor));

            services.AddSchemaBuilder <ContentSchema>();

            services.AddMediatR(typeof(ContentSchema));

            return(services);
        }
        public static TBuilder WithVariable <TBuilder>(this IGraphQLBuilder builder, string name, object value)
            where TBuilder : IGraphQLBuilder
        {
            builder.CreateAndApplyVariables(variables =>
            {
                variables[name] = value;
            });

            return((TBuilder)builder);
        }
예제 #23
0
        public static IGraphQLBuilder AddPolicyValidation(this IGraphQLBuilder builder)
        {
            builder.Services
            .AddHttpContextAccessor()
            .AddTransient <IOperationMessageListener, SubscriptionPrincipalInitializer>()
            .AddTransient <IValidationRule, PolicyValidationRule>()
            .AddAuthorizationCore();

            return(builder);
        }
        /// <summary>
        /// Adds the GraphQL authorization.
        /// </summary>
        /// <param name="builder">The GraphQL builder.</param>
        /// <param name="options">An action delegate to configure the provided <see cref="AuthorizationOptions"/>.</param>
        /// <returns>Reference to the passed <paramref name="builder"/>.</returns>
        public static IGraphQLBuilder AddGraphQLAuthorization(this IGraphQLBuilder builder, Action <AuthorizationOptions> options)
        {
            builder.Services.TryAddTransient <IClaimsPrincipalAccessor, DefaultClaimsPrincipalAccessor>();
            builder.Services
            .AddHttpContextAccessor()
            .AddTransient <IValidationRule, AuthorizationValidationRule>()
            .AddAuthorizationCore(options);

            return(builder);
        }
예제 #25
0
        /// <summary>
        /// Add all types that implement <seealso cref="IGraphType"/> in the specified assembly
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assembly"></param>
        /// <returns></returns>
        public static IGraphQLBuilder AddGraphTypes(this IGraphQLBuilder builder, Assembly assembly)
        {
            // Register all GraphQL types
            foreach (var type in assembly.GetTypes()
                     .Where(x => !x.IsAbstract && typeof(IGraphType).IsAssignableFrom(x)))
            {
                builder.Services.TryAddTransient(type);
            }

            return(builder);
        }
        public static IGraphQLBuilder AddSquidexWriter(this IGraphQLBuilder builder)
        {
            builder.Services.AddSingleton <IDocumentWriter>(c =>
            {
                var serializer = new NewtonsoftJsonSerializer(ConfigureJson(TypeNameHandling.None));

                return(new DefaultDocumentWriter(serializer));
            });

            return(builder);
        }
        public static IGraphQLBuilder AddEntityGraphQueryTypes(this IGraphQLBuilder builder)
        {
            builder.Services.TryAddSingleton <OrderBy_Type>();
            builder.Services.TryAddSingleton <IntComparisonExpr_Type>();
            builder.Services.TryAddSingleton <LongComparisonExpr_Type>();
            builder.Services.TryAddSingleton <StringComparisonExpr_Type>();
            builder.Services.TryAddSingleton <DecimalComparisonExpr_Type>();
            builder.Services.TryAddSingleton <DateTimeComparisonExpr_Type>();

            return(builder);
        }
        public static IGraphQLBuilder AddEntityGraphQueryArguments(this IGraphQLBuilder builder)
        {
            builder.Services.AddSingleton <IEntityGraphQueryArgumentBuilder, LimitGraphQueryArgumentBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryArgumentBuilder, OffsetGraphQueryArgumentBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryArgumentBuilder, OrderByGraphQueryArgumentBuilder>();
            builder.Services.AddSingleton <IEntityGraphQueryArgumentBuilder, PredicateGraphQueryArgumentBuilder>();

            builder.Services.TryAddSingleton <IEntityGraphQueryArgumentsBuilder, EntityGraphQueryArgumentsBuilder>();

            return(builder);
        }
        public static IGraphQLBuilder AddEntityGraphQuery(this IGraphQLBuilder builder)
        {
            builder.Services.TryAddSingleton <IEntityGraphTypeBuilder, EntityGraphTypeBuilder>();

            builder.AddEntityGraphQueryTypes();

            builder.AddEntityGraphQueryArguments();

            builder.AddEntityGraphQueryResolver();

            return(builder);
        }
예제 #30
0
        public static IGraphQLBuilder AddGraphResolvers(this IGraphQLBuilder builder, Assembly assembly)
        {
            var types = assembly.GetTypes()
                        .Where(type => !type.IsAbstract &&
                               typeof(IDocumentIOResolver).IsAssignableFrom(type));

            foreach (var type in types)
            {
                builder.Services.Add(ServiceDescriptor.Scoped(type, type));
            }

            return(builder);
        }