refactor(db): migrate app pages and APIs from Prisma facade to Drizzle (4)

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-08-01 14:15:36 +02:00
1 parent 580972c0a0
commit 9aa4f331bf
40 files changed
+1259 -927

No files matched your search

+88 -75
View File
@@ -1,6 +1,15 @@
import { and, desc, eq, inArray, or } from "drizzle-orm";
import { isBanActive, unixNow } from "@/lib/bans";
import {
AdminAuditLog,
Ban,
db,
StaffActivities,
SupportTickets,
User,
UsersSettings,
} from "@/lib/db";
import { formatDate } from "@/lib/format-date";
import { prisma } from "@/lib/prisma";
export type SanctionEvent = {
id: string;
@@ -37,84 +46,89 @@ export async function loadUserSanctions(
const now = unixNow();
const events: SanctionEvent[] = [];
const [bans, audits, staffActs, cfh, settings] = await Promise.all([
prisma.ban
.findMany({
where: { userId },
orderBy: { timestamp: "desc" },
take: 40,
select: {
id: true,
banReason: true,
type: true,
timestamp: true,
banExpire: true,
userStaffId: true,
},
const [bans, audits, staffActs, cfh, settingsRows] = await Promise.all([
db
.select({
id: Ban.id,
banReason: Ban.banReason,
type: Ban.type,
timestamp: Ban.timestamp,
banExpire: Ban.banExpire,
userStaffId: Ban.userStaffId,
})
.from(Ban)
.where(eq(Ban.userId, userId))
.orderBy(desc(Ban.timestamp))
.limit(40)
.catch(() => []),
prisma.adminAuditLog
.findMany({
where: {
target: "User",
targetId: userId,
action: { in: [...AUDIT_ACTIONS] },
},
orderBy: { id: "desc" },
take: 40,
select: {
id: true,
action: true,
details: true,
createdAt: true,
userId: true,
user: { select: { username: true } },
},
db
.select({
id: AdminAuditLog.id,
action: AdminAuditLog.action,
details: AdminAuditLog.details,
createdAt: AdminAuditLog.createdAt,
userId: AdminAuditLog.userId,
actorUsername: User.username,
})
.from(AdminAuditLog)
.leftJoin(User, eq(AdminAuditLog.userId, User.id))
.where(
and(
eq(AdminAuditLog.target, "User"),
eq(AdminAuditLog.targetId, userId),
inArray(AdminAuditLog.action, [...AUDIT_ACTIONS]),
),
)
.orderBy(desc(AdminAuditLog.id))
.limit(40)
.catch(() => []),
prisma.staffActivities
.findMany({
where: {
targetType: "user",
targetId: BigInt(userId),
},
orderBy: { id: "desc" },
take: 40,
select: {
id: true,
action: true,
description: true,
createdAt: true,
userId: true,
},
db
.select({
id: StaffActivities.id,
action: StaffActivities.action,
description: StaffActivities.description,
createdAt: StaffActivities.createdAt,
userId: StaffActivities.userId,
})
.from(StaffActivities)
.where(
and(
eq(StaffActivities.targetType, "user"),
eq(StaffActivities.targetId, BigInt(userId)),
),
)
.orderBy(desc(StaffActivities.id))
.limit(40)
.catch(() => []),
prisma.supportTickets
.findMany({
where: {
OR: [{ reportedId: userId }, { senderId: userId }],
},
orderBy: { id: "desc" },
take: 20,
select: {
id: true,
issue: true,
state: true,
timestamp: true,
senderId: true,
reportedId: true,
modId: true,
},
db
.select({
id: SupportTickets.id,
issue: SupportTickets.issue,
state: SupportTickets.state,
timestamp: SupportTickets.timestamp,
senderId: SupportTickets.senderId,
reportedId: SupportTickets.reportedId,
modId: SupportTickets.modId,
})
.from(SupportTickets)
.where(
or(
eq(SupportTickets.reportedId, userId),
eq(SupportTickets.senderId, userId),
),
)
.orderBy(desc(SupportTickets.id))
.limit(20)
.catch(() => []),
db
.select({ muteEndTimestamp: UsersSettings.muteEndTimestamp })
.from(UsersSettings)
.where(eq(UsersSettings.userId, userId))
.limit(1)
.catch(() => []),
prisma.usersSettings
.findUnique({
where: { userId },
select: { muteEndTimestamp: true },
})
.catch(() => null),
]);
const settings = settingsRows[0] ?? null;
const muteUntil = settings?.muteEndTimestamp ?? 0;
if (muteUntil > now) {
events.push({
@@ -134,11 +148,10 @@ export async function loadUserSanctions(
];
const staffUsers =
staffIds.length > 0
? await prisma.user
.findMany({
where: { id: { in: staffIds } },
select: { id: true, username: true },
})
? await db
.select({ id: User.id, username: User.username })
.from(User)
.where(inArray(User.id, staffIds))
.catch(() => [])
: [];
const staffName = new Map(staffUsers.map((u) => [u.id, u.username]));
@@ -172,7 +185,7 @@ export async function loadUserSanctions(
kind,
label: a.action,
detail: a.details?.slice(0, 200) || "—",
actor: a.user?.username,
actor: a.actorUsername ?? undefined,
});
}
+78 -54
View File
@@ -1,5 +1,18 @@
import { asc, count, desc, eq, or, sql } from "drizzle-orm";
import { notFound } from "next/navigation";
import { prisma } from "@/lib/prisma";
import {
db,
Rooms,
RoomTradeLog,
User,
UsersBadges,
UsersCurrency,
} from "@/lib/db";
async function rawRows<T>(query: ReturnType<typeof sql>): Promise<T[]> {
const [rows] = (await db.execute(query)) as unknown as [T[], unknown];
return rows ?? [];
}
export async function loadUserById(id: string) {
const numericId = Number(id);
@@ -7,9 +20,11 @@ export async function loadUserById(id: string) {
Number.isSafeInteger(numericId) &&
numericId > 0 &&
String(numericId) === id;
const user = await prisma.user.findUnique({
where: isNumeric ? { id: numericId } : { username: id },
});
const [user] = await db
.select()
.from(User)
.where(isNumeric ? eq(User.id, numericId) : eq(User.username, id))
.limit(1);
if (!user) notFound();
const [
@@ -17,67 +32,76 @@ export async function loadUserById(id: string) {
badges,
bansReceived,
permissionRows,
roomCount,
tradeCount,
roomCountRows,
tradeCountRows,
userRooms,
chatLogs,
commandLogs,
] = await Promise.all([
prisma.usersCurrency.findMany({ where: { userId: user.id } }),
prisma.usersBadges.findMany({
where: { userId: user.id },
orderBy: { slotId: "asc" },
}),
prisma.$queryRaw<
Array<{
id: number;
banReason: string;
type: string;
timestamp: number;
banExpire: number;
staffName: string;
}>
>`
db.select().from(UsersCurrency).where(eq(UsersCurrency.userId, user.id)),
db
.select()
.from(UsersBadges)
.where(eq(UsersBadges.userId, user.id))
.orderBy(asc(UsersBadges.slotId)),
rawRows<{
id: number;
banReason: string;
type: string;
timestamp: number;
banExpire: number;
staffName: string;
}>(sql`
SELECT b.id, b.ban_reason AS banReason, b.type, b.timestamp, b.ban_expire AS banExpire,
COALESCE(s.username, 'Unknown') AS staffName
FROM bans b LEFT JOIN users s ON s.id = b.user_staff_id
WHERE b.user_id = ${user.id} ORDER BY b.id DESC LIMIT 5`,
prisma.$queryRaw<Array<{ rankName: string }>>`
SELECT COALESCE(rank_name, CONCAT('Rank ', id)) AS rankName FROM permissions WHERE id = ${user.rank} LIMIT 1`,
prisma.rooms.count({ where: { ownerId: user.id } }),
prisma.roomTradeLog.count({
where: { OR: [{ userOneId: user.id }, { userTwoId: user.id }] },
}),
prisma.rooms.findMany({
where: { ownerId: user.id },
orderBy: { users: "desc" },
take: 20,
select: {
id: true,
name: true,
state: true,
users: true,
usersMax: true,
},
}),
prisma.$queryRaw<
Array<{ id: number; roomId: number; timestamp: number; message: string }>
>`
WHERE b.user_id = ${user.id} ORDER BY b.id DESC LIMIT 5`),
rawRows<{ rankName: string }>(sql`
SELECT COALESCE(rank_name, CONCAT('Rank ', id)) AS rankName FROM permissions WHERE id = ${user.rank} LIMIT 1`),
db.select({ total: count() }).from(Rooms).where(eq(Rooms.ownerId, user.id)),
db
.select({ total: count() })
.from(RoomTradeLog)
.where(
or(
eq(RoomTradeLog.userOneId, user.id),
eq(RoomTradeLog.userTwoId, user.id),
),
),
db
.select({
id: Rooms.id,
name: Rooms.name,
state: Rooms.state,
users: Rooms.users,
usersMax: Rooms.usersMax,
})
.from(Rooms)
.where(eq(Rooms.ownerId, user.id))
.orderBy(desc(Rooms.users))
.limit(20),
rawRows<{
id: number;
roomId: number;
timestamp: number;
message: string;
}>(sql`
SELECT ROW_NUMBER() OVER (ORDER BY timestamp DESC) AS id, room_id AS roomId, timestamp, message
FROM chatlogs_room WHERE user_from_id = ${user.id} ORDER BY timestamp DESC LIMIT 20`,
prisma.$queryRaw<
Array<{
id: number;
timestamp: number;
command: string;
params: string;
succes: string;
}>
>`
FROM chatlogs_room WHERE user_from_id = ${user.id} ORDER BY timestamp DESC LIMIT 20`),
rawRows<{
id: number;
timestamp: number;
command: string;
params: string;
succes: string;
}>(sql`
SELECT ROW_NUMBER() OVER (ORDER BY timestamp DESC) AS id, timestamp, command, params, succes
FROM commandlogs WHERE user_id = ${user.id} ORDER BY timestamp DESC LIMIT 10`,
FROM commandlogs WHERE user_id = ${user.id} ORDER BY timestamp DESC LIMIT 10`),
]);
const roomCount = Number(roomCountRows[0]?.total ?? 0);
const tradeCount = Number(tradeCountRows[0]?.total ?? 0);
const diamonds =
currencies.find((currency) => currency.type === 5)?.amount ?? 0;
const duckets =
+6 -5
View File
@@ -1,7 +1,8 @@
import { sql } from "drizzle-orm";
import { redirect } from "next/navigation";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { db } from "@/lib/db";
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
import { Prisma, prisma } from "@/lib/prisma";
import { getWatchedUserIds } from "@/lib/services/watch";
import { UserAccountInfo } from "../../_components/user-account-info";
import { UserHero } from "../../_components/user-hero";
@@ -28,10 +29,10 @@ export default async function UserEditPage({
const watched = await getWatchedUserIds(session.user.id);
// Fetch rank list from permissions table for the rank dropdown
const rawRanks: { id: number; rank_name: string }[] = await prisma.$queryRaw(
Prisma.sql`SELECT id, rank_name FROM permissions ORDER BY id ASC`,
);
const ranks = rawRanks.map((r) => ({
const [rawRanks] = (await db.execute(
sql`SELECT id, rank_name FROM permissions ORDER BY id ASC`,
)) as unknown as [{ id: number; rank_name: string }[], unknown];
const ranks = (rawRanks ?? []).map((r) => ({
id: Number(r.id),
name: String(r.rank_name || `Rank ${r.id}`),
}));