In the course of schema customization, sometimes type definitions are insufficient for requirements in Gatsby sites. For example, the GraphQL SDL and Gatsby Type Builders can handle the vast majority of use cases when it comes to adding type definitions, but more granularity is occasionally necessary in the form of custom resolvers, which allow us to specify how fields should be resolved in the GraphQL schema. This is done through implementations of the createResolvers
Node API:
// gatsby-node.js
exports
.
createResolvers
=
({
createResolvers
})
=>
{
const
resolvers
=
{
Frontmatter
:
{
author
:
{
resolve
(
source
,
args
,
context
,
info
)
{
return
context
.
nodeModel
.
getNodeById
({
id
:
source
.
author
,
type
:
"AuthorJson"
,
})
},
},
},
}
createResolvers
(
resolvers
)
}
Implementations of the createResolvers
API enable Gatsby developers to extend types with new fields without overriding the field type. Since the createResolvers
function is executed near the end of the schema generation process, modification of an existing field type would require the regeneration of input types (field
, sort
, etc.), which would be an expensive operation. For this reason, specifying field types is best handled in implementations of the createTypes
action, unless you have more advanced requirements.
While implementing the createResolvers
API, Gatsby permits access to the internal data store and Gatsby’s own query capabilities through the context.nodeModel
object that is made available in each resolver. In this manner, Gatsby developers can directly access nodes by their identifiers by invoking getNodeById
and getNodesByIds
, whereas all nodes can be retrieved through getAllNodes
. You can also issue arbitrary queries from within resolver function logic through runQuery
, which allows for filter
and sort
query arguments.
For example, the following createResolvers
implementation extends the AuthorJson
type with a field that lists all recent articles written by a particular author:
// gatsby-node.js
exports
.
createResolvers
=
({
createResolvers
})
=>
{
const
resolvers
=
{
AuthorJson
:
{
recentPosts
:
{
type
:
[
"MarkdownRemark"
],
resolve
(
source
,
args
,
context
,
info
)
{
return
context
.
nodeModel
.
runQuery
({
query
:
{
filter
:
{
frontmatter
:
{
author
:
{
eq
:
source
.
email
},
date
:
{
gt
:
"2019-01-01"
},
},
},
},
type
:
"MarkdownRemark"
,
firstOnly
:
false
,
})
},
},
},
}
createResolvers
(
resolvers
)
}
If invoking runQuery
from within the API implementation to sort results of the query, note that sort.fields
and sort.order
are both GraphQLList
fields. Meanwhile, nested fields within sort.fields
are accessed through dot notation rather than triple underscores, as we’ve seen in previous examples:
// gatsby-node.js
// ...
return
context
.
nodeModel
.
runQuery
({
query
:
{
sort
:
{
fields
:
[
"frontmatter.date"
],
order
:
[
"DESC"
],
},
},
type
:
"MarkdownRemark"
,
})
// ...
NOTE
A powerful feature available in the createResolvers
API that is beyond the scope of this overview of schema customization is custom query fields. For more information about these, consult the Gatsby documentation.
Leave a Reply