multiAI Summary Pending

prisma-v7

Expert guidance for Prisma ORM v7 (7.0+). Use when working with Prisma schema files, migrations, Prisma Client queries, database setup, or when the user mentions Prisma, schema.prisma, @prisma/client, database models, or ORM. Covers ESM modules, driver adapters, prisma.config.ts, Rust-free client, and migration from v6.

231 stars

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/prisma-v7/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/djordjevuckovic/prisma-v7/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/prisma-v7/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How prisma-v7 Compares

Feature / Agentprisma-v7Standard Approach
Platform SupportmultiLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Expert guidance for Prisma ORM v7 (7.0+). Use when working with Prisma schema files, migrations, Prisma Client queries, database setup, or when the user mentions Prisma, schema.prisma, @prisma/client, database models, or ORM. Covers ESM modules, driver adapters, prisma.config.ts, Rust-free client, and migration from v6.

Which AI agents support this skill?

This skill is compatible with multi.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Prisma ORM v7 Expert Skill

Comprehensive guidance for working with Prisma ORM version 7.x and later.

## Core v7 Changes

### 1. ES Modules (ESM) Required
Prisma v7 ships as an ES module. Your project must use ESM:

**package.json:**
```json
{
  "type": "module"
}
```

**tsconfig.json:**
```json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Node",
    "target": "ES2023",
    "strict": true,
    "esModuleInterop": true
  }
}
```

### 2. Driver Adapters Required
All databases now require driver adapters. The Rust-free client provides better performance and smaller bundle sizes.

**Available Adapters:**
- PostgreSQL: `@prisma/adapter-pg` (with `pg` driver)
- MySQL/MariaDB: `@prisma/adapter-mariadb` (with `mariadb` driver)
- SQLite: `@prisma/adapter-better-sqlite3` (with `better-sqlite3`)
- CockroachDB: `@prisma/adapter-pg` (with `pg` driver)
- Neon: `@prisma/adapter-neon` (with `@neondatabase/serverless`)
- PlanetScale: `@prisma/adapter-planetscale` (with `@planetscale/database`)
- D1 (Cloudflare): `@prisma/adapter-d1`
- MSSQL: `@prisma/adapter-mssql`

### 3. Generator Configuration
The `output` field is now **required** and the new `prisma-client` provider is standard:

```prisma
generator client {
  provider = "prisma-client"
  output   = "./generated/prisma"
}
```

Note: Client is no longer generated in `node_modules` by default.

### 4. Prisma Config File (prisma.config.ts)
Database URLs and CLI configuration now live in `prisma.config.ts` instead of the schema file.

**Basic setup:**
```typescript
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
  schema: 'prisma/schema.prisma',
  migrations: {
    path: 'prisma/migrations',
  },
  datasource: {
    url: env('DATABASE_URL'),
  },
})
```

**Note:** For Bun, skip `import 'dotenv/config'` as it auto-loads .env files.

### 5. Schema Datasource Block
Remove `url`, `directUrl`, and `shadowDatabaseUrl` from schema.prisma:

**v7 schema.prisma:**
```prisma
datasource db {
  provider = "postgresql"
  // url field removed - now in prisma.config.ts
}

generator client {
  provider = "prisma-client"
  output   = "./generated/prisma"
}
```

## Installation & Setup

### New Project

```bash
# Install dependencies
npm install prisma@latest @prisma/client@latest

# Choose appropriate adapter
npm install @prisma/adapter-pg pg          # PostgreSQL
npm install @prisma/adapter-mariadb mariadb # MySQL/MariaDB
npm install @prisma/adapter-better-sqlite3 better-sqlite3 # SQLite

# Install dev tools
npm install -D tsx dotenv

# Initialize Prisma (creates prisma.config.ts automatically)
npx prisma init
```

### Upgrading from v6

```bash
# Update packages
npm install prisma@latest @prisma/client@latest

# Install adapter for your database
npm install @prisma/adapter-pg pg  # for PostgreSQL

# Install dotenv if not using Bun
npm install dotenv

# Regenerate client
npx prisma generate
```

## Client Instantiation

### PostgreSQL Example

```typescript
import { PrismaClient } from './generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import 'dotenv/config'

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL
})

const prisma = new PrismaClient({ adapter })

export default prisma
```

### MySQL/MariaDB Example

```typescript
import { PrismaClient } from './generated/prisma/client'
import { PrismaMariaDb } from '@prisma/adapter-mariadb'
import 'dotenv/config'

const adapter = new PrismaMariaDb({
  host: 'localhost',
  port: 3306,
  connectionLimit: 5
})

const prisma = new PrismaClient({ adapter })

export default prisma
```

### SQLite Example

```typescript
import { PrismaClient } from './generated/prisma/client'
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'
import 'dotenv/config'

const adapter = new PrismaBetterSqlite3({
  url: process.env.DATABASE_URL || 'file:./dev.db'
})

const prisma = new PrismaClient({ adapter })

export default prisma
```

### Prisma Accelerate (Caching/Pooling)

