Prisma ile Seeding oluşturma
Merhabalar,
Bu yazımda Next js ile fullstack bir uygulama geliştirirken Prisma ORM kullanarak nasıl temel veriler oluşturulur onu anlatmaya çalışacağım.
Prisma nedir ne işe yarar?
“Prisma”, geliştiricilere veritabanı işlemlerini yönetme ve sorgulama konusunda kolaylık sağlayan modern ve güçlü bir ORM aracıdır. Kısaca özellikleri:
- Veritabanı Modelleri
- İlişki oluşturma(Relations)
- Sorgu Oluşturma
- Veritabanı Bağlantısı
- TypeScript Desteği
- Migration Yönetimi
Seeding nedir ne işe yarar?
“Seeding”, veritabanına başlangıç verilerini eklemek veya veritabanını örnek verilerle doldurmak anlamına gelir. Bu işlem, uygulamanın geliştirme, test veya başlangıç aşamasında kullanılabilecek veritabanı tablolarına varsayılan veya örnek verileri eklemeyi içerir. Seeding işlemi, bir uygulamanın doğru çalışabilmesi ve test edilebilmesi için gerekli veritabanı içeriğini sağlar.
Örnek projede Kullanılanlar:
- Framework: Next js
- Veritabanı: PostgreSQL
- ORM: Prisma
Proje kurulum
Konumuz seeding olduğu için uygulama kurulumu ve veritabanı bağlantı işlemlerini çok fazla değinmeyeceğim.
- Next js kurulumu:
npx create-next-app@latest
2. Prisma ve diğer paketlerin kurulumu
// paket kurulumu
npm i prisma --save-dev
npm i @prisma/client
npx prisma // bu komutla prisma cli' yı kullanabilirsiniz.
npm i lodash
npm i @faker-js/faker --save-dev
npm i bcrypt
3. Veritabanı oluşturma ve kurulumu
a. Bilgisayarımıza PostgreSQL veritabanı kurulduğunu varsayıp example_db
adında bir veritabanı oluşturalım. Ardından projemizde .env dosyası oluşturup burada veritabanı bağlantı url’ ini ekleyelim.
DATABASE_URL="postgresql://postgres:@localhost:5432/example_db?schema=public"
b. proje ana dizininde `prisma` adında bir klasör oluşturup içinde de `schema.prisma` adında model dosyasını oluşturalım. Bu dosya veritabanı tablolarımızı tanımladığımız kısım.
schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @db.VarChar(255)
content String @db.VarChar(255)
User User @relation(fields: [userId], references: [id])
userId Int
}
model User {
id Int @id @default(autoincrement())
email String @unique
createdAt DateTime @default(now())
name String @db.VarChar(255)
password String? @db.VarChar(255)
posts Post[]
}
c. ardından bu tabloları oluşturmak için şu komutu kullanıyoruz:
npx prisma db push
Veritabanını kontrol edersek tabloların oluştuğunu görmüş oluruz.
4. Seed Dosyası Oluşturma
prisma klasörünün içinde seed.ts dosyası oluşturalım ve temel yapıyı oluşturalım.
seed.ts
export default PostSeed;
import {PrismaClient} from "@prisma/client";
const prisma = new PrismaClient();
const main = async () => {
...
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
Şimdi main() fonksiyonu içinde tanımlayacağımız seeder yapısını oluşturalım. Burada Typescript’in gücünden faydalanacağız. Öncelikle birden fazla seeder dosyası olacağını varsayarak abstract bir class oluşturalım.
Seeder.ts
abstract class Seeder {
protected count: number; // ne kadar veri oluşturacağına karar verir
protected _data: any = []; // seed verisi
constructor(count: number) {
this.count = count;
}
protected abstract createData(): void; // veriyi oluşturacak fonksiyon
get data(): [] {
return this._data;
}
}
export default Seeder;
Şimdi de ilgili tablolar için seed dosyalarımızı oluşturalım.
userSeed.ts
import bcrypt from "bcrypt";
import range from "lodash/range";
import { faker } from "@faker-js/faker";
import Seeder from "./Seeder";
class UserSeed extends Seeder {
constructor(count: number = 10) {
super(count);
this.count = count;
this.createData();
}
createData() {
range(this.count).forEach(() => {
this._data.push({
name: faker.person.firstName(),
createdAt: faker.date.anytime(),
email: faker.internet.email(),
password: bcrypt.hashSync("12345678", 10),
});
});
}
}
export default UserSeed;
postSeed.ts
import range from "lodash/range";
import { faker } from "@faker-js/faker";
import Seeder from "./Seeder";
class PostSeed extends Seeder {
constructor(count: number = 10) {
super(count);
this.count = count;
this.createData();
}
createData() {
range(this.count).forEach(() => {
this._data.push({
title: faker.lorem.sentence(),
createdAt: faker.date.anytime(),
updatedAt: faker.date.anytime(),
content: faker.lorem.sentence(),
});
});
}
}
export default PostSeed;
seed.ts dosyasına geri dönüp oluşturduğumuz seeder’ ları ekleyelim.
seed.ts
import { Simulate } from "react-dom/test-utils";
import error = Simulate.error;
import { PrismaClient } from "@prisma/client";
import UserSeed from "./data/userSeed";
import PostSeed from "./data/postSeeder";
const prisma = new PrismaClient();
const main = async () => {
try {
await prisma.post.deleteMany();
await prisma.user.deleteMany();
const posts = new PostSeed();
const users = new UserSeed(3);
for (const user of users.data) {
await prisma.user.create({
data: {
...(user as any),
posts: {
create: posts.data,
},
},
});
}
console.log(`Database has been seeded. 🚀`);
} catch (e) {
throw error;
}
};
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
5. Seed komutu ekleme
oluşturduğumuz bu seeder’ları çalıştırmak için package.json dosyamıza bir komut eklememiz gerekiyor. Burada dikkat edilmesi gereken bazı hususlar var. Örneğin Next js projesiyle bu işlemi yaparken seed dosyasında modül ekleme hataları olabiliyor. Bunu engellemek için seed komutuna “compiler-options” flag’i eklemek gerek. Böylece işlem tetiklendiğinde modül hatası almayacağız.
package.json
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"db-seed": "prisma db seed"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
},
Son olarak verilemizi oluşturacak komutu çalıştıralım.
npm run db-seed
Burada da görüldüğü gibi başarıyla test verilerimiz oluştu.😊
projenin kaynak kodlarına https://github.com/melihs/prisma-seeding-example bu linkten ulaşabilirsiniz
Bir sonraki yazıda görüşmek dileğiyle 👋🏻