آموزش کار با Prisma

در دنیای دائماً در حال توسعه توسعه وب، انتخاب ابزارها و فریم‌ورک‌های مناسب می‌تواند تغییرات مفید بسیار زیادی را ایجاد کند. یکی از ابزارهایی که مدتی است مورد توجه توسعه‌دهندگان قرار گرفته است، Prisma می‌باشد. Prisma یک ORM و جعبه ابزار دیتابیس مدرن متن باز است که کار با دیتابیس را برای توسعه‌دهندگان آسان‌تر می‌کند. نحوه کار Prisma شبیه به نحوه کار مواردی مانند Sequelize یا Mongoose برای MongoDB است. ما می‌توانیم از Prisma تقریباً برای هر چیزی، از REST API گرفته تا GraphQL API و CLI و برنامه‌های Full-Stack استفاده نماییم.

Prisma چه کاری انجام می‌دهد؟

Prisma مفهوم type safety را فراهم می‌کند و خطاهای مربوط به داده‌ها را در زمان اجرا می‌گیرد. این بدان معناست که ما می‌توانیم مشکلات احتمالی را قبل از اجرای کد شناسایی کرده و به آن رسیدگی کنیم و در نتیجه برنامه‌های مطمئن‌تر و بدون خطا ایجاد نماییم. می‌توانیم از Prisma همراه با جاوااسکریپت یا تایپ اسکریپت استفاده کنیم.

با توجه به ویژگی‌های پروژه‌ای که داریم می‌توانیم از دیتابیس‌های مختلفی استفاده کنیم. Prisma معمولاً با دیتابیس‌های relational مانند Postgres، MySQL، SQLite و غیره مورد استفاده قرار می‌گیرید، اما می‌توانیم از آن همراه با دیتابیس‌های NoSQL مانند MongoDB نیز بهره‌مند شویم. نکته جالب این است که کد و مدل ما بر اساس دیتابیس تغییر نخواهد کرد. بنابراین از نظر فنی می‌توانیم با ویرایش فایل .env و credentialهای دیتابیس خود، یکی را با دیگری تعویض نماییم.

در نهایت Prisma به طور خودکار براساس طرح دیتابیس ما، کد تولید می‌کند. بنابراین اگر تا به حال از مواردی مانند Sequelize یا Mongoose برای MongoDB استفاده کرده باشیم، ایجاد یک schema مشابه کاری است که با آن ابزار انجام می‌دهیم. معمولاً هنگام کار با یک دیتابیس relational، قبل از شروع کدنویسی، باید تمام فیلدهای خود را با تایپ‌ها و جداول در سطح دیتابیس ایجاد کنیم. اما با Prisma می‌توانیم به سادگی کدهایی را اجرا کنیم که به مدل‌های ما نگاه می‌کند و جداول، ردیف‌ها و ستون‌ها و هر محدودیتی را که مشخص می‌کنیم، ایجاد می‌نمایند.

بررسی بخش‌های مختلف prisma

Prisma دارای سه کامپوننت اصلی است که عبارتند از:

می‌توانیم از Prisma Client با هر برنامه Node.js یا تایپ اسکریپتی استفاده کنیم. این مورد شامل برنامه‌های Full Stack، REST API، GraphQL API، CLI و موارد دیگر می‌شود. از تکمیل خودکار و بررسی تایپ در IDE پشتیبانی می‌کند. اگر در حال ساخت یک برنامه تک صفحه‌ای (SPA) هستیم، معمولاً از Prisma client روی سرور استفاده می‌کنیم و سپس مسیرهای خود را می‌سازیم تا endpointهای API را برای رابط کاربری خود ایجاد نماییم تا با آن‌ها تعامل داشته باشد.

  • Prisma Migrate – مدل‌سازی داده‌های تعریف شده و سیستم migration

Prisma Migrate برای ساده‌سازی و خودکارسازی فرآیند مدیریت schema دیتابیس در تکمیل برنامه طراحی شده است. این بخش در طول migrationهای schema، داده‌های ما را حفظ می‌کند. به این صورت که، statementهای SQL را می‌سازد تا تغییرات لازم را در دیتابیس ایجاد نماید و در عین حال از دست دادن داده یا خرابی را به حداقل برساند.

  • Prisma Studio – رابط کاربری گرافیکی برای مشاهده و ویرایش داده‌ها در دیتابیس

Prisma Studio تنها بخشی از Prisma است که متن باز نیست. این یک رابط کاربری گرافیکی می‌باشد که به ما این امکان را می‌دهد تا داده‌ها را در دیتابیس خود مشاهده و ویرایش کنیم. استفاده از Prisma الزامی نیست.

شروع کار با Prisma

