#trpc #TypeScript #full-stack
Context 上下文
Context 是一个在所有的远程过程调用(RPC)中共享的数据对象。通常来说可以存储一些 Session 信息、用户信息等。
配置上下文
之前创建 tRPC 的时候使用了 initTRPC.create()
的方法。而配置上下文就是在 create()
之前调用 .context<TContext>()
。
- 创建一个 Context 对象
server/context.ts
import { getSession } from 'next-auth/react';
import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
import { User } from '.';
export const createContext = async({req, res}: CreateHTTPContextOptions) => {
// 模拟从session获取用户信息, User类型是从index.ts 导出的
const user: User = {
id: 1,
name: 'Alan',
}
return {
user,
req,
res
}
}
export type Context = Awaited<ReturnType<typeof createContext>>;
- 初始化 tRPC 和上下文
server/trpc.ts
import { initTRPC } from "@trpc/server";
import type { Context } from "./context";
const t = initTRPC.context<Context>().create();
// 导出可重复使用的函数
export const router = t.router
export const publicProcedure = t.procedure
使用上下文
在 server/index.ts
的 procedure 中试试能不能使用上下文数据。
在 greet 中通过 opt.ctx
获取上下文内容,可以看到在 VScode 中还能自动识别出我们上下文中的内容,并且按 tab 可以自动补全。
……
greet: publicProcedure.input(z.object({
name: z.string().regex(/^[A-Z][a-zA-Z]*$/, '输入的名字必须是字母且首字母大写'),
})).output((value): string => {
// 必须是字符串并且以Hello开头
if (typeof value !== 'string') {
throw new Error('返回值必须是字符串');
}
if (!value.startsWith('Hello')) {
throw new Error('返回值必须以Hello开头');
}
return value;
}).query((opt) => {
const { input } = opt; // input 是经过验证的名字
console.log('接收到名字:', input.name);
console.log('ctx.user=', opt.ctx.);
return `Hello ${input.name}`;
}),
……
重新运行服务端程序,ts-node server/index.ts
客户端不变,仍然调用 greet 的 procedure。
在服务端控制台可以看到输出了我们在上下文中模拟的用户信息,在实际使用中可以通过 session 来获取真实的用户信息或其他我们需要的信息保存在上下文中供使用。