Saltar al contenido principal
Versión: 11.x

Adaptador para Fastify

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 →

Aplicación de ejemplo

La mejor forma de comenzar con el adaptador de Fastify es revisar la aplicación de ejemplo.

DescriptionLinks
  • Fastify server with WebSocket
  • Simple tRPC client in node

Cómo usar tRPC con Fastify

Instalar dependencias

bash
yarn add @trpc/server fastify zod
bash
yarn add @trpc/server fastify zod

⚠️ Requisito de versión de Fastify

El adaptador de Fastify para tRPC v11 requiere Fastify v5+. Usar Fastify v4 puede causar que las solicitudes devuelvan respuestas vacías sin errores.

Zod no es una dependencia obligatoria, pero se utiliza en el enrutador de ejemplo a continuación.

Crear el enrutador

En primer lugar, necesitas un enrutador para manejar tus consultas, mutaciones y suscripciones.

A continuación se muestra un enrutador de ejemplo; guárdalo en un archivo llamado router.ts.

router.ts
router.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
type User = {
id: string;
name: string;
bio?: string;
};
const users: Record<string, User> = {};
export const t = initTRPC.create();
export const appRouter = t.router({
getUserById: t.procedure.input(z.string()).query((opts) => {
return users[opts.input]; // input type is string
}),
createUser: t.procedure
.input(
z.object({
name: z.string().min(3),
bio: z.string().max(142).optional(),
}),
)
.mutation((opts) => {
const id = Date.now().toString();
const user: User = { id, ...opts.input };
users[user.id] = user;
return user;
}),
});
// export type definition of API
export type AppRouter = typeof appRouter;
router.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
type User = {
id: string;
name: string;
bio?: string;
};
const users: Record<string, User> = {};
export const t = initTRPC.create();
export const appRouter = t.router({
getUserById: t.procedure.input(z.string()).query((opts) => {
return users[opts.input]; // input type is string
}),
createUser: t.procedure
.input(
z.object({
name: z.string().min(3),
bio: z.string().max(142).optional(),
}),
)
.mutation((opts) => {
const id = Date.now().toString();
const user: User = { id, ...opts.input };
users[user.id] = user;
return user;
}),
});
// export type definition of API
export type AppRouter = typeof appRouter;

Si tu archivo de enrutador comienza a ser demasiado grande, divide el enrutador en varios subenrutadores implementados cada uno en su propio archivo. Luego fusiónalos en un único enrutador raíz appRouter.

Crear el contexto

Luego necesitas un contexto que se creará para cada solicitud.

A continuación se muestra un contexto de ejemplo; guárdalo en un archivo llamado context.ts:

