import type { YogaInitialContext } from "graphql-yoga"; import type { FastifyRequest, FastifyReply } from "fastify"; import type { Context } from "./builder"; import { getSession, setSession } from "../lib/auth"; import { db } from "../db/connection"; import { redis } from "../lib/auth"; import { users } from "../db/schema/index"; import { eq } from "drizzle-orm"; type ServerContext = { req: FastifyRequest; reply: FastifyReply; db: typeof db; redis: typeof redis; }; export async function buildContext(ctx: YogaInitialContext & ServerContext): Promise { const request = ctx.request; const cookieHeader = request.headers.get("cookie") || ""; // Parse session_token from cookies const cookies = Object.fromEntries( cookieHeader.split(";").map((c) => { const [k, ...v] = c.trim().split("="); return [k.trim(), v.join("=")]; }), ); const token = cookies["session_token"]; let currentUser = null; if (token) { const session = await getSession(token); // also slides TTL if (session) { const dbInstance = ctx.db || db; const [dbUser] = await dbInstance .select() .from(users) .where(eq(users.id, session.id)) .limit(1); if (dbUser) { currentUser = { id: dbUser.id, email: dbUser.email, role: (dbUser.role === "admin" ? "viewer" : dbUser.role) as "model" | "viewer", is_admin: dbUser.is_admin, first_name: dbUser.first_name, last_name: dbUser.last_name, artist_name: dbUser.artist_name, slug: dbUser.slug, avatar: dbUser.avatar, }; // Refresh cached session with up-to-date data await setSession(token, currentUser); } } } return { db: ctx.db || db, redis: ctx.redis || redis, currentUser, request, reply: ctx.reply, }; }