id | title | sidebar_label | type |
---|---|---|---|
schema-loading |
Loading GraphQL Schemas from different sources |
Schema loading |
Guide |
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 export
s 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 util is using loaders, and implemented using chain-of-responsibility pattern.
Specifying the loader is not necessary. The user need only provide the inputs. The utils will detect it automatically.
For notes on typescript, refer to loaders
Schema and documents 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.
const { loadFiles } = require('@graphql-tools/load-files')
const { createServer } = require('@graphql-yoga/node')
async function main() {
const server = createServer({
server: {
typeDefs: await loadFiles('src/typeDefs/**/*.graphql'),
resolvers: await loadFiles('src/resolvers/**/*.{js,ts}')
}
})
await server.start()
}
loadFiles
doesn't support#import
syntax. See below if you need that.
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()
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!
}
You can extend loaded schema with resolvers
import { join } from 'path'
import { loadSchemaSync } from '@graphql-tools/load'
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
import { addResolversToSchema } from '@graphql-tools/schema'
import { createServer } from '@graphql-yoga/node'
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 server = createServer({
schema: schemaWithResolvers
})
await server.start()
}
main().catch(error => console.error(error))
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;
<iframe width="100%" height="400" src="https://www.youtube.com/embed/I79_b7K0rIk" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen ></iframe>Watch Episode #22 of
graphql.wtf
for a quick introduction to file loaders:
This loader loads your GraphQLSchema from .graphql
files like below;
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader';
import { addResolversToSchema } from '@graphql-tools/schema';
import { loadSchema } from '@graphql-tools/load';
// 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 { loadDocuments } from '@graphql-tools/load'
import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader'
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.
This loader handles schema introspection and document nodes in .json
files.
Introspection is handled in the example below;
import { loadSchema } from '@graphql-tools/load'
import { JsonFileLoader } from '@graphql-tools/json-file-loader'
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 { loadDocuments } from '@graphql-tools/load'
import { JsonFileLoader } from '@graphql-tools/json-file-loader'
const documents = await loadDocuments('**/*-document.json', {
loaders: [new JsonFileLoader()]
})
This loader only supports Node environment because it relies on File System of your platform.
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 { loadDocuments } from '@graphql-tools/load';
import { CodeFileLoader } from '@graphql-tools/code-file-loader';
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 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.
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 { loadSchema } from '@graphql-tools/load'
import { UrlLoader } from '@graphql-tools/url-loader'
import { graphql } from 'graphql'
const schema = await loadSchema('http://localhost:3000/graphql', {
loaders: [new UrlLoader()]
})
const response = await graphql(
schema,
/* GraphQL */ `
{
foo {
bar {
baz
}
}
}
`
)
console.log(response)