context.ts
context.ts
ts
import { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
export function createContext({ req, res }: CreateFastifyContextOptions) {
const user = { name: req.headers.username ?? 'anonymous' };
return { req, res, user };
}
export type Context = Awaited<ReturnType<typeof createContext>>;
context.ts
ts
import { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
export function createContext({ req, res }: CreateFastifyContextOptions) {
const user = { name: req.headers.username ?? 'anonymous' };
return { req, res, user };
}
export type Context = Awaited<ReturnType<typeof createContext>>;

Crear el servidor Fastify

tRPC incluye un adaptador para Fastify listo para usar. Este adaptador te permite convertir tu router de tRPC en un plugin de Fastify. Para evitar errores en solicitudes batch grandes, asegúrate de configurar la opción maxParamLength de Fastify con un valor adecuado, como se muestra.

consejo

Debido a limitaciones en el sistema de plugins e inferencia de tipos de Fastify, podrían existir problemas para obtener tipos correctos en elementos como onError. Puedes agregar satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'] para ayudar a TypeScript y obtener los tipos correctos.

server.ts
ts
import {
fastifyTRPCPlugin,
FastifyTRPCPluginOptions,
} from '@trpc/server/adapters/fastify';
import fastify from 'fastify';
import { createContext } from './context';
import { appRouter, type AppRouter } from './router';
const server = fastify({
routerOptions: {
maxParamLength: 5000,
},
});
server.register(fastifyTRPCPlugin, {
prefix: '/trpc',
trpcOptions: {
router: appRouter,
createContext,
onError({ path, error }) {
// report to error monitoring
console.error(`Error in tRPC handler on path '${path}':`, error);
},
} satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'],
});
(async () => {
try {
await server.listen({ port: 3000 });
} catch (err) {
server.log.error(err);
process.exit(1);
}
})();
server.ts
ts
import {
fastifyTRPCPlugin,
FastifyTRPCPluginOptions,
} from '@trpc/server/adapters/fastify';
import fastify from 'fastify';
import { createContext } from './context';
import { appRouter, type AppRouter } from './router';
const server = fastify({
routerOptions: {
maxParamLength: 5000,
},
});
server.register(fastifyTRPCPlugin, {
prefix: '/trpc',
trpcOptions: {
router: appRouter,
createContext,
onError({ path, error }) {
// report to error monitoring
console.error(`Error in tRPC handler on path '${path}':`, error);
},
} satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'],
});
(async () => {
try {
await server.listen({ port: 3000 });
} catch (err) {
server.log.error(err);
process.exit(1);
}
})();

¡Tus endpoints ahora están disponibles vía HTTP!

EndpointHTTP URI
getUserGET http://localhost:3000/trpc/getUserById?input=INPUT

where INPUT is a URI-encoded JSON string.
createUserPOST http://localhost:3000/trpc/createUser

with req.body of type User

Habilitar WebSockets

El adaptador de Fastify soporta WebSockets mediante el plugin @fastify/websocket. Todo lo que debes hacer adicionalmente a los pasos anteriores es instalar la dependencia, agregar algunas suscripciones a tu router y activar la opción useWSS en el plugin. La versión mínima de Fastify requerida para @fastify/websocket es 3.11.0.

Instalar dependencias

bash
yarn add @fastify/websocket
bash
yarn add @fastify/websocket

Importar y registrar @fastify/websocket

ts
import ws from '@fastify/websocket';
server.register(ws);
ts
import ws from '@fastify/websocket';
server.register(ws);

Agregar algunas suscripciones

Edita el archivo router.ts creado en los pasos anteriores y agrega el siguiente código:

router.ts
ts
import { initTRPC } from '@trpc/server';
import { observable } from '@trpc/server/observable';
const t = initTRPC.create();
export const appRouter = t.router({
randomNumber: t.procedure.subscription(async function* () {
while (true) {
yield { randomNumber: Math.random() };
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}),
});
router.ts
ts
import { initTRPC } from '@trpc/server';
import { observable } from '@trpc/server/observable';
const t = initTRPC.create();
export const appRouter = t.router({
randomNumber: t.procedure.subscription(async function* () {
while (true) {
yield { randomNumber: Math.random() };
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}),
});

Activar la opción useWSS

server.ts
ts
server.register(fastifyTRPCPlugin, {
useWSS: true,
// Enable heartbeat messages to keep connection open (disabled by default)
keepAlive: {
enabled: true,
// server ping message interval in milliseconds
pingMs: 30000,
// connection is terminated if pong message is not received in this many milliseconds
pongWaitMs: 5000,
},
// ...
});
server.ts
ts
server.register(fastifyTRPCPlugin, {
useWSS: true,
// Enable heartbeat messages to keep connection open (disabled by default)
keepAlive: {
enabled: true,
// server ping message interval in milliseconds
pingMs: 30000,
// connection is terminated if pong message is not received in this many milliseconds
pongWaitMs: 5000,
},
// ...
});

¡Listo! Puedes suscribirte al tópico randomNumber y recibirás un número aleatorio cada segundo 🚀.

Opciones del plugin de Fastify

nametypeoptionaldefaultdescription
prefixstringtrue"/trpc"
useWSSbooleantruefalse
trpcOptionsNodeHTTPHandlerOptionsfalsen/a