NestJS + Prisma + PostgreSQL ile REST API Geliştirmek: CRUD, Doğrulama ve Swagger
REST API geliştirirken kodun yalnızca çalışması değil, büyüdükçe sürdürülebilir kalması da önemlidir. Controller, servis, veritabanı erişimi ve doğrulama işlemlerinin belirli bir düzen içerisinde tutulması, özellikle ekip çalışmalarında büyük avantaj sağlar.Bu yazıda NestJS, Prisma ORM ve PostgreSQL kullanarak basit bir blog API'si oluşturacağız. Blog yazıları için CRUD endpoint'leri hazırlayacak ve Swagger üzerinden API dokümantasyonu sunacağız.
1. Teknolojilere genel bakış
NestJS: Node.js üzerinde modüler ve düzenli backend uygulamaları geliştirmeye yardımcı olan bir framework'tür.Prisma ORM: Veritabanı şemasından tip güvenli bir istemci üretir ve veritabanı işlemlerini kolaylaştırır.
PostgreSQL: İlişkisel verileri saklamak için kullanılır.
Swagger / OpenAPI: API endpoint'lerini, parametrelerini ve yanıtlarını dokümante eder.
Bu bileşenleri birlikte kullanarak hem geliştiriciler hem de API tüketicileri için daha anlaşılır bir yapı oluşturabiliriz.
2. NestJS projesi oluşturmak
NestJS CLI kurulumuyla başlayalım:npm install -g @nestjs/cli
nest new blog-api
cd blog-api
Prisma'yı projeye eklemek için:
npm install prisma @prisma/client
npx prisma init
Bu yazıdaki Prisma yapılandırması, Prisma 7 ve NestJS 11 için güncellenmiş kaynak yaklaşımını esas alır. Prisma 7'de veritabanı bağlantısı ve istemci üretimiyle ilgili yapılandırmalar eski sürümlere göre farklılık gösterebilir.
3. PostgreSQL bağlantısı
PostgreSQL üzerinde blog_api isimli bir veritabanı oluşturduğumuzu varsayalım..env dosyasına bağlantı adresini ekleyelim:
DATABASE_URL="postgresql://postgres
assword@localhost:5432/blog_api"Gerçek kullanıcı bilgileri kullanılmalı ve bu dosya kaynak kod deposuna gönderilmemelidir.
Prisma 7 projelerinde bağlantı yapılandırması ayrıca prisma.config.ts üzerinden yönetilir. Örneğin:
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});
Prisma 7'nin veritabanı sürücüsü yaklaşımı nedeniyle PostgreSQL için uygun driver adapter kurulmalı ve Prisma Client bu yapılandırmaya göre oluşturulmalıdır.
4. Blog modeli oluşturmak
prisma/schema.prisma dosyasında blog yazısı modelini tanımlayalım:generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Burada:
- id, her yazı için benzersiz bir kimlik oluşturur.
- title, yazı başlığını tutar.
- content, yazının içeriğini saklar.
- published, yazının yayın durumunu belirtir.
- createdAt ve updatedAt, kayıt zamanlarını yönetir.
Prisma 7'de prisma-client generator'ı için belirtilen çıktı dizini önemlidir. Servis katmanında import yolu, projede üretilen gerçek dosya yapısıyla eşleşmelidir.
5. Migration ve Prisma Client
Şema değişikliklerini veritabanına uygulamak için:npx prisma migrate dev --name init
npx prisma generate
İlk komut migration oluşturup geliştirme veritabanına uygular. İkinci komut Prisma Client'ı üretir.
Üretim ortamında migration uygulamak için genellikle şu komut kullanılır:
npx prisma migrate deploy
Geliştirme ve üretim migration süreçleri birbirinden ayrılmalıdır. Üretimde migrate dev kullanılmamalı, migration dosyaları sürüm kontrolünde tutulmalıdır.
6. Prisma servisi oluşturmak
NestJS içinde veritabanı erişimini ayrı bir servis üzerinden yönetmek düzenli bir mimari sağlar.Prisma 7 için uygun PostgreSQL driver adapter kurulmuş ve PrismaClient doğru bağlantı yapılandırmasıyla oluşturulmuş olmalıdır.
Örneğin servis katmanında temel yaklaşım şu şekildedir:
import { Injectable, OnModuleDestroy } from "@nestjs/common";
import { PrismaClient } from "./generated/prisma/client";
@Injectable()
export class PrismaService
extends PrismaClient
implements OnModuleDestroy
{
async onModuleDestroy() {
await this.$disconnect();
}
}
Bu örnekte PrismaClient import yolu, generator çıktısına göre düzenlenmelidir. Prisma 7 projelerinde uygun driver adapter'ın istemci oluşturulurken yapılandırılması gerekir; bağlantı kurulumu eksik bırakılmamalıdır.
PrismaService daha sonra NestJS modüllerine provider olarak eklenebilir.
7. DTO ve veri doğrulama
API'ye gelen verilerin doğrulanması için DTO kullanabiliriz.Öncelikle gerekli paketleri yükleyelim:
npm install class-validator class-transformer
create-post.dto.ts:
import {
IsBoolean,
IsNotEmpty,
IsOptional,
IsString,
MaxLength,
} from "class-validator";
export class CreatePostDto {
@IsString()
@IsNotEmpty()
@MaxLength(200)
title!: string;
@IsString()
@IsNotEmpty()
content!: string;
@IsOptional()
@IsBoolean()
published?: boolean;
}
Daha sonra main.ts dosyasında global doğrulama katmanını etkinleştirelim:
import { ValidationPipe } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
Bu yapı, DTO'da tanımlanmamış alanların reddedilmesine ve geçersiz isteklerin controller'a ulaşmadan doğrulanmasına yardımcı olur.
8. CRUD servis işlemleri
Blog yazıları için dört temel işlem gerekir:- Create: Yeni yazı oluşturma
- Read: Yazıları veya tek bir yazıyı getirme
- Update: Yazıyı güncelleme
- Delete: Yazıyı silme
import {
Injectable,
NotFoundException,
} from "@nestjs/common";
import { PrismaService } from "../prisma/prisma.service";
import { CreatePostDto } from "./dto/create-post.dto";
@Injectable()
export class PostsService {
constructor(private readonly prisma: PrismaService) {}
create(data: CreatePostDto) {
return this.prisma.post.create({
data,
});
}
findAll() {
return this.prisma.post.findMany({
orderBy: {
createdAt: "desc",
},
});
}
async findOne(id: number) {
const post = await this.prisma.post.findUnique({
where: { id },
});
if (!post) {
throw new NotFoundException("Yazı bulunamadı.");
}
return post;
}
async update(id: number, data: Partial<CreatePostDto>) {
await this.findOne(id);
return this.prisma.post.update({
where: { id },
data,
});
}
async remove(id: number) {
await this.findOne(id);
return this.prisma.post.delete({
where: { id },
});
}
}
Bu servis örneği, CRUD işlemlerinin mantığını gösterir. Gerçek uygulamada güncelleme DTO'su ayrı tanımlanmalı, kullanıcı yetkileri kontrol edilmeli ve Prisma hataları uygun HTTP hata yanıtlarına dönüştürülmelidir.
9. Controller ve REST endpoint'leri
Controller, HTTP isteklerini karşılar ve servis katmanına yönlendirir.posts.controller.ts:
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from "@nestjs/common";
import { PostsService } from "./posts.service";
import { CreatePostDto } from "./dto/create-post.dto";
@Controller("posts")
export class PostsController {
constructor(
private readonly postsService: PostsService,
) {}
@Post()
create(@Body() body: CreatePostDto) {
return this.postsService.create(body);
}
@Get()
findAll() {
return this.postsService.findAll();
}
@Get(":id")
findOne(
@Param("id", ParseIntPipe) id: number,
) {
return this.postsService.findOne(id);
}
@Patch(":id")
update(
@Param("id", ParseIntPipe) id: number,
@Body() body: Partial<CreatePostDto>,
) {
return this.postsService.update(id, body);
}
@Delete(":id")
remove(
@Param("id", ParseIntPipe) id: number,
) {
return this.postsService.remove(id);
}
}
Bu controller aşağıdaki endpoint'leri sağlar:
| HTTP | Endpoint | İşlem |
|---|---|---|
| POST | /posts | Yeni yazı oluşturur |
| GET | /posts | Yazıları listeler |
| GET | /posts/:id | Tek yazıyı getirir |
| PATCH | /posts/:id | Yazıyı günceller |
| DELETE | /posts/:id | Yazıyı siler |
10. Swagger ile API dokümantasyonu
Swagger, API endpoint'lerini görsel bir arayüz üzerinden incelemeyi ve test etmeyi kolaylaştırır.Gerekli paketi yükleyelim:
npm install @nestjs/swagger
main.ts dosyasına Swagger yapılandırmasını ekleyebiliriz:
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
// bootstrap() içinde, app oluşturulduktan sonra:
const config = new DocumentBuilder()
.setTitle("Blog API")
.setDescription("Blog yazılarını yönetmek için REST API")
.setVersion("1.0.0")
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup("api-docs", app, document);
Uygulama çalıştığında:
Linkleri görebilmek için Turkmmo Forumuna ÜYE olmanız gerekmektedir.
adresinden Swagger arayüzüne erişilebilir.
Bu örnekte Swagger kurulumu gösterilmiştir. Endpoint'lerin dokümantasyonda daha ayrıntılı görünmesi için @ApiTags, @ApiOperation, @ApiResponse ve DTO'larda uygun Swagger dekoratörleri de kullanılmalıdır.
11. Production ortamında dikkat edilmesi gerekenler
- Kimlik doğrulama ve rol tabanlı yetkilendirme ekleyin.
- Sayfalama, filtreleme ve sıralama desteği sağlayın.
- Güncelleme DTO'sunu oluşturma DTO'sundan ayırın.
- Hata mesajlarını merkezi olarak yönetin.
- Prisma Client ve PostgreSQL bağlantılarını doğru yapılandırın.
- Migration'ları kontrollü bir deployment sürecine dahil edin.
- API endpoint'lerini otomatik testlerle doğrulayın.
- Üretim ortamında loglama, izleme ve yedekleme süreçlerini planlayın.
Sonuç
NestJS, Prisma ORM ve PostgreSQL birlikte kullanıldığında modüler, tip güvenli ve sürdürülebilir bir REST API geliştirmek mümkündür.NestJS'in controller ve servis yapısı uygulama mantığını düzenlerken Prisma veritabanı işlemlerini kolaylaştırır. Swagger ise API'nin hem ekip içerisinde hem de harici istemciler tarafından anlaşılmasını sağlar.
Bu yazıdaki örnekler temel bir blog API'sinin iskeletini oluşturur. Üretim ortamına geçmeden önce sürüm uyumluluğu, veritabanı bağlantısı, yetkilendirme, hata yönetimi ve test süreçleri tamamlanmalıdır.
Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 2
- Görüntüleme
- 28
- Cevaplar
- 1
- Görüntüleme
- 18
- Cevaplar
- 1
- Görüntüleme
- 25