prisma

Prisma is a next-generation ORM for Node.js and TypeScript. It provides type-safe database access, auto-generated migrations, and an intuitive data modeling language.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "prisma" with this command: npx skills add fractionestate/midnight-dev-skills/fractionestate-midnight-dev-skills-prisma

Prisma ORM

Prisma is a next-generation ORM for Node.js and TypeScript. It provides type-safe database access, auto-generated migrations, and an intuitive data modeling language.

Core Concepts

Schema Definition (schema.prisma)

generator client { provider = "prisma-client-js" }

datasource db { provider = "postgresql" url = env("DATABASE_URL") }

model User { id String @id @default(cuid()) email String @unique name String? password String role Role @default(USER) posts Post[] profile Profile? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt

@@index([email]) }

model Profile { id String @id @default(cuid()) bio String? avatar String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String @unique }

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

@@index([authorId]) @@index([published, createdAt]) }

model Tag { id String @id @default(cuid()) name String @unique posts Post[] }

model Comment { id String @id @default(cuid()) content String post Post @relation(fields: [postId], references: [id], onDelete: Cascade) postId String createdAt DateTime @default(now()) }

enum Role { USER ADMIN MODERATOR }

Client Setup

Singleton Pattern (Next.js)

// lib/prisma.ts import { PrismaClient } from '@prisma/client';

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

export const prisma = globalForPrisma.prisma ?? new PrismaClient({ log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'], });

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

With Extensions

const prisma = new PrismaClient().$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return ${user.firstName} ${user.lastName}; }, }, }, }, });

CRUD Operations

Create

// Single record const user = await prisma.user.create({ data: { email: 'user@example.com', name: 'John Doe', profile: { create: { bio: 'Developer' }, }, }, include: { profile: true }, });

// Multiple records const users = await prisma.user.createMany({ data: [ { email: 'user1@example.com', name: 'User 1' }, { email: 'user2@example.com', name: 'User 2' }, ], skipDuplicates: true, });

// With nested creation const post = await prisma.post.create({ data: { title: 'Hello World', author: { connect: { id: userId } }, tags: { connectOrCreate: [ { where: { name: 'tech' }, create: { name: 'tech' } }, { where: { name: 'news' }, create: { name: 'news' } }, ], }, }, });

Read

// Find unique const user = await prisma.user.findUnique({ where: { email: 'user@example.com' }, include: { posts: true }, });

// Find many with filtering const posts = await prisma.post.findMany({ where: { published: true, author: { email: { contains: '@example.com' } }, OR: [{ title: { contains: 'prisma' } }, { content: { contains: 'prisma' } }], }, orderBy: { createdAt: 'desc' }, take: 10, skip: 0, select: { id: true, title: true, author: { select: { name: true } }, }, });

// Pagination const [posts, total] = await Promise.all([ prisma.post.findMany({ take: 10, skip: (page - 1) * 10, orderBy: { createdAt: 'desc' }, }), prisma.post.count(), ]);

Update

// Single update const user = await prisma.user.update({ where: { id: userId }, data: { name: 'Updated Name' }, });

// Update or create (upsert) const user = await prisma.user.upsert({ where: { email: 'user@example.com' }, update: { name: 'Updated' }, create: { email: 'user@example.com', name: 'New User' }, });

// Update many const result = await prisma.post.updateMany({ where: { authorId: userId }, data: { published: false }, });

// Atomic operations const post = await prisma.post.update({ where: { id: postId }, data: { views: { increment: 1 }, likes: { decrement: 1 }, }, });

Delete

// Single delete await prisma.user.delete({ where: { id: userId }, });

// Delete many await prisma.post.deleteMany({ where: { published: false, createdAt: { lt: new Date('2024-01-01') }, }, });

Transactions

Sequential Operations

const [posts, totalPosts, users] = await prisma.$transaction([ prisma.post.findMany({ where: { published: true } }), prisma.post.count({ where: { published: true } }), prisma.user.findMany(), ]);

Interactive Transactions

const result = await prisma.$transaction( async (tx) => { // Decrement sender balance const sender = await tx.account.update({ where: { id: senderId }, data: { balance: { decrement: amount } }, });

if (sender.balance < 0) {
  throw new Error('Insufficient funds');
}

// Increment receiver balance
const receiver = await tx.account.update({
  where: { id: receiverId },
  data: { balance: { increment: amount } },
});

return { sender, receiver };

}, { maxWait: 5000, timeout: 10000, } );

Relations

One-to-One

model User { id String @id profile Profile? }

model Profile { id String @id user User @relation(fields: [userId], references: [id]) userId String @unique }

One-to-Many

model User { id String @id posts Post[] }

model Post { id String @id author User @relation(fields: [authorId], references: [id]) authorId String }

Many-to-Many

model Post { id String @id tags Tag[] }

model Tag { id String @id posts Post[] }

Migrations

Create migration

npx prisma migrate dev --name init

Apply migrations (production)

npx prisma migrate deploy

Reset database

npx prisma migrate reset

Generate client

npx prisma generate

Open Prisma Studio

npx prisma studio

Best Practices

  • Use cuid() or uuid() for IDs instead of autoincrement

  • Always include indexes for frequently queried fields

  • Use select/include to avoid over-fetching

  • Singleton pattern in Next.js to prevent connection exhaustion

  • Interactive transactions for complex operations

  • Soft deletes with deletedAt field for important data

References

  • references/schema.md - Schema patterns

  • references/query-patterns.md - Advanced queries

  • references/migrations.md - Migration strategies

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

turborepo

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

playwright

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

nextjs

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

testing

No summary provided by upstream source.

Repository SourceNeeds Review