العمل مع قواعد البيانات في TypeScript: PostgreSQL و MongoDB
TypeScript هي لغة برمجة قوية تضيف الكتابة الثابتة (static typing) إلى JavaScript. عند تطوير تطبيقات الويب الحديثة، يعد العمل مع قواعد البيانات جزءًا لا يتجزأ. في هذه المقالة، سننظر في كيفية العمل بفعالية مع قاعدتي بيانات شائعتين — PostgreSQL العلائقية و MongoDB الموجهة للمستندات — باستخدام TypeScript.
1. إعداد البيئة واختيار ORM
قبل البدء، من الضروري إعداد المشروع. قم بإنشاء مشروع Node.js جديد مع دعم TypeScript:
mkdir ts-database-democd ts-database-demonpm init -ynpm install typescript @types/node ts-node --save-devnpx tsc --initللعمل مع قواعد البيانات، سنستخدم المكتبات الشائعة:
- Prisma — ORM حديث لـ PostgreSQL (وقواعد SQL الأخرى)
- Mongoose — ODM لـ MongoDB مع دعم ممتاز لـ TypeScript
قم بتثبيت الحزم اللازمة:
npm install prisma @prisma/client mongoosenpm install @types/mongoose --save-dev2. العمل مع PostgreSQL عبر Prisma
Prisma هو ORM يقوم تلقائيًا بإنشاء أنواع TypeScript بناءً على مخطط قاعدة البيانات الخاص بك. وهذا يضمن أمانًا كاملاً للأنواع.
2.1. إعداد Prisma
قم بتهيئة Prisma في المشروع:
npx prisma initفي ملف prisma/schema.prisma، حدد نموذج البيانات:
generator client { provider = "prisma-client-js"}
datasource db { provider = "postgresql" url = env("DATABASE_URL")}
model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt}
model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt}قم بإنشاء ملف .env مع سلسلة الاتصال:
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"نفذ الترحيل (migration):
npx prisma migrate dev --name init2.2. عمليات CRUD مع TypeScript
الآن سنكتب كودًا مكتوبًا (typed) للعمل مع قاعدة البيانات. قم بإنشاء ملف src/postgres.ts:
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
interface CreateUserInput { email: string; name?: string;}
interface CreatePostInput { title: string; content?: string; authorId: number;}
// إنشاء مستخدمasync function createUser(data: CreateUserInput) { return await prisma.user.create({ data: { email: data.email, name: data.name, }, });}
// الحصول على جميع المستخدمين مع المنشوراتasync function getUsersWithPosts() { return await prisma.user.findMany({ include: { posts: true, }, });}
// إنشاء منشورasync function createPost(data: CreatePostInput) { return await prisma.post.create({ data: { title: data.title, content: data.content, authorId: data.authorId, }, });}
// تحديث مستخدمasync function updateUser(id: number, data: Partial<CreateUserInput>) { return await prisma.user.update({ where: { id }, data, });}
// حذف مستخدمasync function deleteUser(id: number) { return await prisma.user.delete({ where: { id }, });}
// مثال على الاستخدام(async () => { try { const user = await createUser({ email: 'ivan@example.com', n