Ejemplo n.º 1
0
        public static IReadOnlyCollection <ISchemaError> Validate(
            IEnumerable <ITypeSystemObject> typeSystemObjects,
            IReadOnlySchemaOptions options)
        {
            if (typeSystemObjects is null)
            {
                throw new ArgumentNullException(nameof(typeSystemObjects));
            }

            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var types  = typeSystemObjects.ToList();
            var errors = new List <ISchemaError>();

            foreach (ISchemaValidationRule rule in _rules)
            {
                rule.Validate(types, options, errors);
            }

            return(errors);
        }
Ejemplo n.º 2
0
        public void Initialize(
            Func <ISchema> schemaResolver,
            IReadOnlySchemaOptions options)
        {
            if (schemaResolver is null)
            {
                throw new ArgumentNullException(nameof(schemaResolver));
            }

            if (options is null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            // first we are going to find and initialize all types that belong to our schema.
            var typeRegistrar = new TypeDiscoverer(
                _context,
                _typeRegistry,
                _typeLookup,
                _initialTypes,
                _interceptor);

            if (typeRegistrar.DiscoverTypes() is { Count : > 0 } errors)
            {
                throw new SchemaException(errors);
            }

            // next lets tell the type interceptors what types we have initialized.
            if (_interceptor.TriggerAggregations)
            {
                _interceptor.OnTypesInitialized(
                    _typeRegistry.Types.Select(t => t.DiscoveryContext).ToList());
            }

            // before we can start completing type names we need to register the field resolvers.
            RegisterResolvers();

            // now that we have the resolvers sorted and know what types our schema will roughly
            // consist of we are going to have a look if we can infer interface usage
            // from .NET classes that implement .NET interfaces.
            RegisterImplicitInterfaceDependencies();

            // with all types (implicit and explicit) known we complete the type names.
            CompleteNames(schemaResolver);

            // with the type names all known we can now build pairs to bring together types and
            // their type extensions.
            MergeTypeExtensions();

            // external resolvers are resolvers that are defined on the schema and are associated
            // with the types after they have received a name and the extensions are removed.
            RegisterExternalResolvers();

            // with all resolvers in place we compile the once inferred from a C# member.
            CompileResolvers();

            // last we complete the types. Completing types means that we will assign all
            // the fields resolving all missing parts and then making the types immutable.
            CompleteTypes();

            // if we do not have any errors we will validate the types for spec violations.
            if (_errors.Count == 0)
            {
                _errors.AddRange(SchemaValidator.Validate(
                                     _typeRegistry.Types.Select(t => t.Type),
                                     options));
            }

            if (_errors.Count > 0)
            {
                throw new SchemaException(_errors);
            }
        }
Ejemplo n.º 3
0
    private void CompleteResolver(
        ITypeCompletionContext context,
        ObjectFieldDefinition definition)
    {
        var isIntrospectionField = IsIntrospectionField || DeclaringType.IsIntrospectionType();
        IReadOnlyList <FieldMiddlewareDefinition> fieldMiddlewareDefinitions =
            definition.GetMiddlewareDefinitions();
        IReadOnlySchemaOptions options = context.DescriptorContext.Options;

        var skipMiddleware =
            options.FieldMiddleware != FieldMiddlewareApplication.AllFields &&
            isIntrospectionField;

        FieldResolverDelegates resolvers = CompileResolver(context, definition);

        Resolver = resolvers.Resolver;

        if (resolvers.PureResolver is not null && IsPureContext())
        {
            PureResolver = FieldMiddlewareCompiler.Compile(
                definition.GetResultConverters(),
                resolvers.PureResolver,
                skipMiddleware);
        }

        // by definition fields with pure resolvers are parallel executable.
        if (!IsParallelExecutable && PureResolver is not null)
        {
            IsParallelExecutable = true;
        }

        Middleware = FieldMiddlewareCompiler.Compile(
            context.GlobalComponents,
            fieldMiddlewareDefinitions,
            definition.GetResultConverters(),
            Resolver,
            skipMiddleware);

        if (Resolver is null && Middleware is null)
        {
            if (_executableDirectives.Length > 0)
            {
                Middleware = _ => default;
            }
            else
            {
                context.ReportError(
                    ObjectField_HasNoResolver(
                        context.Type.Name,
                        Name,
                        context.Type,
                        SyntaxNode));
            }
        }

        bool IsPureContext()
        {
            return(skipMiddleware ||
                   context.GlobalComponents.Count == 0 &&
                   fieldMiddlewareDefinitions.Count == 0 &&
                   _executableDirectives.Length == 0);
        }
    }