import { initTRPC, TRPCError } from '@trpc/server'; import { z } from 'zod'; import type { TRPCContext } from './types'; // Initialize tRPC with context const t = initTRPC.context().create(); // Middleware for authentication const isAuthenticated = t.middleware(({ ctx, next }) => { if (!ctx.userId) { throw new TRPCError({ code: 'UNAUTHORIZED', message: 'User not authenticated' }); } return next({ ctx: { ...ctx, userId: ctx.userId } }); }); // Middleware for database access const hasDb = t.middleware(({ ctx, next }) => { if (!ctx.db) { throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Database not available' }); } return next({ ctx: { ...ctx, db: ctx.db } }); }); // Base router export const baseRouter = t.router; // Procedure builders export const publicProcedure = t.procedure.use(hasDb); export const protectedProcedure = t.procedure.use(isAuthenticated).use(hasDb); const hasProjectAccess = t.middleware(({ ctx, next }) => { if (!ctx.projectId) { throw new TRPCError({ code: 'FORBIDDEN', message: 'Project access required' }); } return next({ ctx: { ...ctx, projectId: ctx.projectId } }); }); export const projectProcedure = t.procedure .use(isAuthenticated) .use(hasDb) .use(hasProjectAccess); // Validation middleware export const validateInput = (schema: T) => { return t.middleware(({ input, next }) => { const validated = schema.parse(input); return next({ input: validated }); }); }; export { t, TRPCError };