refactor(db): migrate staff and app actions from Prisma facade to Drizzle
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
9854719cfd
commit
ed9c23c702
85 files changed
+2612
-1832
No files matched your search
+74
-41
@@ -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}`);
|
||||
|
||||
Reference in new issue
Block a user