refactor(db): migrate app pages and APIs from Prisma facade to Drizzle (2)
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
7c39aef5d9
commit
2cd0863cb8
40 files changed
+1069
-726
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { and, asc, desc, eq, inArray, or } from "drizzle-orm";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
@@ -12,9 +13,19 @@ import {
|
||||
StatBlock,
|
||||
} from "@/components/public/ui";
|
||||
import { auth } from "@/lib/auth";
|
||||
import {
|
||||
CameraWeb,
|
||||
db,
|
||||
MessengerFriendrequests,
|
||||
MessengerFriendships,
|
||||
Rooms,
|
||||
User,
|
||||
UsersBadges,
|
||||
UsersCurrency,
|
||||
WebsiteUserGuestbooks,
|
||||
} from "@/lib/db";
|
||||
import { avatarImageUrl } from "@/lib/format";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -47,12 +58,12 @@ export async function generateMetadata({
|
||||
params: Promise<{ username: string }>;
|
||||
}): Promise<Metadata> {
|
||||
const { username } = await params;
|
||||
const user = await prisma.user
|
||||
.findUnique({
|
||||
where: { username },
|
||||
select: { username: true, motto: true },
|
||||
})
|
||||
.catch(() => null);
|
||||
const [user] = await db
|
||||
.select({ username: User.username, motto: User.motto })
|
||||
.from(User)
|
||||
.where(eq(User.username, username))
|
||||
.limit(1)
|
||||
.catch(() => []);
|
||||
if (!user) return { title: "Profile" };
|
||||
return {
|
||||
title: user.username,
|
||||
@@ -78,26 +89,28 @@ export default async function ProfilePage({
|
||||
const { username } = await params;
|
||||
const { friend, guestbook: guestbookStatus, error } = await searchParams;
|
||||
|
||||
const [user, imagerBase, session] = await Promise.all([
|
||||
prisma.user.findUnique({
|
||||
where: { username },
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
motto: true,
|
||||
look: true,
|
||||
rank: true,
|
||||
credits: true,
|
||||
online: true,
|
||||
accountCreated: true,
|
||||
},
|
||||
}),
|
||||
const [userRows, imagerBase, session] = await Promise.all([
|
||||
db
|
||||
.select({
|
||||
id: User.id,
|
||||
username: User.username,
|
||||
motto: User.motto,
|
||||
look: User.look,
|
||||
rank: User.rank,
|
||||
credits: User.credits,
|
||||
online: User.online,
|
||||
accountCreated: User.accountCreated,
|
||||
})
|
||||
.from(User)
|
||||
.where(eq(User.username, username))
|
||||
.limit(1),
|
||||
siteSettings.get(
|
||||
"habbo_imaging_url",
|
||||
"https://www.habbo.com/habbo-imaging/avatarimage",
|
||||
),
|
||||
auth(),
|
||||
]);
|
||||
const user = userRows[0] ?? null;
|
||||
|
||||
if (!user) notFound();
|
||||
|
||||
@@ -112,34 +125,50 @@ export default async function ProfilePage({
|
||||
let outgoingPending = false;
|
||||
let incomingPending = false;
|
||||
if (isLoggedIn && !isSelf) {
|
||||
const [friendship, outgoing, incoming] = await Promise.all([
|
||||
prisma.messengerFriendships
|
||||
.findFirst({
|
||||
where: {
|
||||
OR: [
|
||||
{ userOneId: meId, userTwoId: user.id },
|
||||
{ userOneId: user.id, userTwoId: meId },
|
||||
],
|
||||
},
|
||||
select: { id: true },
|
||||
})
|
||||
.catch(() => null),
|
||||
prisma.messengerFriendrequests
|
||||
.findFirst({
|
||||
where: { userFromId: meId, userToId: user.id },
|
||||
select: { id: true },
|
||||
})
|
||||
.catch(() => null),
|
||||
prisma.messengerFriendrequests
|
||||
.findFirst({
|
||||
where: { userFromId: user.id, userToId: meId },
|
||||
select: { id: true },
|
||||
})
|
||||
.catch(() => null),
|
||||
const [friendshipRows, outgoingRows, incomingRows] = await Promise.all([
|
||||
db
|
||||
.select({ id: MessengerFriendships.id })
|
||||
.from(MessengerFriendships)
|
||||
.where(
|
||||
or(
|
||||
and(
|
||||
eq(MessengerFriendships.userOneId, meId),
|
||||
eq(MessengerFriendships.userTwoId, user.id),
|
||||
),
|
||||
and(
|
||||
eq(MessengerFriendships.userOneId, user.id),
|
||||
eq(MessengerFriendships.userTwoId, meId),
|
||||
),
|
||||
),
|
||||
)
|
||||
.limit(1)
|
||||
.catch(() => []),
|
||||
db
|
||||
.select({ id: MessengerFriendrequests.id })
|
||||
.from(MessengerFriendrequests)
|
||||
.where(
|
||||
and(
|
||||
eq(MessengerFriendrequests.userFromId, meId),
|
||||
eq(MessengerFriendrequests.userToId, user.id),
|
||||
),
|
||||
)
|
||||
.limit(1)
|
||||
.catch(() => []),
|
||||
db
|
||||
.select({ id: MessengerFriendrequests.id })
|
||||
.from(MessengerFriendrequests)
|
||||
.where(
|
||||
and(
|
||||
eq(MessengerFriendrequests.userFromId, user.id),
|
||||
eq(MessengerFriendrequests.userToId, meId),
|
||||
),
|
||||
)
|
||||
.limit(1)
|
||||
.catch(() => []),
|
||||
]);
|
||||
isFriend = Boolean(friendship);
|
||||
outgoingPending = Boolean(outgoing);
|
||||
incomingPending = Boolean(incoming);
|
||||
isFriend = Boolean(friendshipRows[0]);
|
||||
outgoingPending = Boolean(outgoingRows[0]);
|
||||
incomingPending = Boolean(incomingRows[0]);
|
||||
}
|
||||
|
||||
const feedbackErrorMessage =
|
||||
@@ -168,14 +197,18 @@ export default async function ProfilePage({
|
||||
|
||||
// Currency ledger rows (duckets/diamonds). Credits live on the users row
|
||||
// itself; the alt-currencies sit in the users_currency ledger keyed by type.
|
||||
const currencyRows = await prisma.usersCurrency
|
||||
.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
type: { in: [CURRENCY_DUCKETS, CURRENCY_DIAMONDS] },
|
||||
},
|
||||
select: { type: true, amount: true },
|
||||
const currencyRows = await db
|
||||
.select({
|
||||
type: UsersCurrency.type,
|
||||
amount: UsersCurrency.amount,
|
||||
})
|
||||
.from(UsersCurrency)
|
||||
.where(
|
||||
and(
|
||||
eq(UsersCurrency.userId, user.id),
|
||||
inArray(UsersCurrency.type, [CURRENCY_DUCKETS, CURRENCY_DIAMONDS]),
|
||||
),
|
||||
)
|
||||
.catch(() => []);
|
||||
const ducketsAmount =
|
||||
currencyRows.find((c) => c.type === CURRENCY_DUCKETS)?.amount ?? 0;
|
||||
@@ -207,21 +240,23 @@ export default async function ProfilePage({
|
||||
|
||||
// Friends. messenger_friendships stores one directed row per pair keyed on
|
||||
// user_one_id; resolve the user_two_id side to usernames/looks for the grid.
|
||||
const friendships = await prisma.messengerFriendships
|
||||
.findMany({
|
||||
where: { userOneId: user.id },
|
||||
orderBy: { friendsSince: "desc" },
|
||||
take: 18,
|
||||
select: { userTwoId: true },
|
||||
})
|
||||
const friendships = await db
|
||||
.select({ userTwoId: MessengerFriendships.userTwoId })
|
||||
.from(MessengerFriendships)
|
||||
.where(eq(MessengerFriendships.userOneId, user.id))
|
||||
.orderBy(desc(MessengerFriendships.friendsSince))
|
||||
.limit(18)
|
||||
.catch(() => []);
|
||||
const friendIds = Array.from(new Set(friendships.map((f) => f.userTwoId)));
|
||||
const friendUsers = friendIds.length
|
||||
? await prisma.user
|
||||
.findMany({
|
||||
where: { id: { in: friendIds } },
|
||||
select: { id: true, username: true, look: true },
|
||||
? await db
|
||||
.select({
|
||||
id: User.id,
|
||||
username: User.username,
|
||||
look: User.look,
|
||||
})
|
||||
.from(User)
|
||||
.where(inArray(User.id, friendIds))
|
||||
.catch(() => [])
|
||||
: [];
|
||||
const friendById = new Map(friendUsers.map((f) => [f.id, f]));
|
||||
@@ -230,52 +265,54 @@ export default async function ProfilePage({
|
||||
.filter((f): f is NonNullable<typeof f> => Boolean(f));
|
||||
|
||||
// Rooms owned by this user.
|
||||
const rooms = await prisma.rooms
|
||||
.findMany({
|
||||
where: { ownerId: user.id },
|
||||
orderBy: { users: "desc" },
|
||||
take: 8,
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
users: true,
|
||||
usersMax: true,
|
||||
state: true,
|
||||
},
|
||||
const rooms = await db
|
||||
.select({
|
||||
id: Rooms.id,
|
||||
name: Rooms.name,
|
||||
users: Rooms.users,
|
||||
usersMax: Rooms.usersMax,
|
||||
state: Rooms.state,
|
||||
})
|
||||
.from(Rooms)
|
||||
.where(eq(Rooms.ownerId, user.id))
|
||||
.orderBy(desc(Rooms.users))
|
||||
.limit(8)
|
||||
.catch(() => []);
|
||||
|
||||
const badges = await prisma.usersBadges
|
||||
.findMany({
|
||||
where: { userId: user.id },
|
||||
orderBy: { slotId: "asc" },
|
||||
})
|
||||
const badges = await db
|
||||
.select()
|
||||
.from(UsersBadges)
|
||||
.where(eq(UsersBadges.userId, user.id))
|
||||
.orderBy(asc(UsersBadges.slotId))
|
||||
.catch(() => []);
|
||||
|
||||
const photos = await prisma.cameraWeb
|
||||
.findMany({
|
||||
where: { userId: user.id },
|
||||
orderBy: { timestamp: "desc" },
|
||||
take: 6,
|
||||
})
|
||||
const photos = await db
|
||||
.select()
|
||||
.from(CameraWeb)
|
||||
.where(eq(CameraWeb.userId, user.id))
|
||||
.orderBy(desc(CameraWeb.timestamp))
|
||||
.limit(6)
|
||||
.catch(() => []);
|
||||
|
||||
const guestbook = await prisma.websiteUserGuestbooks
|
||||
.findMany({
|
||||
where: { profileId: user.id },
|
||||
orderBy: { createdAt: "desc" },
|
||||
take: 30,
|
||||
})
|
||||
const guestbook = await db
|
||||
.select()
|
||||
.from(WebsiteUserGuestbooks)
|
||||
.where(eq(WebsiteUserGuestbooks.profileId, user.id))
|
||||
.orderBy(desc(WebsiteUserGuestbooks.createdAt))
|
||||
.limit(30)
|
||||
.catch(() => []);
|
||||
|
||||
// Resolve author usernames/looks for the guestbook entries in one query.
|
||||
const authorIds = Array.from(new Set(guestbook.map((g) => g.userId)));
|
||||
const authors = authorIds.length
|
||||
? await prisma.user
|
||||
.findMany({
|
||||
where: { id: { in: authorIds } },
|
||||
select: { id: true, username: true, look: true },
|
||||
? await db
|
||||
.select({
|
||||
id: User.id,
|
||||
username: User.username,
|
||||
look: User.look,
|
||||
})
|
||||
.from(User)
|
||||
.where(inArray(User.id, authorIds))
|
||||
.catch(() => [])
|
||||
: [];
|
||||
const authorById = new Map(authors.map((a) => [a.id, a]));
|
||||
|
||||
Reference in new issue
Block a user