If using Prisma Accelerate for caching, do NOT use a driver adapter:

```typescript
import { PrismaClient } from './generated/prisma/client'
import { withAccelerate } from '@prisma/extension-accelerate'

const prisma = new PrismaClient({
  accelerateUrl: process.env.DATABASE_URL // prisma:// or prisma+postgres:// URL
}).$extends(withAccelerate())

export default prisma
```

**Important:** Never pass `prisma://` or `prisma+postgres://` URLs to driver adapters.

## Schema Best Practices

### Complete Schema Example

```prisma
// schema.prisma
datasource db {
  provider = "postgresql"
}

generator client {
  provider = "prisma-client"
  output   = "./generated/prisma"
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@index([authorId])
}
```

### Relations

**One-to-Many:**
```prisma
model User {
  id    Int    @id @default(autoincrement())
  posts Post[]
}

model Post {
  id       Int  @id @default(autoincrement())
  author   User @relation(fields: [authorId], references: [id])
  authorId Int
  
  @@index([authorId])
}
```

**Many-to-Many:**
```prisma
model Post {
  id         Int        @id @default(autoincrement())
  categories Category[]
}

model Category {
  id    Int    @id @default(autoincrement())
  posts Post[]
}
```

**One-to-One:**
```prisma
model User {
  id      Int      @id @default(autoincrement())
  profile Profile?
}

model Profile {
  id     Int  @id @default(autoincrement())
  user   User @relation(fields: [userId], references: [id])
  userId Int  @unique
}
```

## Common Commands

```bash
# Generate Prisma Client
npx prisma generate

# Create and apply migration
npx prisma migrate dev --name init

# Apply migrations in production
npx prisma migrate deploy

# Reset database (dev only)
npx prisma migrate reset

# Open Prisma Studio
npx prisma studio

# Format schema
npx prisma format

# Validate schema
npx prisma validate

# Pull schema from database
npx prisma db pull

# Push schema to database (prototyping)
npx prisma db push

# Seed database
npx prisma db seed
```

## Prisma Client Queries

### Basic CRUD

```typescript
// Create
const user = await prisma.user.create({
  data: {
    email: 'user@example.com',
    name: 'John Doe',
  },
})

// Read
const user = await prisma.user.findUnique({
  where: { id: 1 },
})

const users = await prisma.user.findMany({
  where: { email: { contains: '@example.com' } },
  orderBy: { createdAt: 'desc' },
  take: 10,
})

// Update
const user = await prisma.user.update({
  where: { id: 1 },
  data: { name: 'Jane Doe' },
})

// Delete
const user = await prisma.user.delete({
  where: { id: 1 },
})
```

### Relations

```typescript
// Create with relations
const user = await prisma.user.create({
  data: {
    email: 'user@example.com',
    posts: {
      create: [
        { title: 'First Post', content: 'Content...' },
        { title: 'Second Post', content: 'More content...' },
      ],
    },
  },
})

// Query with relations
const userWithPosts = await prisma.user.findUnique({
  where: { id: 1 },
  include: {
    posts: true,
  },
})

// Select specific fields
const user = await prisma.user.findUnique({
  where: { id: 1 },
  select: {
    id: true,
    email: true,
    posts: {
      select: {
        id: true,
        title: true,
      },
    },
  },
})
```

### Advanced Queries

```typescript
// Filtering
const posts = await prisma.post.findMany({
  where: {
    OR: [
      { title: { contains: 'Prisma' } },
      { content: { contains: 'database' } },
    ],
    published: true,
    author: {
      email: { endsWith: '@prisma.io' },
    },
  },
})

// Aggregations
const result = await prisma.post.aggregate({
  _count: true,
  _avg: { authorId: true },
  _sum: { authorId: true },
})

// Group by
const groups = await prisma.post.groupBy({
  by: ['authorId'],
  _count: true,
  having: {
    authorId: { gt: 10 },
  },
})

// Transactions
const [user, post] = await prisma.$transaction([
  prisma.user.create({ data: { email: 'user@example.com' } }),
  prisma.post.create({ data: { title: 'Post', authorId: 1 } }),
])

// Interactive transactions
await prisma.$transaction(async (tx) => {
  const user = await tx.user.create({
    data: { email: 'user@example.com' },
  })
  
  await tx.post.create({
    data: { title: 'Post', authorId: user.id },
  })
})
```

## Migration Workflow

### Development
```bash
# Create migration and apply
npx prisma migrate dev --name add_user_table

# Apply pending migrations
npx prisma migrate dev

# Reset database
npx prisma migrate reset
```

### Production
```bash
# Apply migrations
npx prisma migrate deploy

# Check migration status
npx prisma migrate status
```

### Prototyping
```bash
# Push schema changes without creating migrations
npx prisma db push
```

## Environment Variables

**.env:**
```bash
# PostgreSQL
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"

# MySQL
DATABASE_URL="mysql://user:password@localhost:3306/mydb"

# SQLite
DATABASE_URL="file:./dev.db"

# Prisma Accelerate
DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=..."

# Direct URL (for migrations with Accelerate)
DIRECT_DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
```

