refactor(db): migrate app pages and APIs from Prisma facade to Drizzle (3)
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
2cd0863cb8
commit
580972c0a0
40 files changed
+1089
-808
No files matched your search
@@ -1,7 +1,8 @@
|
||||
import { sql } from "drizzle-orm";
|
||||
import { redirect } from "next/navigation";
|
||||
import { calcPagination, parseListParams } from "@/lib/admin-helpers";
|
||||
import { db } from "@/lib/db";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
type ListParamsInput = {
|
||||
searchParams: Promise<Record<string, string>>;
|
||||
@@ -25,6 +26,11 @@ function parsePageParams(
|
||||
return { search: parsed.search.trim(), page: parsed.page, perPage };
|
||||
}
|
||||
|
||||
async function rawRows<T>(query: ReturnType<typeof sql>): Promise<T[]> {
|
||||
const [rows] = (await db.execute(query)) as unknown as [T[], unknown];
|
||||
return rows ?? [];
|
||||
}
|
||||
|
||||
export type ChatLogListRow = {
|
||||
id: number;
|
||||
username: string;
|
||||
@@ -51,35 +57,35 @@ export async function loadChatLogList({
|
||||
username: string | null;
|
||||
};
|
||||
|
||||
const [rawRows, countRows] = search
|
||||
const [rawRowsResult, countRows] = search
|
||||
? await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT c.room_id AS roomId, c.message, c.timestamp, u.username AS username
|
||||
FROM chatlogs_room c
|
||||
LEFT JOIN users u ON u.id = c.user_from_id
|
||||
WHERE c.message LIKE ${like} OR u.username LIKE ${like}
|
||||
ORDER BY c.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count
|
||||
FROM chatlogs_room c
|
||||
LEFT JOIN users u ON u.id = c.user_from_id
|
||||
WHERE c.message LIKE ${like} OR u.username LIKE ${like}`,
|
||||
WHERE c.message LIKE ${like} OR u.username LIKE ${like}`),
|
||||
])
|
||||
: await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT c.room_id AS roomId, c.message, c.timestamp, u.username AS username
|
||||
FROM chatlogs_room c
|
||||
LEFT JOIN users u ON u.id = c.user_from_id
|
||||
ORDER BY c.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
SELECT COUNT(*) AS count FROM chatlogs_room`,
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count FROM chatlogs_room`),
|
||||
]);
|
||||
|
||||
const total = Number(countRows[0]?.count ?? 0);
|
||||
const pagination = calcPagination(total, page, perPage);
|
||||
const rows: ChatLogListRow[] = rawRows.map((row, index) => ({
|
||||
const rows: ChatLogListRow[] = rawRowsResult.map((row, index) => ({
|
||||
id: pagination.offset + index + 1,
|
||||
username: row.username ?? "-",
|
||||
message: row.message,
|
||||
@@ -116,9 +122,9 @@ export async function loadCommandLogList({
|
||||
username: string | null;
|
||||
};
|
||||
|
||||
const [rawRows, countRows] = search
|
||||
const [rawRowsResult, countRows] = search
|
||||
? await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT c.command, c.params, c.timestamp, u.username AS username
|
||||
FROM commandlogs c
|
||||
LEFT JOIN users u ON u.id = c.user_id
|
||||
@@ -126,29 +132,29 @@ export async function loadCommandLogList({
|
||||
OR c.params LIKE ${like}
|
||||
OR u.username LIKE ${like}
|
||||
ORDER BY c.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count
|
||||
FROM commandlogs c
|
||||
LEFT JOIN users u ON u.id = c.user_id
|
||||
WHERE c.command LIKE ${like}
|
||||
OR c.params LIKE ${like}
|
||||
OR u.username LIKE ${like}`,
|
||||
OR u.username LIKE ${like}`),
|
||||
])
|
||||
: await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT c.command, c.params, c.timestamp, u.username AS username
|
||||
FROM commandlogs c
|
||||
LEFT JOIN users u ON u.id = c.user_id
|
||||
ORDER BY c.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
SELECT COUNT(*) AS count FROM commandlogs`,
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count FROM commandlogs`),
|
||||
]);
|
||||
|
||||
const total = Number(countRows[0]?.count ?? 0);
|
||||
const pagination = calcPagination(total, page, perPage);
|
||||
const rows: CommandLogListRow[] = rawRows.map((row, index) => ({
|
||||
const rows: CommandLogListRow[] = rawRowsResult.map((row, index) => ({
|
||||
id: pagination.offset + index + 1,
|
||||
username: row.username ?? "-",
|
||||
command: row.command,
|
||||
@@ -185,9 +191,9 @@ export async function loadTradeLogList({
|
||||
userTwoName: string | null;
|
||||
};
|
||||
|
||||
const [rawRows, countRows] = search
|
||||
const [rawRowsResult, countRows] = search
|
||||
? await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT t.id, t.timestamp,
|
||||
u1.username AS userOneName, u2.username AS userTwoName
|
||||
FROM room_trade_log t
|
||||
@@ -195,30 +201,30 @@ export async function loadTradeLogList({
|
||||
LEFT JOIN users u2 ON u2.id = t.user_two_id
|
||||
WHERE u1.username LIKE ${like} OR u2.username LIKE ${like}
|
||||
ORDER BY t.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count
|
||||
FROM room_trade_log t
|
||||
LEFT JOIN users u1 ON u1.id = t.user_one_id
|
||||
LEFT JOIN users u2 ON u2.id = t.user_two_id
|
||||
WHERE u1.username LIKE ${like} OR u2.username LIKE ${like}`,
|
||||
WHERE u1.username LIKE ${like} OR u2.username LIKE ${like}`),
|
||||
])
|
||||
: await Promise.all([
|
||||
prisma.$queryRaw<RawRow[]>`
|
||||
rawRows<RawRow>(sql`
|
||||
SELECT t.id, t.timestamp,
|
||||
u1.username AS userOneName, u2.username AS userTwoName
|
||||
FROM room_trade_log t
|
||||
LEFT JOIN users u1 ON u1.id = t.user_one_id
|
||||
LEFT JOIN users u2 ON u2.id = t.user_two_id
|
||||
ORDER BY t.timestamp DESC
|
||||
LIMIT ${perPage} OFFSET ${offset}`,
|
||||
prisma.$queryRaw<{ count: bigint }[]>`
|
||||
SELECT COUNT(*) AS count FROM room_trade_log`,
|
||||
LIMIT ${perPage} OFFSET ${offset}`),
|
||||
rawRows<{ count: bigint }>(sql`
|
||||
SELECT COUNT(*) AS count FROM room_trade_log`),
|
||||
]);
|
||||
|
||||
const total = Number(countRows[0]?.count ?? 0);
|
||||
const pagination = calcPagination(total, page, perPage);
|
||||
const rows: TradeLogListRow[] = rawRows.map((row) => ({
|
||||
const rows: TradeLogListRow[] = rawRowsResult.map((row) => ({
|
||||
id: row.id,
|
||||
userOneName: row.userOneName ?? "-",
|
||||
userTwoName: row.userTwoName ?? "-",
|
||||
|
||||
+57
-36
@@ -1,20 +1,29 @@
|
||||
import {
|
||||
and,
|
||||
asc,
|
||||
count,
|
||||
desc,
|
||||
inArray,
|
||||
like,
|
||||
type SQL,
|
||||
sql,
|
||||
} from "drizzle-orm";
|
||||
import { ClipboardList } from "lucide-react";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { AdminPageShell } from "@/components/admin/admin-page-shell";
|
||||
import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { buildStaffActivityWhere } from "@/lib/admin/log-filters";
|
||||
import { calcPagination, parseListParams } from "@/lib/admin-helpers";
|
||||
import { db, StaffActivities, User } from "@/lib/db";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { StaffActivitiesTable } from "./staff-activities-table";
|
||||
|
||||
const SORT_MAP: Record<string, "createdAt" | "userId" | "action"> = {
|
||||
when: "createdAt",
|
||||
staff: "userId",
|
||||
action: "action",
|
||||
};
|
||||
const SORT_MAP = {
|
||||
when: StaffActivities.createdAt,
|
||||
staff: StaffActivities.userId,
|
||||
action: StaffActivities.action,
|
||||
} as const;
|
||||
|
||||
export default async function AdminStaffActivities({
|
||||
searchParams,
|
||||
@@ -30,36 +39,49 @@ export default async function AdminStaffActivities({
|
||||
const raw = await searchParams;
|
||||
const parsed = parseListParams(new URLSearchParams(raw));
|
||||
const authorizationOnly = raw.filter_authorization === "1";
|
||||
const whereClause = buildStaffActivityWhere({
|
||||
q: parsed.search,
|
||||
authorizationOnly,
|
||||
});
|
||||
|
||||
const sortField = SORT_MAP[parsed.sort ?? ""] ?? "createdAt";
|
||||
const conditions: SQL[] = [];
|
||||
if (parsed.search.trim()) {
|
||||
const q = parsed.search.trim();
|
||||
conditions.push(
|
||||
sql`(${like(StaffActivities.action, `%${q}%`)} OR ${like(StaffActivities.description, `%${q}%`)} OR ${like(StaffActivities.ipAddress, `%${q}%`)})`,
|
||||
);
|
||||
}
|
||||
if (authorizationOnly) {
|
||||
conditions.push(like(StaffActivities.action, "permission.%"));
|
||||
}
|
||||
const where = conditions.length > 0 ? and(...conditions) : undefined;
|
||||
|
||||
const total = await prisma.staffActivities
|
||||
.count({ where: whereClause })
|
||||
.catch(() => 0);
|
||||
const sortCol =
|
||||
SORT_MAP[(parsed.sort ?? "") as keyof typeof SORT_MAP] ??
|
||||
StaffActivities.createdAt;
|
||||
const orderBy = parsed.order === "asc" ? asc(sortCol) : desc(sortCol);
|
||||
|
||||
const [totalRows] = await db
|
||||
.select({ total: count() })
|
||||
.from(StaffActivities)
|
||||
.where(where)
|
||||
.catch(() => [{ total: 0 }]);
|
||||
const total = Number(totalRows?.total ?? 0);
|
||||
|
||||
const pagination = calcPagination(total, parsed.page, parsed.perPage);
|
||||
|
||||
const activities = await prisma.staffActivities
|
||||
.findMany({
|
||||
where: whereClause,
|
||||
select: {
|
||||
id: true,
|
||||
userId: true,
|
||||
action: true,
|
||||
description: true,
|
||||
targetType: true,
|
||||
targetId: true,
|
||||
ipAddress: true,
|
||||
createdAt: true,
|
||||
},
|
||||
orderBy: { [sortField]: parsed.order },
|
||||
skip: pagination.offset,
|
||||
take: pagination.perPage,
|
||||
const activities = await db
|
||||
.select({
|
||||
id: StaffActivities.id,
|
||||
userId: StaffActivities.userId,
|
||||
action: StaffActivities.action,
|
||||
description: StaffActivities.description,
|
||||
targetType: StaffActivities.targetType,
|
||||
targetId: StaffActivities.targetId,
|
||||
ipAddress: StaffActivities.ipAddress,
|
||||
createdAt: StaffActivities.createdAt,
|
||||
})
|
||||
.from(StaffActivities)
|
||||
.where(where)
|
||||
.orderBy(orderBy)
|
||||
.limit(pagination.perPage)
|
||||
.offset(pagination.offset)
|
||||
.catch(() => []);
|
||||
|
||||
const staffIds = Array.from(
|
||||
@@ -67,11 +89,10 @@ export default async function AdminStaffActivities({
|
||||
).filter((n) => n > 0);
|
||||
let nameById = new Map<number, string>();
|
||||
if (staffIds.length) {
|
||||
const users = await prisma.user
|
||||
.findMany({
|
||||
where: { id: { in: staffIds } },
|
||||
select: { id: true, username: true },
|
||||
})
|
||||
const users = await db
|
||||
.select({ id: User.id, username: User.username })
|
||||
.from(User)
|
||||
.where(inArray(User.id, staffIds))
|
||||
.catch(() => []);
|
||||
nameById = new Map(users.map((x) => [x.id, x.username]));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user