Midday / apps /api /src /trpc /routers /user.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { updateUserSchema } from "@api/schemas/users";
import { resend } from "@api/services/resend";
import { createTRPCRouter, protectedProcedure } from "@api/trpc/init";
import { withRetryOnPrimary } from "@api/utils/db-retry";
import {
deleteUser,
getUserById,
getUserInvites,
updateUser,
} from "@midday/db/queries";
import { generateFileKey } from "@midday/encryption";
export const userRouter = createTRPCRouter({
me: protectedProcedure.query(async ({ ctx: { db, session } }) => {
// Cookie-based approach handles replication lag for new users via x-force-primary header
// Retry logic still handles connection errors/timeouts
const result = await withRetryOnPrimary(db, async (dbInstance) =>
getUserById(dbInstance, session.user.id),
);
if (!result) {
return undefined;
}
return {
...result,
fileKey: result.teamId ? await generateFileKey(result.teamId) : null,
};
}),
update: protectedProcedure
.input(updateUserSchema)
.mutation(async ({ ctx: { db, session }, input }) => {
return updateUser(db, {
id: session.user.id,
...input,
});
}),
delete: protectedProcedure.mutation(
async ({ ctx: { supabase, db, session } }) => {
const [data] = await Promise.all([
deleteUser(db, session.user.id),
supabase.auth.admin.deleteUser(session.user.id),
resend.contacts.remove({
email: session.user.email!,
audienceId: process.env.RESEND_AUDIENCE_ID!,
}),
]);
return data;
},
),
invites: protectedProcedure.query(async ({ ctx: { db, session } }) => {
if (!session.user.email) {
return [];
}
return getUserInvites(db, session.user.email);
}),
});