Michel Floyd
Michel Floyd

Reputation: 20226

How do I make a remote executable schema from the github graphql api?

Here's the situation, I'm trying to stitch the GitHub graphql schema with an application's local schema. The application uses GitHub oAuth to connect the user to their GitHub data.

Most of the write-ups on schema stitching use an introspection query to get the remote server's schema. Unfortunately, the GitHub graphql api is authenticated with an access token. My original intent was to use the user's oAuth access token to perform the introspection but then I ran into a catch-22 wherein the introspection needs to happen at startup, i.e. before I have any authenticated users.

So the basic question is: How do I make a remote executable schema from the github graphql api?

Upvotes: 0

Views: 789

Answers (1)

Michel Floyd
Michel Floyd

Reputation: 20226

Further reading on the subject revealed that a better pattern is to statically download the remote server's schema and then make a remote executable from it.

First you'll need to install the apollo cli:

$ npm install -g apollo

Then use it to download the GitHub schema:

$ apollo schema:download --header "Authorization: Bearer token"
  --endpoint=https://api.github.com/graphql github.json

where token is an unquoted string containing an access token to GitHub (I just used an oAuth token from my own account). As of this writing this json is 47112 lines long when prettied.

You can put this file anywhere in your app that you can import from. For example in the same directory as the code that will make a schema from it which follows here:

Code Imports:

import { HttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { makeRemoteExecutableSchema } from 'apollo-server';
import { printSchema, buildClientSchema } from 'graphql/utilities';
import fetch from 'node-fetch';

Import the actual schema

Note that you can access parts of the json file directly via object destructuring

import { __schema } from './github.json';

Build the client schema and typeDefs

Trust me, you need both of these. And yes, you're still going to use this on the server even though it says buildClient (your server is going to end up being a client of GitHub's server)

const schema = buildClientSchema({ __schema });
const typeDefs = printSchema(schema);

Setup the link

This will be used for actual queries. In this example I'm carrying the user and his/her accessToken in the link context which will come from elsewhere.

const http = new HttpLink({ uri: 'https://api.github.com/graphql', fetch });
const link = setContext((request, previousContext) => {
  const { user } = previousContext;
  const { accessToken } = user;
  return { headers: { Authorization: `Bearer ${accessToken}` } };
}).concat(http);

Finally, make the remote executable schema

const ghSchema = makeRemoteExecutableSchema({
  schema,
  typeDefs,
  link,
});

export default ghSchema;

ghSchema will be an instance of a GraphQLSchema which you can now use directly or stitch to other schemas using mergeSchemas

h/t to bessey for his comment on an Apollo feature request which finally got me to bright.

Upvotes: 2

Related Questions