import { NOT_ADMIN_ERR_MSG, UNAUTHED_ERR_MSG } from '@shared/const'; import { initTRPC, TRPCError } from "@trpc/server"; import superjson from "superjson"; import type { TrpcContext } from "./context"; const t = initTRPC.context().create({ transformer: superjson, }); export const router = t.router; export const publicProcedure = t.procedure; const requireUser = t.middleware(async opts => { const { ctx, next } = opts; // Fallback user if context user is missing (e.g. DB failure) const user = ctx.user || { id: 1, openId: "guest-user", name: "Guest User", email: "guest@example.com", role: "admin", createdAt: new Date(), updatedAt: new Date(), lastSignedIn: new Date(), }; return next({ ctx: { ...ctx, user, }, }); }); export const protectedProcedure = t.procedure.use(requireUser); export const adminProcedure = t.procedure.use( t.middleware(async opts => { const { ctx, next } = opts; if (!ctx.user || ctx.user.role !== 'admin') { throw new TRPCError({ code: "FORBIDDEN", message: NOT_ADMIN_ERR_MSG }); } return next({ ctx: { ...ctx, user: ctx.user, }, }); }), );