Graphql-tools: mergeSchemas should also merge existing directives defined the schemas.

Created on 30 Jan 2018  路  14Comments  路  Source: ardatan/graphql-tools

After calling mergeSchemas the new resulting schema would not have any defined directives. See example below.

const _                   = require('lodash')
const {DirectiveLocation} = require('graphql/type/directives');
const {mergeSchemas}      = require('graphql-tools')
const {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLDirective
} = require('graphql');



const GraphQLUpperDirective = new GraphQLDirective({
  name: 'upper',
  description: 'Converts a string frield to uppercase.',
  locations: [DirectiveLocation.FIELD],
  args: {},
});

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      hello: {
        type: GraphQLString,
        resolve(source, args, context, info) {
          const directive       = _.get(info, 'fieldNodes[0].directives[0]');

          if(_.get(directive, 'name.value') === 'upper') {
            return 'WORLD'
          }
          console.log(directive)
          return 'world';
        }
      }
    }
  }),
  directives : [GraphQLUpperDirective]
});

const schema2 = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      bye: {
        type: GraphQLString,
        resolve() {
          return 'for now';
        }
      }
    }
  }),
});


module.exports = mergeSchemas({schemas : [schema, schema2]})
schema stitching

Most helpful comment

@lfades Please do a PR, I don't see a reason why bug fix like that should not be accepted :)

All 14 comments

Added a launch pad example = https://launchpad.graphql.com/r98zrv91vn

Happy to create a PR if someone could point me to the right direction. I have tried passing the directive to the GraphQLSchema constructor with no success.

Directives that are applied to schema types, fields, etc. exist in the AST of the schema, so when you're merging two schema objects that both have @directives attached to them, I think you should look at their schemaTypeObject.astNode.directives arrays, and try to combine them into one array, maybe throwing an exception if the directives conflict. This might require a more general strategy for merging .astNode information (I'm honestly not sure if schema stitching does that already or not), but you might be able to get .astNode.directives to work without worrying about the rest.

In addition to merging the @directives on schema types, you should also make sure any directive declarations in the two schemas end up in the merged schema, though I suspect this is already happening automatically, since directive declarations are just GraphQLNamedTypes. An example would be

directive @myDirective(arg: Int = 3) on UNION | FIELD_DEFINITION | ...

The schema.getDirectives() method returns an array of these declarations. Again, this part is probably working already, but I think you'll need to look at the AST to merge the individual usages of @directive syntax.

@puttyman Any progress on this? I might want to take a shot if you haven't started. Might.

@lastmjs I did give it a try with no luck. I have tried to pass the new directives to the graphql constructor it was visible in the ast node but was still getting errors when resolving the fields.

Please give it a go and let me know your findings. Cheers.

I think I've found a way around this for my needs for now. I'm not sure I'll be giving it a go anytime soon. I'll keep you updated if I do

@puttyman @lastmjs Hi guys, is any of you working on this ? I'm building a package for auth with graphql and it exports a schema with directives, I can do the pr

I'm not working on it directly, I was able to find a potentially more elegant solution. It's described here: https://github.com/apollographql/graphql-tools/issues/673

I'm hoping mergeSchemas can work similarly some day

Ok, thank you @lastmjs for the info, I definitely think this is required so I'll see what can be done here

@lastmjs thanks for sharing. The reason mergeSchema from apollo tools was my preferred choice is because it takes in a graphql schema object.

In my case I want to merge a schema generated by library and extend it with some of my own query indexes and directives.

I already did the required changes to mergeSchema and now it's including directives, I'm a little confused about where should I put the tests.

Right now I'm thinking in adding a schema with directives here and then create a new test here that will be similar to this one

@stubailo

According to this blog post: https://dev-blog.apollodata.com/reusable-graphql-schema-directives-131fb3a177d1 I should also support the new schemaDirectives, I can do that an include tests

@benjamn Can I do a pr about this ?

@lfades Please do a PR, I don't see a reason why bug fix like that should not be accepted :)

Should this be closed now?

Closed by #1003

Was this page helpful?
0 / 5 - 0 ratings