Files
stats/packages/trpc/src/routers/notification.ts
Carl-Gerhard Lindesvärd 81a7e5d62e feat: dashboard v2, esm, upgrades (#211)
* esm

* wip

* wip

* wip

* wip

* wip

* wip

* subscription notice

* wip

* wip

* wip

* fix envs

* fix: update docker build

* fix

* esm/types

* delete dashboard :D

* add patches to dockerfiles

* update packages + catalogs + ts

* wip

* remove native libs

* ts

* improvements

* fix redirects and fetching session

* try fix favicon

* fixes

* fix

* order and resize reportds within a dashboard

* improvements

* wip

* added userjot to dashboard

* fix

* add op

* wip

* different cache key

* improve date picker

* fix table

* event details loading

* redo onboarding completely

* fix login

* fix

* fix

* extend session, billing and improve bars

* fix

* reduce price on 10M
2025-10-16 12:27:44 +02:00

153 lines
4.1 KiB
TypeScript

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,
},
});
}),
});