Using a single source of code for standard and nested mutations
The GraphQL server supports 2 behaviors:
- The standard behavior for mutations, by default
- Nested mutations, as an opt-in
As a consequence, it will expose types QueryRoot
and MutationRoot
by default, and switch to exposing a single Root
type for nested mutations.
When providing the resolvers, we wouldn't want to provide two resolvers, one for each solution. It's better that the same resolver used to resolve fields for Root
can also resolve fields from QueryRoot
and MutationRoot
.
Implementation details
The server uses an object called FieldResolver
to resolve fields, and an object called MutationResolver
to execute the actual mutation. The same MutationResolver
object can be referenced by different FieldResolvers
implementing different fields, so the code is implemented only once and used in many places, following the SOLID approach.
We know if a field is a mutation or not if the FieldResolver
declares a MutationResolver
object for that field, done through function resolveFieldMutationResolverClass
.
For instance, field Root.replyComment
provides object AddCommentToCustomPostMutationResolver
. This same object is also used by field Comment.reply
.
Furthermore, when coding the FieldResolver
, the root fields are added to the Root
type only. For the standard GraphQL behavior, the server can retrieve this configuration, and automatically add these fields to either MutationRoot
or QueryRoot
depending on if they are mutations or not.
As a result, since we are using a single source for the code powering both the standard behavior and nested mutations, we are able to execute queries with nested mutations for no extra effort.