Field Resolvers
We'll be working with the below Post struct for this section.
type Post struct { ID groot.ID `json:"id"` Title string `json:"title"` Author User `json:"author"` Comments []Comment `json:"comments"` // this field will not be in the graphql schema AuthorID string `json:"-"`}Resolver Method#
The resolver for a field is defined the method on the struct with name Resolve{field-name}.
The resolvers return type must be (FieldType, error) if you want to return a value, or if you want to return a thunk (a function returned by a function), it must be (func() (FieldType, error), error). The method should be defined on the value struct (Post) and not the pointer of the struct (*Post).
The method signature of the resolver can be any of the following:
()- No Arguments(args ArgsStruct)- Arguments to accept from the API(ctx context.Context)- Context of a request(info graphql.ResolverInfo)- Info about the GraphQL request(args ArgsStruct, ctx context.Context)(args ArgsStruct, info graphql.ResolverInfo)(ctx context.Context, info graphql.ResolverInfo)(args ArgsStruct, ctx context.Context, info graphql.ResolverInfo)
For example, we can define a resolver for Author like below:
func (post Post) ResolveAuthor() (User, error) { return db.GetUser(post.AuthorID) loader := loader.UserLoaderFromCtx(ctx) user, err := loader.Load(post.AuthorID) return user, err}
// Returning a thunk with dataloaderfunc (post Post) ResolveAuthor() (func() (User, error), error) { thunk := userLoader.Load(post.AuthorID) return func() (User, error) { return thunk(), nil }, nil}Don't worry about making a mistake with the argument or return types, Groot will almost always catch it and panic.
Accepting Arguments#
Say we want to accept the argument first, and after for the comments field for pagintion. First, we need to define a struct with the arguments.
type PaginationArgs struct { First string `json:"first"` After string `json:"after"`}Next, we can accept these arguments in the resolver method like below:
func (post Post) ResolveComments(args PaginationArgs) ([]Comment, error) { comments, err := db.GetPostComments(post.Id, args.First, args.After) return comments, err}You can also accept nested structures like below:
type BarInput struct { BarText string `json:"barText"`}
type FooArgs struct { FooText string `json:"fooText"` Bar BarInput `json:"bar"`}
func (m Mutation) ResolveNewFoo(args FooArgs) (Foo, error) { return db.CreateFoo(args)}For the above example, Groot will create an input type named BarInput and reference that in the argument field type.