import type EventEmitter from 'node:events' import type { Knex } from 'knex' import _ from 'lodash' import RestQueriesFactory from '../../lib/knex_rest_queries.ts' import type { NewAdmission } from './types.ts' export const columns = ['id', 'regex', 'createdAt', 'createdById', 'modifiedAt', 'modifiedById'] export const Selects = (knex: Knex) => ({ roles: knex .select(knex.raw('json_agg(roles)')) .from( knex .select('id', 'name') .from('role') .innerJoin('admissions_roles', 'role.id', 'admissions_roles.role_id') .where('admissions_roles.admission_id', knex.ref('admission.id')) .orderBy('name') .as('roles'), ), createdBy: knex .select(knex.raw('row_to_json("user")')) .from(knex.select('id', 'email').from('user').where('id', knex.ref('admission.created_by_id')).as('user')), }) export default ({ knex, emitter }: { emitter: EventEmitter; knex: Knex }) => { const selects = Selects(knex) const queries = RestQueriesFactory({ knex, emitter, table: 'admission', columns, selects, }) return { ...queries, create(json: NewAdmission, client = knex) { return client.transaction(async (trx) => { const admission = await queries.create(_.omit(json, 'roles'), trx) const roles = json.roles.map((role) => ({ admission_id: admission.id, role_id: role, })) await trx.table('admissions_roles').insert(roles) return queries.findById(admission.id, trx) }) }, update(id: number, json: NewAdmission, client = knex) { return client.transaction(async (trx) => { await queries.update(id, _.omit(json, ['roles']), trx) // TODO decide how to handle this, ie should an empty array delete all? if (json.roles?.length) { await trx.table('admissions_roles').delete().where('admission_id', id).whereNotIn('role_id', json.roles) await trx.raw( `INSERT INTO admissions_roles(admission_id, role_id) SELECT :admissionId, role_ids FROM unnest(:roleIds::int[]) AS role_ids WHERE NOT EXISTS (SELECT 1 FROM admissions_roles WHERE admission_id = :admissionId AND role_id = role_ids)`, { admissionId: id, roleIds: json.roles }, ) } return queries.findById(id, trx) }) }, findMatches(email: string, client = knex) { return client('admission') .select([...columns, selects]) .then((admissions) => { if (admissions) { admissions = admissions.filter((admission) => { const regex = new RegExp(admission.regex) return regex.test(email) }) // if (!admissions.length) admissions = undefined } return admissions }) }, } }