# Pathrule Pattern: Prisma ORM (1.0.0)
# ::pathrule:package:prisma-orm

### [RULE] Use the prisma-client generator with an explicit output  (path: /prisma)
<!-- scope: folder | priority: high | strict -->

Prisma 7 made the Rust-free client the default and changed how it is generated. The old block simply does not work, and the import path changed with it.

- The generator block is `generator client { provider = "prisma-client" output = "./generated/prisma" }`. `output` is required; `prisma-client-js` and `engineType` are gone.
- Import from the generated location (`import { PrismaClient } from "./generated/prisma/client"`), not from `@prisma/client`. Fix the import everywhere in the same change, because the old path resolves to something that will not run.
- Decide whether the generated directory is committed or generated in CI, then be consistent: if it is gitignored, `prisma generate` must run in every build and before typecheck, since types now come from that folder.
- Put configuration (schema path, migrations, seed command) in `prisma.config.ts` at the project root rather than in `package.json`, which is where Prisma 7 expects it.
- Seeding is explicit now: run `prisma db seed` yourself, because migrations no longer trigger it.

---

### [RULE] One client per process, constructed with a driver adapter  (path: /src/db)
<!-- scope: folder | priority: high | strict -->

In Prisma 7 every database connection goes through a driver adapter, and the client owns a connection pool. Creating one per request or per module reload is how a small app exhausts a database.

- Build the adapter for your database (`new PrismaPg({ connectionString })` for Postgres, the matching adapter for MySQL, SQLite, or a serverless driver) and pass it in: `new PrismaClient({ adapter })`.
- Export one instance from a single module and import that everywhere. In development, cache it on `globalThis` so hot reload does not open a new pool on every file save.
- In serverless or edge runtimes, keep the client in module scope so it is reused across invocations of the same instance, and put a pooler (PgBouncer, a platform pooler, or a serverless driver adapter) between the function and the database. Concurrency there is the number of instances, not the number of requests.
- Do not call `$connect()` eagerly or `$disconnect()` per request; the client connects lazily and disconnecting per request defeats pooling. Disconnect only in scripts and tests that end.
- Extend behaviour with client extensions (`$extends`) for logging, soft delete, computed fields, or row-level filters. The `$use` middleware API was removed.

---

### [RULE] Select explicitly, batch relations, and keep transactions short  (path: /src/db)
<!-- scope: folder | priority: high | strict -->

Prisma makes over-fetching easy to write and hard to see: a model query returns every column, and a relation accessed in a loop is a query per row.

- Use `select` (or a narrow `include`) on anything that leaves a request handler. A default query returns all scalar fields, which is how a token or a hashed password ends up in an API response.
- Load relations in the query with `include` or `select`, not by iterating results and querying per item. When you truly need per-item work, fetch the set in one `findMany({ where: { id: { in: ids } } })` and key it in memory.
- Wrap multi-write invariants in a transaction: `$transaction([...])` for independent writes, the interactive form only when a later write depends on an earlier read. Keep interactive transactions free of network calls and set a timeout; a long one holds locks and blocks other writers.
- Paginate with cursor pagination on a stable indexed column for large or infinite lists; `skip` grows more expensive as the offset grows.
- Only use `$queryRaw` with tagged-template parameters. `$queryRawUnsafe` with interpolated input is SQL injection, and `$executeRaw` bypasses every extension you rely on.

---

### [MEMORY] Migration workflow and what Prisma 7 removed  (path: /prisma)

The migration model is unchanged, but several conveniences were removed in 7, and code or scripts that relied on them fail quietly.

- Locally, change the schema and run `prisma migrate dev` to generate and apply a migration. In CI and production, run `prisma migrate deploy`, which only applies pending files and never generates or resets.
- `prisma db push` is for prototyping against a scratch database. It does not create migration files, so never run it against an environment whose history matters.
- Never edit a migration that has been applied anywhere shared. Add a new one, even for a typo.
- Removed in 7 and worth knowing before you write a script: the `$use` middleware API (use `$extends`), the metrics preview feature, the `--skip-generate` and `--skip-seed` CLI flags, `--schema`/`--url` on `prisma db execute`, and automatic seeding as part of migrate.
- Write destructive changes as multi-step: add the new column, deploy code that writes both, backfill, switch reads, then drop. A single migration that renames a column is a deploy-time outage.

See /src/db for the client and query rules, and the postgres-schema pattern for index and constraint design underneath Prisma.

---

### [SKILL] prisma-v7-upgrade  (path: /)

---
name: prisma-v7-upgrade
description: Ordered procedure to move a codebase from Prisma 6 to Prisma 7: generator block, generated client import, driver adapters, middleware to extensions, and the removed CLI flags. Use when upgrading or when a Prisma 6 shape appears in a Prisma 7 project.
---

# Prisma 6 to 7 upgrade

Run in order. Each step leaves the repo buildable.

1. **Pin and read.** Upgrade `prisma` and `@prisma/client` together to the same 7.x version. Mismatched versions produce confusing type errors.
2. **Switch the generator.** In `schema.prisma`, replace the client generator with:
   `generator client { provider = "prisma-client" output = "./generated/prisma" }`
   Remove `engineType`. Decide now whether `output` is committed or gitignored.
3. **Regenerate.** Run `prisma generate` and confirm the directory appears where `output` points.
4. **Fix imports.** Replace every `from "@prisma/client"` with the generated path (`./generated/prisma/client`, adjusted per file or via a path alias). Include types (`Prisma`, model types, enums), not just `PrismaClient`.
5. **Add the driver adapter.** Install the adapter for your database, construct it from the connection string, and pass it to the client: `new PrismaClient({ adapter })`. Do this in the single module that exports the client.
6. **Replace middleware.** Rewrite every `prisma.$use(...)` as a `$extends` client extension (query extension for interception, result extension for computed fields). There is no compatibility shim.
7. **Move config.** Create `prisma.config.ts` for schema path, migrations, and the seed command, and delete the `prisma` block from `package.json`.
8. **Fix scripts and CI.** Remove `--skip-generate` and `--skip-seed`, add an explicit `prisma db seed` step where seeding was implicit, and drop `--schema`/`--url` from any `prisma db execute` call.
9. **Verify.** Typecheck, run the test suite against a real database, and check that `prisma migrate deploy` is still the production command.

## Done when
- [ ] No import from `@prisma/client` remains.
- [ ] The client is constructed once, with an adapter.
- [ ] No `$use` call remains anywhere.
- [ ] CI generates the client before typecheck and seeds explicitly.
