import { z } from "zod/v4"; import { auditLog } from "@/src/features/audit-logs/auditLog"; import { throwIfNoProjectAccess } from "@/src/features/rbac/utils/checkProjectAccess"; import { createTRPCRouter, protectedProjectProcedure, } from "@/src/server/api/trpc"; import { decrypt, encrypt } from "@langfuse/shared/encryption"; import { posthogIntegrationFormSchema } from "@/src/features/posthog-integration/types"; import { TRPCError } from "@trpc/server"; import { env } from "@/src/env.mjs"; export const posthogIntegrationRouter = createTRPCRouter({ get: protectedProjectProcedure .input(z.object({ projectId: z.string() })) .query(async ({ input, ctx }) => { throwIfNoProjectAccess({ session: ctx.session, projectId: input.projectId, scope: "integrations:CRUD", }); try { const dbConfig = await ctx.prisma.posthogIntegration.findFirst({ where: { projectId: input.projectId, }, }); if (!dbConfig) { return null; } const { encryptedPosthogApiKey, ...config } = dbConfig; return { ...config, posthogApiKey: decrypt(encryptedPosthogApiKey), }; } catch (e) { console.error("posthog integration get", e); throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", }); } }), update: protectedProjectProcedure .input(posthogIntegrationFormSchema.extend({ projectId: z.string() })) .mutation(async ({ input, ctx }) => { throwIfNoProjectAccess({ session: ctx.session, projectId: input.projectId, scope: "integrations:CRUD", }); if (!env.ENCRYPTION_KEY) { if (env.NEXT_PUBLIC_LANGFUSE_CLOUD_REGION) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Internal server error", }); } else { throw new TRPCError({ code: "BAD_REQUEST", message: "Missing environment variable: `ENCRYPTION_KEY`. Please consult our docs: https://langfuse.com/self-hosting", }); } } await auditLog({ session: ctx.session, action: "update", resourceType: "posthogIntegration", resourceId: input.projectId, }); const { posthogProjectApiKey, ...config } = input; const encryptedPosthogApiKey = encrypt(posthogProjectApiKey); await ctx.prisma.posthogIntegration.upsert({ where: { projectId: input.projectId, }, create: { projectId: input.projectId, posthogHostName: config.posthogHostname, encryptedPosthogApiKey, enabled: config.enabled, }, update: { encryptedPosthogApiKey, posthogHostName: config.posthogHostname, enabled: config.enabled, }, }); }), delete: protectedProjectProcedure .input(z.object({ projectId: z.string() })) .mutation(async ({ input, ctx }) => { try { throwIfNoProjectAccess({ session: ctx.session, projectId: input.projectId, scope: "integrations:CRUD", }); await auditLog({ session: ctx.session, action: "delete", resourceType: "posthogIntegration", resourceId: input.projectId, }); await ctx.prisma.posthogIntegration.delete({ where: { projectId: input.projectId, }, }); } catch (e) { console.log("posthog integration delete", e); throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", }); } }), });