در ابتدا کار یک فولدر جدید می‌سازیم. آن فایل را در ویرایشگر یا IDE خود باز می‌کنیم که ما از VS Code استفاده خواهیم کرد.

قصد داریم یک پروژه جدید Node.js را مقداردهی اولیه کنیم. می‌توانیم این کار را با اجرای npm init -y انجام دهیم. با این کار یک فایل package.json جدید برای ما ایجاد می‌شود.

ما یک پروژه تایپ اسکریپت ایجاد خواهیم کرد، بنابراین TypeScript، ts-node و type را برای Node.js نصب می‌کنیم. با اجرای دستور زیر می‌توانیم این کار را انجام دهیم:

npm install typescript ts-node @types/node -D

ts-node یک محیط اجرای تایپ اسکریپت برای Node.js است. این محیط به ما اجازه می‌دهد تا فایل‌های .ts را مستقیماً بدون نیاز به کامپایل اجرا کنیم.

@types/node تعاریف تایپ تایپ اسکریپت را برای ماژول‌های اصلی Node.js و کتابخانه استاندارد ارائه می‌دهد.

اکنون، با اجرای دستور زیر یک پروژه تایپ اسکریپت جدید را راه‌اندازی می‌کنیم:

npx tsc --init

با این کار یک فایل tsconfig.json برای ما ایجاد می‌شود. ما در این مقاله از تایپ اسکریپت فقط برای اجرای کوئری‌های Prisma استفاده می‌کنیم. اگر قصد یادگیری زبان برنامه نویسی تایپ اسکریپت را دارید، ویدیو آموزش TypeScript – دوره فشرده کانال یوتیوب فرانت کست را پیشنهاد می‌کنیم.

اکنون می‌توانیم Prisma CLI را نصب کنیم. این کار را با اجرای دستور زیر انجام می‌دهیم:

npm install prisma -D

حالا می‌خواهیم یک پروژه جدید Prisma را مقداردهی اولیه کنیم. می‌توانیم از دیتابیسی مانند Postres، MySQL یا MongoDB استفاده کنیم، اما مطمئناً باید هر چیزی را که استفاده می‌کنیم روی سیستم خود نصب داشته باشیم. ما در این آموزش از SQLite استفاده می‌کنیم. نحوه استفاده از Prisma و تنظیم مدل‌های داده، صرف نظر از نوع دیتابیسی که استفاده می‌کنیم، یکسان است.

می‌توانیم با اجرای دستور زیر یک پروژه جدید Prisma را راه‌اندازی کرده و از SQLite به عنوان provider استفاده نماییم:

npx prisma init --datasource-provider sqlite

با این کار یک پوشه prisma جدید برای ما ایجاد می‌شود. در داخل آن پوشه، یک فایل schema.prisma خواهیم داشت. این فایل، جایی است که مدل داده خود را تعریف می‌کنیم. یک فایل env نیز وجود دارد که اتصال دیتابیس خود را در آن تعریف خواهیم کرد. اگر از مواردی مانند PostgreSQL استفاده کنیم، باید اتصال دیتابیس خود را در فایل .env تعریف نماییم. از آنجایی که ما از SQLite استفاده می‌کنیم، باید موارد زیر را در فایل .env خود داشته باشیم:

DATABASE_URL = 'file:./dev.db';

نیازی نیست که ما این فایل را بسازیم. وقتی migration را اجرا کنیم، Prisma این فایل را برای ما ایجاد خواهد کرد.

منظور از مدل‌سازی داده چیست؟

مدل‌سازی داده فرآیند تعریف الزامات داده‌ها و ساختارهای یک سیستم است. ما از مدل‌سازی برای تعریف مدل داده برای دیتابیس استفاده می‌کنیم.

در Prisma، مدل‌سازی داده معمولاً شامل توصیف schema دیتابیس از جمله جداول، فیلدها، تایپ‌های داده‌ها و روابط بین آن‌ها می‌باشد. مدل‌سازی داده‌های موثر در Prisma بسیار مهم است. زیرا پایه و اساس ساخت عملیات دیتابیس و کوئری‌ها را تشکیل می‌دهد و تضمین می‌کند که داده‌ها به طور کارآمد، دقیق و به گونه‌ای که با نیازهای برنامه هماهنگ باشند، ساخته شوند.

منظور از Prisma schema چیست؟

Prisma schema جایی است که ما مدل داده خود را تعریف می‌کنیم. این به زبان Prisma schema نوشته شده است. زبان Prisma schema یک زبان declarative است که به ما این امکان را می‌دهد که مدل داده و روابط بین مدل‌های خود را تعریف کنیم.

فایل schema.prisma را باز می‌کنیم. باید چیزی شبیه به مقادیر زیر را در آن ببینیم:

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

