Saltar al contenido principal
Versión: 11.x

OpenAPI (alfa)

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

precaución

Este paquete está en fase alfa. Las API pueden cambiar sin previo aviso.

El paquete @trpc/openapi genera una especificación OpenAPI 3.1 desde tu router tRPC. Utiliza el spec para:

  • Generar un cliente API con tipado seguro en cualquier lenguaje

  • Llamar a endpoints tRPC mediante herramientas HTTP como Postman o Insomnia

  • Habilitar integraciones con agentes de IA como servidores MCP

Instalación

bash
pnpm add @trpc/openapi
bash
pnpm add @trpc/openapi
Agentes de IA

Si utilizas un agente de IA para programación, instala habilidades de tRPC para una mejor generación de código:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install
nota

@trpc/openapi actualmente tiene versiones como 11.x.x-alfa, y debería funcionar con cualquier versión reciente de tRPC v11, pero como siempre recomendamos alinear los números de versión

Adaptando tu configuración tRPC

El generador funciona con tu router existente — no se requieren anotaciones ni decoradores. Algunos aspectos a considerar:

  • No necesitas tipos de salida — a diferencia de otras herramientas OpenAPI, los esquemas .output() son opcionales. El generador infiere los tipos de retorno automáticamente desde tu implementación.

  • Transformers — si tu servidor usa un data transformer, tus clientes OpenAPI deben usar el mismo. Consulta Transformers para opciones de configuración y uso entre lenguajes.

  • Suscripciones — actualmente excluidas del spec generado. Se planea soporte para SSE (Server-Sent Events).

  • Descripciones — las llamadas .describe() de Zod y los comentarios JSDoc en tipos, routers y procedimientos se convierten en campos description en el spec.

Generar el spec

CLI

bash
pnpm exec trpc-openapi ./src/server/router.ts
bash
pnpm exec trpc-openapi ./src/server/router.ts
OptionDefaultDescription
-e, --export <name>AppRouterName of the exported router type
-o, --output <file>openapi.jsonOutput file path
--title <text>tRPC APIOpenAPI info.title
--version <ver>0.0.0OpenAPI info.version
bash
pnpm exec trpc-openapi ./src/server/router.ts -o api.json --title "My API" --version 1.0.0
bash
pnpm exec trpc-openapi ./src/server/router.ts -o api.json --title "My API" --version 1.0.0

Programático

scripts/generate-openapi.ts
ts
import { generateOpenAPIDocument } from '@trpc/openapi';
const doc = generateOpenAPIDocument('./src/server/router.ts', {
exportName: 'AppRouter',
title: 'My API',
version: '1.0.0',
});
scripts/generate-openapi.ts
ts
import { generateOpenAPIDocument } from '@trpc/openapi';
const doc = generateOpenAPIDocument('./src/server/router.ts', {
exportName: 'AppRouter',
title: 'My API',
version: '1.0.0',
});

El generador analiza estáticamente los tipos TypeScript de tu router — nunca ejecuta tu código.

Generar un cliente desde el spec

Cualquier generador de clientes OpenAPI debería funcionar, pero la integración más probada es con Hey API.

Un cliente generado producirá funciones SDK tipadas que coinciden con tus procedimientos tRPC:

  • ConsultasGET /procedure.path

  • MutacionesPOST /procedure.path

  • Subscriptions se ignoran (SSE próximamente)

Hey API (TypeScript)

Documentación de Hey API

bash
pnpm add @trpc/openapi @hey-api/openapi-ts
bash
pnpm add @trpc/openapi @hey-api/openapi-ts

Por defecto, un cliente generado por OpenAPI no conocerá tu configuración de transformer ni cómo codificar parámetros de consulta. El paquete @trpc/openapi/heyapi provee un helper configureTRPCHeyApiClient que cubre este vacío — configura la serialización de solicitudes, el análisis de respuestas y la deserialización de errores para que el SDK generado funcione correctamente con endpoints tRPC.

Sin transformer

Puedes generar tu cliente usando la CLI de Hey API o su API programática en este caso

