Openstatus www.openstatus.dev
at 4c0f4c00a38753a5d0dfd7e7b7b7706dec6f1503 175 lines 4.7 kB view raw
1import { TRPCError } from "@trpc/server"; 2import { z } from "zod"; 3 4import { Events } from "@openstatus/analytics"; 5import { and, eq } from "@openstatus/db"; 6import { page, pageSubscriber } from "@openstatus/db/src/schema"; 7 8import { createTRPCRouter, protectedProcedure } from "../trpc"; 9 10export const pageSubscriberRouter = createTRPCRouter({ 11 getPageSubscribersByPageId: protectedProcedure 12 .input(z.object({ id: z.number() })) 13 .query(async (opts) => { 14 const _page = await opts.ctx.db.query.page.findFirst({ 15 where: and( 16 eq(page.workspaceId, opts.ctx.workspace.id), 17 eq(page.id, opts.input.id), 18 ), 19 }); 20 21 if (!_page) { 22 throw new TRPCError({ 23 code: "UNAUTHORIZED", 24 message: "Unauthorized to get subscribers", 25 }); 26 } 27 28 const data = await opts.ctx.db.query.pageSubscriber.findMany({ 29 where: and(eq(pageSubscriber.pageId, _page.id)), 30 }); 31 return data; 32 }), 33 34 unsubscribeById: protectedProcedure 35 .input(z.object({ id: z.number() })) 36 .mutation(async (opts) => { 37 const subscriber = await opts.ctx.db.query.pageSubscriber.findFirst({ 38 where: and(eq(pageSubscriber.id, opts.input.id)), 39 }); 40 41 if (!subscriber) { 42 throw new TRPCError({ 43 code: "NOT_FOUND", 44 message: "Subscriber not found", 45 }); 46 } 47 48 const _page = await opts.ctx.db.query.page.findFirst({ 49 where: and( 50 eq(page.id, subscriber.pageId), 51 eq(page.workspaceId, opts.ctx.workspace.id), 52 ), 53 }); 54 55 if (!_page) { 56 throw new TRPCError({ 57 code: "UNAUTHORIZED", 58 message: "Unauthorized to unsubscribe", 59 }); 60 } 61 62 return await opts.ctx.db 63 .delete(pageSubscriber) 64 .where(eq(pageSubscriber.id, subscriber.id)); 65 }), 66 67 acceptSubscriberById: protectedProcedure 68 .meta({ track: Events.SubscribePage }) 69 .input(z.object({ id: z.number() })) 70 .mutation(async (opts) => { 71 const subscriber = await opts.ctx.db.query.pageSubscriber.findFirst({ 72 where: and(eq(pageSubscriber.id, opts.input.id)), 73 }); 74 75 if (!subscriber) { 76 throw new TRPCError({ 77 code: "NOT_FOUND", 78 message: "Subscriber not found", 79 }); 80 } 81 82 const _page = await opts.ctx.db.query.page.findFirst({ 83 where: and( 84 eq(page.id, subscriber.pageId), 85 eq(page.workspaceId, opts.ctx.workspace.id), 86 ), 87 }); 88 89 if (!_page) { 90 throw new TRPCError({ 91 code: "UNAUTHORIZED", 92 message: "Unauthorized to unsubscribe", 93 }); 94 } 95 96 return await opts.ctx.db 97 .update(pageSubscriber) 98 .set({ 99 acceptedAt: new Date(), 100 updatedAt: new Date(), 101 }) 102 .where(eq(pageSubscriber.id, subscriber.id)); 103 }), 104 105 // DASHBOARD 106 107 list: protectedProcedure 108 .input( 109 z.object({ 110 pageId: z.number(), 111 order: z.enum(["asc", "desc"]).optional(), 112 }), 113 ) 114 .query(async (opts) => { 115 const data = await opts.ctx.db.transaction(async (tx) => { 116 const _page = await tx.query.page.findFirst({ 117 where: and( 118 eq(page.workspaceId, opts.ctx.workspace.id), 119 eq(page.id, opts.input.pageId), 120 ), 121 }); 122 123 if (!_page) { 124 throw new TRPCError({ 125 code: "NOT_FOUND", 126 message: "Page not found", 127 }); 128 } 129 130 return await tx.query.pageSubscriber.findMany({ 131 where: eq(pageSubscriber.pageId, _page.id), 132 }); 133 }); 134 135 return data; 136 }), 137 138 delete: protectedProcedure 139 .input(z.object({ id: z.number(), pageId: z.number() })) 140 .mutation(async (opts) => { 141 await opts.ctx.db.transaction(async (tx) => { 142 const _page = await tx.query.page.findFirst({ 143 where: and( 144 eq(page.workspaceId, opts.ctx.workspace.id), 145 eq(page.id, opts.input.pageId), 146 ), 147 }); 148 149 if (!_page) { 150 throw new TRPCError({ 151 code: "NOT_FOUND", 152 message: "Page not found", 153 }); 154 } 155 156 const subscriber = await tx.query.pageSubscriber.findFirst({ 157 where: and( 158 eq(pageSubscriber.id, opts.input.id), 159 eq(pageSubscriber.pageId, opts.input.pageId), 160 ), 161 }); 162 163 if (!subscriber) { 164 throw new TRPCError({ 165 code: "NOT_FOUND", 166 message: "Subscriber not found", 167 }); 168 } 169 170 return await tx 171 .delete(pageSubscriber) 172 .where(eq(pageSubscriber.id, opts.input.id)); 173 }); 174 }), 175});