On this page

Loading GraphQL Schemas from Different Sources

Loading GraphQL Schemas from Different Sources — GraphQL Tools documentation.

These utils are useful for scanning, loading and building a GraphQL schema from any input.

You can specify a GraphQL endpoint, local introspection JSON file, code file that exports a GraphQLSchema, AST string and .graphql files (with support for glob expression).

All found schema files can be merged into a complete schema. There is support for #import syntax (formerly known as graphql-import).

The user is given the option of implementing their own loader (implement the interface SchemaLoader).

The schema loading until is using loaders, and implemented using chain-of-responsibility pattern.

Specifying the loader is not necessary. The user needs only provide the inputs. The utils will detect it automatically.

For notes on typescript, refer to loaders

Load typeDefs/DocumentNode and resolvers from Files

const { loadFiles } = require('@graphql-tools/load-files')
const { createYoga, createSchema } = require('graphql-yoga')
const { createServer } = require('http')

async function main() {
  const schema = createSchema({
    typeDefs: await loadFiles('src/typeDefs/**/*.graphql'),
    resolvers: await loadFiles('src/resolvers/**/*.{js,ts}')
  })

  const yoga = createYoga({
    schema
  })

  const server = createServer(yoga)

  server.listen(4000, () => {
    console.log('Server is running on http://localhost:4000')
  })
}

main().catch(error => {
  console.error(error)
  process.exit(1)
})

Load GraphQLSchema by Using Different Loaders from Different Sources

const { loadSchema } = require('@graphql-tools/load')
const { UrlLoader } = require('@graphql-tools/url-loader')
const { JsonFileLoader } = require('@graphql-tools/json-file-loader')
const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader')

async function main() {
  // Load from string w/ no loaders
  const schema1 = await loadSchema('type A { foo: String }')

  // Load from endpoint
  const schema2 = await loadSchema('http://localhost:3000/graphql', { loaders: [new UrlLoader()] })

  // Load from local json file
  const schema3 = await loadSchema('./schema.json', { loaders: [new JsonFileLoader()] })

  // Load from a single schema file
  const schema4 = await loadSchema('schema.graphql', { loaders: [new GraphQLFileLoader()] })

  // Load from multiple files using glob
  const schema5 = await loadSchema('./src/**/*.graphql', { loaders: [new GraphQLFileLoader()] })
}

main()

Using #import Expression

Assume the following directory structure:

.
├── schema.graphql
├── posts.graphql
└── comments.graphql
schema.graphql
#import Post from "posts.graphql"

type Query {
  posts: [Post]
}
posts.graphql
#import Comment from 'comments.graphql'

type Post {
  comments: [Comment]
  id: ID!
  text: String!
  tags: [String]
}
comments.graphql
type Comment {
  id: ID!
  text: String!
}

Running loadSchema produces the following output:

type Query {
  posts: [Post]
}

type Post {
  comments: [Comment]
  id: ID!
  text: String!
  tags: [String]
}

type Comment {
  id: ID!
  text: String!
}

#import can also resolve npm packages (and other require.resolve specifiers) with a require: prefix, from the importing file’s directory:

# import Post, Comment from "require:blog-graphql-types/schema.graphql"
# import Shared from "require:./shared.graphql"

Binding to HTTP Server

You can extend the loaded schema with resolvers

import { createServer } from 'http'
import { join } from 'node:path'
import { createYoga } from 'graphql-yoga'
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
import { loadSchema } from '@graphql-tools/load'
import { addResolversToSchema } from '@graphql-tools/schema'

async function main() {
  // Load schema from the file
  const schema = await loadSchema(join(__dirname, './schema.graphql'), {
    loaders: [new GraphQLFileLoader()]
  })

  // Write some resolvers
  const resolvers = {}

  // Add resolvers to the schema
  const schemaWithResolvers = addResolversToSchema({ schema, resolvers })

  const yoga = createYoga({
    schema: schemaWithResolvers
  })

  const server = createServer(yoga)

  server.listen(4000, () => {
    console.log('Server is running on http://localhost:4000')
  })
}

main().catch(error => {
  console.error(error)
  process.exit(1)
})

Loaders

There are a lot of loaders that load your schemas and documents from different sources. You need to provide those loaders under loaders parameter like below:

GraphQLFileLoader

This loader loads your GraphQLSchema from .graphql files like below:

import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
import { loadSchema } from '@graphql-tools/load'
import { addResolversToSchema } from '@graphql-tools/schema'

// schema is `GraphQLSchema` instance
const schema = await loadSchema('schema.graphql', {
  // load from a single schema file
  loaders: [new GraphQLFileLoader()]
})

// You can add resolvers to that schema
const schemaWithResolvers = addResolversToSchema({
  schema,
  resolvers: {
    Query: {
      //  ...
    }
  }
})

This loader also supports glob pattern;

import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
import { loadSchema } from '@graphql-tools/load'

const schema = await loadSchema('graphql/**/*.graphql', {
  // load files and merge them into a single schema object
  loaders: [new GraphQLFileLoader()]
})

If you use loadDocuments, it gives you an array of document source objects;

import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
import { loadDocuments } from '@graphql-tools/load'

const documents = await loadDocuments('graphql/**/*.graphql', {
  // load files and merge them into a single schema object
  loaders: [new GraphQLFileLoader()]
})

JsonFileLoader

This loader handles schema introspection and document nodes in .json files.

Introspection is handled in the example below:

import { JsonFileLoader } from '@graphql-tools/json-file-loader'
import { loadSchema } from '@graphql-tools/load'
import { addMocksToSchema } from '@graphql-tools/mock'

const schema = await loadSchema('schema-introspection.json', {
  loaders: [new JsonFileLoader()]
})

// Mocked non-executable schema generated from an introspection
const mockedSchema = addMocksToSchema({ schema })

This loader handles json files if they represent DocumentNode, and returns an array of document sources.

import { JsonFileLoader } from '@graphql-tools/json-file-loader'
import { loadDocuments } from '@graphql-tools/load'

const documents = await loadDocuments('**/*-document.json', {
  loaders: [new JsonFileLoader()]
})

CodeFileLoader

This loader extracts GraphQL SDL string, exported GraphQLSchema and DocumentNode from TypeScript and JavaScript code files. Let’s say you have the following code file;

const ME_QUERY = gql`
  query Me {
    me {
      id
      name
      username
      age
    }
  }
`

And the following code will extract Me query operation from that code file without executing it using GraphQL Tag Pluck. It understands /* GraphQL */ magic comment and gql literals. You can configure GraphQL Tag Pluck using pluckConfig.

import { CodeFileLoader } from '@graphql-tools/code-file-loader'
import { loadDocuments } from '@graphql-tools/load'

const documents = await loadDocuments('./src/**/graphql/*.ts', {
  loaders: [new CodeFileLoader()],
  pluckConfig: {
    // ...
  }
})

You can also load your schema from code files like below:

import { GraphQLSchema } from 'graphql'

// typeDefs.ts
export const typeDefs = /* GraphQL */ `
  type Query {
    foo: String
  }
`
// or schema.ts
export const schema = new GraphQLSchema(/* ... */)

UrlLoader

This loader generates (a fully executable remote schema using @graphql-tools/wrap) from a URL endpoint.

import { loadSchema } from '@graphql-tools/load'
import { UrlLoader } from '@graphql-tools/url-loader'

const schema = await loadSchema('http://localhost:3000/graphql', {
  loaders: [new UrlLoader()]
})

You can provide custom headers, HTTP method and custom W3C fetch method.

import { loadSchema } from '@graphql-tools/load'
import { UrlLoader } from '@graphql-tools/url-loader'

const schema = await loadSchema('http://localhost:3000/graphql', {
  loaders: [new UrlLoader()],
  headers: {
    Accept: 'application/json'
  },
  method: 'POST',
  fetch: myFetch
})

In browser this remote schema can be called using vanilla GraphQL-js and act like a simple GraphQL client.

import { graphql } from 'graphql'
import { loadSchema } from '@graphql-tools/load'
import { UrlLoader } from '@graphql-tools/url-loader'

const schema = await loadSchema('http://localhost:3000/graphql', {
  loaders: [new UrlLoader()]
})

const response = await graphql(
  schema,
  /* GraphQL */ `
    {
      foo {
        bar {
          baz
        }
      }
    }
  `
)

console.log(response)