bash
pnpm exec openapi-ts -i openapi.json -o ./generated
bash
pnpm exec openapi-ts -i openapi.json -o ./generated

Luego se requiere un poco de configuración en tiempo de ejecución:

src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { Sdk } from './generated/sdk.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
});
const sdk = new Sdk({ client });
const result = await sdk.greeting({ query: { input: { name: 'World' } } });
const user = await sdk.user.create({ body: { name: 'Bob', age: 30 } });
src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { Sdk } from './generated/sdk.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
});
const sdk = new Sdk({ client });
const result = await sdk.greeting({ query: { input: { name: 'World' } } });
const user = await sdk.user.create({ body: { name: 'Bob', age: 30 } });

Con transformer (superjson, devalue, etc.)

advertencia

Si tu backend usa un data transformer como superjson, debes pasarlo a la configuración del cliente. Sin esto, fechas, mapas, conjuntos y otros tipos no JSON pueden ser incorrectos silenciosamente.

Primero genera tu código cliente usando la API programática de Hey API, así puedes usar createTRPCHeyApiTypeResolvers para garantizar que tus tipos emitidos sean correctos:

src/client.ts
ts
import { createClient } from '@hey-api/openapi-ts';
import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';
const openApiJson = './path/to/openapi.json'
const outputDir = './generated'
await createClient({
input: openApiJson,
output: outputDir,
plugins: [
{
name: '@hey-api/typescript',
// Important: this ensures that your emitted types like Dates are correct
'~resolvers': createTRPCHeyApiTypeResolvers(),
},
{
name: '@hey-api/sdk',
operations: { strategy: 'single' },
},
],
});
src/client.ts
ts
import { createClient } from '@hey-api/openapi-ts';
import { createTRPCHeyApiTypeResolvers } from '@trpc/openapi/heyapi';
const openApiJson = './path/to/openapi.json'
const outputDir = './generated'
await createClient({
input: openApiJson,
output: outputDir,
plugins: [
{
name: '@hey-api/typescript',
// Important: this ensures that your emitted types like Dates are correct
'~resolvers': createTRPCHeyApiTypeResolvers(),
},
{
name: '@hey-api/sdk',
operations: { strategy: 'single' },
},
],
});

En tiempo de ejecución configura el cliente generado con tu transformer. Luego puedes pasar tipos nativos directamente y recibirlos deserializados:

src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
// Important, this transformer must match your tRPC API's transformer:
transformer: superjson,
});
const sdk = new Sdk({ client });
const event = await sdk.getEvent({
query: { input: { id: 'evt_1', at: new Date('2025-06-15T10:00:00Z') } },
});
// event.data.result.data.at is a Date object ✅
const created = await sdk.createEvent({
body: { name: 'Conference', at: new Date('2025-09-01T09:00:00Z') },
});
src/usage.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
// Important, this transformer must match your tRPC API's transformer:
transformer: superjson,
});
const sdk = new Sdk({ client });
const event = await sdk.getEvent({
query: { input: { id: 'evt_1', at: new Date('2025-06-15T10:00:00Z') } },
});
// event.data.result.data.at is a Date object ✅
const created = await sdk.createEvent({
body: { name: 'Conference', at: new Date('2025-09-01T09:00:00Z') },
});

Usando un generador o lenguaje diferente

La especificación OpenAPI generada funciona con cualquier generador de clientes compatible con OpenAPI que pueda:

  • Emitir tipos precisos para clases como Date

  • Soportar personalización de parámetros de búsqueda y serialización del cuerpo de solicitudes/respuestas

Para integrarse correctamente con el protocolo de tRPC, debes configurar tu cliente generado para hacer dos cosas:

  • Transformadores — Si tu API de tRPC usa un transformador, el cliente debe serializar inputs y deserializar outputs usando el mismo formato

  • Inputs de consultas — Las solicitudes GET codifican el input como ?input=<JSON>, no como parámetros de consulta individuales

Consulta la configuración de Hey API para ver una implementación de referencia completa.

Transformadores

