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

+74 -41
View File
@@ -1,9 +1,15 @@
"use server";
import { and, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { z } from "zod";
import {
db,
WebsitePoll,
WebsitePollQuestion,
WebsitePollVote,
} 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";
@@ -19,15 +25,20 @@ import {
export const createPoll = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: createPollSchema },
async (ctx) => {
const poll = await prisma.websitePoll.create({ data: ctx.data });
const now = new Date();
const [result] = await db.insert(WebsitePoll).values({
...ctx.data,
updatedAt: now,
});
const pollId = Number(result.insertId);
logAudit({
userId: ctx.session.user.id,
action: "poll_create",
target: "WebsitePoll",
targetId: poll.id,
after: { title: poll.title },
targetId: pollId,
after: { title: ctx.data.title },
});
return actionOk({ id: poll.id });
return actionOk({ id: pollId });
},
);
@@ -39,10 +50,21 @@ export const updatePoll = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: updatePollInput },
async (ctx) => {
const { id, ...data } = ctx.data;
const existing = await prisma.websitePoll.findUnique({ where: { id } });
const [existing] = await db
.select({
id: WebsitePoll.id,
title: WebsitePoll.title,
status: WebsitePoll.status,
})
.from(WebsitePoll)
.where(eq(WebsitePoll.id, id))
.limit(1);
if (!existing) throw new ActionError("Poll not found");
await prisma.websitePoll.update({ where: { id }, data });
await db
.update(WebsitePoll)
.set({ ...data, updatedAt: new Date() })
.where(eq(WebsitePoll.id, id));
logAudit({
userId: ctx.session.user.id,
action: "poll_update",
@@ -62,12 +84,14 @@ const deletePollInput = z.object({
export const deletePoll = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: deletePollInput },
async (ctx) => {
const existing = await prisma.websitePoll.findUnique({
where: { id: ctx.data.id },
});
const [existing] = await db
.select({ id: WebsitePoll.id, title: WebsitePoll.title })
.from(WebsitePoll)
.where(eq(WebsitePoll.id, ctx.data.id))
.limit(1);
if (!existing) throw new ActionError("Poll not found");
await prisma.websitePoll.delete({ where: { id: ctx.data.id } });
await db.delete(WebsitePoll).where(eq(WebsitePoll.id, ctx.data.id));
logAudit({
userId: ctx.session.user.id,
action: "poll_delete",
@@ -84,10 +108,8 @@ export const deletePoll = adminAction(
export const addPollQuestion = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: pollQuestionSchema },
async (ctx) => {
const question = await prisma.websitePollQuestion.create({
data: ctx.data,
});
return actionOk({ id: question.id });
const [result] = await db.insert(WebsitePollQuestion).values(ctx.data);
return actionOk({ id: Number(result.insertId) });
},
);
@@ -99,7 +121,10 @@ export const updatePollQuestion = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: updateQuestionInput },
async (ctx) => {
const { id, ...data } = ctx.data;
await prisma.websitePollQuestion.update({ where: { id }, data });
await db
.update(WebsitePollQuestion)
.set(data)
.where(eq(WebsitePollQuestion.id, id));
return actionOk({ id });
},
);
@@ -111,7 +136,9 @@ const deleteQuestionInput = z.object({
export const deletePollQuestion = adminAction(
{ permission: PERMS.POLLS_EDIT, schema: deleteQuestionInput },
async (ctx) => {
await prisma.websitePollQuestion.delete({ where: { id: ctx.data.id } });
await db
.delete(WebsitePollQuestion)
.where(eq(WebsitePollQuestion.id, ctx.data.id));
return actionOk();
},
);
@@ -138,10 +165,11 @@ export const voteOnPoll = authAction(
return actionError("Unauthorized");
}
const poll = await prisma.websitePoll.findUnique({
where: { id: ctx.data.pollId },
include: { questions: true },
});
const [poll] = await db
.select()
.from(WebsitePoll)
.where(eq(WebsitePoll.id, ctx.data.pollId))
.limit(1);
if (!poll) return actionError("Poll not found");
if (poll.status !== "active") {
@@ -155,7 +183,12 @@ export const voteOnPoll = authAction(
return actionError("This poll has ended");
}
const questionById = new Map(poll.questions.map((q) => [q.id, q]));
const questions = await db
.select()
.from(WebsitePollQuestion)
.where(eq(WebsitePollQuestion.pollId, poll.id));
const questionById = new Map(questions.map((q) => [q.id, q]));
const seen = new Set<number>();
for (const vote of ctx.data.votes) {
@@ -194,30 +227,30 @@ export const voteOnPoll = authAction(
}
}
const existing = await prisma.websitePollVote.findUnique({
where: {
questionId_userId: {
questionId: vote.questionId,
userId,
},
},
});
const [existing] = await db
.select({ id: WebsitePollVote.id })
.from(WebsitePollVote)
.where(
and(
eq(WebsitePollVote.questionId, vote.questionId),
eq(WebsitePollVote.userId, userId),
),
)
.limit(1);
if (existing) {
return actionError("You have already voted on this poll");
}
}
await prisma.$transaction(
ctx.data.votes.map((vote) =>
prisma.websitePollVote.create({
data: {
questionId: vote.questionId,
userId,
answer: vote.answer.trim(),
},
}),
),
);
await db.transaction(async (tx) => {
for (const vote of ctx.data.votes) {
await tx.insert(WebsitePollVote).values({
questionId: vote.questionId,
userId,
answer: vote.answer.trim(),
});
}
});
revalidatePath("/polls");
revalidatePath(`/polls/${poll.id}`);