How to use internal mechanisms for dynamic population/projection for custom resolver
Hello!
Let's suppose that we've got the below 2 resolvers:
{
userById: UserTC.mongooseResolvers.findById(),
userGetMe: UserTC.addResolver({
name:"userGetMe",
args: {},
type: User,
resolve: (_,__,context) => {
const {auth} = context;
const {myId} = auth;
return User.findById(myId);
},
}).getResolver("userGetMe").withMiddlewares([getMyAuthId])
}
As you can see both of the resolvers above eventually utilize findById of mongoose. The only difference is that userGetMe resolver does not take any arguments but returns the User with the id of the current authenticated user.
The solution above is ideal and not realistic. In reality I have to manually populate any nested fields in the User.findById(myId) call, based on the fields request inside the graphql query. So basically I need to write helper functions like what you've got here in order to achieve my result.
My question is, is there a clever way to overcome this? Is there a way for the userGetMe resolver to eventually use the UserTC.mongooseResolvers.findById() resolver to fetch the User fields correctly populated, projected etc?
You can try to reuse findById:
schemaComposer.Query.addFields({
...requireMiddlewares([authMiddleware, permissionCustomerMiddleware], {
me: SysUserTC.mongooseResolvers
.findById({ lean: true })
.setDescription("Current User's Profile")
.removeArg("_id") // <=== remove arg _id
.wrapResolve((next) => (rp) => {
const { userId } = rp.context.request;
rp.args._id = userId
return next(rp);
}),
sysUserById: SysUserTC.mongooseResolvers.findById({ lean: true }),
}),
})
Thanks for the reply @yurtaev, it worked!
Quick question regarding the requireMiddlewares, why aren't you using withMiddlewares? Just personal preference?
requireMiddlewares just helper
/**
* Add middlewares to resolvers
* https://graphql-compose.github.io/docs/api/Resolver.html#withmiddlewares
*/
export const requireMiddlewares = (
middlewares: Array<ResolverMiddleware<unknown, GraphQLContext>> = [],
resolvers: ObjMap<Resolver>,
): ObjMap<Resolver> => {
Object.keys(resolvers).forEach((k) => {
resolvers[k] = resolvers[k].withMiddlewares(middlewares)
})
return resolvers
}