إنتقل إلى المحتوى الرئيسي

تطوير Prisma ORM في Cursor: دليل شامل

تطوير Prisma في Cursor

Prisma هو ORM من الجيل التالي لـ TypeScript يوفر عميل قاعدة بيانات آمن الأنواع، وتهجرات مخطط تعريفية، ومتصفح قاعدة بيانات مرئي يُسمى Prisma Studio. يُلغي Prisma كود الوصول لقاعدة البيانات المتكرر ويلتقط أخطاء الاستعلام في وقت التجميع. يُعد Cursor، بمساعد الذكاء الاصطناعي المدمج وأساسه المتوافق مع VS Code، محرراً ممتازاً لتطوير Prisma -- فهو يوفر IntelliSense للغة مخطط Prisma، ويُكمل تلقائياً استعلامات Prisma Client، ويمكنه إنشاء مخططات كاملة من أوصاف اللغة الطبيعية.

يغطي هذا الدليل سير عمل تطوير Prisma الكامل في Cursor: التثبيت والإعداد، تصميم المخطط، التهجرات، استعلامات Prisma Client، العلاقات، Prisma Studio، وإنشاء المخطط بمساعدة الذكاء الاصطناعي.

تثبيت وإعداد Prisma في Cursor​

المتطلبات الأساسية​

يعمل Prisma مع Node.js 18+ ويدعم PostgreSQL و MySQL و SQLite و MongoDB و SQL Server. تحقق من إصدار Node.js:

node --version
تلميح

