Prisma ORM Skill
Expert assistance for Prisma ORM schema design, migrations, relations, query optimization, and database integration patterns.
Capabilities
- Design Prisma schemas with proper relations
- Generate and manage database migrations
- Optimize queries for performance
- Implement type-safe database access
- Configure multi-database support
- Set up seeding and testing strategies
Usage
Invoke this skill when you need to:
- Design database schemas with Prisma
- Set up migrations and database workflows
- Optimize database queries
- Implement complex relations
- Configure Prisma with Next.js or other frameworks
Inputs
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | database | string | No | postgresql, mysql, sqlite, mongodb | | models | array | No | List of models to create | | relations | array | No | Model relationships | | features | array | No | migrations, seeding, edge |
Schema Configuration
{
"database": "postgresql",
"models": [
{
"name": "User",
"fields": [
{ "name": "email", "type": "String", "unique": true },
{ "name": "name", "type": "String", "optional": true },
{ "name": "posts", "type": "Post", "relation": "one-to-many" }
]
},
{
"name": "Post",
"fields": [
{ "name": "title", "type": "String" },
{ "name": "content", "type": "String", "optional": true },
{ "name": "author", "type": "User", "relation": "many-to-one" }
]
}
]
}
Output Structure
project/
├── prisma/
│ ├── schema.prisma # Database schema
│ ├── migrations/ # Migration files
│ │ └── 20240101_init/
│ │ └── migration.sql
│ └── seed.ts # Seed script
├── lib/
│ └── db/
│ ├── prisma.ts # Prisma client singleton
│ ├── queries/
│ │ ├── users.ts # User queries
│ │ └── posts.ts # Post queries
│ └── types.ts # Extended types
└── package.json
Generated Code Patterns
Prisma Schema
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}
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[]
comments Comment[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email])
@@map("users")
}
model Profile {
id String @id @default(cuid())
bio String?
avatar String?
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("profiles")
}
model Post {
id String @id @default(cuid())
title String
slug String @unique
content String?
published Boolean @default(false)
authorId String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
categories Category[]
comments Comment[]
tags Tag[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([authorId])
@@index([slug])
@@map("posts")
}
model Category {
id String @id @default(cuid())
name String @unique
posts Post[]
@@map("categories")
}
model Tag {
id String @id @default(cuid())
name String @unique
posts Post[]
@@map("tags")
}
model Comment {
id String @id @default(cuid())
content String
postId String
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
authorId String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
parentId String?
parent Comment? @relation("CommentReplies", fields: [parentId], references: [id])
replies Comment[] @relation("CommentReplies")
createdAt DateTime @default(now())
@@index([postId])
@@index([authorId])
@@map("comments")
}
enum Role {
USER
ADMIN
MODERATOR
}
Prisma Client Singleton
// lib/db/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;
export default prisma;
Query Functions
// lib/db/queries/users.ts
import { prisma } from '../prisma';
import { Prisma } from '@prisma/client';
export type UserWithPosts = Prisma.UserGetPayload<{
include: { posts: true; profile: true };
}>;
export async function getUserById(id: string): Promise<UserWithPosts | null> {
return prisma.user.findUnique({
where: { id },
include: {
posts: {
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
},
profile: true,
},
});
}
export async function getUserByEmail(email: string) {
return prisma.user.findUnique({
where: { email },
select: {
id: true,
email: true,
name: true,
role: true,
},
});
}
export async function createUser(data: Prisma.UserCreateInput) {
return prisma.user.create({
data,
include: {
profile: true,
},
});
}
export async function updateUser(id: string, data: Prisma.UserUpdateInput) {
return prisma.user.update({
where: { id },
data,
});
}
export async function deleteUser(id: string) {
return prisma.user.delete({
where: { id },
});
}
export async function getUsers(params: {
skip?: number;
take?: number;
where?: Prisma.UserWhereInput;
orderBy?: Prisma.UserOrderByWithRelationInput;
}) {
const { skip = 0, take = 10, where, orderBy = { createdAt: 'desc' } } = params;
const [users, total] = await prisma.$transaction([
prisma.user.findMany({
skip,
take,
where,
orderBy,
select: {
id: true,
email: true,
name: true,
role: true,
createdAt: true,
_count: {
select: { posts: true },
},
},
}),
prisma.user.count({ where }),
]);
return {
users,
total,
pages: Math.ceil(total / take),
};
}
Post Queries with Relations
// lib/db/queries/posts.ts
import { prisma } from '../prisma';
import { Prisma } from '@prisma/client';
export async function getPublishedPosts(params: {
page?: number;
limit?: number;
categoryId?: string;
authorId?: string;
search?: string;
}) {
const { page = 1, limit = 10, categoryId, authorId, search } = params;
const skip = (page - 1) * limit;
const where: Prisma.PostWhereInput = {
published: true,
...(categoryId && {
categories: { some: { id: categoryId } },
}),
...(authorId && { authorId }),
...(search && {
OR: [
{ title: { contains: search, mode: 'insensitive' } },
{ content: { contains: search, mode: 'insensitive' } },
],
}),
};
const [posts, total] = await prisma.$transaction([
prisma.post.findMany({
where,
skip,
take: limit,
orderBy: { createdAt: 'desc' },
include: {
author: {
select: { id: true, name: true, email: true },
},
categories: true,
tags: true,
_count: {
select: { comments: true },
},
},
}),
prisma.post.count({ where }),
]);
return {
posts,
pagination: {
page,
limit,
total,
pages: Math.ceil(total / limit),
},
};
}
export async function getPostBySlug(slug: string) {
return prisma.post.findUnique({
where: { s