Graphql-tools: `onTypeConflict` not working as expected

Created on 21 Nov 2017  路  5Comments  路  Source: ardatan/graphql-tools

I'm trying to use onTypeConflict to determine which resolver should be called when merging two schemas with mergeSchemas, but the result always seems to be the same.

Here is my code:

const { makeExecutableSchema, mergeSchemas } = require('graphql-tools')
const { GraphQLSchema, graphql } = require('graphql')

const makeSchemaA = () => {
  const typeDefs = `
  type Query {
    greeting: Greeting
  }

  type Greeting {
    text: String
  }`

  const resolvers = {
    Query: {
      greeting: () => ({text: null})
    },
    Greeting: {
      text: () => 'Hello'
    }
  }
  return makeExecutableSchema({ typeDefs, resolvers })
}

const makeSchemaB = () => {
  const typeDefs = `
  type Query {
    greeting: Greeting
  }

  type Greeting {
    text: String
  }`

  const resolvers = {
    Query: {
      greeting: () => ({text: null})      
    },
    Greeting: {
      text: root => 'A fine day, good sir!'
    }
  }

  return makeExecutableSchema({ typeDefs, resolvers })
}

const schemaA = makeSchemaA() 
const schemaB = makeSchemaB()

const mergedSchema = mergeSchemas({
  schemas: [schemaA, schemaB],
  onTypeConflict: (left, right) => right
})

const greetingQuery = `
  {
    greeting {
      text
    }
  }`
graphql(mergedSchema, greetingQuery).then(result => {
  console.log(`Query:\n  ${greetingQuery}\nResult:\n  ${JSON.stringify(result)}`)
})

No matter whether I return left or right for onTypeConflict, the result is always the same. Is my understanding incorrect that onTypeConflict can be used to switch between the two different Greeting types from my schemas or is this a bug somewhere?

bug schema stitching

All 5 comments

Aha, I've found an issue in how resolvers are merged. Thanks a lot! I'll fix it in next version.

So what happens is - onTypeConflict is called correctly and you get the Greeting from the other type. However query fields are merged left to right, so last resolver would always take priority. This means greeting will still delegate to last schema.

I'm not sure there is an easy solution here, I don't want to make it an error, cause someone is probably overriding their root field resolvers this way already. However, we are redesigning how root types are created in https://github.com/apollographql/graphql-tools/issues/495 and it should fix this issue.

Stumbled around the same issue, here's a launchpad reproducing the bug:
https://launchpad.graphql.com/37l70x1lpv

By default, first type takes precedence but root fields are overridden left to right so you end-up with your "new" type being resolved with your "old" resolver

I understand that schema transforms should fix all issues with conflicting types, but I still think onTypeConflict is desirable

I'm currently working in a project where I want to merge, and use, schemas from 2 different apps. Both have type User declared, but since I will be authenticating only with the first app, I can ignore the type User on the second schema. I don't want to transform the second schema since it would transform all types in that schema and I only want to blacklist one type.

Is there a solution for blacklisting types without using onTypeConflict that I'm not aware of ? Thanks !

I don't want to transform the second schema since it would transform all types in that schema and I only want to blacklist one type.

You can simply remove the type, which will leave all of the other types unchanged. Is this not possible using FilterTypes?

Also, going to close this issue since we aren't going to add onTypeConflict back unless it's really needed, and would prefer to instead make the transform approach work better and easier (I agree it could be much better than it is today!)

Was this page helpful?
0 / 5 - 0 ratings