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
+74
-47
@@ -1,9 +1,18 @@
|
||||
"use server";
|
||||
|
||||
import { and, count, eq, inArray, sql } from "drizzle-orm";
|
||||
import type { ResultSetHeader } from "mysql2";
|
||||
import { revalidateTag } from "next/cache";
|
||||
import { z } from "zod";
|
||||
import {
|
||||
AclModelPermission,
|
||||
AclModelRole,
|
||||
AclPermission,
|
||||
AclRole,
|
||||
db,
|
||||
User,
|
||||
} from "@/lib/db";
|
||||
import { PERMS } from "@/lib/permission-slugs";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { adminAction } from "@/lib/safe-action";
|
||||
import { ActionError, actionOk } from "@/lib/safe-action-shared";
|
||||
import {
|
||||
@@ -22,16 +31,15 @@ const createRankSchema = z.object({
|
||||
export const createRank = adminAction(
|
||||
{ schema: createRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
||||
async (ctx) => {
|
||||
const id = await createEmulatorRank(prisma, ctx.data);
|
||||
await prisma.aclRole.upsert({
|
||||
where: { slug: `rank_${id}` },
|
||||
create: {
|
||||
const id = await createEmulatorRank(db, ctx.data);
|
||||
await db
|
||||
.insert(AclRole)
|
||||
.values({
|
||||
slug: `rank_${id}`,
|
||||
title: ctx.data.rank_name,
|
||||
description: "CMS role synchronized from permission_ranks",
|
||||
},
|
||||
update: { title: ctx.data.rank_name },
|
||||
});
|
||||
})
|
||||
.onDuplicateKeyUpdate({ set: { title: ctx.data.rank_name } });
|
||||
await logStaffActivity({
|
||||
staffId: ctx.session.user.id,
|
||||
action: "rank_create",
|
||||
@@ -50,21 +58,32 @@ const deleteRankSchema = z.object({ id: z.coerce.number().int().positive() });
|
||||
export const deleteRank = adminAction(
|
||||
{ schema: deleteRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
||||
async (ctx) => {
|
||||
const users = await prisma.user.count({ where: { rank: ctx.data.id } });
|
||||
const [userCount] = await db
|
||||
.select({ total: count() })
|
||||
.from(User)
|
||||
.where(eq(User.rank, ctx.data.id));
|
||||
const users = userCount?.total ?? 0;
|
||||
if (users > 0)
|
||||
throw new ActionError(`Cannot delete: ${users} users have this rank`);
|
||||
const role = await prisma.aclRole.findFirst({
|
||||
where: { slug: `rank_${ctx.data.id}` },
|
||||
});
|
||||
await deleteEmulatorRank(prisma, ctx.data.id);
|
||||
const [role] = await db
|
||||
.select({ id: AclRole.id })
|
||||
.from(AclRole)
|
||||
.where(eq(AclRole.slug, `rank_${ctx.data.id}`))
|
||||
.limit(1);
|
||||
await deleteEmulatorRank(db, ctx.data.id);
|
||||
if (role) {
|
||||
await prisma.$transaction([
|
||||
prisma.aclModelPermission.deleteMany({
|
||||
where: { modelId: role.id, modelType: "Role" },
|
||||
}),
|
||||
prisma.aclModelRole.deleteMany({ where: { roleId: role.id } }),
|
||||
prisma.aclRole.delete({ where: { id: role.id } }),
|
||||
]);
|
||||
await db.transaction(async (tx) => {
|
||||
await tx
|
||||
.delete(AclModelPermission)
|
||||
.where(
|
||||
and(
|
||||
eq(AclModelPermission.modelId, role.id),
|
||||
eq(AclModelPermission.modelType, "Role"),
|
||||
),
|
||||
);
|
||||
await tx.delete(AclModelRole).where(eq(AclModelRole.roleId, role.id));
|
||||
await tx.delete(AclRole).where(eq(AclRole.id, role.id));
|
||||
});
|
||||
}
|
||||
await logStaffActivity({
|
||||
staffId: ctx.session.user.id,
|
||||
@@ -87,12 +106,12 @@ const saveRankSchema = z.object({
|
||||
export const saveRank = adminAction(
|
||||
{ schema: saveRankSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
||||
async (ctx) => {
|
||||
await updateEmulatorRank(prisma, ctx.data.id, ctx.data.fields);
|
||||
await updateEmulatorRank(db, ctx.data.id, ctx.data.fields);
|
||||
if (typeof ctx.data.fields.rank_name === "string") {
|
||||
await prisma.aclRole.updateMany({
|
||||
where: { slug: `rank_${ctx.data.id}` },
|
||||
data: { title: ctx.data.fields.rank_name },
|
||||
});
|
||||
await db
|
||||
.update(AclRole)
|
||||
.set({ title: ctx.data.fields.rank_name })
|
||||
.where(eq(AclRole.slug, `rank_${ctx.data.id}`));
|
||||
}
|
||||
await logStaffActivity({
|
||||
staffId: ctx.session.user.id,
|
||||
@@ -115,27 +134,33 @@ const setCmsPermsSchema = z.object({
|
||||
export const setCmsPermissions = adminAction(
|
||||
{ schema: setCmsPermsSchema, permission: PERMS.PERMISSIONS_MANAGE },
|
||||
async (ctx) => {
|
||||
const role = await prisma.aclRole.findUnique({
|
||||
where: { id: ctx.data.roleId },
|
||||
select: { id: true, slug: true },
|
||||
});
|
||||
const [role] = await db
|
||||
.select({ id: AclRole.id, slug: AclRole.slug })
|
||||
.from(AclRole)
|
||||
.where(eq(AclRole.id, ctx.data.roleId))
|
||||
.limit(1);
|
||||
if (!role) throw new ActionError("Role not found");
|
||||
const permissions = await prisma.aclPermission.findMany({
|
||||
where: { slug: { in: ctx.data.permissionSlugs } },
|
||||
select: { id: true },
|
||||
});
|
||||
await prisma.$transaction(async (tx) => {
|
||||
await tx.aclModelPermission.deleteMany({
|
||||
where: { modelId: role.id, modelType: "Role" },
|
||||
});
|
||||
const permissions = await db
|
||||
.select({ id: AclPermission.id })
|
||||
.from(AclPermission)
|
||||
.where(inArray(AclPermission.slug, ctx.data.permissionSlugs));
|
||||
await db.transaction(async (tx) => {
|
||||
await tx
|
||||
.delete(AclModelPermission)
|
||||
.where(
|
||||
and(
|
||||
eq(AclModelPermission.modelId, role.id),
|
||||
eq(AclModelPermission.modelType, "Role"),
|
||||
),
|
||||
);
|
||||
if (permissions.length) {
|
||||
await tx.aclModelPermission.createMany({
|
||||
data: permissions.map((permission) => ({
|
||||
await tx.insert(AclModelPermission).values(
|
||||
permissions.map((permission) => ({
|
||||
modelId: role.id,
|
||||
modelType: "Role",
|
||||
permissionId: permission.id,
|
||||
})),
|
||||
});
|
||||
);
|
||||
}
|
||||
});
|
||||
await logStaffActivity({
|
||||
@@ -159,7 +184,7 @@ export const setCmsPermissions = adminAction(
|
||||
export const repairAdminNavAclGrants = adminAction(
|
||||
{ permission: PERMS.PERMISSIONS_MANAGE },
|
||||
async (ctx) => {
|
||||
const dashboardFill = await prisma.$executeRaw`
|
||||
const [dashboardFillResult] = await db.execute(sql`
|
||||
INSERT INTO \`acl_model_permissions\` (\`model_type\`, \`model_id\`, \`permission_id\`)
|
||||
SELECT 'Role', ar.id, ap.id
|
||||
FROM \`acl_roles\` ar
|
||||
@@ -179,9 +204,9 @@ export const repairAdminNavAclGrants = adminAction(
|
||||
AND amp2.model_id = ar.id
|
||||
AND amp2.permission_id = ap.id
|
||||
)
|
||||
`;
|
||||
`);
|
||||
|
||||
const midRankViews = await prisma.$executeRaw`
|
||||
const [midRankViewsResult] = await db.execute(sql`
|
||||
INSERT INTO \`acl_model_permissions\` (\`model_type\`, \`model_id\`, \`permission_id\`)
|
||||
SELECT 'Role', ar.id, ap.id
|
||||
FROM \`permission_ranks\` pr
|
||||
@@ -198,9 +223,9 @@ export const repairAdminNavAclGrants = adminAction(
|
||||
AND amp.model_id = ar.id
|
||||
AND amp.permission_id = ap.id
|
||||
)
|
||||
`;
|
||||
`);
|
||||
|
||||
const highRankTools = await prisma.$executeRaw`
|
||||
const [highRankToolsResult] = await db.execute(sql`
|
||||
INSERT INTO \`acl_model_permissions\` (\`model_type\`, \`model_id\`, \`permission_id\`)
|
||||
SELECT 'Role', ar.id, ap.id
|
||||
FROM \`permission_ranks\` pr
|
||||
@@ -226,10 +251,12 @@ export const repairAdminNavAclGrants = adminAction(
|
||||
AND amp.model_id = ar.id
|
||||
AND amp.permission_id = ap.id
|
||||
)
|
||||
`;
|
||||
`);
|
||||
|
||||
const inserted =
|
||||
Number(dashboardFill) + Number(midRankViews) + Number(highRankTools);
|
||||
Number((dashboardFillResult as ResultSetHeader).affectedRows) +
|
||||
Number((midRankViewsResult as ResultSetHeader).affectedRows) +
|
||||
Number((highRankToolsResult as ResultSetHeader).affectedRows);
|
||||
|
||||
await logStaffActivity({
|
||||
staffId: ctx.session.user.id,
|
||||
|
||||
Reference in new issue
Block a user