الطرفية المدمجة في Cursor (Ctrl+`) تبقى متزامنة مع لوحة Explorer. يمكنك تشغيل أوامر Prisma CLI ورؤية الملفات المُنشأة تظهر فوراً في شجرة الملفات.

تثبيت إضافة Prisma​

يرث Cursor توافق إضافات VS Code. ثبّت إضافة Prisma الرسمية من عرض الإضافات (Ctrl+Shift+X):

  1. ابحث عن "Prisma".
  2. ثبّت الإضافة التي نشرتها Prisma.
  3. أعد تحميل Cursor إذا طُلب منك ذلك.

توفر الإضافة:

  • تمييز الصياغة لملفات مخطط .prisma.
  • التنسيق التلقائي عند الحفظ.
  • IntelliSense لحقول النماذج والسمات والعلاقات.
  • تحقق مضمن لأخطاء المخطط.
  • إجراءات كود للإصلاحات السريعة.
warning

إذا لم تُثبّت إضافة Prisma، سيعامل Cursor ملفات .prisma كنص عادي. ستفقد تمييز الصياغة والإكمال التلقائي واكتشاف الأخطاء. ثبّت دائماً الإضافة الرسمية قبل تحرير ملفات المخطط.

تهيئة Prisma في مشروع​

ثبّت Prisma CLI وتهيئة إعداد Prisma جديد:

npm install prisma --save-dev
npm install @prisma/client

npx prisma init

هذا ينشئ:

  • prisma/schema.prisma -- ملف المخطط الرئيسي.
  • .env -- ملف البيئة مع عنصر نائب DATABASE_URL.

عيّن سلسلة اتصال قاعدة البيانات في .env:

# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
تلميح

اطلب من Cursor: "Set up Prisma with PostgreSQL in my project. Create the schema file with a User model and configure the database connection." سيقوم Cursor بتشغيل أوامر التهيئة وإنشاء المخطط وإعداد ملف .env.

تصميم المخطط​

مخطط Prisma هو المصدر الوحيد للحقيقة لبنية قاعدة البيانات الخاصة بك. يُعرّف النماذج والعلاقات والـ enums وتكوين مصدر البيانات.

فهم ملف المخطط​

// prisma/schema.prisma

// Generator: tells Prisma how to generate the client
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "postgresqlExtensions"]
}

// Datasource: database connection
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
extensions = [pgcrypto, postgis]
}

// Model: maps to a database table
model User {
id String @id @default(uuid())
email String @unique
name String?
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

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

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

model Category {
id String @id @default(uuid())
name String @unique
posts Post[]
}

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

enum Role {
USER
ADMIN
EDITOR
}

سمات الحقول الشائعة​

السمةالوصف
@idتُحدد الحقل كمفتاح أساسي
@default(uuid())تُنشئ UUID تلقائياً عند الإدراج
@default(autoincrement())عدد صحيح يزداد تلقائياً (MySQL/PostgreSQL)
@uniqueتُطبّق التفرد على الحقل
@updatedAtتُحدّث الطابع الزمني تلقائياً عند تحديث السجل
@relationتُعرّف علاقة بين النماذج
@mapتربط الحقل بعمود باسم مختلف
@@indexتُنشئ فهرس قاعدة بيانات على الحقل/الحقول
@@uniqueقيد تفريد مركب
@@mapتربط النموذج بجدول باسم مختلف
تلميح

اطلب من Cursor: "Generate a Prisma schema for an e-commerce platform with User, Product, Order, OrderItem, and Category models. Include appropriate relations, indexes, and enums for order status and product availability." سينتج Cursor مخططاً كاملاً ومُتحققاً منه بصياغة علاقات صحيحة.

العلاقات​

يدعم Prisma علاقات واحد لواحد، واحد لكثير، وكثير لكثير.

واحد لواحد:

model User {
id String @id @default(uuid())
profile Profile?
}

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

واحد لكثير:

model User {
id String @id @default(uuid())
posts Post[]
}

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

كثير لكثير (ضمني):

model Post {
id String @id @default(uuid())
categories Category[]
}

model Category {
id String @id @default(uuid())
posts Post[]
}

كثير لكثير (صريح، مع حقول إضافية على جدول الوصل):

model Post {
id String @id @default(uuid())
tags PostTag[]
}

model Tag {
id String @id @default(uuid())
posts PostTag[]
}

model PostTag {
post Post @relation(fields: [postId], references: [id])
postId String
tag Tag @relation(fields: [tagId], references: [id])
tagId String
assignedAt DateTime @default(now())

@@id([postId, tagId])
}
warning

عند استخدام علاقات كثير لكثير الضمنية، يُنشئ Prisma جدول وصل مخفي تلقائياً. لا يمكنك إضافة حقول إضافية (مثل assignedAt أو createdBy) إلى هذا الجدول المخفي. إذا كنت بحاجة إلى بيانات وصفية على العلاقة، استخدم جدول وصل صريح كما هو موضح أعلاه.

التهجرات​

يُنشئ Prisma Migrate تغييرات مخطط قاعدة البيانات ويُطبقها بطريقة مُنمذجة وقابلة للعكس.

إنشاء أول تهجيرة​

بعد تعريف مخططك، أنشئ التهجيرة الأولية:

npx prisma migrate dev --name init

هذا الأمر:

  1. يُنشئ ملف تهجيرة SQL في prisma/migrations/.
  2. يُطبّق التهجيرة على قاعدة البيانات.
  3. يُعيد إنشاء Prisma Client.
تلميح

استخدم أسماء تهجيرة وصفية: npx prisma migrate dev --name add_order_status_enum. تظهر هذه الأسماء في سجل التهجرات وتساعدك على تتبع تطور المخطط.

تعديل المخطط​

عند تغيير المخطط، أنشئ تهجيرة جديدة:

# After editing schema.prisma
npx prisma migrate dev --name add_post_view_count

يكتشف Prisma الفرق بين مخططك وقاعدة البيانات، ويُنشئ تهجيرة، ويُطبقها.

سير عمل التهجيرة للإنتاج​

لقواعد بيانات الإنتاج، استخدم prisma migrate deploy الذي يُطبّق التهجرات المعلقة دون إعادة تعيين البيانات:

# Apply migrations in production
npx prisma migrate deploy
warning

لا تُشغّل أبداً prisma migrate dev ضد قاعدة بيانات إنتاج. يمكن للأمر dev إعادة تعيين قاعدة البيانات إذا اكتشف انحراف المخطط. استخدم دائماً migrate deploy في بيئات الإنتاج.

إعادة تعيين قاعدة البيانات​

أثناء التطوير، قد تحتاج إلى إعادة تعيين قاعدة البيانات وإعادة تطبيق جميع التهجرات:

npx prisma migrate reset

هذا يُسقط جميع البيانات والجداول، ثم يُعيد تطبيق جميع التهجرات من الصفر.

بذر قاعدة البيانات​

أنشئ سكربت بذر لتعبئة قاعدة البيانات بالبيانات الأولية:

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

const prisma = new PrismaClient();

async function main() {
// Create users
const alice = await prisma.user.create({
data: {
name: 'Alice Johnson',
role: 'ADMIN',
profile: {
create: {
bio: 'Software engineer and blogger',
},
},
},
});

const bob = await prisma.user.create({
data: {
name: 'Bob Smith',
role: 'USER',
},
});

// Create posts
const post1 = await prisma.post.create({
data: {
title: 'Getting Started with Prisma',
content: 'Prisma is a type-safe ORM...',
published: true,
author: { connect: { id: alice.id } },
},
});

const post2 = await prisma.post.create({
data: {
title: 'Advanced Prisma Relations',
content: 'Relations in Prisma...',
published: true,
author: { connect: { id: alice.id } },
},
});

console.log('Seed data created successfully');
}

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

كوّن أمر البذر في package.json:

{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}

شغّل البذر:

npx prisma db seed
تلميح

اطلب من Cursor: "Create a seed script for my Prisma schema with 5 users, 20 posts, and 10 categories. Make sure some posts are unpublished and some users have profiles while others do not." سيقوم Cursor بإنشاء سكربت بذر واقعي يُمارس جميع أنواع العلاقات.

استعلامات Prisma Client​

Prisma Client هو منشئ استعلامات آمن الأنواع يُنشأ تلقائياً ويحل محل نماذج ORM التقليدية و SQL الخام.

إنشاء مثيل العميل​

أنشئ مثيل singleton لتجنب اتصالات متعددة في التطوير:

// 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: ['query', 'info', 'warn', 'error'],
});

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

في التطوير مع إعادة تحميل الوحدات الساخنة، إنشاء PrismaClient جديد عند كل تغيير ملف يسبب استنزاف تجمع الاتصالات. نمط Singleton أعلاه يمنع ذلك عن طريق تخزين المثيل مؤقتاً على globalThis.

عمليات CRUD​

إنشاء:

// Create a single record
const user = await prisma.user.create({
data: {
name: 'Charlie Brown',
profile: {
create: {
bio: 'New user bio',
},
},
},
});

// Create multiple records
const users = await prisma.user.createMany({
data: [
{ email: '[email protected]', name: 'User One' },
{ email: '[email protected]', name: 'User Two' },
{ email: '[email protected]', name: 'User Three' },
],
});

قراءة:

// Find a single record
const user = await prisma.user.findUnique({
where: { email: '[email protected]' },
include: { profile: true, posts: true },
});

// Find multiple records with filtering and sorting
const publishedPosts = await prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
skip: 0,
include: {
author: {
select: { id: true, name: true, email: true },
},
},
});

// Count records
const totalPosts = await prisma.post.count({
where: { published: true },
});

تحديث:

// Update a single record
const updatedPost = await prisma.post.update({
where: { id: postId },
data: {
title: 'Updated Title',
viewCount: { increment: 1 },
},
});

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

حذف:

// Delete a single record
const deletedUser = await prisma.user.delete({
where: { id: userId },
});

// Delete multiple records
const result = await prisma.post.deleteMany({
where: { authorId: userId, published: false },
});

التصفية المتقدمة​

const posts = await prisma.post.findMany({
where: {
AND: [
{ published: true },
{
OR: [
{ title: { contains: 'prisma', mode: 'insensitive' } },
{ content: { contains: 'orm', mode: 'insensitive' } },
],
},
],
createdAt: {
gte: new Date('2024-01-01'),
lte: new Date('2024-12-31'),
},
author: {
role: { in: ['ADMIN', 'EDITOR'] },
},
},
orderBy: [{ viewCount: 'desc' }, { createdAt: 'desc' }],
});

المعاملات​

// Interactive transaction
const result = await prisma.$transaction(async (tx) => {
const author = await tx.user.create({
data: { email: '[email protected]', name: 'New Author' },
});

const post = await tx.post.create({
data: {
title: 'My First Post',
content: 'Hello world',
authorId: author.id,
},
});

await tx.profile.create({
data: {
bio: 'New author profile',
userId: author.id,
},
});

return { author, post };
});
تلميح

اطلب من Cursor: "Write a Prisma transaction that transfers credits between two users. Deduct from sender, add to receiver, and create a transfer record. Roll back if the sender has insufficient balance." سيقوم Cursor بإنشاء المعاملة التفاعلية مع معالجة أخطاء مناسبة.

ترقيم الصفحات​

// Offset-based pagination
const page = 1;
const pageSize = 10;

const [posts, totalCount] = await prisma.$transaction([
prisma.post.findMany({
where: { published: true },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
include: { author: true },
}),
prisma.post.count({ where: { published: true } }),
]);

const totalPages = Math.ceil(totalCount / pageSize);

Prisma Studio​

Prisma Studio هو متصفح قاعدة بيانات مرئي يعمل في متصفحك. يتيح لك عرض السجلات وإنشائها وتحديثها وحذفها دون كتابة استعلامات.

تشغيل Prisma Studio​

npx prisma studio

هذا يفتح واجهة متصفح على http://localhost:5555 حيث يمكنك:

  • تصفح جميع النماذج المُعرفة في مخططك.
  • عرض السجلات في جدول قابل للفرز والتصفية.
  • إنشاء سجلات جديدة بواجهة نموذج.
  • تحرير السجلات الموجودة بالنقر على الخلايا.
  • حذف السجلات مع مربع حوار تأكيد.
  • تصفية وبحث السجلات بقيم الحقول.
تلميح

Prisma Studio لا يُقدر بثمن للتصحيح أثناء التطوير. بدلاً من كتابة استعلامات مؤقتة، شغّل Studio، افحص بياناتك، وقم بتعديلات سريعة. يعكس التغييرات في الوقت الفعلي.

warning

يكتب Prisma Studio مباشرة إلى قاعدة البيانات. كن حذراً عند استخدامه ضد قاعدة بيانات إنتاج -- لا يوجد تراجع عن الحذف أو التعديل. احتفظ دائماً بنسخة احتياطية من بياناتك قبل إجراء تغييرات يدوية في Studio.

التصفية في Studio​

يدعم Prisma Studio التصفية بـ:

  • اسم الحقل (اختر أي عمود).
  • عامل التصفية (يساوي، لا يساوي، يحتوي، يبدأ بـ، ينتهي بـ، إلخ).
  • مرشحات متعددة مُجمعة بمنطق AND/OR.

إنشاء المخطط بمساعدة الذكاء الاصطناعي في Cursor​

يتفوق مساعد الذكاء الاصطناعي في Cursor في إنشاء مخططات Prisma واستعلامات واستراتيجيات تهجيرة من أوصاف اللغة الطبيعية.

إنشاء مخطط من وصف​

افتح Cursor Chat (Ctrl+L) وصف نموذج بياناتك:

Generate a Prisma schema for a project management application with these models:
- User (id, email, name, avatar, role enum: ADMIN/MEMBER/VIEWER)
- Workspace (id, name, slug, ownerId)
- Project (id, name, description, workspaceId, status enum)
- Task (id, title, description, status, priority, assigneeId, projectId, dueDate)
- Comment (id, content, authorId, taskId)
- Label (id, name, color, projectId)
Include all necessary relations, indexes on foreign keys, and timestamps.
Use PostgreSQL with UUID primary keys.

سيقوم Cursor بإنشاء مخطط كامل مع جميع النماذج والعلاقات والـ enums والفهارس. يتضمن المخطط المُنشأ نماذج User و Workspace و Project و Task و Comment و Label مع علاقات المفاتيح الأجنبية الصحيحة، وقيد التفريد المركب، وفهارس قاعدة البيانات على جميع أعمدة المفاتيح الأجنبية.

تلميح

عند طلب إنشاء مخططات من Cursor، حدد مزود قاعدة البيانات (PostgreSQL، MySQL، إلخ)، ونوع المفتاح الأساسي (UUID مقابل الزيادة التلقائية)، وما إذا كنت بحاجة إلى فهارس. هذا يضمن استخدام المخطط المُنشأ لميزات قاعدة البيانات المحددة بشكل صحيح.

إنشاء الاستعلامات بمساعدة الذكاء الاصطناعي​

اطلب من Cursor كتابة استعلامات معقدة:

Write a Prisma query to fetch the top 5 most active users in a workspace,
sorted by the number of completed tasks. Include each user's name, email,
avatar, and task count. Only count tasks created in the last 30 days.
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

const topUsers = await prisma.user.findMany({
where: {
assignedTasks: {
some: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
project: { workspaceId },
},
},
},
select: {
id: true,
name: true,
email: true,
avatar: true,
_count: {
select: {
assignedTasks: {
where: {
status: 'DONE',
createdAt: { gte: thirtyDaysAgo },
},
},
},
},
},
orderBy: {
assignedTasks: {
_count: 'desc',
},
},
take: 5,
});
warning

يمكن لـ _count في Prisma مع التصفية المتداخلة إنشاء استعلامات SQL مكلفة. تحقق دائماً من SQL المُنشأ (فعّل تسجيل الاستعلامات باستخدام new PrismaClient({ log: ['query'] })) وأضف فهارس قاعدة البيانات المناسبة لتجنب عمليات مسح الجدول الكامل.

الخلاصة​

يُنشئ اقتران Prisma مع Cursor تجربة تطوير قواعد بيانات مبسطة. ملف المخطط التعريفي بمثابة مصدر وحيد للحقيقة، وتوفر التهجرات مساراً آمناً لتطور المخطط، ويلتقط Prisma Client الآمن الأنواع أخطاء الاستعلام في وقت التجميع، ويوفر Prisma Studio واجهة مرئية لفحص البيانات. يسرّع مساعد الذكاء الاصطناعي في Cursor كل خطوة -- من إنشاء مخططات كاملة لنماذج مجال معقدة إلى كتابة استعلامات مُحسّنة مع تضمينات متداخلة وتجميعات. ابدأ بتثبيت إضافة Prisma، عرّف نماذجك بعلاقات وفهارس مناسبة، استخدم migrate dev أثناء التطوير و migrate deploy في الإنتاج، ودع Cursor يُنشأ الكود المتكرر لتركز على طبقة بيانات تطبيقك.