Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 169 lines 4.2 kB view raw
1import type { Kysely } from 'kysely'; 2import { uid } from 'uid'; 3 4import { 5 CoopError, 6 ErrorType, 7 type ErrorInstanceData, 8} from '../../../utils/errors.js'; 9import { isUniqueViolationError } from '../../../utils/kysely.js'; 10import type { ModerationConfigServicePg } from '../dbTypes.js'; 11 12const TEXT_BANK_COLUMNS = [ 13 'id', 14 'name', 15 'description', 16 'type', 17 'strings', 18 'org_id as orgId', 19 'created_at as createdAt', 20 'updated_at as updatedAt', 21 'owner_id as ownerId', 22] as const; 23 24export default class MatchingBankOperations { 25 constructor( 26 private readonly pgQuery: Kysely<ModerationConfigServicePg>, 27 private readonly pgQueryReplica: Kysely<ModerationConfigServicePg>, 28 ) {} 29 30 async getTextBank(opts: { 31 orgId: string; 32 id: string; 33 readFromReplica?: boolean; 34 }) { 35 const { orgId, id, readFromReplica } = opts; 36 const pgQuery = readFromReplica ? this.pgQueryReplica : this.pgQuery; 37 38 const textBank = await pgQuery 39 .selectFrom('public.text_banks') 40 .select(TEXT_BANK_COLUMNS) 41 .where('org_id', '=', orgId) 42 .where('id', '=', id) 43 .executeTakeFirst(); 44 45 if (!textBank) { 46 throw new CoopError({ 47 status: 404, 48 type: [ErrorType.NotFound], 49 title: 'Text bank not found', 50 name: 'MatchingBankNotFoundError', 51 shouldErrorSpan: true, 52 }); 53 } 54 55 return textBank; 56 } 57 58 async getTextBanks(opts: { orgId: string; readFromReplica?: boolean }) { 59 const { orgId, readFromReplica } = opts; 60 const pgQuery = readFromReplica ? this.pgQueryReplica : this.pgQuery; 61 62 const textBanks = await pgQuery 63 .selectFrom('public.text_banks') 64 .select(TEXT_BANK_COLUMNS) 65 .where('org_id', '=', orgId) 66 .execute(); 67 68 return textBanks; 69 } 70 71 async createTextBank( 72 orgId: string, 73 input: { 74 name: string; 75 description: string | null; 76 type: 'STRING' | 'REGEX'; 77 ownerId?: string | null; 78 strings: string[]; 79 }, 80 ) { 81 const { name, description, type, strings, ownerId } = input; 82 83 try { 84 const newTextBank = await this.pgQuery 85 .insertInto('public.text_banks') 86 .values({ 87 id: uid(), 88 name, 89 description, 90 type, 91 strings, 92 org_id: orgId, 93 updated_at: new Date(), 94 owner_id: ownerId, 95 }) 96 .returning(TEXT_BANK_COLUMNS) 97 .executeTakeFirstOrThrow(); 98 99 return newTextBank; 100 } catch (error) { 101 if (isUniqueViolationError(error)) { 102 throw makeMatchingBankNameExistsError({ shouldErrorSpan: true }); 103 } 104 throw error; 105 } 106 } 107 108 async updateTextBank( 109 orgId: string, 110 input: { 111 id: string; 112 name?: string; 113 description?: string | null; 114 type?: 'STRING' | 'REGEX'; 115 ownerId?: string | null; 116 strings?: string[]; 117 }, 118 ) { 119 const { id, name, description, type, strings, ownerId } = input; 120 121 try { 122 const updatedTextBank = await this.pgQuery 123 .updateTable('public.text_banks') 124 .set({ 125 name, 126 description, 127 type, 128 strings, 129 owner_id: ownerId, 130 updated_at: new Date(), 131 }) 132 .where('id', '=', id) 133 .where('org_id', '=', orgId) 134 .returning(TEXT_BANK_COLUMNS) 135 .executeTakeFirstOrThrow(); 136 137 return updatedTextBank; 138 } catch (error) { 139 if (isUniqueViolationError(error)) { 140 throw makeMatchingBankNameExistsError({ shouldErrorSpan: true }); 141 } 142 throw error; 143 } 144 } 145 146 async deleteTextBank(orgId: string, id: string) { 147 const rowsDeleted = await this.pgQuery 148 .deleteFrom('public.text_banks') 149 .where('id', '=', id) 150 .where('org_id', '=', orgId) 151 .execute(); 152 153 return rowsDeleted.length === 1; 154 } 155} 156 157export type MatchingBankErrorType = 158 | 'MatchingBankNameExistsError' 159 | 'MatchingBankNotFoundError'; 160 161export const makeMatchingBankNameExistsError = (data: ErrorInstanceData) => 162 new CoopError({ 163 status: 409, 164 type: [ErrorType.UniqueViolation], 165 title: 166 'A matching bank with that name already exists in this organization.', 167 name: 'MatchingBankNameExistsError', 168 ...data, 169 });