Staying DRY and Type-Safe using the Prefetch-pattern for Prisma-backed apps
We love using Graphcool ‘s Prisma and GraphQL (graphql-yoga) at Smidyo — with the drawback being that they are both young technologies. So it feels like some things aren’t quite figured out yet. There doesn’t seem to be one solid consensus on what’s the very best practice. So here’s our take!
When making our mutations and queries, things got verbose very fast. Imagine an already signed up user. You have mutations for
- changing user info
- changing user email
- changing user password
- etc.
All of those need a resolver, and all of those resolvers need to first fetch the user from Prisma, in order to validate, etc. So instead of doing that on every resolver function, writing different helper functions for all data types, I present to you the “prefetch-pattern”. What this allows you to do, is pre-fetch certain Prisma database nodes, and inject them into the context.
Please read through the comments to get an idea of what’s being done here. Essentially we are just taking in standard resolver functions, but we are ‘wrapping’ them and running Pre-fetchers before them, and injecting the result of those into the Context.
As you can see, you can also choose whether you want to throw an error if the prefetch succeeded or not.
If you want to read more about the type-safe resolvers — check out this article!
So how do we go about implementing this? This is one example:
This is an example of a mutation to remove a company a user is an admin of.
The removal of the company is a critical operation, so it requires the user to give his password again in the request, so it can be checked in the resolver once again before removing the company.
The two Pre-fetchers provide the company and the user’s password to check against, in the Context object. But only if the user is authorised to do this, otherwise we throw an AuthError that we provided in the throwIfNone property.
After making some Pre-fetchers, they can be reused in different sets of resolvers, as long as you give them descriptive names.
I was thinking about making an NPM library out of this, but it’s a bit too simple for that, I think. It also has its flaws. The arguments the Pre-fetcher uses is hard-coded into the Pre-fetcher functions, but if you use standardised arguments name over your project, it shouldn’t be a problem.
If you found this useful, don’t forget to give a few claps! 👏 Perhaps even give the Smidyo Codex a follow?
You can find me on twitter @kankki (or down in the comments) if you have any ideas on how to better this system / pattern.