Apply directives

Directives are annotations for your GraphQL schema or operations.

See also

Tanka GraphQL provides support for execution and schema directives:

  • Execution directives: Include and Skip
  • Schema directives

Currrently schema directives are only supported on fields of object types

Schema directives

Schema directives can be used to modify field for example by modifying the resolver of the field.

        public async Task Part3_ApplyDirectives_on_Object_fields()
            // Create builder, load sdl with our types
            // and bind the resolvers
            var builder = new SchemaBuilder()
                    directive @duplicate on FIELD_DEFINITION

                    type Query {
                        name: String @duplicate                
                .GetQuery(out var query)
                    new ObjectTypeMap
                            query.Name, new FieldResolversMap
                                    "name", context =>
                                        var result = Resolve.As("Test");
                                        return new ValueTask<IResolverResult>(result);

            // Apply directives to schema by providing a visitor which
            // will transform the fields with the directive into new
            // fields with the directive logic. Note that the original
            // field will be replaced.
            builder.ApplyDirectives(new Dictionary<string, CreateDirectiveVisitor>()
                ["duplicate"] = _ => new DirectiveVisitor()
                    // Visitor will visit field definitions
                    FieldDefinition = (directive, fieldDefinition) =>
                        // We will create new field definition with 
                        // new resolver. New resolver will execute the 
                        // original resolver, duplicate value and return it
                        return fieldDefinition
                            .WithResolver(resolver => 
                                resolver.Use(async (context, next) =>
                            // We need to first call the original resolver to 
                            // get the initial value
                            var result = await next(context);

                            // for simplicity we expect value to be string
                            var initialValue = result.Value.ToString();

                            // return new value
                            return Resolve.As(initialValue + initialValue);

            // Build schema
            var schema = builder.Build();

            // Get resolver for field
            var nameResolver = schema.GetResolver(schema.Query.Name, "name");

            // Execute the resolver. This is normally handled by the executor.
            var nameValue = await nameResolver(null);
            Assert.Equal("TestTest", nameValue.Value);