Catch the highlights of GraphQLConf 2023! Click for recordings. Or check out our recap blog post.
Docs
Schema Loading

Loading GraphQL Schemas from Different Sources

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

⚠️

Schema and document loading doesn’t work non Node.js environments, and if you are using a bundler like webpack, rollup or Vite, you cannot use dynamic 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)
})
⚠️

loadFiles doesn’t support #import syntax. See below if you need that.

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!
}

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:

πŸ’‘

Watch Episode #22 of graphql.wtf for a quick introduction to file loaders:

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()]
})
πŸ’‘

This loader only supports Node environment because it relies on File System of your platform.

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()]
})
πŸ’‘

This loader only supports Node environment because it relies on File System of your platform.

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(/* ... */)
⚠️

This loader only supports Node.js environment because it relies on File System of your platform.

⚠️

Note: If you are using typescript and path aliases, you may also need tsconfig-paths. Further reading can be found at the GitHub issue.

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
})
πŸͺ„
This loader supports both browser and node environments.

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)