Skip to main contentprisma
Prisma ORM patterns, schema design, migrations, MySQL integration. Trigger: When writing Prisma schemas, queries, migrations, or seed files.
الانتقال إلى التثبيت التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/cosechasistema/GentlemanClaude --skill prismaيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
المهن ذات الصلةSOC
استنادا إلى تصنيف SOC المهني
| name | prisma |
| description | Prisma ORM patterns, schema design, migrations, MySQL integration. Trigger: When writing Prisma schemas, queries, migrations, or seed files.
|
| license | Apache-2.0 |
| metadata | {"author":"gentleman-programming","version":"1.0"} |
When to Use
- Designing or modifying Prisma schemas
- Writing queries (findMany, create, update, transactions)
- Running migrations
- Setting up Prisma with NestJS
- Seeding the database
- Handling Prisma errors
Schema Design (MySQL)
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
email String @unique @db.VarChar(255)
name String @db.VarChar(100)
bio String? @db.Text
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now()) @db.DateTime(0)
updatedAt DateTime @updatedAt @db.DateTime(0)
deletedAt DateTime? @db.DateTime(0)
@@index([email])
@@index([deletedAt])
@@map("users")
}
model Post {
id String @id @default(cuid())
title String @db.VarChar(255)
content String @db.Text
published Boolean @default(false)
authorId String
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
categories Category[]
@@index([authorId])
@@index([published])
@@map("posts")
}
model Category {
id String @id @default(cuid())
name String @unique @db.VarChar(50)
posts Post[]
@@map("categories")
}
enum Role {
USER
ADMIN
MODERATOR
}
Schema Rules
- ALWAYS use
@db.* native types for every field
- ALWAYS add
@@index on foreign keys and frequently queried fields
- ALWAYS use
@@map("snake_case") for table names
- Use
cuid() or uuid() for IDs, not autoincrement (unless required)
- Use
@db.DateTime(0) for MySQL datetime fields
- Use
@db.Decimal(10, 2) for money fields
- Use
@db.Text for long strings, @db.VarChar(n) for bounded strings
Relations
// One-to-One
model Profile {
userId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
// One-to-Many
model Post {
authorId String
author User @relation(fields: [authorId], references: [id])
@@index([authorId])
}
// Many-to-Many (implicit — Prisma creates join table)
model Post { categories Category[] }
model Category { posts Post[] }
// Many-to-Many (explicit — with metadata)
model CategoryOnPost {
postId String
categoryId String
assignedAt DateTime @default(now())
post Post @relation(fields: [postId], references: [id])
category Category @relation(fields: [categoryId], references: [id])
@@id([postId, categoryId])
}
Query Patterns
Select Only What You Need
const users = await prisma.user.findMany({
select: { id: true, email: true, name: true },
})
const user = await prisma.user.findUnique({
where: { id },
include: {
posts: { where: { published: true }, select: { id: true, title: true } },
},
})
Pagination
const posts = await prisma.post.findMany({
take: 10,
skip: 1,
cursor: { id: lastPostId },
orderBy: { id: 'asc' },
})
const posts = await prisma.post.findMany({
skip: (page - 1) * pageSize,
take: pageSize,
})
Decision: Large dataset or infinite scroll → cursor. Small dataset or page numbers → offset.
Transactions
const [user, post] = await prisma.$transaction([
prisma.user.create({ data: userData }),
prisma.post.delete({ where: { id: postId } }),
])
const result = await prisma.$transaction(async (tx) => {
const account = await tx.account.findUnique({ where: { id: fromId } })
if (account.balance < amount) throw new Error('Insufficient funds')
await tx.account.update({ where: { id: fromId }, data: { balance: { decrement: amount } } })
await tx.account.update({ where: { id: toId }, data: { balance: { increment: amount } } })
return { success: true }
})
CRITICAL: Keep interactive transactions SHORT. NEVER make HTTP calls inside them.
Error Handling
import { Prisma } from '@prisma/client';
try {
await prisma.user.create({ data });
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
switch (error.code) {
case 'P2002':
throw new ConflictException('Resource already exists');
case 'P2025':
throw new NotFoundException('Resource not found');
case 'P2003':
throw new BadRequestException('Related resource not found');
}
}
throw error;
}
NestJS Integration
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
async onModuleInit() { await this.$connect(); }
async onModuleDestroy() { await this.$disconnect(); }
}
@Global()
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}
@Injectable()
export class UsersService {
constructor(private prisma: PrismaService) {}
async findAll() { return this.prisma.user.findMany(); }
}
Prisma Exception Filter (NestJS)
@Catch(Prisma.PrismaClientKnownRequestError)
export class PrismaExceptionFilter extends BaseExceptionFilter {
catch(exception: Prisma.PrismaClientKnownRequestError, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const map: Record<string, number> = {
P2002: HttpStatus.CONFLICT,
P2025: HttpStatus.NOT_FOUND,
P2003: HttpStatus.BAD_REQUEST,
};
const status = map[exception.code] ?? HttpStatus.INTERNAL_SERVER_ERROR;
response.status(status).json({ statusCode: status, error: exception.code });
}
}
Seeding
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
await prisma.user.deleteMany();
await prisma.user.create({
data: {
email: 'admin@example.com',
name: 'Admin',
role: 'ADMIN',
posts: { create: [{ title: 'First Post', content: 'Hello', published: true }] },
},
});
}
main()
.catch((e) => { console.error(e); process.exit(1); })
.finally(() => prisma.$disconnect());
{ "prisma": { "seed": "tsx prisma/seed.ts" } }
Soft Delete Pattern
model User {
deletedAt DateTime? @db.DateTime(0)
@@index([deletedAt])
}
const prisma = new PrismaClient().$extends({
query: {
$allModels: {
async findMany({ args, query }) {
args.where = { ...args.where, deletedAt: null };
return query(args);
},
async delete({ args, query }) {
return (query as any)({ ...args, data: { deletedAt: new Date() } });
},
},
},
});
Commands
npx prisma init
npx prisma generate
npx prisma migrate dev --name init
npx prisma migrate deploy
npx prisma migrate reset
npx prisma db push
npx prisma db seed
npx prisma studio
npx prisma format
npx prisma validate