Prisma schema دارای سه قسمت می‌باشد که عبارتند از:

  • Datasource – بلاک datasource جایی است که اتصال دیتابیس خود را تعریف می‌کنیم. می‌توانیم از هر دیتابیسی که Prisma از آن‌ها پشتیبانی می‌کند استفاده کنیم، از جمله: PostgreSQL، MySQL، SQLite و MongoDB.
  • Generator – بلوک generator جایی است که ما Prisma Client generator را تعریف می‌کنیم. این همان چیزی است که Prisma Client را برای ما می‌سازد. برای این کار می‌توانیم از هر زبانی که Prisma از آن‌ها پشتیبانی می‎‌کند استفاده کنیم، از جمله: جاوااسکریپت، تایپ اسکریپت، Go و Rust.
  • Model – بلاک model جایی است که ما مدل‌های داده خود و فیلدهای آن‌ها را تعریف می‌کنیم. همچنین می‌توانیم روابط بین مدل‌های خود را نیز در این قسمت مشخص نماییم.

در ادامه مدل‌های داده User و Article را تعریف می‌کنیم:

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  articles Article[]
}

model Article {
  id        Int     @id @default(autoincrement())
  title     String
  body   String?
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

برای مدل User یک فیلد id داریم که یک Int است و کلید اصلی می‌باشد. همچنین یک فیلد email داریم که هم تایپ رشته دارد و منحصربه‌فرد است. پس از آن یک فیلد name داریم که تایپ آن هم رشته می‌باشد و یک ? دارد تا آن را به عنوان یک فیلد اختیاری علامت‌گذاری می‌کند. همچنین یک فیلد articles هم داریم که آرایه‌ای از مدل‌های Article را شامل می‌شود.

برای مدل Article یک فیلد id داریم که یک Int است و کلید اصلی می‌باشد. پس از آن یک فیلد title داریم که تایپ آن رشته می‌باشد. همینطور یک فیلد body داریم که تایپ آن رشته می‌باشد و یک ? دارد تا آن را به عنوان یک فیلد اختیاری علامت گذاری می‌کند. سپس فیلد author را داریم که یک مدل User است. در نهایت هم فیلد authorId را داریم که تایپ آن هم Int می‌باشد.

همچنین روابط بین مدل‌های خود را این گونه تنظیم کرده‌ایم که یک کاربر می‌تواند دارای چندین تعداد مقاله باشد اما هر مقاله فقط می‌تواند یک نویسنده داشته باشد. همینطور، فیلد autorId در مدل Article به فیلد id در مدل User رفرنس دارد.

اجرای Migration

اکنون که مدل داده خود را تعریف کردیم، باید migration را اجرا کنیم. migration راهی است که schema دیتابیس را به‌روزرسانی می‌کند و در نتیجه این کار، می‌توانیم schema دیتابیس خود را با Prisma schema هماهنگ کنیم.

migration را با دستور زیر اجرا می‌کنیم:

npx prisma migrate dev --name init

این دستور یک migration جدید ایجاد کرده و آن را اجرا می‌کند. flag --name به ما اجازه می‌دهد تا یک نام به migration خود اختصاص بدهیم، که گزینه اختیاری است. زیرا، اگر نامی ارائه نکنیم Prisma یک نام برای آن ایجاد خواهد کرد.

اگر از PostgreSQL یا چیز دیگری هم استفاده می‌کردیم، همین کار را انجام می‌دادیم. تنها تفاوت این است که باید اتصال دیتابیس خود را در فایل env. تعریف کنیم.

ارسال کوئری‌ها از طریق Prisma Client

ما می‌توانیم یک فایل تایپ اسکریپت جدید برای ارسال کوئری از طریق Prisma Client ایجاد کنیم. برای این کار، یک فایل جدید به نام index.ts در root پروژه ساخته و کد زیر را به آن اضافه می‌کنیم:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  // Prisma Queries
}

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

در این کد، ما PrismaClient را از @prisma/client import می‌کنیم و یک نمونه جدید از PrismaClient می‌سازیم. همچنین یک تابع async به نام main را هم ایجاد می‌کنیم. در داخل تابع main، کوئری‌های Prisma Client خود را می‌نویسیم.

تابع main را فراخوانی می‌کنیم و در نمونه prisma که ساختیم، متد $disconnect را فراخوانی می‌نماییم. این متد برای قطع ارتباط با دیتابیس پس از اتمام کار است. همچنین هر گونه خطا را شناسایی کرده و آن‌ها را در کنسول ثبت می‌کنیم.

اکنون قصد داریم که یک کوئری بنویسیم تا یک کاربر جدید بسازیم. این کد را بعد از کامنت // Prisma Queries اضافه می‌کنیم:

