Graphql resolver is a middleware
that converts a request
to a call to some data provider that will retrieve the information requested.
field
in a GQL query.The return type
of each resolver function ideally complies to the type defined on the field
/node
.
Graph
Query
is the base (top most) field/node of every query.
query
starts with a Query
entrypoint in the graph.Connections in Graphql are directional.
node/edge
in the graph
If we're getting User's City
, User -> Address
connection would be established by passing User's Id
value to Address
resolver which would retrieve details like City
by calling its respective service method.
Address
type (as a node) has City
field definedUser Service
would have a method getUser
defined with an interface User
which alone should satisfy the node.User {
...user,
address,
email
}
User
graph node may extend to other fields like Address
and Email
address
and email
field calls its own corresponding resolver functionUser
can be passed to either of the subnodes.When a field does not have a specified resolver
to match the field name, a default resolver
will look in root
to find a property with the same name as the field.
Regardless of whether the default resolver has the matching field or not, the inner fields are evaluated as a distinct resolver.
To override inner field resolver, you need to reference the default resolver value in the inner resolver using root
.
const resolvers = { Book: { title: (root, args, context) => { // when no default value provided, will return "inner field" // reference to root here will result in "outer root" return root.title || "inner field"; }, content: (root, args, context) => { return "inner field overrides outer default"; } }, Query: { // getBook's return is typed to Book type getBook: (root, args, context) => { return { title: "outer root", content: "outer default will never return because inner exists" } } } }
Nested Field defined on a resolver is available because of the resolver chain
.
Query.libraries() > Library.books() > Book.author() > Author.name()
arg
values from Library
(entrypoint) to Books
to Author
(in books) to get Author.name
.# schema schema { query: Query } type Query { library: Library } type Library { books: Books } type Books { authors: [Author] } type Author { name: String }
// resolver { Query: { library: () => getLibrary(); }, Library: { books: (parent, args, contextValue, info) => getBooks(parent); }, Books: { authors: (parent, args, contextValue, info) => getAuthors(parent); }, Author: { name: (parent, args, contextValue, info) => getName(); }, }