trpc / trpc

๐Ÿง™โ€โ™€๏ธ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.
https://tRPC.io
MIT License
33.78k stars 1.2k forks source link

feat: Client side error transformation #5581

Open RyanClementsHax opened 4 months ago

RyanClementsHax commented 4 months ago

Describe the feature you'd like to request

Sometimes TRPC calls don't directly go to the TRPC server. Sometimes they go through proxies that process the request against rules including checking the authorization header.

If you don't control these proxies, they can return JSON that isn't in the format that TRPC expects which results in a formatting error.

For example, Supabase's edge functions return the following response on an invalid JWT.

{"msg": "Invalid JWT"}

This line fails because result.type doesn't exist in the json. The TRPC loggerLink then logs it like this.

 ERROR   << mutation #1 recipes.create '{"context": {}, "elapsedMs": 203, "input": {"recipe": {"description": "", "ingredients": [Array], "name": "test", "steps": [Array]}}, "result": [TRPCClientError: Unable to transform response from server]}'

Describe the solution you'd like to see

What I'd like to do is

  1. Recover from the error if possible
  2. Make it easier to debug when it happens

In service of that, it would be nice to have one of the following

  1. Ability to transform the json parsed without completely overhauling deserialization
  2. Ability to introspect the json parsed for logging/debugging purposes

Describe alternate solutions

I attempted to use a custom link, but this error happens inside of the httpBatchLink itself and doesn't expose the json or error in what is returned down the chain.

I also looked at using the transformer option, but this isn't defined as of @trpc/client@10.45.2.

I considered overriding the fetch function that was used by TRPC, but it would be hard to transform the response since TRPC parses the json itself without giving the option for transformation

Additional information

No response

๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ Contributing

Funding

Fund with Polar

KATT commented 4 months ago

You should be able to do a custom link to intercept it this - the error should contain the Response in the context that you can sniff

RyanClementsHax commented 4 months ago

Oh so something like this?

const customLoggingLink = (): TRPCLink<AppRouter> => () => {
    return ({ next, op }) => {
        return observable((observer) => {
            return next(op)
                .pipe(
                    tap({
                        error(err) {
                            const response = err?.meta?.response;
                        },
                    })
                )
                .subscribe(observer);
        });
    };
};
KATT commented 4 months ago

https://trpc.io/docs/client/links#example