Los transformadores de datos de tRPC permiten enviar tipos complejos como Date, Map, Set y BigInt a través de la red. Al usar el cliente OpenAPI, el mismo transformador debe configurarse tanto en el servidor como en el cliente para que los inputs se serialicen y los outputs se deserialicen correctamente.

Cualquier transformador que implemente la interfaz DataTransformer de tRPC (serialize / deserialize) funciona con configureTRPCHeyApiClient. A continuación algunas opciones probadas.

SuperJSON

El transformador más popular para configuraciones TypeScript-to-TypeScript. Maneja Date, Map, Set, BigInt, RegExp y más.

bash
pnpm add superjson
bash
pnpm add superjson
src/server.ts
ts
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';
const t = initTRPC.create({ transformer: superjson });
src/server.ts
ts
import { initTRPC } from '@trpc/server';
import superjson from 'superjson';
const t = initTRPC.create({ transformer: superjson });
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: superjson,
});
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import superjson from 'superjson';
import { client } from './generated/client.gen';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: superjson,
});

Consulta la prueba de superjson para ver un ejemplo completo de extremo a extremo.

MongoDB Extended JSON v2

EJSON es una buena opción cuando necesitas soporte multiplataforma. El paquete npm bson proporciona EJSON.serialize / EJSON.deserialize que se mapean directamente a un DataTransformer de tRPC.

Disponible en: C, C#, C++, Go, Java, Node.js, Perl, PHP, Python, Ruby, Scala

bash
pnpm add bson
bash
pnpm add bson
src/transformer.ts
ts
import { EJSON } from 'bson';
import type { TRPCDataTransformer } from '@trpc/server';
export const ejsonTransformer: TRPCDataTransformer = {
serialize: (value) => EJSON.serialize(value),
deserialize: (value) => EJSON.deserialize(value as Document),
};
src/transformer.ts
ts
import { EJSON } from 'bson';
import type { TRPCDataTransformer } from '@trpc/server';
export const ejsonTransformer: TRPCDataTransformer = {
serialize: (value) => EJSON.serialize(value),
deserialize: (value) => EJSON.deserialize(value as Document),
};
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { ejsonTransformer } from './transformer';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: ejsonTransformer,
});
src/client.ts
ts
import { configureTRPCHeyApiClient } from '@trpc/openapi/heyapi';
import { client } from './generated/client.gen';
import { ejsonTransformer } from './transformer';
configureTRPCHeyApiClient(client, {
baseUrl: 'http://localhost:3000',
transformer: ejsonTransformer,
});

Consulta la prueba de MongoDB EJSON para ver un ejemplo completo de extremo a extremo.

Amazon Ion

Amazon Ion es un formato de datos con tipos complejos y amplio soporte de lenguajes. No implementa directamente la interfaz TRPCDataTransformer y requiere código adicional para funcionar con tRPC en JS/TS, pero puede ser una buena opción para sistemas personalizados.

Disponible en: C, C#, D, Go, Java, JavaScript, PHP, Python, Rust

bash
pnpm add ion-js
bash
pnpm add ion-js

Consulta la prueba de Amazon Ion para ver la implementación del transformador, código adicional y un ejemplo completo de extremo a extremo.

Crear un transformador personalizado

Cualquier objeto con métodos serialize y deserialize funciona:

ts
import type { TRPCDataTransformer } from '@trpc/server';
const myTransformer: TRPCDataTransformer = {
serialize: (value) => {
/* encode rich types */
},
deserialize: (value) => {
/* decode them back */
},
};
ts
import type { TRPCDataTransformer } from '@trpc/server';
const myTransformer: TRPCDataTransformer = {
serialize: (value) => {
/* encode rich types */
},
deserialize: (value) => {
/* decode them back */
},
};

Pásalo tanto a initTRPC.create({ transformer }) en el servidor como a configureTRPCHeyApiClient(client, { transformer }) en el cliente. Consulta la documentación de transformadores de datos para más detalles.

Ejemplo completo

Para un proyecto ejecutable que integra todos estos pasos, consulta el ejemplo openapi-codegen.