2

Apollo graphql-tools now have Schema Stitching, which is great. I want to merge multiple endpoints to generate a schema similar to GraphQL Hub, like this:

query { github: { ... } # GitHub Schema twitter: { ... } # Twitter Schema myOwnGraphqlSchema: { ... } }

How is the best approach to do that?

GitHub issue: https://github.com/apollographql/graphql-tools/issues/439

Fork here for testing: https://launchpad.graphql.com/3xlrn31pv

Thank you.

Bruno Lemos
  • 8,847
  • 5
  • 40
  • 51

2 Answers2

6

EDIT: I believe this is now possible with the new graphql-tools 3.0!

https://dev-blog.apollodata.com/the-next-generation-of-schema-stitching-2716b3b259c0


Original answer:

Here is a solution (hack?) I came up with, but probably there are better ways to do it:

  1. Get the remote schema by using introspectSchema and makeRemoteExecutableSchema
  2. Get the schema type defs by using printSchema
  3. Rename the root typedefs Query and Mutation received by printSchema to something else, e.g. GitHubQuery and GitHubMutation
  4. Create the root Query typedef with a github field with the type GitHubQuery
  5. Create a github resolver that uses the execute method to run the GitHubQuery in the remote github schema

Source code: https://launchpad.graphql.com/3xlrn31pv

import 'apollo-link'
import fetch from 'node-fetch'
import {
  introspectSchema,
  makeExecutableSchema,
  makeRemoteExecutableSchema,
} from 'graphql-tools'
import { HttpLink } from 'apollo-link-http'
import { execute, printSchema } from 'graphql'

const link = new HttpLink({ uri: 'http://api.githunt.com/graphql', fetch })

async function getGithubRemoteSchema() {
  return makeRemoteExecutableSchema({
    schema: await introspectSchema(link),
    link,
  })
}

async function makeSchema() {
  const githubSchema = await getGithubRemoteSchema()
  const githubTypeDefs = printSchema(githubSchema)

  const typeDefs = `
        ${githubTypeDefs // ugly hack #1
      .replace('type Query', 'type GitHubQuery')
      .replace('type Mutation', 'type GitHubMutation')}

    type Query {
      github: GitHubQuery
    }

    type Mutation {
      github: GitHubMutation
    }
    `

  return makeExecutableSchema({
    typeDefs,
    resolvers: {
      Query: {
        async github(parent, args, context, info) {
          // TODO: FIX THIS

          // ugly hack #2
          // remove github root field from query
          const operation = {
            ...info.operation,
            selectionSet:
              info.operation.selectionSet.selections[0].selectionSet,
          }
          const doc = { kind: 'Document', definitions: [operation] }

          const result = await execute(
            githubSchema,
            doc,
            info.rootValue,
            context,
            info.variableValues,
            info.operation.name
          )

          return (result || {}).data
        },
      },
    },
  })
}

export const schema = makeSchema()
Bruno Lemos
  • 8,847
  • 5
  • 40
  • 51
0

Supported directly in graphql-tools-fork (https://www.npmjs.com/package/graphql-tools-fork) using the WrapType transform.

See https://github.com/yaacovCR/graphql-tools-fork/issues/24

Yaacov
  • 185
  • 4