跳至主要内容
版本:11.x

Fastify 适配器

示例应用程序

开始使用 Fastify 适配器的最佳方法是查看示例应用程序。

描述链接
  • 带有 WebSocket 的 Fastify 服务器
  • 节点中的简单 tRPC 客户端

如何在 Fastify 中使用 tRPC

安装依赖项

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

Zod 不是必需的依赖项,但它在下面的示例路由器中使用。

创建路由器

首先,您需要一个 路由器 来处理您的查询、变异和订阅。

下面给出了一个示例路由器,将其保存在名为 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;

如果您的路由器文件开始变得太大,请将您的路由器拆分为多个子路由器,每个子路由器都在其自己的文件中实现。然后 将它们 合并到单个根 appRouter 中。

创建上下文

然后,您需要一个 上下文,它将在每个请求中创建。

下面给出了一个示例上下文,将其保存在名为 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>>;

创建 Fastify 服务器

tRPC 包含一个用于 Fastify 的适配器。此适配器允许您将 tRPC 路由器转换为 Fastify 插件。为了防止在大型批处理请求期间出现错误,请确保将 maxParamLength Fastify 选项设置为适当的值,如所示。

提示

由于 Fastify 插件系统和类型推断的限制,在获取例如 onError 的正确类型时可能会遇到一些问题。您可以添加 satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'] 来帮助 TypeScript 并获取正确的类型。

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

您的端点现在可以通过 HTTP 访问!

端点HTTP URI
getUserGET http://localhost:3000/trpc/getUserById?input=INPUT

其中 INPUT 是一个 URI 编码的 JSON 字符串。
createUserPOST 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.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(() => {
return observable<{ randomNumber: number }>((emit) => {
const timer = setInterval(() => {
emit.next({ randomNumber: Math.random() });
}, 1000);
return () => {
clearInterval(timer);
};
});
}),
});
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(() => {
return observable<{ randomNumber: number }>((emit) => {
const timer = setInterval(() => {
emit.next({ randomNumber: Math.random() });
}, 1000);
return () => {
clearInterval(timer);
};
});
}),
});

激活 useWSS 选项

server.ts
ts
server.register(fastifyTRPCPlugin, {
useWSS: true,
// ...
});
server.ts
ts
server.register(fastifyTRPCPlugin, {
useWSS: true,
// ...
});

没关系,您可以订阅主题 randomNumber,并且您应该每秒收到一个随机数 🚀。

Fastify 插件选项

名称类型可选默认描述
前缀字符串真的"/trpc"
useWSS布尔值真的错误的
trpcOptionsNodeHTTPHandlerOptions错误的n/a