typescript - tRPC 如何封裝中介軟體?
我正在嘗試把中介軟體放到它自己的函數中,但我在給它正確的 TypeScript 類型時遇到了困難。
目前我正在如下編寫中介軟體,但這並不理想,因為從中介軟體返回後,context 和 metadata 的類型資訊會丟失。
在中介軟體內
import { MiddlewareFunction } from "@trpc/server/dist/declarations/src/internals/middlewares";
import { TRPCError } from "@trpc/server";
export const authMiddleware : MiddlewareFunction<any, any, any> = async ({ ctx, next, path, rawInput, type, meta }) => {
if (!meta?.auth)
return next();
// some random logic
return next();
}
這就是我想要消費它的方式
createRouter()
.middleware(authMiddleware)
.mutation('', {
meta: {
auth: "user",
appCheck: true
},
input: object({
workshopId: idSchema,
}),
resolve: async ({ input, ctx, type }) => {
// Here ctx has been widened to any
// ...
提前感謝你。
答案#1
const t = initTRPC.context<Context>().create();
const middleware = t.middleware;
const authMiddleware = t.middleware(({ next, ctx }) => {
if (!ctx.session) {
throw new TRPCError({
code: "UNAUTHORIZED",
});
}
return next({
ctx: {
// Infers the `session` as non-nullable
session: ctx.session,
},
});
})
答案#2
我遇到了同樣的問題(trpc v9.27),所以我直接從 trpc 路由器上的中介軟體方法取得了類型。
import * as trpc from "@trpc/server"
// context for router
const createContext = async () => ({hi: "hi"})
type Context = trpc.inferAsyncReturnType<typeof createContext>
// router initialization function
const trpcRouter = () => trpc.router<Context>()
const router = trpcRouter()
// don't forget to add the return type for your middleware
// in the generic
const init = router.middleware<Context>
type MiddlewareFunction = Parameters<typeof init>[0]
// now use for your middlewares
const myMiddleware: MiddlewareFunction = ({next, ctx}) => {
console.log("my context", ctx)
next()
}
// go nuts and use it where you want
export const myCoolRoutes = router
.middleware(myMiddleware)
.query("coolio", ({ctx}) => true)
請注意,如果你打算在你的某個中介軟體函數中更改上下文,router.middleware 泛型應該要反映這一點。例如,如果你想在中介軟體中向上下文添加鍵,你需要定義一個新的上下文類型,來添加你想要的鍵:
// add your keys to context
type keys = {newKey: number}
const mutatingMiddleware = router.middleware<Context & keys>
type Mutate = Parameters<typeof mutatingMiddleware>[0]
const mutatator: Mutate = ({ctx, next}) => {
return next({ctx: {...ctx, newKey: 0}})
}
希望這對你有幫助。
