From 9a8905c726b559c95e32f9ef010420a59e692a1b Mon Sep 17 00:00:00 2001 From: openhands Date: Fri, 31 Jul 2026 14:26:09 +0200 Subject: [PATCH] docs: update README for Drizzle ORM migration - Document Drizzle ORM as primary data layer with CLI usage examples - Add Prisma compatibility facade section (backwards compatibility) - Document legacy Prisma CLI removal (migrate dev, studio, db push no longer used) - Update architecture tree with src/db/ and scripts/ directories - Update migration count (19 SQL files) - Add contributing guidelines for Drizzle-based code --- README.md | 65 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 87c24615..a4184a1e 100644 --- a/README.md +++ b/README.md @@ -58,21 +58,45 @@ APP_URL=http://localhost:3000 See `.env.example` for all optional variables (RCON, email, Redis, OAuth, PayPal, etc.). -### 4. Type Generation (Optional for Development) +### 4. ORM Setup & Type Generation + +#### Drizzle ORM (Primary Data Layer) + +Drizzle ORM is the runtime data layer. The connection is a singleton in `src/lib/db.ts`: + +```ts +import { db } from "@/lib/db"; +import { users } from "@/db/schema"; +import { eq } from "drizzle-orm/expressions"; + +const found = await db.select() + .from(users) + .where(eq(users.username, "hello")); +``` + +**Drizzle CLI** (`drizzle-kit`) is used for local development tasks — it is a devDependency and is never bundled in production. + +| Command | What it does | +| ------- | ------------ | +| `npx drizzle-kit generate --dialect mysql --schema src/db/schema.ts --out src/db/migrations` | Inspect the Drizzle schema and emit migration SQL | +| `npx drizzle-kit studio` | Open a local DB browser (dev only) | +| `npx drizzle-kit introspect` | Reverse-engineer an existing DB into a Drizzle schema | + +> The CMS does **not** use `drizzle-kit push` — the database is owned by the emulator and is never auto-migrated. CMS-owned tables are created via the SQL migration runner (step 5). + +#### Prisma Compatibility Facade (Backwards Compatibility) + +A Prisma-compatible facade at `@/lib/prisma` allows existing code to keep calling `prisma.users.findMany()` without refactoring. At runtime, the facade routes every query through Drizzle. **There is zero Prisma client or query-engine overhead in production.** + +Generate the Prisma type stubs used for type-checking the facade: ```bash pnpm prisma:generate ``` -Generates TypeScript types in `src/generated/prisma/`. This is only needed for developer type-checking of the `prisma` facade — it does not add any Prisma runtime overhead in production. The facade (`src/lib/prisma-facade.ts`) routes all queries through Drizzle ORM at runtime. +This creates `src/generated/prisma/` (a local, `gitignore`d build artifact) with TypeScript types only. It is never shipped in the production bundle. -Alternatively, you can work with Drizzle directly via the typed schema in `src/db/schema.ts`: - -```ts -import { db } from "@/lib/db"; -import { users } from "@/db/schema"; -const result = await db.select().from(users).where(eq(users.username, "hello")); -``` +> **Legacy CLI command removed:** The `prisma` CLI is now a devDependency used **only** for type generation. Old commands such as `prisma migrate dev`, `prisma studio`, or `prisma db push` are no longer applicable — use the SQL migration runner (`pnpm db:migrate`) or Drizzle CLI instead. ### 5. Run CMS Migrations @@ -140,10 +164,18 @@ The CMS runs behind an nginx reverse proxy on the default port 3000. Static asse | `pnpm test` | Run all tests (Vitest) | | `pnpm db:migrate` | Apply pending SQL migrations | | `pnpm db:migrate:status` | Show migration status | +| `pnpm prisma:generate` | Regenerate Prisma type stubs (dev only, not prod) | | `pnpm analyze` | Build + open bundle analyzer | | `pnpm jobs:worker` | Start background task worker (systemd / PM2) | | `pnpm biome:check` | Lint and format code | +**Drizzle CLI (dev only, run with `npx`):** +| Command | Description | +| ------- | ----------- | +| `drizzle-kit generate` | Generate migration SQL from Drizzle schema | +| `drizzle-kit studio` | Local Drizzle Studio database browser | +| `drizzle-kit introspect` | Reverse-engineer DB → Drizzle schema | + --- ## Performance Features @@ -171,12 +203,17 @@ The CMS runs behind an nginx reverse proxy on the default port 3000. Static asse ``` ├── prisma/ -│ ├── schema.prisma # ~190 models (emulator + CMS) — used for type generation only -│ └── migrations/ # 16 SQL migrations for CMS tables +│ ├── schema.prisma # ~190 models (emulator + CMS) — used for type generation only (legacy) +│ └── migrations/ # 19 SQL migrations for CMS tables (idempotent, never re-run) +├── scripts/ +│ ├── apply-migrations.ts # SQL migration runner (apply + status) +│ ├── jobs-worker.ts # Background task scheduler +│ ├── merge-config.cjs # Utility: merge split config files +│ └── generate-drizzle-schema.mjs # One-off: generate src/db/schema.ts from schema.prisma ├── src/ │ ├── db/ │ │ ├── schema.ts # Drizzle ORM schema (176 tables — runtime data layer) -│ │ └── migrations/ # Drizzle migration files (if used) +│ │ └── migrations/ # Drizzle migration files (local dev only) │ ├── app/ # Next.js App Router (pages & API routes) │ ├── actions/ # Server Actions │ ├── components/ # UI components @@ -206,7 +243,7 @@ The CMS runs behind an nginx reverse proxy on the default port 3000. Static asse | Component | Type | Migrations | | ------------------------------------------------- | ----------------------- | ----------------------------------- | | Emulator tables (`users`, `items`, `rooms`, etc.) | Existing Polaris schema | None — CMS reads/writes only | -| CMS tables (`website_*`, `radio_*`, etc.) | CMS-owned | `prisma/migrations/*.sql` (16 files) | +| CMS tables (`website_*`, `radio_*`, etc.) | CMS-owned | `prisma/migrations/*.sql` (19 files) | | Migration tracking | `cms_migrations` table | Auto-created by migration runner | ### ORM Architecture @@ -282,6 +319,8 @@ pnpm biome:check # Lint and format 2. Follow existing code conventions (Server Components where possible, minimal client boundaries) 3. Use the `src/lib/motion.ts` animation variants for consistent animations 4. SQL migrations in `prisma/migrations/` must be idempotent +5. For new database code, use the Drizzle runtime directly (`import { db } from "@/lib/db"`) — see [ORM Setup](#4-orm-setup--type-generation) +6. Avoid `any` — use `eslint-disable` or `biome-ignore` comments only when unavoidable (e.g., Prisma facade compatibility) ---