0

I'm trying to create a custom graphql schema to use on my graphql yoga server. The graphql yoga server is just a proxy to another graphql API from which I have managed to retrieve a schema from in JSON format. Here is a preview of what that schema looks like:

{
  "data": {
    "__schema": {
      "queryType": {
        "name": "Query"
      },
      "mutationType": null,
      "subscriptionType": null,
      "types": [
        {
          "kind": "OBJECT",
          "name": "Core",
          "description": null,
          "fields": [
            {
              "name": "_meta",
              "description": null,
              "args": [],
              "type": {
                "kind": "NON_NULL",
                "name": null,
                "ofType": {
                  "kind": "OBJECT",
                  "name": "Meta",
                  "ofType": null
                }
              },
              "isDeprecated": false,
              "deprecationReason": null
            },
            {
              "name": "_linkType",
              "description": null,
              "args": [],
              "type": {
                "kind": "SCALAR",
                "name": "String",
                "ofType": null
              },
              "isDeprecated": false,
              "deprecationReason": null
            }
          ],
          "inputFields": null,
          "interfaces": [
            { 

I now want to take this generated JSON schema and use it to create a graphql schema to use in my graphql yoga server. I believe the correct way to do this is by using the new GraphQLSchema method from graphql along with a root query. Here is my code attempting this:

schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: schema.data.__schema
  })
});

The above code gives me the following error:

Error: Query.mutationType field config must be an object

Not entirely sure where it's going wrong or if this is the proper approach to creating a graphql schema from generated JSON?

1 Answer 1

5

The JSON you have is the results of an introspection query. Unfortunately, introspection will not allow you to copy a remote schema. That's because while it does identify what fields exist in a schema, it does not tell you anything about how they should be executed. For example, based on the snippet you posted, we know the remote server exposes a _meta query that returns a Meta type -- but we don't know what code to run to resolve the value returned by the query.

Technically, it's possible to pass the results of an introspection query to buildClientSchema from the graphql/utilities module. However, the schema will not be executable, as the docs point out:

Given the result of a client running the introspection query, creates and returns a GraphQLSchema instance which can be then used with all GraphQL.js tools, but cannot be used to execute a query, as introspection does not represent the "resolver", "parse" or "serialize" functions or any other server-internal mechanisms.

If you want to create a proxy to another GraphQL endpoint, the easiest way is to use makeRemoteExecutableSchema from graphql-tools.

Here's the example based on the docs:

import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

const link = new HttpLink({ uri: 'http://your-endpoint-url/graphql', fetch });
async function getRemoteSchema () {
  const schema = await introspectSchema(link);
  return makeRemoteExecutableSchema({
    schema,
    link,
  });
}

The resulting schema is a GraphQLSchema object that can be used like normal:

import { GraphQLServer } from 'graphql-yoga'

async function startServer () {
  const schema = await introspectSchema(link);
  const executableSchema = makeRemoteExecutableSchema({
    schema,
    link,
  });
  const server = new GraphQLServer({ schema: executableSchema })
  server.start()
}

startServer()

graphql-tools also allows you to stitch schemas together if you not only wanted to proxy the existing endpoint, but wanted to add on to it as well.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your response. So presumably I should be able to just insert the schema into the graphql yoga config like so : const server = new GraphQLServer({ schema: getRemoteSchema(), context: req => ({ ...req, Prismic }) }). If so it's generating an error saying "Unexpected token < in JSON at position 0"
I should also note that getRemoteSchema is returning me something thats not an error
In the example, getRemoteSchema returns a Promise, so you can't just pass it directly to GraphQLServer's constructor. I've updated the answer with a more complete example using graphql-yoga. If you're seeing a malformed JSON error, though, that probably means your call to the external server is failing. Check your endpoint URL.
Works perfectly now, thanks for the detailed explanation!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.