tRPC Integration
This guide explains how to integrate oRPC with tRPC, allowing you to leverage oRPC features in your existing tRPC applications.
Installation
npm install @orpc/trpc@betayarn add @orpc/trpc@betapnpm add @orpc/trpc@betabun add @orpc/trpc@betadeno add npm:@orpc/trpc@betaRouter Conversion
toORPCRouter converts a tRPC router into an oRPC router:
import { toORPCRouter } from '@orpc/trpc'
const orpcRouter = toORPCRouter(trpcRouter)The result is a regular oRPC router, so you can use it with any oRPC feature. For example, expose it through an RPC Handler or OpenAPI Handler, call it directly with Server-Side Clients, generate an OpenAPI Specification, and combine it with oRPC middlewares, plugins, and interceptors.
import { call, createRouterClient } from '@orpc/server'
// call a procedure directly
const output = await call(orpcRouter.ping, { input: 123 }, { context: {} })
// or create a server-side client
const client = createRouterClient(orpcRouter, { context: {} })
const result = await client.nested.pong({ id: '123' })INFO
Input/output validation stays in tRPC's hands: converted procedures delegate execution to the original tRPC procedures, so your tRPC middlewares, validation, and transforms run exactly as before.
OpenAPI
Once converted, your tRPC app gets first-class OpenAPI support. Define OpenAPI metadata under the '~openapi' key in your tRPC meta by bridging oRPC meta plugins with toTRPCMeta:
import type { Meta } from '@orpc/server'
import { openapi } from '@orpc/openapi'
import { toTRPCMeta } from '@orpc/trpc'
export const t = initTRPC.context<Context>().meta<Meta>().create()
const example = t.procedure
.meta(toTRPCMeta(openapi({ path: '/hello', summary: 'Hello procedure' })))
.input(z.object({ name: z.string() }))
.query(({ input }) => {
return `Hello, ${input.name}!`
})WARNING
Unlike oRPC builders, chained tRPC .meta() calls merge shallowly, so plugin merge logic (e.g. accumulating tags) only applies to plugins resolved within a single toTRPCMeta call.
Learn more in OpenAPI Specification and OpenAPI Handler.
Error Formatting
The toORPCRouter does not support tRPC Error Formatting. You should catch errors and format them manually using interceptors:
const handler = new OpenAPIHandler(orpcRouter, {
interceptors: [
async ({ next }) => {
try {
return await next()
}
catch (error) {
if (
error instanceof ORPCError
&& error.cause instanceof TRPCError
&& error.cause.cause instanceof z.ZodError
) {
throw new ORPCError('UNPROCESSABLE_CONTENT', {
message: z.prettifyError(error.cause.cause),
data: z.flattenError(error.cause.cause),
cause: error.cause.cause,
})
}
throw error
}
},
],
})
