Right now, TRPC forces procedures to be defined as single methods. Then it forces those methods to fall under one of the categories: query, mutation, or subscription. This imposes ambiguity on the consumer in cases where methods fall into many or none of the categories. Some examples:
flushOutput
, neither returns nor mutates server data - it just performs some side effect.items
, a resource which can be read, mutated, or subscribed to.TRPC does not allow you to model these concepts well, and subsequently the client api surface is exposed to redundant names (getData.query()
rather than just getData()
). There are some minor changes that could really improve that.
If procedures could be defined such that client callers didn't have to supply .query(...)
or .mutate(...)
, that would solve the first dilemma:
How the client would see it:
// Instead of this:
client.flushOutput.mutate(...);
// This (no forcing a side-effects procedure to declare itself as a mutation):
client.flushOutput(...)
How the server might define it:
// Instead of this:
publicProcedure.input(...).mutation(...);
// This:
publicProcedure.input(...).execute(...);
Alternative approach, allow custom categorization (like execute
) to extend mutations to other verbs. But my impression learning TRPC is that to a client, the categorization is largely redundant if we use descriptive procedure names.
For the items
resource case where multiple operations can happen on the resource:
How the client would see it:
// Instead of this:
client.getItems.query(...);
client.updateItems.mutate(...);
client.subscribeToItems.subscribe(...);
// This:
client.items.query(...);
client.items.mutate(...);
client.items.subscribe(...);
How the server might define it:
const test = router({
items: {
query: publicProcedure
.input(z.string())
.query(({ input }) => {
return `Hello ${input}!`;
}),
mutation: publicProcedure
.input(z.object())
.mutation(() => {}),
subscription: publicProcedure.subscription(() => {
// ...
}),
}
});
I can work around TRPC by wrapping it and stripping off the extra overhead at the client layer, rough sketch... but also gross hack imo:
function createClient() {
const client = createTRPCProxyClient( ... );
return Object.keys(client).reduce((obj, name) => {
const { query, mutate, subscribe } = client[name];
obj[name] = query || mutate || subscribe;
// TODO: also handle subscription
return obj;
}, {});
}
No response
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too