refactor(db): migrate staff and app actions from Prisma facade to Drizzle

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-31 21:35:05 +02:00
1 parent 9854719cfd
commit ed9c23c702
85 files changed
+2612 -1832

No files matched your search

+103 -56
View File
@@ -1,9 +1,17 @@
"use server";
import { and, count, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import {
db,
WebsiteEvent,
WebsiteEventPrize,
WebsiteEventRegistration,
WebsiteEventType,
WebsiteEventWinner,
} from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import { prisma } from "@/lib/prisma";
import { adminAction, authAction } from "@/lib/safe-action";
import { ActionError, actionError, actionOk } from "@/lib/safe-action-shared";
import { logAudit } from "@/lib/services/audit";
@@ -21,17 +29,16 @@ import {
export const createEventType = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: eventTypeSchema },
async (ctx) => {
const eventType = await prisma.websiteEventType.create({
data: ctx.data,
});
const [result] = await db.insert(WebsiteEventType).values(ctx.data);
const eventTypeId = Number(result.insertId);
logAudit({
userId: ctx.session.user.id,
action: "event_type_create",
target: "WebsiteEventType",
targetId: eventType.id,
after: { name: eventType.name },
targetId: eventTypeId,
after: { name: ctx.data.name },
});
return actionOk({ id: eventType.id });
return actionOk({ id: eventTypeId });
},
);
@@ -43,12 +50,17 @@ export const updateEventType = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: updateEventTypeInput },
async (ctx) => {
const { id, ...data } = ctx.data;
const existing = await prisma.websiteEventType.findUnique({
where: { id },
});
const [existing] = await db
.select({ id: WebsiteEventType.id, name: WebsiteEventType.name })
.from(WebsiteEventType)
.where(eq(WebsiteEventType.id, id))
.limit(1);
if (!existing) throw new ActionError("Event type not found");
await prisma.websiteEventType.update({ where: { id }, data });
await db
.update(WebsiteEventType)
.set(data)
.where(eq(WebsiteEventType.id, id));
logAudit({
userId: ctx.session.user.id,
action: "event_type_update",
@@ -68,12 +80,16 @@ const deleteEventTypeInput = z.object({
export const deleteEventType = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: deleteEventTypeInput },
async (ctx) => {
const existing = await prisma.websiteEventType.findUnique({
where: { id: ctx.data.id },
});
const [existing] = await db
.select({ id: WebsiteEventType.id, name: WebsiteEventType.name })
.from(WebsiteEventType)
.where(eq(WebsiteEventType.id, ctx.data.id))
.limit(1);
if (!existing) throw new ActionError("Event type not found");
await prisma.websiteEventType.delete({ where: { id: ctx.data.id } });
await db
.delete(WebsiteEventType)
.where(eq(WebsiteEventType.id, ctx.data.id));
logAudit({
userId: ctx.session.user.id,
action: "event_type_delete",
@@ -90,20 +106,21 @@ export const deleteEventType = adminAction(
export const createEvent = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: createEventSchema },
async (ctx) => {
const event = await prisma.websiteEvent.create({
data: {
...ctx.data,
hostUserId: Number(ctx.session.user.id),
},
const now = new Date();
const [result] = await db.insert(WebsiteEvent).values({
...ctx.data,
hostUserId: Number(ctx.session.user.id),
updatedAt: now,
});
const eventId = Number(result.insertId);
logAudit({
userId: ctx.session.user.id,
action: "event_create",
target: "WebsiteEvent",
targetId: event.id,
after: { title: event.title },
targetId: eventId,
after: { title: ctx.data.title },
});
return actionOk({ id: event.id });
return actionOk({ id: eventId });
},
);
@@ -115,10 +132,21 @@ export const updateEvent = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: updateEventInput },
async (ctx) => {
const { id, ...data } = ctx.data;
const existing = await prisma.websiteEvent.findUnique({ where: { id } });
const [existing] = await db
.select({
id: WebsiteEvent.id,
title: WebsiteEvent.title,
status: WebsiteEvent.status,
})
.from(WebsiteEvent)
.where(eq(WebsiteEvent.id, id))
.limit(1);
if (!existing) throw new ActionError("Event not found");
await prisma.websiteEvent.update({ where: { id }, data });
await db
.update(WebsiteEvent)
.set({ ...data, updatedAt: new Date() })
.where(eq(WebsiteEvent.id, id));
logAudit({
userId: ctx.session.user.id,
action: "event_update",
@@ -138,12 +166,14 @@ const deleteEventInput = z.object({
export const deleteEvent = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: deleteEventInput },
async (ctx) => {
const existing = await prisma.websiteEvent.findUnique({
where: { id: ctx.data.id },
});
const [existing] = await db
.select({ id: WebsiteEvent.id, title: WebsiteEvent.title })
.from(WebsiteEvent)
.where(eq(WebsiteEvent.id, ctx.data.id))
.limit(1);
if (!existing) throw new ActionError("Event not found");
await prisma.websiteEvent.delete({ where: { id: ctx.data.id } });
await db.delete(WebsiteEvent).where(eq(WebsiteEvent.id, ctx.data.id));
logAudit({
userId: ctx.session.user.id,
action: "event_delete",
@@ -160,8 +190,8 @@ export const deleteEvent = adminAction(
export const addEventPrize = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: eventPrizeSchema },
async (ctx) => {
const prize = await prisma.websiteEventPrize.create({ data: ctx.data });
return actionOk({ id: prize.id });
const [result] = await db.insert(WebsiteEventPrize).values(ctx.data);
return actionOk({ id: Number(result.insertId) });
},
);
@@ -170,7 +200,9 @@ const deletePrizeInput = z.object({ id: z.coerce.number().int().positive() });
export const deleteEventPrize = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: deletePrizeInput },
async (ctx) => {
await prisma.websiteEventPrize.delete({ where: { id: ctx.data.id } });
await db
.delete(WebsiteEventPrize)
.where(eq(WebsiteEventPrize.id, ctx.data.id));
return actionOk();
},
);
@@ -180,19 +212,20 @@ export const deleteEventPrize = adminAction(
export const addEventWinner = adminAction(
{ permission: PERMS.EVENTS_EDIT, schema: eventWinnerSchema },
async (ctx) => {
const winner = await prisma.websiteEventWinner.create({ data: ctx.data });
const [result] = await db.insert(WebsiteEventWinner).values(ctx.data);
const winnerId = Number(result.insertId);
logAudit({
userId: ctx.session.user.id,
action: "event_winner_add",
target: "WebsiteEventWinner",
targetId: winner.id,
targetId: winnerId,
after: {
eventId: ctx.data.eventId,
userId: ctx.data.userId,
position: ctx.data.position,
},
});
return actionOk({ id: winner.id });
return actionOk({ id: winnerId });
},
);
@@ -211,13 +244,18 @@ export const registerForEvent = authAction(
return actionError("Unauthorized");
}
const event = await prisma.websiteEvent.findUnique({
where: { id: ctx.data.eventId },
include: {
type: true,
_count: { select: { registrations: true } },
},
});
const [event] = await db
.select({
id: WebsiteEvent.id,
status: WebsiteEvent.status,
endsAt: WebsiteEvent.endsAt,
maxPlayers: WebsiteEvent.maxPlayers,
minRank: WebsiteEventType.minRank,
})
.from(WebsiteEvent)
.innerJoin(WebsiteEventType, eq(WebsiteEvent.typeId, WebsiteEventType.id))
.where(eq(WebsiteEvent.id, ctx.data.eventId))
.limit(1);
if (!event) return actionError("Event not found");
if (event.status !== "published") {
@@ -226,28 +264,37 @@ export const registerForEvent = authAction(
if (event.endsAt && event.endsAt.getTime() < Date.now()) {
return actionError("This event has already ended");
}
if (event.type.minRank > 0) {
if (event.minRank > 0) {
const rank = Number(ctx.session.user.rank ?? 0);
if (rank < event.type.minRank) {
if (rank < event.minRank) {
return actionError("Your rank is too low to join this event");
}
}
if (
event.maxPlayers != null &&
event._count.registrations >= event.maxPlayers
) {
return actionError("This event is full");
if (event.maxPlayers != null) {
const [regCount] = await db
.select({ value: count() })
.from(WebsiteEventRegistration)
.where(eq(WebsiteEventRegistration.eventId, event.id));
if ((regCount?.value ?? 0) >= event.maxPlayers) {
return actionError("This event is full");
}
}
const existing = await prisma.websiteEventRegistration.findUnique({
where: {
eventId_userId: { eventId: event.id, userId },
},
});
const [existing] = await db
.select({ id: WebsiteEventRegistration.id })
.from(WebsiteEventRegistration)
.where(
and(
eq(WebsiteEventRegistration.eventId, event.id),
eq(WebsiteEventRegistration.userId, userId),
),
)
.limit(1);
if (existing) return actionError("You are already registered");
await prisma.websiteEventRegistration.create({
data: { eventId: event.id, userId },
await db.insert(WebsiteEventRegistration).values({
eventId: event.id,
userId,
});
revalidatePath("/events");