ITSkillsCenter
تطوير الويب

Bun + Drizzle ORM مع PostgreSQL: درس كامل 2026

2 min de lecture

عند بناء API حديث في TypeScript، اختيار ORM يغير جودة حياة المطور جذرياً. Drizzle ORM أصبح في 2026 الخيار المهيمن لمشاريع Bun و Node.js الحديثة: type-safe من البداية للنهاية، بدون توليد كود، تركيب قريب من SQL، دعم أصلي PostgreSQL.

راجع دليل Bun.

لماذا Drizzle؟

  • بدون codegen: كل شيء مستنتج من أنواع TypeScript
  • Type-safety كامل: SELECT، JOIN، INSERT تعيد أنواعاً محسوبة
  • تركيب قريب من SQL
  • خفيف: ~10 KB gzip vs 200+ KB لـ Prisma
  • Migrations عبر drizzle-kit
  • أداء ممتاز: لا RPC داخلي، فقط SQL

الخطوة 1 — التثبيت

bun add drizzle-orm postgres
bun add -D drizzle-kit @types/bun

الخطوة 2 — تعريف المخطط

import { pgTable, serial, varchar, integer, timestamp, boolean } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  email: varchar("email", { length: 255 }).notNull().unique(),
  name: varchar("name", { length: 100 }).notNull(),
  passwordHash: varchar("password_hash", { length: 255 }).notNull(),
  createdAt: timestamp("created_at").defaultNow().notNull(),
});

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;

الخطوة 3 — العميل

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";

const client = postgres(process.env.DATABASE_URL!, {
  max: 10,
  prepare: false, // مهم لـ PgBouncer transaction mode
});

export const db = drizzle(client);

الخطوة 4 — Migrations

// drizzle.config.ts
import { defineConfig } from "drizzle-kit";
export default defineConfig({
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dialect: "postgresql",
  dbCredentials: { url: process.env.DATABASE_URL! },
});

// أوامر
bun drizzle-kit generate
bun drizzle-kit migrate

الخطوة 5 — استعلامات

import { eq, and, desc } from "drizzle-orm";

const allUsers = await db.select().from(users);

const aissatou = await db.select().from(users)
  .where(eq(users.email, "a@exemple.sn"));

const [newUser] = await db.insert(users).values({
  email: "modou@exemple.sn",
  name: "Modou",
  passwordHash: await Bun.password.hash("secret"),
}).returning();

await db.update(users).set({ name: "Modou D." })
  .where(eq(users.id, newUser.id));

await db.delete(users).where(eq(users.id, newUser.id));

الخطوة 6 — JOIN ومعاملات

// JOIN
const postsWithAuthors = await db
  .select({
    title: posts.title,
    authorName: users.name,
  })
  .from(posts)
  .leftJoin(users, eq(posts.authorId, users.id))
  .where(eq(posts.published, true));

// معاملة atomic
await db.transaction(async (tx) => {
  const [user] = await tx.insert(users).values({...}).returning();
  await tx.insert(posts).values({ authorId: user.id, ... });
});

الخطوة 7 — في الإنتاج

  • migrations في CI/CD قبل النشر
  • متغير DATABASE_URL وحده
  • ضبط max pool حسب عدد الحاويات
  • pg_stat_statements للمراقبة
  • PgBouncer مع prepare: false

التكييف

Drizzle له ميزة خاصة للمشاريع الصغيرة: استهلاك ذاكرة أدنى وسرعة تناسب VPS متواضع. على نفس hardware، Drizzle + Bun عند 80-100 MB، Prisma + Node عند 200-300 MB.

أخطاء شائعة

الخطأالسببالحل
SSL requiredPostgres يفرض SSLpostgres(url, { ssl: ‘require’ })
any غير متوقعschema غير مستوردdrizzle(client, { schema })
أداء يتدهور مع PgBouncerprepare: trueprepare: false

لمعرفة المزيد

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité