Fastify 适配器
示例应用程序
开始使用 Fastify 适配器的最佳方法是查看示例应用程序。
描述 | 链接 |
---|---|
|
如何在 Fastify 中使用 tRPC
安装依赖项
bash
yarn add @trpc/server fastify zod
bash
yarn add @trpc/server fastify zod
Zod 不是必需的依赖项,但它在下面的示例路由器中使用。
创建路由器
首先,您需要一个 路由器 来处理您的查询、变异和订阅。
下面给出了一个示例路由器,将其保存在名为 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
中。
创建上下文
然后,您需要一个 上下文,它将在每个请求中创建。
下面给出了一个示例上下文,将其保存在名为 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 服务器
tRPC 包含一个用于 Fastify 的适配器。此适配器允许您将 tRPC 路由器转换为 Fastify 插件。为了防止在大型批处理请求期间出现错误,请确保将 maxParamLength
Fastify 选项设置为适当的值,如所示。
由于 Fastify 插件系统和类型推断的限制,在获取例如 onError
的正确类型时可能会遇到一些问题。您可以添加 satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions']
来帮助 TypeScript 并获取正确的类型。
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: appRouter,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: appRouter,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 访问!
端点 | HTTP URI |
---|---|
getUser | GET http://localhost:3000/trpc/getUserById?input=INPUT 其中 INPUT 是一个 URI 编码的 JSON 字符串。 |
createUser | POST http://localhost:3000/trpc/createUser 使用 req.body 类型为 User |
如何启用订阅(WebSocket)
Fastify 适配器通过 @fastify/websocket 插件支持 订阅。除了上述步骤之外,您需要做的就是安装依赖项,将一些订阅添加到您的路由器中,并激活 useWSS
选项 在插件中。@fastify/websocket
所需的最低 Fastify 版本是 3.11.0
。
安装依赖项
bash
yarn add @fastify/websocket
bash
yarn add @fastify/websocket
导入并注册 @fastify/websocket
ts
import ws from '@fastify/websocket';server.register(ws);
ts
import ws from '@fastify/websocket';server.register(ws);
添加一些订阅
编辑在前面的步骤中创建的 router.ts
文件,并添加以下代码
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
选项
server.tsts
server.register(fastifyTRPCPlugin, {useWSS: true,// ...});
server.tsts
server.register(fastifyTRPCPlugin, {useWSS: true,// ...});
没关系,您可以订阅主题 randomNumber
,并且您应该每秒收到一个随机数 🚀。
Fastify 插件选项
名称 | 类型 | 可选 | 默认 | 描述 |
---|---|---|---|---|
前缀 | 字符串 | 真的 | "/trpc" | |
useWSS | 布尔值 | 真的 | 错误的 | |
trpcOptions | NodeHTTPHandlerOptions | 错误的 | n/a |