chore(db): finish Prisma cutover to Drizzle Kit tooling
CI / check (push) Failing after 9s
CI / release (push) Skipped
CI / deploy (push) Skipped

Move CMS SQL to drizzle/migrations, drop prisma packages/schema, wire drizzle-kit scripts, and regenerate schema names from src/db/schema.ts.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-08-01 15:02:21 +02:00
1 parent d8199ea1e4
commit ba82789166
47 files changed
+365 -2787

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ export const revalidate = 300;
export const metadata = { title: "Leaderboard" };
// Currency type ids (see prisma/schema.prisma UsersCurrency):
// Currency type ids (see UsersCurrency in src/db/schema.ts):
// Credits = -1 (lives on users.credits), Duckets = 0, Diamonds = 5.
const TABS = [
{ key: "credits", label: "Credits", coin: "credits" },
+1 -1
View File
@@ -35,7 +35,7 @@ export default async function PhotosPage() {
}
// Pre-shape for the client lightbox: translate captions server-side so the
// client component stays free of i18n/prisma dependencies.
// client component stays free of i18n/db dependencies.
const items: LightboxPhoto[] = photos.map((p) => ({
id: String(p.id),
url: p.url,
+1 -1
View File
@@ -10,7 +10,7 @@ import { useCallback, useEffect, useState } from "react";
* toggled by state — closes on backdrop click, on the ✕ button, or with Esc.
*
* Photos are pre-shaped on the server (caption strings already translated) so
* this component carries no prisma/i18n dependency.
* this component carries no db/i18n dependency.
*/
export type LightboxPhoto = {
id: string;
+1 -1
View File
@@ -10,7 +10,7 @@ import { useEventSource } from "@/lib/use-event-source";
* radio via a hidden <audio> element, with play/pause, a volume slider, the
* current DJ / now-playing text, and a live listener count.
*
* It is a CLIENT component and must NOT import prisma / siteSettings.
* It is a CLIENT component and must NOT import db / siteSettings.
* Config is fetched once on mount; now-playing + listeners come via SSE
* (/api/radio/stream) for real-time updates.
*
+2 -2
View File
@@ -1,6 +1,6 @@
// AUTO-GENERATED by scripts/generate-drizzle-schema.mjs — DO NOT EDIT.
// TS field names mirror prisma/schema.prisma (camelCase); column names are the
// real MySQL columns. Run `pnpm db:schema:generate` after schema changes.
// TS field names come from the previous src/db/schema.ts; column types from the
// live MySQL DB. Run `pnpm db:schema:generate` after schema/map changes.
import { sql } from "drizzle-orm";
import {
@@ -19,15 +19,17 @@ const tables = [
describe("admin content module port", () => {
it("owns every required table through schema and migration contracts", () => {
const schema = readFileSync(resolve("prisma/schema.prisma"), "utf8");
const schema = readFileSync(resolve("src/db/schema.ts"), "utf8");
const migration = readFileSync(
resolve("prisma/migrations/0013_admin_events_polls_banners_prefixes.sql"),
resolve(
"drizzle/migrations/0013_admin_events_polls_banners_prefixes.sql",
),
"utf8",
);
for (const table of tables) {
expect(migration).toContain(`CREATE TABLE IF NOT EXISTS \`${table}\``);
if (!table.startsWith("custom_prefix"))
expect(schema).toContain(`@@map("${table}")`);
expect(schema).toContain(`"${table}"`);
}
});
@@ -13,7 +13,7 @@ describe("ACL management contract", () => {
it("ships an idempotent ACL completion migration", () => {
const sql = readFileSync(
"prisma/migrations/0014_complete_acl_and_import_permissions.sql",
"drizzle/migrations/0014_complete_acl_and_import_permissions.sql",
"utf8",
);
expect(sql).toContain("admin.assets.import");
+1 -1
View File
@@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
describe("production ACL migration", () => {
const migrationsDir = resolve(process.cwd(), "prisma/migrations");
const migrationsDir = resolve(process.cwd(), "drizzle/migrations");
const allSql = readdirSync(migrationsDir)
.filter((name) => name.endsWith(".sql"))
.map((name) => readFileSync(resolve(migrationsDir, name), "utf8"))
+1
View File
@@ -36,6 +36,7 @@ describe("CI workflow", () => {
const release = workflow.slice(workflow.indexOf("\n release:"));
expect(release).toContain("pnpm db:migrate");
expect(release).not.toContain("pnpm prisma:generate");
expect(release).toContain("pnpm db:migrate");
expect(release).toContain("src/db/schema.ts");
const migrateAt = release.indexOf("pnpm db:migrate");
const buildAt = release.indexOf("pnpm build");
-8
View File
@@ -249,14 +249,6 @@ export function handleActionError(error: unknown): ActionFailure {
if (error instanceof Error && error.name === "ZodError") {
return fail("Validation failed");
}
if (
error instanceof Error &&
(error.constructor.name === "PrismaClientKnownRequestError" ||
error.name === "PrismaClientKnownRequestError") &&
(error as Error & { code?: string }).code === "P2025"
) {
return fail("Not found");
}
reportError(error, "Action error");
return fail("Internal server error");
+1 -1
View File
@@ -1,6 +1,6 @@
// ── Permission Slug Constants ───────────────────────────────────────
// Extracted to its own file so it can be imported by client components
// (modules.ts → sidebar.tsx) without pulling in prisma/server-only deps.
// (modules.ts → sidebar.tsx) without pulling in db/server-only deps.
export const PERMS = {
ADMIN_DASHBOARD: "admin.dashboard",
+1 -1
View File
@@ -9,7 +9,7 @@ describe("proxy authentication boundary", () => {
expect(proxy).toContain('from "@/lib/proxy-auth"');
expect(proxy).not.toContain('from "@/lib/auth"');
expect(proxyAuth).not.toMatch(
/from\s+["'][^"']*(prisma|site-settings|credentials)[^"']*["']/i,
/from\s+["'][^"']*(db|site-settings|credentials|prisma)[^"']*["']/i,
);
});
});
+1 -1
View File
@@ -38,7 +38,7 @@ export interface UploadParams {
const MIGRATIONS_DIR = path.resolve(
/*turbopackIgnore: true*/ process.cwd(),
"prisma/migrations",
"drizzle/migrations",
);
let itemsBaseIdAllocChain: Promise<unknown> = Promise.resolve();
+15
View File
@@ -49,6 +49,21 @@ describe("staff smoke contract", () => {
).toContain("UserSanctionTimeline");
});
it("applies CMS SQL from drizzle/migrations (not Prisma)", () => {
expect(existsSync("drizzle/migrations")).toBe(true);
expect(existsSync("prisma")).toBe(false);
expect(readFileSync("scripts/apply-migrations.ts", "utf8")).toContain(
"drizzle/migrations",
);
expect(readFileSync("package.json", "utf8")).not.toContain('"prisma"');
expect(readFileSync("package.json", "utf8")).not.toContain(
'"@prisma/client"',
);
expect(readFileSync("drizzle.config.ts", "utf8")).toContain(
"./drizzle/drafts",
);
});
it("ships shared ops + ticket queue helpers", () => {
expect(existsSync("src/lib/admin/ops-health.ts")).toBe(true);
const ops = readFileSync("src/lib/admin/ops-health.ts", "utf8");