Prisma مع NestJS
ليس TypeORM الخيار الوحيد. Prisma ORM حديث وآمن الأنواع تفضّله فِرَق كثيرة لتجربة TypeScript الممتازة وملفّ مخطّط واحد قابل للقراءة. يعمل NestJS مع Prisma بنظافة — تُغلّف عميل Prisma في خدمة قابلة للحقن.
كيف يختلف Prisma عن TypeORM
- المخطّط أولًا: تُعرّف النماذج في ملفّ
schema.prisma واحد، لا في أصناف كيانات متناثرة.
- عميل مُولَّد: يولّد Prisma عميلًا كامل الأنواع من ذلك المخطّط — إكمال تلقائي وفحص أنواع في كل استعلام.
- استعلامات صريحة: لا تحميل كسول ولا سحر خفيّ؛ تطلب البيانات التي تريدها بالضبط.
مخطّط Prisma
النماذج والعلاقات في ملفّ تصريحي واحد:
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
}
تشغيل npx prisma generate يُنتج العميل المكتوب الأنواع؛ وnpx prisma migrate dev يُنشئ ويُطبّق ترحيلًا من المخطّط.
تغليف Prisma في خدمة NestJS
التكامل الاصطلاحي خدمة PrismaService تمدّد PrismaClient وتتّصل عند تهيئة الوحدة:
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}
لاحظ كيف أنّ خطّاف دورة الحياة من قبل (onModuleInit) هو المكان الصحيح تمامًا لفتح الاتصال.
استخدامها في خدمة ميزة
import { Injectable } from '@nestjs/common';
import { PrismaService } from './prisma.service';
@Injectable()
export class UsersService {
constructor(private prisma: PrismaService) {}
findAll() {
return this.prisma.user.findMany({ include: { posts: true } });
}
create(data: { email: string; name: string }) {
return this.prisma.user.create({ data });
}
}
أمان أنواع Prisma هو قوّته الخارقة. كل نتيجة استعلام مكتوبة الأنواع من المخطّط، فخطأ مطبعي في اسم حقل أو شكل خاطئ يصبح خطأ وقت تجميع — لا مفاجأة وقت تشغيل. ويُكمّل المحرّر تلقائيًا العلاقات والمرشّحات والتحديدات.
المعاملات في Prisma
يوفّر Prisma معاملات أيضًا، عبر $transaction() — إمّا مصفوفة عمليات أو ردّ نداء تفاعلي كالموجود في TypeORM:
await this.prisma.$transaction(async (tx) => {
await tx.account.update({ where: { id: from }, data: { balance: { decrement: amount } } });
await tx.account.update({ where: { id: to }, data: { balance: { increment: amount } } });
});
TypeORM أم Prisma؟ كلاهما ممتاز. TypeORM قائم على المُزخرِفات/الأصناف ويبدو أصيلًا لأعراف NestJS؛ ويوفّر Prisma أمان أنواع أقوى من طرف لطرف وملفّ مخطّط واحدًا. اختر واحدًا لكل مشروع والتزم به — فهما لا يُمزَجان.
الخلاصة
Prisma بديل عن TypeORM، مخطّط-أولًا وآمن الأنواع. عرّف النماذج في schema.prisma، ولّد العميل المكتوب الأنواع، وادمجه بتغليف PrismaClient في PrismaService تتّصل في onModuleInit. استعلم بدوال كاملة الأنواع كـ findMany/create، واستخدم $transaction() للذرّية. تاليًا: العمل مع قاعدة بيانات NoSQL، MongoDB.