Replies: 6 comments
-
Cal's reasoning was their lambdas got reaaally big so they needed to reduce size in order to reduce cold start latencies by lazy-loading every handler. I'd say they're one of the biggest trpc routers out there and for a normal size you won't see any benefits to this. What's your reasoning for this? |
Beta Was this translation helpful? Give feedback.
-
Not referencing their UNSTABLE_CACHE stuff. Just mainly the way they separate routers from handlers. You can also see it in my repo I mentioned, which is what I believe most trpc users should follow imo. It's mainly for making it easier to call any handler from any other one. |
Beta Was this translation helpful? Give feedback.
-
The router declarations would look like this: export const userRouter = {
changeName: protectedProcedure
.input(ZChangeNameInputSchema)
.mutation(changeNameHandler),
getAll: publicProcedure.query(getAllHandler),
getNotifications: protectedProcedure.query(getNotificationsHandler),
getOne: protectedProcedure.input(ZGetOneInputSchema).query(getOneHandler),
switchActiveTeam: protectedProcedure
.input(ZSwitchActiveTeamInputSchema)
.mutation(switchActiveTeamHandler),
} satisfies TRPCRouterRecord; Notice how the handlers are defined elsewhere, allowing for them to be called very naturally from any other endpoint |
Beta Was this translation helpful? Give feedback.
-
I personally don't think this is a good default. If this works better for you then go for it! But you're separating things before you even know you need that separation, resulting in a lot of jumping back and forth between packages (assuming all your validators are put in For someone new coming to a repo, I think it's easier to reason about "functions", which is why I advocate for shared code to be broken out into their own functions: // api/src/some-file.ts
export function getThing(id: string) { ... }
// api/src/router-1.ts
someProc: protectedProcedure.input(...).query(() => {
const thing = getThing(input.id)
}),
// api/src/router-2.ts
someOtherProc: protectedProcedure.input(...).query(() => {
const thing = getThing(input.id)
}), In this (contrived) example, why should i forward the entire procedure's input and context when it only needs an id? I just struggle to see a proper use-case when a handler should call another handler. |
Beta Was this translation helpful? Give feedback.
-
We can keep the |
Beta Was this translation helpful? Give feedback.
-
I see. Thanks for the feedback! Yes, it might just be better to keep it as is. For my use case I definitely felt that doing the separation was better. But I can definitely see how it might not be the best default for most people. trim.E168A7E6-291E-4620-9CB9-675BC2D78268.MOV |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
As of a few months ago,
@acme/validators
was introduced to this repo. This was a great change, as we now are able to for example calluseForm
with the same exact same zod validator as the target api for that form's handleSubmit. We can call the validation logic even before leaving our network card which is awesome.Alongside this change, I would highly recommend using Cal.com's api structure, which separates the router definitions from their respective handlers. There is a main reason for this: being able to call any handler from within any other handler.
We've seen how the question of "how do I call a procedure from within another procedure" causes some confusion to people: https://trpc.io/docs/server/server-side-calls (first image in this trpc page explains how to do it)
I have copied Cal.com's file structure to my repo, which you can check here and am using separate handlers. This vastly simplifies the ability of calling any dedicated handler from within anywhere else.
Describe the solution you'd like to see
Separated handlers from their definitions at the router, with
_router.ts
files at the root of the router folder, and multiple other handler files next to it.Additional information
So, if this is something that we should do, I'd love to file a PR. For the purposes of this repo it's very simple since it's just 2 routers
Beta Was this translation helpful? Give feedback.
All reactions