typescript 无法访问tRPC createContext(express)中的用户对象

31moq8wy  于 2022-11-26  发布在  TypeScript
关注(0)|答案(2)|浏览(152)

我遇到了一个问题,我的tRPC配置无法访问请求对象上的快速会话。
我正在使用passport.js与谷歌和Facebook提供商,并在任何正常的http路由(不是在tRPC路由器),我得到的用户信息时,调用req.user
app.ts:

import * as trpc from '@trpc/server';
import * as trpcExpress from '@trpc/server/adapters/express';

const appRouter = trpc
    .router()
    .mutation('addTodo', {
        input: z.string(),
        resolve: ({input, ctx}) => {
            // Add a todo
        },
    });

const app = express();
app.use(
    session({
        secret: 'use an env-variable here',
    }),
);
app.use(passport.initialize());
app.use(passport.session());

app.use(
    '/trpc',
    trpcExpress.createExpressMiddleware({
        router: appRouter,
        createContext: (ctx: trpcExpress.CreateExpressContextOptions) => {
            // === HERE LIES THE ISSUE ===
            console.log(ctx.req.user);
            //                   ^ THIS RETURNS UNDEFINED
            return ctx;
        },
    }),
);

app.get("ping", (req, res) => {
    console.log(req.user);
    //                ^ THIS RETURNS THE USER
    res.send("pong");
})

说tRPC不支持给予你用户很容易,但一定有某种变通办法,对吗?

daolsyd0

daolsyd01#

我不知道passport是如何工作的,因为我通常使用express会话,但也许概念是相同的

function createContext(opts: trpcExpress.CreateExpressContextOptions) {
  let user = {};
  if (opts.req.session.user) {
    user = opts.req.session.user;
  }

  return {
    user
  };
}

type Context = inferAsyncReturnType<typeof createContext>;
const t = initTRPC.context<Context>().create();
const appRouter = t.router({
  hello: t.procedure.query(({ ctx, input }) => {
    console.log("user", ctx.req?.session?.user);
    console.log({ input });
    return "Hello world";
  }),

  session: t.procedure.query(({ ctx, input }) => {
    console.log({ input });
    ctx.req.session.user = { name: "jane" };
    return "session created";
  }),
});

app.use(
  "/trpc",
  trpcExpress.createExpressMiddleware({ router: appRouter, createContext })
);

tldr:检查用户的req.session对象,然后将其添加到上下文返回的对象中

b4wnujal

b4wnujal2#

我也有类似的问题,尽管是 typescript 。我注意到请求类型不同,必须键入不同的类型才能匹配,这样我就可以让我的会话可用。
如果您使用的是typescript,则可以如下所示键入上下文

import { CreateExpressContextOptions } from '@trpc/server/adapters/express'
import { Request } from 'express'
import session from 'express-session'

// create my session type by extending the session type from 'express-session' and adding my userId on it
export type Session = session.Session &
  Partial<session.SessionData> & { userId?: string }

// Replace the req object from trpc's CreateExpressContextOptions with the express request and add my session onto it
type ExpressRequest = Omit<CreateExpressContextOptions, 'req'> & {
  req: Request & { session: Session }
}

export const createContext = ({
  req,
  res,
}: ExpressRequest) => {
  return {
    req,
    res,
  }
}

export type Context = inferAsyncReturnType<typeof createContext>

相关问题