jlalmes / trpc-openapi

OpenAPI support for tRPC 🧩
https://www.npmjs.com/package/trpc-openapi
MIT License
2.12k stars 136 forks source link

Support customizing an error response body #440

Open rhinodavid opened 4 months ago

rhinodavid commented 4 months ago

trpc-openapi is opinionated about the body of error responses:

 const body: OpenApiErrorResponse = {
        message: isInputValidationError
          ? 'Input validation failed'
          : errorShape?.message ?? error.message ?? 'An error occurred',
        code: error.code,
        issues: isInputValidationError ? (error.cause as ZodError).errors : undefined,

There is an ability to customize the message for errors which don't throw from input validation, but no ability to modify the body otherwise.

I'm trying to convert an existing express-only server to use tRPC with trpc-openapi so we get the TypeScript client, autogen'd docs, etc.

The problem I'm running into is that we currently return a property reason in the error response body, and unfortunately there is a requirement to maintain this behavior.

Right now this is possible, but it's nasty.

For the onError argument I'm hijacking the NodeHTTPResponse end function:

const openApiMiddleware = createOpenApiExpressMiddleware({
    onError: ({ error, req }) => {
        const res = req.res;
        if (!res) return;

        const originalEndFn = res.end;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const overrideEndFn: typeof res.end = (arg1: any, arg2?: any, arg3?: any) => {
            console.log('Original error was', inspect(error));
            if (typeof arg1 === 'string') {
                const bodyOverride = {
                    message: "fail",
                    reason: "FOR_REASONS",
                };
                return originalEndFn.call(res, JSON.stringify(bodyOverride), arg2, arg3);
            }
            return originalEndFn.call(res, arg1, arg2, arg3);
        };
        res.end = overrideEndFn;
    },
    router,
});

I'm wondering if you would be open to PRs to enable more error customization. The change would probably involve making onError return a body and status code. I'm not sure how this would affect the openApi spec generation, or how exactly it would interact with responseMeta, but I'm sure we could figure out details.