## Connection Pooling

In v7, connection pooling is handled by the driver adapter, not by Prisma's URL parameters.

**PostgreSQL with pg driver:**
```typescript
import { Pool } from 'pg'
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from './generated/prisma/client'

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 10, // connection pool size
})

const adapter = new PrismaPg(pool)
const prisma = new PrismaClient({ adapter })
```

## Seeding

**package.json:**
```json
{
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  }
}
```

**prisma/seed.ts:**
```typescript
import { PrismaClient } from '../generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import 'dotenv/config'

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL
})

const prisma = new PrismaClient({ adapter })

async function main() {
  const user = await prisma.user.create({
    data: {
      email: 'admin@example.com',
      name: 'Admin User',
    },
  })
  
  console.log('Seeded:', user)
}

main()
  .catch((e) => {
    console.error(e)
    process.exit(1)
  })
  .finally(async () => {
    await prisma.$disconnect()
  })
```

Run with: `npx prisma db seed`

## Troubleshooting

### Module Resolution Errors
**Problem:** `Cannot find module './generated/prisma/client'`

**Solution:**
1. Ensure `"type": "module"` in package.json
2. Run `npx prisma generate`
3. Check output path in generator block
4. Restart TypeScript server

### Connection Errors (P1017)
**Problem:** Cannot connect to database

**Solution:**
1. Verify DATABASE_URL is correct
2. Ensure `import 'dotenv/config'` is at the top of files
3. Check network connectivity
4. Verify database is running

### Migration Fails
**Problem:** Migration cannot be applied

**Solution:**
1. Check schema syntax with `npx prisma validate`
2. Review migration file in `prisma/migrations/`
3. Use `npx prisma migrate reset` in development
4. For production, manually fix and use `npx prisma migrate resolve`

## Performance Tips

1. **Use select instead of include** when you don't need all fields
2. **Add indexes** for frequently queried fields:
   ```prisma
   @@index([email])
   @@index([authorId, createdAt])
   ```
3. **Use connection pooling** with appropriate pool sizes
4. **Batch operations** when possible:
   ```typescript
   await prisma.user.createMany({
     data: [{ email: 'a@b.com' }, { email: 'c@d.com' }]
   })
   ```
5. **Use raw queries** for complex operations:
   ```typescript
   await prisma.$queryRaw`SELECT * FROM users WHERE email LIKE ${'%@example.com'}`
   ```

## Security Best Practices

1. **Never commit .env files** - add to .gitignore
2. **Use environment variables** for sensitive data
3. **Validate input** before passing to Prisma queries
4. **Use parameterized queries** (Prisma does this automatically)
5. **Limit exposed fields** with select/omit in production APIs
6. **Set appropriate connection limits** to prevent exhaustion
7. **Use read replicas** for scaling read operations

## Key Differences from v6

| Aspect | v6 | v7 |
|--------|----|----|
| Module System | CommonJS or ESM | ESM only |
| Client Generator | `prisma-client-js` | `prisma-client` |
| Output Location | `node_modules` default | Custom path required |
| Database Connection | Built-in drivers | Driver adapters required |
| Config Location | schema.prisma | prisma.config.ts |
| Environment Variables | Auto-loaded | Must use dotenv or Bun |
| Rust Dependencies | Yes | No (Rust-free) |

## Additional Resources

- Official Docs: https://www.prisma.io/docs
- Migration Guide: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7
- Driver Adapters: https://www.prisma.io/docs/orm/overview/databases/database-drivers
- Prisma Schema Reference: https://www.prisma.io/docs/orm/reference/prisma-schema-reference

## Common Patterns

### Singleton Pattern for Prisma Client
```typescript
// lib/prisma.ts
import { PrismaClient } from './generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
import 'dotenv/config'

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined
}

const adapter = new PrismaPg({
  connectionString: process.env.DATABASE_URL
})

export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter })

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}
```

### Type-safe Enums
```prisma
enum Role {
  USER
  ADMIN
  MODERATOR
}

model User {
  id   Int  @id @default(autoincrement())
  role Role @default(USER)
}
```

Usage:
```typescript
import { Role } from './generated/prisma/client'

const admin = await prisma.user.create({
  data: {
    email: 'admin@example.com',
    role: Role.ADMIN,
  },
})
```

## When to Use Prisma

**Good fit:**
- Type-safe database access
- Complex relations and queries
- Auto-generated migrations
- TypeScript projects
- Need for type safety and IntelliSense

**Consider alternatives if:**
- Need MongoDB (wait for v7 support)
- Existing complex SQL procedures
- Extreme performance requirements
- Very simple CRUD without relations

## Notes

- Always run `npx prisma generate` after schema changes
- Use `npx prisma studio` to visualize your database
- Keep migrations in version control
- Test migrations on staging before production
- Use `npx prisma format` to keep schema clean
- The Rust-free client in v7 is faster and has a smaller bundle size
- Driver adapters enable serverless/edge deployment