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

+20 -18
View File
@@ -1,13 +1,14 @@
// Public REST API — the currently signed-in user.
//
// Reads the NextAuth session, then re-queries prisma.user by the session id to
// Reads the NextAuth session, then re-queries users by the session id to
// return a safe field set (never password / auth_ticket / 2FA secrets / pincode
// / mail). Returns { user: null } only when unauthenticated or missing.
import { eq } from "drizzle-orm";
import { apiJson, apiUnavailable } from "@/lib/api";
import { auth } from "@/lib/auth";
import { sessionUserId } from "@/lib/auth/session-user";
import { prisma } from "@/lib/prisma";
import { db, User } from "@/lib/db";
export const dynamic = "force-dynamic";
@@ -19,22 +20,23 @@ export async function GET(_req: Request) {
}
try {
const user = await prisma.user.findUnique({
where: { id },
select: {
id: true,
username: true,
look: true,
motto: true,
rank: true,
credits: true,
pixels: true,
points: true,
gender: true,
online: true,
accountCreated: true,
},
});
const [user] = await db
.select({
id: User.id,
username: User.username,
look: User.look,
motto: User.motto,
rank: User.rank,
credits: User.credits,
pixels: User.pixels,
points: User.points,
gender: User.gender,
online: User.online,
accountCreated: User.accountCreated,
})
.from(User)
.where(eq(User.id, id))
.limit(1);
if (!user) {
return apiJson({ user: null });
+29 -10
View File
@@ -8,11 +8,13 @@
// to the user via personal_access_tokens.tokenable_id (a BigInt). NOTE: the live
// table has no expires_at column, so it is never read or written here.
import { and, desc, eq } from "drizzle-orm";
import type { ResultSetHeader } from "mysql2";
import { apiError, apiJson, apiUnavailable, positiveBigInt } from "@/lib/api";
import { auth } from "@/lib/auth";
import { personalTokenScope } from "@/lib/auth/personal-token-scope";
import { sessionUserId } from "@/lib/auth/session-user";
import { prisma } from "@/lib/prisma";
import { db, PersonalAccessTokens } from "@/lib/db";
export const dynamic = "force-dynamic";
@@ -26,11 +28,21 @@ export async function GET(_req: Request) {
if (!id) return apiError("Unauthorized", 401);
try {
const tokens = await prisma.personalAccessTokens.findMany({
where: personalTokenScope(id),
select: { id: true, name: true, lastUsedAt: true },
orderBy: { id: "desc" },
});
const scope = personalTokenScope(id);
const tokens = await db
.select({
id: PersonalAccessTokens.id,
name: PersonalAccessTokens.name,
lastUsedAt: PersonalAccessTokens.lastUsedAt,
})
.from(PersonalAccessTokens)
.where(
and(
eq(PersonalAccessTokens.tokenableId, scope.tokenableId),
eq(PersonalAccessTokens.tokenableType, scope.tokenableType),
),
)
.orderBy(desc(PersonalAccessTokens.id));
// Never expose the token hash.
return apiJson({ data: tokens });
} catch {
@@ -50,10 +62,17 @@ export async function DELETE(req: Request) {
try {
// Scope the delete to the owner so users cannot revoke others' tokens.
const result = await prisma.personalAccessTokens.deleteMany({
where: { id: parsedTokenId, ...personalTokenScope(id) },
});
if (result.count === 0) {
const scope = personalTokenScope(id);
const [result] = (await db
.delete(PersonalAccessTokens)
.where(
and(
eq(PersonalAccessTokens.id, parsedTokenId),
eq(PersonalAccessTokens.tokenableId, scope.tokenableId),
eq(PersonalAccessTokens.tokenableType, scope.tokenableType),
),
)) as unknown as [ResultSetHeader];
if (!result.affectedRows) {
return apiError("Token not found", 404);
}
return apiJson({ ok: true });