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

+84 -67
View File
@@ -1,11 +1,17 @@
"use server";
import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";
import { positiveBigInt } from "@/lib/api";
import { auth } from "@/lib/auth";
import { prisma } from "@/lib/prisma";
import {
db,
WebsiteHelpCenterCategories,
WebsiteHelpCenterTicketReplies,
WebsiteHelpCenterTickets,
} from "@/lib/db";
import { clientIp, rateLimit } from "@/lib/rate-limit";
import { moderateOrThrow } from "@/lib/services/moderation";
import { createOwnedTicketReply } from "@/lib/services/ticket-replies";
@@ -109,34 +115,30 @@ export async function createTicket(formData: FormData): Promise<void> {
if (!/ban\s*appeal/i.test(ticketTitle)) {
ticketTitle = `[Ban appeal] ${ticketTitle}`.slice(0, 255);
}
const existing = await prisma.websiteHelpCenterCategories.findFirst(
{
where: { name: { equals: "Ban appeal" } },
select: { id: true },
},
);
const [existing] = await db
.select({ id: WebsiteHelpCenterCategories.id })
.from(WebsiteHelpCenterCategories)
.where(eq(WebsiteHelpCenterCategories.name, "Ban appeal"))
.limit(1);
if (existing) {
categoryId = existing.id;
} else {
try {
const created = await prisma.websiteHelpCenterCategories.create(
{
data: {
name: "Ban appeal",
content:
"Appeals for account bans. Staff can lift bans from the ticket.",
position: 0,
},
select: { id: true },
},
);
categoryId = created.id;
} catch {
const again =
await prisma.websiteHelpCenterCategories.findFirst({
where: { name: { equals: "Ban appeal" } },
select: { id: true },
const [created] = await db
.insert(WebsiteHelpCenterCategories)
.values({
name: "Ban appeal",
content:
"Appeals for account bans. Staff can lift bans from the ticket.",
position: 0,
});
categoryId = BigInt(created.insertId);
} catch {
const [again] = await db
.select({ id: WebsiteHelpCenterCategories.id })
.from(WebsiteHelpCenterCategories)
.where(eq(WebsiteHelpCenterCategories.name, "Ban appeal"))
.limit(1);
categoryId = again?.id ?? null;
}
}
@@ -148,16 +150,14 @@ export async function createTicket(formData: FormData): Promise<void> {
}
const now = new Date();
await prisma.websiteHelpCenterTickets.create({
data: {
userId,
title: ticketTitle,
content,
categoryId,
open: true,
createdAt: now,
updatedAt: now,
},
await db.insert(WebsiteHelpCenterTickets).values({
userId,
title: ticketTitle,
content,
categoryId,
open: true,
createdAt: now,
updatedAt: now,
});
outcome = "created";
}
@@ -204,10 +204,15 @@ export async function replyHelpTicket(formData: FormData): Promise<void> {
if (!parsed.success) {
outcome = "invalid";
} else {
const ticket = await prisma.websiteHelpCenterTickets.findUnique({
where: { id: ticketId },
select: { id: true, userId: true, open: true },
});
const [ticket] = await db
.select({
id: WebsiteHelpCenterTickets.id,
userId: WebsiteHelpCenterTickets.userId,
open: WebsiteHelpCenterTickets.open,
})
.from(WebsiteHelpCenterTickets)
.where(eq(WebsiteHelpCenterTickets.id, ticketId))
.limit(1);
if (!ticket || ticket.userId !== userId) {
outcome = "not_found";
@@ -223,30 +228,37 @@ export async function replyHelpTicket(formData: FormData): Promise<void> {
}
if (!moderated) {
const created = await prisma.$transaction((tx) =>
const created = await db.transaction(async (tx) =>
createOwnedTicketReply(
{
findTicket: (id) =>
tx.websiteHelpCenterTickets.findUnique({
where: { id },
select: { id: true, userId: true, open: true },
}),
createReply: (data) =>
tx.websiteHelpCenterTicketReplies.create({
data,
select: {
id: true,
userId: true,
content: true,
createdAt: true,
},
}),
findTicket: async (id) => {
const [row] = await tx
.select({
id: WebsiteHelpCenterTickets.id,
userId: WebsiteHelpCenterTickets.userId,
open: WebsiteHelpCenterTickets.open,
})
.from(WebsiteHelpCenterTickets)
.where(eq(WebsiteHelpCenterTickets.id, id))
.limit(1);
return row ?? null;
},
createReply: async (data) => {
const [result] = await tx
.insert(WebsiteHelpCenterTicketReplies)
.values(data);
return {
id: BigInt(result.insertId),
userId: data.userId,
content: data.content,
createdAt: data.createdAt,
};
},
touchTicket: (id, updatedAt) =>
tx.websiteHelpCenterTickets.update({
where: { id },
data: { updatedAt },
select: { id: true },
}),
tx
.update(WebsiteHelpCenterTickets)
.set({ updatedAt })
.where(eq(WebsiteHelpCenterTickets.id, id)),
},
{
ticketId,
@@ -289,10 +301,15 @@ export async function closeHelpTicket(formData: FormData): Promise<void> {
if (!(await rateLimit(`ticket-close:${userId}`, 10, 60_000)).ok) {
outcome = "ratelimit";
} else {
const ticket = await prisma.websiteHelpCenterTickets.findUnique({
where: { id: ticketId },
select: { id: true, userId: true, open: true },
});
const [ticket] = await db
.select({
id: WebsiteHelpCenterTickets.id,
userId: WebsiteHelpCenterTickets.userId,
open: WebsiteHelpCenterTickets.open,
})
.from(WebsiteHelpCenterTickets)
.where(eq(WebsiteHelpCenterTickets.id, ticketId))
.limit(1);
if (!ticket || ticket.userId !== userId) {
outcome = "not_found";
@@ -300,10 +317,10 @@ export async function closeHelpTicket(formData: FormData): Promise<void> {
outcome = "closed_ticket";
} else {
const now = new Date();
await prisma.websiteHelpCenterTickets.update({
where: { id: ticketId },
data: { open: false, updatedAt: now },
});
await db
.update(WebsiteHelpCenterTickets)
.set({ open: false, updatedAt: now })
.where(eq(WebsiteHelpCenterTickets.id, ticketId));
outcome = "closed";
}
}