Fastify 适配器
示例应用
¥Example app
开始使用 Fastify 适配器的最佳方法是查看示例应用。
¥The best way to start with the Fastify adapter is to take a look at the example application.
描述 | 链接 |
---|---|
|
如何将 tRPC 与 Fastify 结合使用
¥How to use tRPC with Fastify
安装依赖
¥Install dependencies
bash
yarn add @trpc/server fastify zod
bash
yarn add @trpc/server fastify zod
Zod 不是必需的依赖,但它在下面的示例路由中使用。
¥Zod isn't a required dependency, but it's used in the sample router below.
创建路由
¥Create the router
首先,你需要一个 router 来处理你的查询、突变和订阅。
¥First of all you need a router to handle your queries, mutations and subscriptions.
下面给出了一个示例路由,将其保存在名为 router.ts
.txt 的文件中。
¥A sample router is given below, save it in a file named router.ts
.
router.ts
router.tsts
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 APIexport type AppRouter = typeof appRouter;
router.tsts
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 APIexport type AppRouter = typeof appRouter;
如果你的路由文件开始变得太大,请将你的路由拆分为多个子路由,每个子路由都在自己的文件中实现。然后将 合并它们 变成单根 appRouter
。
¥If your router file starts getting too big, split your router into several subrouters each implemented in its own file. Then merge them into a single root appRouter
.
创建上下文
¥Create the context
然后你需要为每个请求创建一个 context。
¥Then you need a context that will be created for each request.
下面给出了一个示例上下文,将其保存在名为 context.ts
的文件中:
¥A sample context is given below, save it in a file named context.ts
:
context.ts
context.tsts
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.tsts
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>>;
创建 Fastify 服务器
¥Create Fastify server
tRPC 包括一个开箱即用的 Fastify 适配器。该适配器可让你将 tRPC 路由转换为 Fastify 插件。为了防止大量批量请求期间出现错误,请确保将 maxParamLength
Fastify 选项设置为合适的值,如图所示。
¥tRPC includes an adapter for Fastify out of the box. This adapter lets you convert your tRPC router into a Fastify plugin. In order to prevent errors during large batch requests, make sure to set the maxParamLength
Fastify option to a suitable value, as shown.
由于 Fastify 插件系统和类型推断的限制,可能会出现一些问题,例如正确输入 onError
。你可以添加 satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions']
来帮助 TypeScript 获取正确的类型。
¥Due to limitations in Fastify's plugin system and type inference, there might be some issues getting for example onError
typed correctly. You can add a satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions']
to help TypeScript out and get the correct types.
server.tsts
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({maxParamLength: 5000,});server.register(fastifyTRPCPlugin, {prefix: '/trpc',trpcOptions: {router,createContext,onError({ path, error }) {// report to error monitoringconsole.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.tsts
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({maxParamLength: 5000,});server.register(fastifyTRPCPlugin, {prefix: '/trpc',trpcOptions: {router,createContext,onError({ path, error }) {// report to error monitoringconsole.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);}})();
你的端点现在可以通过 HTTP 访问!
¥Your endpoints are now available via HTTP!
端点 | HTTP URI |
---|---|
getUser | GET http://localhost:3000/trpc/getUserById?input=INPUT 其中 INPUT 是 URI 编码的 JSON 字符串。 |
createUser | POST http://localhost:3000/trpc/createUser 与 User 类型的 req.body |
如何启用订阅 (WebSocket)
¥How to enable subscriptions (WebSocket)
Fastify 适配器通过 @fastify/websocket 插件支持 subscriptions。除了上述步骤之外,你所要做的就是安装依赖,向路由添加一些订阅并激活插件中的 useWSS
option。@fastify/websocket
所需的最低 Fastify 版本是 3.11.0
。
¥The Fastify adapter supports subscriptions via the @fastify/websocket plugin. All you have to do in addition to the above steps is install the dependency, add some subscriptions to your router and activate the useWSS
option in the plugin. The minimum Fastify version required for @fastify/websocket
is 3.11.0
.
安装依赖
¥Install dependencies
bash
yarn add @fastify/websocket
bash
yarn add @fastify/websocket
导入并注册 @fastify/websocket
¥Import and register @fastify/websocket
ts
import ws from '@fastify/websocket';server.register(ws);
ts
import ws from '@fastify/websocket';server.register(ws);
添加一些订阅
¥Add some subscriptions
编辑在前面的步骤中创建的 router.ts
文件并添加以下代码:
¥Edit the router.ts
file created in the previous steps and add the following code:
router.tsts
import { initTRPC } from '@trpc/server';import { observable } from '@trpc/server/observable';const t = initTRPC.create();export const appRouter = t.router({randomNumber: t.procedure.subscription(() => {return observable<{ randomNumber: number }>((emit) => {const timer = setInterval(() => {emit.next({ randomNumber: Math.random() });}, 1000);return () => {clearInterval(timer);};});}),});
router.tsts
import { initTRPC } from '@trpc/server';import { observable } from '@trpc/server/observable';const t = initTRPC.create();export const appRouter = t.router({randomNumber: t.procedure.subscription(() => {return observable<{ randomNumber: number }>((emit) => {const timer = setInterval(() => {emit.next({ randomNumber: Math.random() });}, 1000);return () => {clearInterval(timer);};});}),});
激活 useWSS
选项
¥Activate the useWSS
option
server.tsts
server.register(fastifyTRPCPlugin, {useWSS: true,// ...});
server.tsts
server.register(fastifyTRPCPlugin, {useWSS: true,// ...});
没关系,你可以订阅主题 randomNumber
,你应该每秒都会收到一个随机数🚀。
¥It's alright, you can subscribe to the topic randomNumber
and you should receive a random number every second 🚀.
Fastify 插件选项
¥Fastify plugin options
name | type | optional | default | description |
---|---|---|---|---|
prefix | string | true | "/trpc" | |
useWSS | boolean | true | false | |
trpcOptions | NodeHTTPHandlerOptions | false | n/a |