const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: 'john@gmail.com',
  },
});
console.log(user);

با استفاده از دستور زیر، فایل را اجرا می‌کنیم:

npx ts-node index.ts

با این کد یک کاربر جدید می‌سازیم و آن را در کنسول نمایش می‌دهیم.

برای این که لیست همه کاربران را بدست بیاوریم، می‌توانیم از کد زیر استفاده کنیم:

const users = await prisma.user.findMany();
console.log(users);

اکنون اگر فایل را دوباره اجرا کنیم می‌توانیم لیست کاربرانی که وارد آرایه شده‌اند را در کنسول ببینیم.

نحوه کار با Relationshipها

یک article جدید می‌سازیم و یک ارتباط بین آن مقاله و یک کاربر ایجاد می‌کنیم:

const article = await prisma.article.create({
  data: {
    title: 'Johns First Article',
    body: 'This is Johns first article',
    author: {
      connect: {
        id: 1,
      },
    },
  },
});
console.log(article);

ما می‌توانیم لیست تمام مقالات را با کمک دستور زیر دریافت نماییم:

const articles = await prisma.article.findMany();
console.log(articles);

اکنون، یک کاربر جدید می‌سازیم و آن را با یک مقاله مرتبط می‌کنیم:

const user = await prisma.user.create({
  data: {
    name: 'Sara Smith',
    email: 'sara@gmail.com',
    articles: {
      create: {
        title: 'Saras First Article',
        body: 'This is my first article',
      },
    },
  },
});

دوباره لیست همه مقالات را دریافت می‌کنیم:

const articles = await prisma.article.findMany();
console.log(articles);

فایل را اجرا کرده و مقالات ثبت شده در کنسول را می‌بینیم.

اگر برای دریافت لیست کاربران کد زیر را اجرا کنیم:

const users = await prisma.user.findMany();
console.log(users);

در این حالت ما فقط فیلدهای اسکالر را خواهیم دید و فیلد مقالات را مشاهده نخواهیم کرد. دلیل این اتفاق این است که فیلد articles یک فیلد relation است. برای بدست آوردن فیلدهای relation باید از گزینه include استفاده کنیم. کوئری را به‌روزرسانی می‌کنیم تا کاربران فیلد articles را هم داشته باشیم:

const users = await prisma.user.findMany({
  include: {
    articles: true,
  },
});
console.log(users);

اکنون می‌توانیم فیلد articles را در کنسول را مشاهده نماییم. فیلد articles آرایه‌ای از آبجکت‌ها می‌باشد.

در ادامه بر روی users یک loop ایجاد می‌کنیم تا داده‌های user و article را در کنسول نمایش دهیم:

users.forEach((user) => {
  console.log(`User: ${user.name}, Email: ${user.email}`);
  console.log('Articles:');
  user.articles.forEach((article) => {
    console.log(`- Title: ${article.title}, Body: ${article.body}`);
  });
  console.log('\n');
});

در نتیجه می‌توانیم ببینیم که Prisma Client کار کردن با relationshipها را آسان‌تر می‌کند.

به‌روزرسانی داده‌ها

در این بخش قصد داریم تا نام کاربر را ویرایش کنیم:

const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    name: 'John Doe Jr.',
  },
});
console.log(user);

حذف داده‌ها

در این قسمت هم می‌خواهیم مقاله اول را حذف کنیم:

const article = await prisma.article.delete({
  where: {
    id: 1,
  },
});

اکنون اگر مقالات و یا کاربران همراه با مقاله را در کنسول نمایش دهیم، می‌بینیم که این مقاله دیگر وجود ندارد.

console.log(articles);
console.log(users);

Prisma Studio

Prisma Studio یک رابط کاربری گرافیکی (GUI) است که به ما این امکان را می‌دهد تا داده‌ها را در دیتابیس خود مشاهده و ویرایش کنیم. استفاده از Prisma الزامی نیست، اما داشتن آن ابزار خوبی است. برای راه‌اندازی Prisma Studio، می‌توانیم دستور زیر را اجرا کنیم:

npx prisma studio

پس از اجرای دستور، Prisma Studio در مرورگر ما باز می‌شود. از این طریق می‌توانیم داده‌های خود را مشاهده و ویرایش نماییم. همچنین می‌توانیم مدل داده‌های خود را هم ببینیم و کوئری‌ها را اجرا کنیم.

جمع‌بندی

همانطور که در این مقاله دیدیم، Prisma کار با دیتابیس را ساده‌تر می‌کند. برای کسب اطلاعات بیشتر درمورد Prisma مطالعه مستندات می‌تواند مفید باشد.

دیدگاه‌ها:

افزودن دیدگاه جدید