In many tutorials that I have read, the most common way of using graphql resolvers is like below.
export const rootResolvers: IResolvers = {
Query: {
getUserById: async (root, { id }, context, info) => {
return await getUserController(id);
},
getUsers: async (root, args, context, info) => {
return await getUsersController();
},
},
Mutation: {
createUser: async (_, args, {userData}, info) => {
return registerUserController(userData);
},
updateUser: async (_, args, {userData}, info) => {
return updateUserController(userData);
},
},
}
But I want to write directly the busness logic in my resolvers without using controllers, and since each resolevr can have a lot of code, I decided to split my rootResolver like this.
const getUserResolver = {
Query: {
getUsers: async (root, args, context, info) => {
return await getUsersController();
},
},
}
}
...
const userCreateResolver = {
Mutation: {
createUser: async (_, args, {userData}, info) => {
return registerUserController(userData);
},
}
}
const userUpdateResolver = {
Mutation: {
updateUser: async (_, args, {userData}, info) => {
return registerUserController(userData);
},
}
}
Now I use the spread operator to combine all my resolvers in order to obtain one resolver object.
const rootResolver: IResolvers = {
...getUserResolver.Query,
...userCreateResolver.Mutation,
...userUpdateResolver.Mutation
}
I want to know if this way is the best practise. Note: I used lodash and graphql-tools/merge packages but got an error on the definition of graphql server ( I am using @mercuriusjs and the resolver must be an object not an array of object.
// Register mercurius to the server.
app.register(mercurius, {
schema: buildFederationSchema(rootTypeDefs, {
isGateway: false,
}),
resolvers: rootResolver, <--------------------
context: buildContext,
graphiql: true,
queryDepth: 7,
});
You can do this but don't include the Query
or Mutation
levels in your individual resolvers, use them at the end:
const getUserResolver = {
getUsers: getUsersController
}
const userCreateResolver = {
createUser: (_, __, {userData}) => registerUserController(userData)
}
const userUpdateResolver = {
updateUser: (_, __, {userData}) => registerUserController(userData)
}
You don't have to
await
resolvers in their code, resolvers can return promises.
Then:
const rootResolver: IResolvers = {
Query: {
...getUserResolver.Query,
},
Mutation: {
...userCreateResolver.Mutation,
...userUpdateResolver.Mutation
}
}