Aller au contenu principal
Version : 11.x

Adaptateur Fastify

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

Exemple d'application

La meilleure façon de démarrer avec l'adaptateur Fastify est de consulter l'exemple d'application.

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

Utiliser tRPC avec Fastify

Installer les dépendances

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

⚠️ Exigence de version de Fastify

L'adaptateur Fastify de tRPC v11 nécessite Fastify v5 ou ultérieur. L'utilisation de Fastify v4 peut entraîner le retour de réponses vides sans erreurs.

Zod n'est pas obligatoire mais est utilisé dans l'exemple de routeur ci-dessous.

Agents IA

Si vous utilisez un agent de codage IA, installez les compétences tRPC pour une meilleure génération de code :

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

Créer le routeur

Vous devez d'abord créer un routeur pour gérer vos requêtes, mutations et abonnements.

Un exemple de routeur est fourni ci-dessous - enregistrez-le dans un fichier 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 votre routeur devient trop volumineux, découpez-le en sous-routeurs autonomes dans des fichiers séparés, puis fusionnez-les dans un routeur racine appRouter.

Créer le contexte

Vous devez ensuite définir un contexte généré pour chaque requête.

Exemple de contexte à enregistrer dans 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>>;

Créer le serveur Fastify

tRPC inclut nativement un adaptateur pour Fastify. Cet adaptateur vous permet de convertir votre routeur tRPC en plugin Fastify. Pour éviter les erreurs lors de requêtes batch volumineuses, assurez-vous de définir l'option maxParamLength de Fastify à une valeur appropriée, comme illustré.

astuce

En raison des limitations du système de plugins et de l'inférence de types de Fastify, vous pourriez rencontrer des problèmes pour typer correctement onError. Vous pouvez ajouter satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'] pour aider TypeScript et obtenir les types corrects.

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);
}
})();

Vos endpoints sont maintenant disponibles via HTTP !

EndpointHTTP URI
getUserByIdGET 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

Activer les WebSockets

L'adaptateur Fastify prend en charge les WebSockets via le plugin @fastify/websocket. En plus des étapes précédentes, vous devez simplement installer la dépendance, ajouter des abonnements à votre routeur et activer l'option useWSS dans le plugin. La version minimale requise de @fastify/websocket est 3.11.0.

Installer les dépendances

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

Importer et enregistrer @fastify/websocket

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

Ajouter des subscriptions

Modifiez le fichier router.ts créé précédemment et ajoutez le code suivant :

router.ts
ts
import { initTRPC } from '@trpc/server';
 
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';
 
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));
}
}),
});

Activer l'option useWSS

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();
 
server.register(fastifyTRPCPlugin, {
useWSS: true,
trpcOptions: {
router: appRouter,
createContext,
// 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
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();
 
server.register(fastifyTRPCPlugin, {
useWSS: true,
trpcOptions: {
router: appRouter,
createContext,
// 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,
},
},
});

Vous pouvez désormais vous abonner au topic randomNumber et devriez recevoir un nombre aléatoire chaque seconde 🚀.

Options du plugin Fastify

nametypeoptionaldefaultdescription
prefixstringtrue"/trpc"URL prefix for tRPC routes
useWSSbooleantruefalseEnable WebSocket support via @fastify/websocket
trpcOptionsFastifyHandlerOptions<AppRouter, Request, Reply>falsen/atRPC handler options including router, createContext, etc.