When using tRPC, itâs easy to run into a problem of duplicating output logic to try to hide/modify/change the output consistently.
Iâm going to show you how you can use tRPC middleware to dedupe that logic in a clean and reusable way.
Letâs imagine your application has Projects and Users.
We have two types of Users (admins and members).
For simplicity, letâs say we only want to return project descriptions for admins. Members cannot view descriptions.
Simplest solution
Did you notice the duplication? đą
Extracting shared logic
Letâs try to refactor some of this logic so thereâs less duplicated code.
Weâll create a mapProject function that takes in a project and whether the user is an admin and decides
how to map the project.
Using middleware to define the function with âcontextâ
Alright, this is starting to look a little cleaner. Letâs introduce âmiddlewareâ into the mix
to see how this can help us clean up some more code.
Instead of creating the mapProject function outside of tRPC and using it, we can actually create it within our tRPC middleware.
It will have all the information from the request that we need to make a decision. In this case, we can check if the user is an admin
and decide if we should return a âdescriptionâ from within the middleware.
Using tRPC middleware to itâs full potential
We can actually do the entire mapping within the middleware so we donât need to even think
about it inside of queries/mutations. Imagine a new engineer joins the project, you donât want to have to remind them to use the ctx.mapProject function.
Maybe youâre on vacation and they accidentally ship code that reveals the description to all members. That would be horrible.
Letâs see how tRPC middleware can solve this for us in a clean, reusable way.
FirstâŚour updated router. Look how simple this is.
Already, hereâs the moment weâve all been waiting forâŚ
In our tRPC middleware, we can actually call the next() function and await the result. This will return the result from the query/mutation
which we can use before returning the value to the client.
We await the result, make sure it was successful and then we check the return type to see if it is a project or list of projects, if so, we call the mapProject
on each project to hide the description for non-admin users.