BlairCurrey / trpc-koa-adapter

Add trpc to your koa server
https://www.npmjs.com/package/trpc-koa-adapter
MIT License
22 stars 5 forks source link

Using the Koa context and cookies in createContext #28

Open justinfagnani opened 2 months ago

justinfagnani commented 2 months ago

I have a custom auth middleware that runs before the trpc middleware that verifies the session cookie and puts the user ID in the Koa context. I would like to just use this user ID, but I can't seem to access it, so instead I have to scan headers to find the session cookie manually, then run duplicate auth code to verify the cookie.

Is there a way to access the Koa context in createContext()? I don't see anything on the CreateTrpcKoaContextOptions object. That would make custom data and cookies accessible. Thanks!

BlairCurrey commented 2 months ago

Hi @justinfagnani thank you for bringing this to my attention - definitely something that should be supported.

There is no way to do this currently but I have some changes penciled in that would add it. This adapter leverages trpc's generic nodeHTTPRequestHandler which deals in terms of req and res. I can add the koa context to req to make it available in createContext like so:

  const createContext = async ({ req, res }: CreateTrpcKoaContextOptions) => {
    const { userId } = req.koaCtx
    // ...
  };

This should meet the needs you described. Does make me try to imagine a more koa-friendly interface and the ramifications of that, but will probably opt for the solution described above for now.

BaileyNepe commented 2 months ago

Could you do something like this in the meantime?

export const createContext = (ctx: CreateTrpcKoaContextOptions, koaContext: Context) => ({
  koaContext,
  req: ctx.req,
  res: ctx.res,
});
app.use((koaCtx, next) =>
  createKoaMiddleware({
    router: apiRouter,
    prefix: '/trpc/v1',
    allowMethodOverride: true,
    createContext: (ctx) => createContext(ctx, koaCtx),
    onError({ error }) {
      logError(error);
    },
  })(koaCtx, next),
);
BlairCurrey commented 1 month ago

@BaileyNepe working for me - thanks for chiming in. Slightly more minimal example for adding the middleware (allowMethodOverride not required for example):

app.use((koaCtx, next) =>
  createKoaMiddleware({
    router: apiRouter,
    prefix: '/trpc/v1',
    createContext: (ctx) => createContext(ctx, koaCtx),
  })(koaCtx, next)
);

This has me reconsidering adding koaCtx to req. Making koaCtx available in the createContext fn as you have seems ideal. This is a good solution for the current adapter and I think we can move this higher order function to the middleware itself to keep adding the middleware simple.