T
tRPC

❓-help

Ability to mutate/extend `input` from middlewares

WWeezyEzo2/9/2024
Hi I have a global middleware that should run for every route. This middleware simply coerces '' (empty string) to undefined for the whole input object. Here is my setup:
export const defaultProcedure = t.procedure.use(async ({ next, getRawInput }) => {
const input = await getRawInput()
const newInput = coerceEmptyStringsToUndefined(input)
return next({
input: newInput,
})
})
export const defaultProcedure = t.procedure.use(async ({ next, getRawInput }) => {
const input = await getRawInput()
const newInput = coerceEmptyStringsToUndefined(input)
return next({
input: newInput,
})
})
the function coerceEmptyStringsToUndefined is guarnteed to work as expected. Here is the implementation btw:
import mapValues from 'lodash.mapvalues'

// Note: not working with arrays
export function coerceEmptyStringsToUndefined(o: unknown): any {
if (typeof o === 'object' && o !== null) {
if (Array.isArray(o)) {
// return something here if you want it to work with arrays
} else {
return mapValues(o, coerceEmptyStringsToUndefined)
}
}
return o === '' ? undefined : o
}
import mapValues from 'lodash.mapvalues'

// Note: not working with arrays
export function coerceEmptyStringsToUndefined(o: unknown): any {
if (typeof o === 'object' && o !== null) {
if (Array.isArray(o)) {
// return something here if you want it to work with arrays
} else {
return mapValues(o, coerceEmptyStringsToUndefined)
}
}
return o === '' ? undefined : o
}
The problem: this code throws a validation error
const testRouter = createTRPCRouter({
test: defaultProcedure
.input(
z.object({
a: z.number().optional(),
})
)
.query(async ({ input }) => {
console.log(input)
}),
})
const testRouter = createTRPCRouter({
test: defaultProcedure
.input(
z.object({
a: z.number().optional(),
})
)
.query(async ({ input }) => {
console.log(input)
}),
})
The error is from zod which is: {received: '""', expected: 'number'}.
Nnlucas2/9/2024
This sounds like a hack Why not just fix the data being sent to the API? And what’s wrong with defining your inputs in each procedure? Much easier to maintain if you don’t have global behaviour Zod has coerce by the way, might also be a fix for your actual types
WWeezyEzo2/9/2024
This would be an overhead. In my application, empty strings are considered as undefined. Using something like sendDataToTrpcRoute({ a: a === '' ? undefined: a}) for every piece of data is not a good solution for me
Nnlucas2/9/2024
Well Zod has tools to let you manipulate stuff. Coerce and Preprocess are likely what you want. Maybe refine/suoerRefine/transform too You could define some custom string type that you use instead of z.string()
WWeezyEzo2/9/2024
I still think that mutating input is the responsibility of trpc. A lot of web frameworks allow you to mutate the input passed. Trpc itself lets you extend the context. Implementing it for input would be convenient as well. This idea will introduce the same overhead, that is, I have to change every schema to transform to coerce empty strings to undefined.
Nnlucas2/9/2024
Well I think you can already do this, it’s just a bad idea
WWeezyEzo2/9/2024
I have to mention that I like TRPC and since I have used I didn't use any other approach for backend routes. Just to be clear.
Nnlucas2/9/2024
Pretty sure you can chain input calls
WWeezyEzo2/9/2024
It would be nice if you can provide a sample code that works for my case
Nnlucas2/9/2024
Have a look at how our input parser works internally, it’s just a middleware to begin with .input() isn’t real
WWeezyEzo2/9/2024
So here is what i found. tldr: none of the functions are exported for external use. There is a function called createNewBuilder It does what i want, but it is not exported for external use. There are some other functions that could help (for example, createResolver to create a custom reoslver with my middlewares applied), but I was not able to import them.
GitHub
trpc/packages/server/src/unstable-core-do-not-import/procedureBuild...
🧙‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy. - trpc/trpc
WWeezyEzo2/16/2024
Currently, there is no way to implement this functionality outside @trpc/server package. I do not have time to work on this. But if you have a working approach I would be more than happy. For now, i will fix the data before sending it to trpc Is there any hope that this will be a feature request or something? I would appreciate this

Looking for more? Join the community!

Recommended Posts
Hot to redirect in middleware when using createCallerFactoryHello. I do have this tiny middleware: ```typescript const authMiddleware = middleware(async (opts) Remix: How can I return headers from a query or mutation back to the action/loader?I'm using Supabase Auth and a requirement is to return the headers back from its client creation funUsing output validator breaks query return type inference on react queryHi! I am not sure whether this is expected and whether there is some way to fix that but here it goeHow to pass headers from serverActions in Next.js App router.I'm using tRPC with Clerk auth provider in Next.js App directory. I created a `serverClient` to use Need Guidance Optimizing Multi-Select Typeahead### What your environment is: Node 18? Bun? pnpm / yarn / npm? - Bun v1.0.23 - Next.js v14.1.0 (app Private API, public clientsHey everyone, we're about to OSS some good stuff at my company and I'm wondering what's the best appHow to get the type of context after middleware context extension?I have a middleware where I validate and set a userId. My router knows that userId is no longer undewhat am i doing wrong?My turbo repo containing expo-clerk-trpc does NOT work. and I've tried everything I have no idea whaReusable Component to take router as props / dependency injection. How to type?for example: ```ts export const Content = async ({ api }) => { const items = await api.getAll.quertRPC mutate call firing two requests with custom linkNode: 18.16 tRPC: 10.38.0 pnpm What's wrong with this custom link that's causing it's addition to aIssue with Fastify / tRPC / AngularWe are trying to setup Angular project with tRPC. In Angular we get following error: ``` Error: nodDrizzle query not working only inside trpcMy drizzle query works inside a regular nextjs api route. The same query running inside trpc throws Server freezes when doing mutations...I have the exact same issue as mentioned in this post: https://discord-questions.trpc.io/m/117697170Create Wrapper only for Procedures that support Infinite QueryGreetings, I'm attempting to create a help that will handle some generic logic I desire for a seriWhy am I getting 'Argument type is not assignable to parameter type ProcedureResolver<unknown>'?I have this warning in my editor (jetbrains InteliJ): ``` Argument type () => any[] is not assignabEfficient way to use tRPC client with auth headers from secure storageWondering if anyone has a recommended pattern on caching the deviceId / authHeader using a React ConUsing tRPC with Expo API Routes feature?Is there a possibility to merge "tRPC Express Adapter" with "Expo API Route Express Deployment"? tRTRPC not working on multi tenant appEverything works on localhost. When I deploy it on the vercel None of the mutations work. Every qTRPCClientError: Unable to transform response from serverHi 🙂 I've just started - so nothing more than boiler plate code but for some reason it doesn't workoptimistic updates tRPC v11 + TanStack Query v5I am reading https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates#if-the