GraphQL Schema Extension
Keystone automatically generates a GraphQL schema based on your Keystone config. This schema contains all GraphQL types, queries and mutations based on your lists and ends up as the generated schema.graphql
file found in the root of your Keystone project. Generally changing the behavior of Keystone can be performed through Hooks, however, there are times when you need an extra GraphQL type or want a custom mutation or query, for these instances, Keystone has the extendGraphqlSchema
option.
The extendGraphqlSchema
option expects a function that takes the GraphQL Schema generated by Keystone and returns a valid GraphQL schema. You can then use this function to add or replace resolvers and types.
Using Keystone's graphql.extend
Keystone exports graphql
from @keystone/core
, this uses @graphql-ts/schema which can be used in combination with Context
from .keystone/types
to extend your GraphQL schema in a type-safe way.
You can then import this into your Keystone configuration file
import { graphql } from '@keystone/core';
Then you can use graphql.extend
to add custom resolvers to your GraphQL Schema.
The following example adds a custom mutation called publishPost
to the base
Keystone Schema. It accepts one argument (args
) of id
which cannot be null and has the type of ID (graphql.nonNull(graphql.ID)
). It updates the Post with the corresponding id
and sets its status
to 'published' and publishDate
to the current time. It then returns the Post that is updated which has a GraphQL type of Post
that is passed in from the base
schema (base.object('Post')
).
import { graphql, config } from '@keystone/core';import { Context } from '.keystone/types';export default config({{/* ... */},extendGraphqlSchema: graphql.extend(base => {return {mutation: {publishPost: graphql.field({type: base.object('Post'),args: { id: graphql.arg({ type: graphql.nonNull(graphql.ID) }) },resolve(source, { id }, context:Context) {return context.db.Post.updateOne({where: { id },data: { status: 'published', publishDate: new Date().toISOString() },});},}),},};}),});
Note context.db
is used in the resolver, this ensures the correct Internal object with the correct type is returned to GraphQL.
A full example project using graphql-ts
can be found in examples/extend-graphql-schema-graphql-ts on the Keystone GitHub repo.
Using Third-Party Tools
As extendGraphqlSchema
expects a function that returns a valid GraphQL schema you can also use third-party GraphQL schema tools to help generate or merge schemas.
GraphQL-Tools Merge Schemas
GraphQL Tools mergeSchemas
is a third-party package that can help with schema merging and adding custom resolvers and types, and then return an updated GraphQL schema to Keystone.
Start by installing @graphql-tools/schema
npm install @graphql-tools/schema
Then import into your Keystone configuration
import { mergeSchemas } from '@graphql-tools/schema';
You can then write custom resolvers
and typeDefs
to merge with your Keystone schema
. For example, to add the same custom mutation as above (publishPost
), you would add the typeDefs
for publishPost
and then the resolvers.Mutation.publishPost
which performs the same function as above.
export default config({{/* ... */},extendGraphqlSchema: schema =>mergeSchemas({schemas: [schema],typeDefs: `type Mutation {publishPost(id: ID!): Post`,resolvers: {Mutation: {publishPost: (root, { id }, context) => {return context.db.Post.updateOne({where: { id },data: { status: 'published', publishDate: new Date().toUTCString() },});},},},}),});
Note - Before version 3.0.0
of @keystone-6/core
, @graphql-tools/schema
was exported from @keystone/core
as graphQLSchemaExtension
this was removed in favor of using the tool directly if required
A full example project using @graphql-tools/schema
can be found in examples/extend-graphql-schema-graphql-tools on the Keystone GitHub repo.
Related resources
Config API Reference →
The complete reference for the base keystone configuration
Example Project: Extend GraphQL Schema with graphql-ts →
A full keystone project illustrating how to extend your GraphQL schema using graphql-ts provided by Keystone.
Example Project: Extend GraphQL Schema with GraphQL-Tools →
A full keystone project illustrating how to extend your GraphQL schema using @graphql-tools/schema.
Example Project: Extend GraphQL Schema with Nexus →
A full keystone project illustrating how to extend your GraphQL schema using Nexus and @graphql-tools/schema.