162 lines
4.3 KiB
TypeScript
162 lines
4.3 KiB
TypeScript
import * as z from 'zod'
|
|
import type { FastifyPluginCallbackZod } from 'fastify-type-provider-zod'
|
|
import { sql } from 'kysely'
|
|
import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres'
|
|
|
|
import { AdmissionSchema, RoleSchema } from '../../schemas/db.ts'
|
|
|
|
const admissionsPlugin: FastifyPluginCallbackZod = (fastify, _options, done) => {
|
|
const { db } = fastify
|
|
|
|
// fastify.addHook('onRequest', fastify.auth)
|
|
|
|
fastify.route({
|
|
url: '/',
|
|
method: 'GET',
|
|
schema: {
|
|
response: {
|
|
200: z.array(
|
|
AdmissionSchema.extend({
|
|
roles: z.array(RoleSchema.pick({ id: true, name: true })),
|
|
}),
|
|
),
|
|
},
|
|
},
|
|
handler() {
|
|
return db
|
|
.selectFrom('admission as a')
|
|
.selectAll()
|
|
.select((eb) => [
|
|
jsonObjectFrom(eb.selectFrom('user as u').select(['u.id', 'u.email']).whereRef('u.id', '=', 'a.createdById'))
|
|
.$notNull()
|
|
.as('createdBy'),
|
|
jsonObjectFrom(
|
|
eb.selectFrom('user as u').select(['u.id', 'u.email']).whereRef('u.id', '=', 'a.modifiedById'),
|
|
).as('modifiedBy'),
|
|
jsonArrayFrom(
|
|
eb
|
|
.selectFrom('role as r')
|
|
.innerJoin('admissions_roles as ra', 'ra.roleId', 'r.id')
|
|
.select(['r.id', 'r.name'])
|
|
.whereRef('ra.admissionId', '=', 'a.id'),
|
|
).as('roles'),
|
|
])
|
|
.execute()
|
|
},
|
|
})
|
|
|
|
fastify.route({
|
|
url: '/',
|
|
method: 'POST',
|
|
schema: {
|
|
body: AdmissionSchema.pick({ regex: true }).extend({
|
|
roles: z.array(z.coerce.number()),
|
|
}),
|
|
response: {
|
|
201: AdmissionSchema,
|
|
},
|
|
},
|
|
async handler(request) {
|
|
const { roles, ...admissionProps } = request.body
|
|
|
|
const trx = await db.startTransaction().execute()
|
|
|
|
const admission = await trx
|
|
.insertInto('admission')
|
|
.values({ ...admissionProps, createdById: request.session.userId })
|
|
.returningAll()
|
|
.executeTakeFirstOrThrow()
|
|
|
|
await trx
|
|
.insertInto('admissions_roles')
|
|
.values(roles.map((roleId) => ({ admissionId: admission.id, roleId })))
|
|
.execute()
|
|
|
|
await trx.commit().execute()
|
|
|
|
return {
|
|
...admission,
|
|
roles: await db
|
|
.selectFrom('role as r')
|
|
.innerJoin('admissions_roles as ar', 'ar.roleId', 'r.id')
|
|
.select(['r.id', 'r.name'])
|
|
.execute(),
|
|
}
|
|
},
|
|
})
|
|
|
|
fastify.route({
|
|
url: '/:id',
|
|
method: 'DELETE',
|
|
schema: {
|
|
params: z.object({
|
|
id: z.coerce.number(),
|
|
}),
|
|
response: {
|
|
204: {},
|
|
404: {},
|
|
},
|
|
},
|
|
handler() {
|
|
return {}
|
|
|
|
// return queries.removeById(request.params.id).then((count: number) => reply.status(count > 0 ? 204 : 404).send())
|
|
},
|
|
})
|
|
|
|
fastify.route({
|
|
url: '/:id',
|
|
method: 'PATCH',
|
|
schema: {
|
|
params: z.object({
|
|
id: z.coerce.number(),
|
|
}),
|
|
body: AdmissionSchema.pick({ regex: true }).extend({
|
|
roles: z.array(z.coerce.number()),
|
|
}),
|
|
response: {
|
|
204: {},
|
|
},
|
|
},
|
|
async handler(request) {
|
|
const { roles, ...admissionProps } = request.body
|
|
const trx = await db.startTransaction().execute()
|
|
const admissionId = request.params.id
|
|
|
|
const [updatedAdmission] = await Promise.all([
|
|
trx
|
|
.updateTable('admission')
|
|
.set({ ...admissionProps, modifiedById: request.session.userId })
|
|
.where('id', '=', request.params.id)
|
|
.returningAll()
|
|
.execute(),
|
|
trx
|
|
.deleteFrom('admissions_roles')
|
|
.where('admissionId', '=', request.params.id)
|
|
.where('roleId', 'not in', roles)
|
|
.execute(),
|
|
sql`INSERT INTO admissions_roles("admissionId", "roleId")
|
|
SELECT ${admissionId}, "roleIds" FROM unnest(${roles}::int[]) AS "roleIds" WHERE NOT EXISTS
|
|
(SELECT 1 FROM admissions_roles WHERE "admissionId" = ${request.params.id} AND "roleId" = "roleIds")`.execute(
|
|
trx,
|
|
),
|
|
])
|
|
|
|
await trx.commit().execute()
|
|
|
|
return {
|
|
...updatedAdmission,
|
|
roles: await db
|
|
.selectFrom('role as r')
|
|
.innerJoin('admissions_roles as ar', 'ar.roleId', 'r.id')
|
|
.select(['r.id', 'r.name'])
|
|
.execute(),
|
|
}
|
|
},
|
|
})
|
|
|
|
done()
|
|
}
|
|
|
|
export default admissionsPlugin
|