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

+73 -68
View File
@@ -1,8 +1,9 @@
import { eq, sql } from "drizzle-orm";
import { apiJson } from "@/lib/api";
import { bearerUserId } from "@/lib/api-auth";
import { auth } from "@/lib/auth";
import { db, User, UsersSettings } from "@/lib/db";
import { logger } from "@/lib/logger";
import { Prisma, prisma } from "@/lib/prisma";
export const dynamic = "force-dynamic";
@@ -60,21 +61,27 @@ function rankEntries(
.map((e, i) => ({ ...e, rank: i + 1 }));
}
async function rawRows<T>(query: ReturnType<typeof sql>): Promise<T[]> {
const [rows] = (await db.execute(query)) as unknown as [T[], unknown];
return rows;
}
async function loadTotalBadgesBoard(
userId: number | null,
): Promise<BadgeLeaderboardBoard> {
const rows = await prisma.$queryRaw<
Array<{ userId: bigint; username: string; look: string; cnt: bigint }>
>(
Prisma.sql`
const rows = await rawRows<{
userId: bigint;
username: string;
look: string;
cnt: bigint;
}>(sql`
SELECT ub.user_id AS userId, u.username, u.look, COUNT(*) AS cnt
FROM users_badges ub
JOIN users u ON u.id = ub.user_id
GROUP BY ub.user_id
ORDER BY cnt DESC
LIMIT 20
`,
);
`);
const entries = rankEntries(
rows.map((r) => ({
@@ -90,8 +97,8 @@ async function loadTotalBadgesBoard(
entries.length > 0
? Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`SELECT COUNT(DISTINCT user_id) AS cnt FROM users_badges`,
await rawRows<{ cnt: bigint }>(
sql`SELECT COUNT(DISTINCT user_id) AS cnt FROM users_badges`,
)
)[0]?.cnt ?? 0,
)
@@ -99,8 +106,8 @@ async function loadTotalBadgesBoard(
let viewerEntry: Partial<BadgeLeaderboardEntry> | undefined;
if (userId) {
const viewerRow = await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`SELECT COUNT(*) AS cnt FROM users_badges WHERE user_id = ${userId}`,
const viewerRow = await rawRows<{ cnt: bigint }>(
sql`SELECT COUNT(*) AS cnt FROM users_badges WHERE user_id = ${userId}`,
);
const viewerScore = Number(viewerRow[0]?.cnt ?? 0);
if (viewerScore > 0) {
@@ -108,20 +115,19 @@ async function loadTotalBadgesBoard(
entries.length > 0
? Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`
await rawRows<{ cnt: bigint }>(sql`
SELECT COUNT(*) + 1 AS cnt
FROM (SELECT user_id, COUNT(*) AS total FROM users_badges GROUP BY user_id) t
WHERE t.total > ${viewerScore}
`,
)
`)
)[0]?.cnt ?? entries.length + 1,
)
: 1;
const viewerUser = await prisma.user.findUnique({
where: { id: userId },
select: { username: true, look: true },
});
const [viewerUser] = await db
.select({ username: User.username, look: User.look })
.from(User)
.where(eq(User.id, userId))
.limit(1);
if (viewerUser) {
viewerEntry = {
userId,
@@ -140,17 +146,18 @@ async function loadTotalBadgesBoard(
async function loadAchievementBoard(
userId: number | null,
): Promise<BadgeLeaderboardBoard> {
const rows = await prisma.$queryRaw<
Array<{ userId: bigint; username: string; look: string; score: number }>
>(
Prisma.sql`
const rows = await rawRows<{
userId: bigint;
username: string;
look: string;
score: number;
}>(sql`
SELECT us.user_id AS userId, u.username, u.look, us.achievement_score AS score
FROM users_settings us
JOIN users u ON u.id = us.user_id
ORDER BY us.achievement_score DESC
LIMIT 20
`,
);
`);
const entries = rankEntries(
rows.map((r) => ({
@@ -166,8 +173,8 @@ async function loadAchievementBoard(
entries.length > 0
? Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`SELECT COUNT(*) AS cnt FROM users_settings WHERE achievement_score > 0`,
await rawRows<{ cnt: bigint }>(
sql`SELECT COUNT(*) AS cnt FROM users_settings WHERE achievement_score > 0`,
)
)[0]?.cnt ?? 0,
)
@@ -175,23 +182,23 @@ async function loadAchievementBoard(
let viewerEntry: Partial<BadgeLeaderboardEntry> | undefined;
if (userId) {
const viewerUser = await prisma.user.findUnique({
where: { id: userId },
select: { username: true, look: true },
});
const [viewerUser] = await db
.select({ username: User.username, look: User.look })
.from(User)
.where(eq(User.id, userId))
.limit(1);
if (viewerUser) {
const viewerSettings = await prisma.usersSettings.findUnique({
where: { userId },
select: { achievementScore: true },
});
const [viewerSettings] = await db
.select({ achievementScore: UsersSettings.achievementScore })
.from(UsersSettings)
.where(eq(UsersSettings.userId, userId))
.limit(1);
if (viewerSettings && viewerSettings.achievementScore > 0) {
const viewerRank = Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`
await rawRows<{ cnt: bigint }>(sql`
SELECT COUNT(*) + 1 AS cnt FROM users_settings WHERE achievement_score > ${viewerSettings.achievementScore}
`,
)
`)
)[0]?.cnt ?? entries.length + 1,
);
viewerEntry = {
@@ -215,12 +222,17 @@ async function loadRarityBoard(
): Promise<BadgeLeaderboardBoard> {
if (badgeCodes.length === 0) return { entries: [], totalPlayers: 0 };
const codes = Prisma.join(badgeCodes);
const codes = sql.join(
badgeCodes.map((c) => sql`${c}`),
sql`, `,
);
const rows = await prisma.$queryRaw<
Array<{ userId: bigint; username: string; look: string; cnt: bigint }>
>(
Prisma.sql`
const rows = await rawRows<{
userId: bigint;
username: string;
look: string;
cnt: bigint;
}>(sql`
SELECT ub.user_id AS userId, u.username, u.look, COUNT(*) AS cnt
FROM users_badges ub
JOIN users u ON u.id = ub.user_id
@@ -228,8 +240,7 @@ async function loadRarityBoard(
GROUP BY ub.user_id
ORDER BY cnt DESC
LIMIT 20
`,
);
`);
const entries = rankEntries(
rows.map((r) => ({
@@ -245,39 +256,34 @@ async function loadRarityBoard(
rows.length > 0
? Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`
await rawRows<{ cnt: bigint }>(sql`
SELECT COUNT(DISTINCT user_id) AS cnt FROM users_badges WHERE badge_code IN (${codes})
`,
)
`)
)[0]?.cnt ?? 0,
)
: 0;
let viewerEntry: Partial<BadgeLeaderboardEntry> | undefined;
if (userId) {
const viewerRow = await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`
const viewerRow = await rawRows<{ cnt: bigint }>(sql`
SELECT COUNT(*) AS cnt FROM users_badges
WHERE user_id = ${userId} AND badge_code IN (${codes})
`,
);
`);
const viewerScore = Number(viewerRow[0]?.cnt ?? 0);
if (viewerScore > 0) {
const viewerUser = await prisma.user.findUnique({
where: { id: userId },
select: { username: true, look: true },
});
const [viewerUser] = await db
.select({ username: User.username, look: User.look })
.from(User)
.where(eq(User.id, userId))
.limit(1);
if (viewerUser) {
const viewerRank = Number(
(
await prisma.$queryRaw<Array<{ cnt: bigint }>>(
Prisma.sql`
await rawRows<{ cnt: bigint }>(sql`
SELECT COUNT(*) + 1 AS cnt
FROM (SELECT user_id, COUNT(*) AS total FROM users_badges WHERE badge_code IN (${codes}) GROUP BY user_id) t
WHERE t.total > ${viewerScore}
`,
)
`)
)[0]?.cnt ?? entries.length + 1,
);
viewerEntry = {
@@ -302,15 +308,14 @@ export async function GET(req: Request) {
userId = session?.user?.id ? Number(session.user.id) : null;
}
const badgeStatsRaw = await prisma.$queryRaw<
Array<{ badgeCode: string; ownerCount: bigint }>
>(
Prisma.sql`
const badgeStatsRaw = await rawRows<{
badgeCode: string;
ownerCount: bigint;
}>(sql`
SELECT badge_code AS badgeCode, COUNT(DISTINCT user_id) AS ownerCount
FROM users_badges
GROUP BY badge_code
`,
);
`);
const badgeStats: BadgeLeaderboardStat[] = badgeStatsRaw.map((r) => ({
badgeCode: r.badgeCode,