import { z } from 'zod'; import { BASE_INTEGRATIONS, db } from '@openpanel/db'; import { getSlackInstallUrl } from '@openpanel/integrations/src/slack'; import { type ISlackConfig, zCreateDiscordIntegration, zCreateSlackIntegration, zCreateWebhookIntegration, } from '@openpanel/validation'; import { getOrganizationAccessCached } from '../access'; import { TRPCAccessError } from '../errors'; import { createTRPCRouter, protectedProcedure } from '../trpc'; export const integrationRouter = createTRPCRouter({ get: protectedProcedure .input(z.object({ id: z.string() })) .query(async ({ input, ctx }) => { const integration = await db.integration.findUniqueOrThrow({ where: { id: input.id, }, }); const access = await getOrganizationAccessCached({ userId: ctx.session.userId, organizationId: integration.organizationId, }); if (!access) { throw TRPCAccessError('You do not have access to this project'); } return integration; }), list: protectedProcedure .input(z.object({ organizationId: z.string() })) .query(async ({ input }) => { const integrations = await db.integration.findMany({ where: { organizationId: input.organizationId, config: { not: {}, }, }, }); return [...BASE_INTEGRATIONS, ...integrations]; }), createOrUpdateSlack: protectedProcedure .input(zCreateSlackIntegration) .mutation(async ({ input }) => { if (input.id) { const res = await db.integration.update({ where: { id: input.id, organizationId: input.organizationId, }, data: { name: input.name, // This is empty and will be filled by the webhook config: {} as ISlackConfig, }, }); return { ...res, slackInstallUrl: await getSlackInstallUrl({ integrationId: res.id, organizationId: input.organizationId, projectId: input.projectId, }), }; } const res = await db.integration.create({ data: { name: input.name, organizationId: input.organizationId, // This is empty and will be filled by the webhook config: {} as ISlackConfig, }, }); return { ...res, slackInstallUrl: await getSlackInstallUrl({ integrationId: res.id, organizationId: input.organizationId, projectId: input.projectId, }), }; }), createOrUpdate: protectedProcedure .input(z.union([zCreateDiscordIntegration, zCreateWebhookIntegration])) .mutation(async ({ input }) => { if (input.id) { return db.integration.update({ where: { id: input.id, organizationId: input.organizationId, }, data: { name: input.name, config: input.config, }, }); } return db.integration.create({ data: { name: input.name, organizationId: input.organizationId, config: input.config, }, }); }), delete: protectedProcedure .input(z.object({ id: z.string() })) .mutation(async ({ input: { id }, ctx }) => { const integration = await db.integration.findUniqueOrThrow({ where: { id, }, }); const access = await getOrganizationAccessCached({ userId: ctx.session.userId, organizationId: integration.organizationId, }); if (!access) { throw TRPCAccessError('You do not have access to this project'); } return db.integration.delete({ where: { id, }, }); }), });