import { z } from 'zod'; import { APP_NOTIFICATION_INTEGRATION_ID, BASE_INTEGRATIONS, EMAIL_NOTIFICATION_INTEGRATION_ID, db, getNotificationRulesByProjectId, isBaseIntegration, } from '@openpanel/db'; import { zCreateNotificationRule } from '@openpanel/validation'; import { getProjectAccess } from '../access'; import { TRPCAccessError } from '../errors'; import { createTRPCRouter, protectedProcedure } from '../trpc'; export const notificationRouter = createTRPCRouter({ list: protectedProcedure .input(z.object({ projectId: z.string() })) .query(async ({ input }) => { return db.notification.findMany({ where: { projectId: input.projectId, }, orderBy: { createdAt: 'desc', }, include: { integration: { select: { name: true, }, }, notificationRule: { select: { name: true, }, }, }, take: 5000, }); }), rules: protectedProcedure .input(z.object({ projectId: z.string() })) .query(async ({ input }) => { return db.notificationRule .findMany({ where: { projectId: input.projectId, }, include: { integrations: true, }, orderBy: { createdAt: 'desc', }, }) .then((rules) => { return rules.map((rule) => { return { ...rule, integrations: [ ...BASE_INTEGRATIONS.filter((integration) => { return ( (integration.id === APP_NOTIFICATION_INTEGRATION_ID && rule.sendToApp) || (integration.id === EMAIL_NOTIFICATION_INTEGRATION_ID && rule.sendToEmail) ); }), ...rule.integrations, ], }; }); }); }), createOrUpdateRule: protectedProcedure .input(zCreateNotificationRule) .mutation(async ({ input }) => { // Clear the cache for the project await getNotificationRulesByProjectId.clear(input.projectId); if (input.id) { return db.notificationRule.update({ where: { id: input.id, }, data: { name: input.name, projectId: input.projectId, sendToApp: !!input.integrations.find( (id) => id === APP_NOTIFICATION_INTEGRATION_ID, ), sendToEmail: !!input.integrations.find( (id) => id === EMAIL_NOTIFICATION_INTEGRATION_ID, ), integrations: { set: input.integrations .filter((id) => !isBaseIntegration(id)) .map((id) => ({ id })), }, config: input.config, template: input.template || null, }, }); } return db.notificationRule.create({ data: { name: input.name, projectId: input.projectId, sendToApp: !!input.integrations.find( (id) => id === APP_NOTIFICATION_INTEGRATION_ID, ), sendToEmail: !!input.integrations.find( (id) => id === EMAIL_NOTIFICATION_INTEGRATION_ID, ), integrations: { connect: input.integrations .filter((id) => !isBaseIntegration(id)) .map((id) => ({ id })), }, config: input.config, template: input.template || null, }, }); }), deleteRule: protectedProcedure .input(z.object({ id: z.string() })) .mutation(async ({ input: { id }, ctx }) => { const rule = await db.notificationRule.findUniqueOrThrow({ where: { id, }, }); const access = await getProjectAccess({ userId: ctx.session.userId, projectId: rule.projectId, }); if (!access) { throw TRPCAccessError('You do not have access to this project'); } return db.notificationRule.delete({ where: { id, }, }); }), });