NestJS — Node.js للمؤسسات

الترحيلات والبذور

16 دقيقة الدرس 22 من 30

الترحيلات والبذور

في التطوير، تُحدّث synchronize: true مخطّطك تلقائيًا — مريح لكن خطير. في الإنتاج تحتاج الترحيلات: سكربتات مُؤرَّخة وقابلة للمراجعة تُغيّر مخطّط قاعدة البيانات بأمان وبقابلية للتراجع. ومقترنةً بـ البذر (تعبئة بيانات مرجعية أو اختبارية)، تمنحك تحكّمًا كاملًا في حالة قاعدة بياناتك.

لماذا الترحيلات؟

  • آمنة — تغييرات صريحة، بلا حذف أعمدة مفاجئ.
  • مُؤرَّخة — كل تغيير مخطّط يُودَع في إدارة المصادر.
  • قابلة للتراجع — لكل ترحيل up (تطبيق) وdown (تراجع).
  • قابلة للتكرار — يعمل التسلسل نفسه بشكل متطابق على كل بيئة.

تشريح ترحيل

الترحيل صنف بدالّتين. تُقدّم up() المخطّط؛ وتتراجع down() عنه:

import { MigrationInterface, QueryRunner, Table } from 'typeorm'; export class CreateUsers1700000000000 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.createTable(new Table({ name: 'users', columns: [ { name: 'id', type: 'int', isPrimary: true, isGenerated: true }, { name: 'email', type: 'varchar', isUnique: true }, ], })); } async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.dropTable('users'); } }

توليد الترحيلات وتشغيلها

يستطيع TypeORM توليد ترحيل بمقارنة كياناتك بقاعدة البيانات الحالية — ثم تراجعه قبل التطبيق:

# توليد ترحيل من تغييرات الكيانات npx typeorm migration:generate ./src/migrations/AddUsers -d ./data-source.ts # تطبيق الترحيلات المعلّقة npx typeorm migration:run -d ./data-source.ts # التراجع عن الأخير npx typeorm migration:revert -d ./data-source.ts
راجِع دائمًا الترحيل المُولَّد قبل تشغيله. التوليد التلقائي نقطة بداية لا نصّ مقدّس — قد يُنتج تغييرات مدمّرة أو خارج الترتيب. اقرأ up() وdown()، خصوصًا لأي شيء يحذف أو يعيد التسمية.

بذر البيانات

يعبّئ البذر قاعدة البيانات ببيانات أولية: جداول مرجعية (الأدوار، الفئات)، أو مستخدم مدير، أو بيانات عيّنة للاختبار. نهج نظيف هو سكربت مستقلّ يستخدم سياق التطبيق من درس دورة الحياة:

import { NestFactory } from '@nestjs/core'; async function seed() { const app = await NestFactory.createApplicationContext(AppModule); const usersService = app.get(UsersService); await usersService.create({ name: 'Admin', email: 'admin@app.com' }); await app.close(); } seed();
اجعل البذور idempotent. تحقّق هل السجلّ موجود قبل الإدراج (find-or-create). عندها لا يُنشئ تشغيل البذر مرّتين تكرارات — آمن للتشغيل في كل نشر.

الترحيلات مقابل البذر

أبقِهما منفصلين: الترحيلات تُغيّر المخطّط (البنية)، والبذور تُدرِج البيانات (المحتوى). خلط إدراج البيانات في ترحيلات المخطّط يجعل كليهما أصعب فهمًا وتراجعًا.

الخلاصة

استخدم الترحيلات — سكربتات up/down مُؤرَّخة — لكل تغييرات مخطّط الإنتاج بدل synchronize. ولّدها من فروقات الكيانات، لكن راجِع دائمًا قبل التشغيل. ابذُر البيانات الأولية والمرجعية بسكربتات idempotent، ويُفضَّل عبر سياق التطبيق المستقلّ. أبقِ اهتمامات المخطّط (الترحيلات) والبيانات (البذور) منفصلة. تاليًا: المعاملات، للتغييرات التي يجب أن تنجح كلّها أو تفشل كلّها.