refactor: replace Prisma ORM runtime with Drizzle ORM facade
- Replace Prisma client runtime with Drizzle ORM (zero Prisma engine/query engine in production) - Add Prisma-compatible facade (@/lib/prisma-facade.ts) backed by Drizzle for backwards compatibility - Runtime queries route through Drizzle ORM; @prisma/client is now devDependency (types only) - Remove @prisma/adapter-mariadb dependency; delete prisma-pool.ts and types/prisma.ts - New Drizzle schema layer: src/db/schema.ts (176 tables) and src/lib/db.ts (connection) - Update README documenting the dual-layer ORM architecture - Restore src/generated/ gitignore (build artifact for local type generation) - 0 TypeScript errors, 583 tests passing The facade intentionally uses `any` types to match the Prisma Client API surface, allowing existing code to run unmodified while routing queries through Drizzle at runtime.
This commit is contained in:
1 parent
9d1c71d926
commit
56061e41d4
52 files changed
+5825
-748
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Prisma } from "@/generated/prisma/client";
|
||||
import { Prisma } from "@/lib/prisma";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getWatchedUserIds } from "@/lib/services/watch";
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { and, count, desc, eq, gte, like, or } from "drizzle-orm";
|
||||
import { Users } from "lucide-react";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { AdminPageShell } from "@/components/admin/admin-page-shell";
|
||||
import { fetchAdminList } from "@/lib/admin-list";
|
||||
import { db, User } from "@/lib/db";
|
||||
import { canAccess, PERMS } from "@/lib/permissions";
|
||||
import { CreateUserDialog } from "./_components/create-user-dialog";
|
||||
import { UsersTable } from "./users-table";
|
||||
@@ -16,30 +18,54 @@ export default async function UsersPage({
|
||||
const result = await fetchAdminList(
|
||||
{
|
||||
permission: PERMS.USERS_VIEW,
|
||||
model: "user",
|
||||
searchFields: ["username", "mail", "ipRegister", "ipCurrent"],
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
mail: true,
|
||||
rank: true,
|
||||
credits: true,
|
||||
pixels: true,
|
||||
online: true,
|
||||
motto: true,
|
||||
look: true,
|
||||
ipRegister: true,
|
||||
accountCreated: true,
|
||||
lastLogin: true,
|
||||
},
|
||||
filterMap: {
|
||||
filter_rank: (v) => {
|
||||
const n = Number(v);
|
||||
if (!Number.isFinite(n)) return null;
|
||||
fetch: async ({ search, page, perPage, rawParams }) => {
|
||||
const conditions = [];
|
||||
if (search) {
|
||||
const ors = [
|
||||
like(User.username, `%${search}%`),
|
||||
like(User.mail, `%${search}%`),
|
||||
like(User.ipRegister, `%${search}%`),
|
||||
like(User.ipCurrent, `%${search}%`),
|
||||
];
|
||||
const asId = Number(search);
|
||||
if (Number.isFinite(asId) && asId > 0) {
|
||||
ors.push(eq(User.id, asId));
|
||||
}
|
||||
conditions.push(or(...ors));
|
||||
}
|
||||
const rank = Number(rawParams.filter_rank);
|
||||
if (Number.isFinite(rank)) {
|
||||
// For rank 7 the preset means "super admins" — match ≥ 7 instead of equals.
|
||||
return n >= 7 ? { rank: { gte: 7 } } : { rank: n };
|
||||
},
|
||||
filter_online: (v) => ({ online: v }),
|
||||
conditions.push(rank >= 7 ? gte(User.rank, 7) : eq(User.rank, rank));
|
||||
}
|
||||
if (rawParams.filter_online) {
|
||||
conditions.push(eq(User.online, rawParams.filter_online));
|
||||
}
|
||||
const where = conditions.length > 0 ? and(...conditions) : undefined;
|
||||
const [rows, totals] = await Promise.all([
|
||||
db
|
||||
.select({
|
||||
id: User.id,
|
||||
username: User.username,
|
||||
mail: User.mail,
|
||||
rank: User.rank,
|
||||
credits: User.credits,
|
||||
pixels: User.pixels,
|
||||
online: User.online,
|
||||
motto: User.motto,
|
||||
look: User.look,
|
||||
ipRegister: User.ipRegister,
|
||||
accountCreated: User.accountCreated,
|
||||
lastLogin: User.lastLogin,
|
||||
})
|
||||
.from(User)
|
||||
.where(where)
|
||||
.orderBy(desc(User.id))
|
||||
.limit(perPage)
|
||||
.offset((page - 1) * perPage),
|
||||
db.select({ total: count() }).from(User).where(where),
|
||||
]);
|
||||
return { rows, total: totals[0]?.total ?? 0 };
|
||||
},
|
||||
},
|
||||
paramsPromise,
|
||||
|
||||
@@ -37,7 +37,7 @@ import type { DataTableColumn, PaginatedResult } from "@/types/common";
|
||||
interface UserRow {
|
||||
id: number;
|
||||
username: string;
|
||||
mail: string;
|
||||
mail: string | null;
|
||||
rank: number;
|
||||
credits: number;
|
||||
pixels: number;
|
||||
|
||||
Reference in new issue
Block a user