Modern web uygulamaları geliştirirken, güçlü ve esnek API’lere sahip olmak kritik öneme sahiptir. GraphQL, API geliştirme sürecine yeni bir soluk getirirken, Prisma veritabanı etkileşimlerini kolaylaştıran güçlü bir ORM (Object-Relational Mapper) olarak öne çıkıyor. Bu rehberde, bu iki teknolojiyi bir araya getirerek bir GraphQL API’si oluşturacak ve ardından bu API’yi DigitalOcean’ın yönetimi kolay App Platform’una nasıl dağıtacağınızı adım adım öğreneceksiniz.
Bu kombinasyon, geliştiricilere hızlı prototipleme, ölçeklenebilir mimari ve sorunsuz dağıtım avantajları sunar. GraphQL ile istemciler ihtiyaç duydukları veriyi tam olarak talep edebilirken, Prisma veritabanı işlemlerini soyutlayarak güvenli ve tip-güvenli kod yazmayı sağlar. DigitalOcean App Platform ise bu uygulamaları bulutta barındırmak için mükemmel bir PaaS (Platform-as-a-Service) çözümüdür.
Geliştirme Ortamını Hazırlama
API’mizi oluşturmaya başlamadan önce, gerekli araçların sisteminizde kurulu olduğundan emin olmalıyız. Node.js ve npm (Node Package Manager) veya yarn, JavaScript ekosistemindeki projeler için temel gereksinimlerdir. TypeScript kullanarak daha güvenli ve bakımı kolay kod yazmayı tercih edeceğiz.
Ön Gereksinimler
- Node.js ve npm/yarn: Sisteminizde kurulu olduğundan emin olun.
- Git: Kodunuzu versiyonlamak ve DigitalOcean’a dağıtmak için gereklidir.
- Metin Düzenleyici: VS Code gibi bir IDE kullanmanız şiddetle tavsiye edilir.
Proje Başlatma ve Bağımlılıkları Yükleme
Öncelikle yeni bir proje dizini oluşturalım ve temel Node.js projemizi başlatalım:
mkdir my-graphql-prisma-api
cd my-graphql-prisma-api
npm init -y
Şimdi gerekli bağımlılıkları yükleyelim. GraphQL API’miz için Express ve Apollo Server’ı, veritabanı etkileşimleri için Prisma’yı kullanacağız. TypeScript desteği için ilgili paketleri de ekleyelim:
npm install express apollo-server-express graphql prisma @prisma/client
npm install -D typescript ts-node nodemon @types/node
express: Temel web sunucusu çatısı.apollo-server-express: Express ile Apollo Server’ı entegre etmek için.graphql: GraphQL çalışma zamanı.prismave@prisma/client: Prisma ORM ve istemcisi.typescript: TypeScript derleyicisi.ts-node: TypeScript dosyalarını doğrudan çalıştırmak için (geliştirme ortamında).nodemon: Dosya değişikliklerinde sunucuyu otomatik yeniden başlatmak için.@types/node: Node.js için TypeScript tip tanımları.
TypeScript Yapılandırması
TypeScript projemizi başlatmak için tsc --init komutunu kullanalım ve tsconfig.json dosyamızı düzenleyelim:
npx tsc --init
tsconfig.json dosyasında aşağıdaki değişiklikleri yapın:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"rootDir": "./src", // Kaynak dosyalarımızın bulunduğu dizin
"outDir": "./dist", // Derlenmiş JavaScript dosyalarının çıkacağı dizin
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
},
"include": ["src//*.ts"], // Hangi dosyaların derleneceğini belirtir
"exclude": ["node_modules"]
}
Son olarak, package.json dosyamıza bazı scriptler ekleyelim:
{
"name": "my-graphql-prisma-api",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"scripts": {
"dev": "nodemon --exec ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^3.13.0",
"express": "^4.19.2",
"graphql": "^16.8.1",
"prisma": "^5.14.0",
"@prisma/client": "^5.14.0"
},
"devDependencies": {
"@types/node": "^20.12.12",
"nodemon": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
Prisma ile Veritabanı Modellerini Tanımlama ve Yönetme
API’mizin temelini oluşturacak veritabanı modellerini Prisma ile tanımlayacağız. Prisma, veritabanı şemanızı tanımlamanıza, migration’ları yönetmenize ve veritabanıyla etkileşim kurmanız için tip-güvenli bir istemci oluşturmanıza olanak tanır.
Prisma’yı Başlatma
Projemizde Prisma’yı başlatmak için aşağıdaki komutu kullanalım. PostgreSQL kullanacağımız için --datasource-provider postgresql bayrağını ekliyoruz:
npx prisma init --datasource-provider postgresql
Bu komut, projenizin kök dizininde bir prisma klasörü ve içinde schema.prisma dosyası ile bir .env dosyası oluşturacaktır. .env dosyası, veritabanı bağlantı URL’nizi içerecektir.
Veritabanı Şemasını Tanımlama
prisma/schema.prisma dosyasını açın ve örnek bir User ve Post modeli tanımlayalım:
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
.env dosyanızda DATABASE_URL değişkenini ayarlamanız gerekecek. Yerel geliştirme için Docker ile hızlıca bir PostgreSQL veritabanı kurabilir veya bir bulut sağlayıcısından (DigitalOcean gibi) geçici bir veritabanı bağlantı dizesi kullanabilirsiniz.
# .env
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
Migration Oluşturma ve Uygulama
Şemamızı tanımladıktan sonra, veritabanımızı bu şemaya göre güncellemek için bir migration oluşturalım ve uygulayalım:
npx prisma migrate dev --name init
Bu komut, prisma/migrations dizininde yeni bir migration dosyası oluşturacak ve ardından veritabanınıza uygulayacaktır. Bu işlem, tanımladığımız User ve Post tablolarını veritabanınızda oluşturacaktır.
Prisma Client’ı Oluşturma
Migration’ları uyguladıktan sonra, Prisma Client’ı oluşturmamız gerekir. Bu istemci, TypeScript kodumuzda veritabanıyla etkileşim kurmamızı sağlayacak tip-güvenli bir API sağlar.
npx prisma generate
Bu komutu her schema.prisma dosyasını değiştirdiğinizde çalıştırmanız gerekecektir. Geliştirme sürecinde bu genellikle otomatik olarak yapılır, ancak dağıtım öncesi manuel çalıştırmak iyi bir alışkanlıktır.
GraphQL API’sini Oluşturma
Şema ve veritabanı etkileşimlerimiz hazır olduğuna göre, GraphQL API’mizi Apollo Server kullanarak oluşturalım. API’miz üç ana bölümden oluşacak: Type Definitions (GraphQL şeması), Resolvers (veri işleme mantığı) ve Apollo Server kurulumu.
GraphQL Type Definitions (Şema)
src/schema.ts adında bir dosya oluşturalım ve GraphQL şemamızı (SDL – Schema Definition Language) tanımlayalım:
// src/schema.ts
import { gql } from 'apollo-server-express';
export const typeDefs = gql
type User {
id: Int!
email: String!
name: String
posts: [Post!]!
createdAt: String!
updatedAt: String!
}
type Post {
id: Int!
title: String!
content: String
published: Boolean!
author: User!
authorId: Int!
createdAt: String!
updatedAt: String!
}
type Query {
users: [User!]!
posts: [Post!]!
user(id: Int!): User
post(id: Int!): Post
}
type Mutation {
createUser(email: String!, name: String): User!
createPost(title: String!, content: String, authorId: Int!, published: Boolean): Post!
publishPost(id: Int!): Post
deletePost(id: Int!): Post
}
;
GraphQL Resolvers
Şimdi src/resolvers.ts dosyasını oluşturalım. Resolvers, GraphQL şemasındaki her alan için veri getirme veya değiştirme mantığını içerir. Burada Prisma Client’ı kullanarak veritabanı işlemlerini yapacağız.
// src/resolvers.ts
import { PrismaClient } from '@prisma/client';
// Prisma istemcisini burada başlatmak yerine, her istek için bir bağlam (context) içinde sağlamak daha iyidir.
// Bunu src/index.ts içinde yapacağız.
interface Context {
prisma: PrismaClient;
}
export const resolvers = {
Query: {
users: (parent: any, args: any, context: Context) => {
return context.prisma.user.findMany({ include: { posts: true } });
},
posts: (parent: any, args: any, context: Context) => {
return context.prisma.post.findMany({ include: { author: true } });
},
user: (parent: any, args: { id: number }, context: Context) => {
return context.prisma.user.findUnique({ where: { id: args.id }, include: { posts: true } });
},
post: (parent: any, args: { id: number }, context: Context) => {
return context.prisma.post.findUnique({ where: { id: args.id }, include: { author: true } });
},
},
Mutation: {
createUser: (parent: any, args: { email: string; name?: string }, context: Context) => {
return context.prisma.user.create({
data: {
email: args.email,
name: args.name,
},
});
},
createPost: (parent: any, args: { title: string; content?: string; authorId: number; published?: boolean }, context: Context) => {
return context.prisma.post.create({
data: {
title: args.title,
content: args.content,
published: args.published || false,
author: {
connect: { id: args.authorId },
},
},
});
},
publishPost: (parent: any, args: { id: number }, context: Context) => {
return context.prisma.post.update({
where: { id: args.id },
data: { published: true },
});
},
deletePost: (parent: any, args: { id: number }, context: Context) => {
return context.prisma.post.delete({
where: { id: args.id },
});
},
},
};
Apollo Server’ı Başlatma
Şimdi src/index.ts dosyamızı oluşturalım ve Express ile Apollo Server’ı entegre edelim:
// src/index.ts
import 'reflect-metadata'; // Bazı kütüphaneler için gerekli olabilir
import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import { PrismaClient } from '@prisma/client';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';
const prisma = new PrismaClient();
async function startApolloServer() {
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }) => ({ prisma }), // Her isteğe Prisma istemcisini ekliyoruz
});
await server.start();
server.applyMiddleware({ app, path: '/graphql' });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.log(Server is running on http://localhost:${PORT}/graphql);
});
}
startApolloServer().catch(error => {
console.error("Apollo Server could not be started:", error);
});
Artık API’mizi yerel olarak çalıştırabiliriz:
npm run dev
Tarayıcınızda http://localhost:4000/graphql adresine giderek Apollo Sandbox veya GraphQL Playground arayüzünü görebilir ve API’nizi test edebilirsiniz.
DigitalOcean App Platform’a Dağıtma
API’miz yerel olarak çalıştığına göre, şimdi onu DigitalOcean App Platform’a dağıtalım. App Platform, uygulamaları kolayca dağıtmak, ölçeklendirmek ve yönetmek için tasarlanmış bir PaaS çözümüdür.
DigitalOcean Veritabanı Oluşturma
Öncelikle, DigitalOcean hesabınızda bir Managed PostgreSQL Database oluşturmanız gerekmektedir. Projenize uygun bir plan seçin ve veritabanını oluşturun. Veritabanı oluşturulduktan sonra, “Connection Details” (Bağlantı Detayları) bölümünden DATABASE_URL‘nizi kopyalayın.
Git Deposu Oluşturma
Uygulamanızı DigitalOcean’a dağıtmak için kodunuzun bir Git deposunda (örneğin GitHub, GitLab, Bitbucket) olması gerekir. Projenizin kök dizininde bir Git deposu başlatın ve kodunuzu uzak bir depoya gönderin:
git init
git add .
git commit -m "Initial GraphQL API with Prisma"
git branch -M main
git remote add origin
git push -u origin main
DigitalOcean App Platform’da Uygulama Oluşturma
- DigitalOcean kontrol panelinize gidin ve “Apps” (Uygulamalar) bölümünden “Create App” (Uygulama Oluştur) seçeneğine tıklayın.
- Kodunuzun bulunduğu Git sağlayıcısını seçin (GitHub, GitLab vb.) ve deponuzu bağlayın.
- Deponuzu ve dağıtmak istediğiniz ana dalı (genellikle
mainveyamaster) seçin. - DigitalOcean, projenizi otomatik olarak algılayacak ve bir “Web Service” bileşeni önerecektir.
Uygulama Ayarlarını Yapılandırma
App Platform’da uygulamanız için aşağıdaki ayarları yapılandırmanız gerekecektir:
-
Environment Variables (Ortam Değişkenleri):
DATABASE_URL: DigitalOcean Managed PostgreSQL veritabanınızdan kopyaladığınız bağlantı dizesini buraya yapıştırın.NODE_ENV:productionolarak ayarlayın.PORT: DigitalOcean tarafından otomatik olarak sağlanır, manuel olarak ayarlamanıza gerek yoktur.
-
Build Command (Derleme Komutu): Uygulamanızın derlenmesi için gerekli komutları belirtin. Prisma Client’ın ve TypeScript kodunun derlenmesi önemlidir.
npm install && npx prisma generate && npm run buildBu komutlar, bağımlılıkları yükleyecek, Prisma Client’ı oluşturacak ve TypeScript kodunuzu JavaScript’e derleyecektir.
-
Run Command (Çalıştırma Komutu): Uygulamanızı başlatmak için kullanılacak komut.
npm startBu komut,
package.jsondosyanızdakistartscriptini çalıştıracaktır (node dist/index.js). -
Post-Deploy Command (Dağıtım Sonrası Komutu – İsteğe Bağlı ama Önemli): Veritabanı migration’larını uygulamak için bu komutu kullanabilirsiniz. Bu, yeni bir sürüm dağıtıldığında veritabanınızın güncel kalmasını sağlar.
npx prisma migrate deployBu komut, uygulamanız başarıyla dağıtıldıktan sonra çalışacak ve bekleyen tüm migration’ları uygulayacaktır.
Tüm ayarları yaptıktan sonra, uygulamanızı oluşturun. DigitalOcean App Platform, kodunuzu çekecek, derleyecek ve dağıtacaktır. Dağıtım süreci tamamlandığında, uygulamanızın canlı URL’sine erişebilir ve GraphQL API’nizi kullanmaya başlayabilirsiniz.
Sonuç ve Sıkça Sorulan Sorular
Bu rehberde, GraphQL API’si oluşturmak için Prisma ve Apollo Server’ı nasıl kullanacağınızı ve bu API’yi DigitalOcean App Platform’a nasıl dağıtacağınızı adım adım öğrendiniz. Bu güçlü araçların birleşimi, modern, ölçeklenebilir ve bakımı kolay API’ler geliştirmenize olanak tanır. GraphQL’in esnekliği, Prisma’nın veritabanı soyutlaması ve DigitalOcean App Platform’un kolay dağıtım yetenekleri, geliştirme sürecinizi önemli ölçüde hızlandırabilir.
Sıkça Sorulan Sorular (SSS)
Q: Neden GraphQL kullanmalıyım?
A: GraphQL, istemcilerin tam olarak ihtiyaç duydukları veriyi tek bir istekte talep etmelerine olanak tanır, bu da fazla veya eksik veri getirme sorunlarını ortadan kaldırır. Ayrıca, API’nin evrimini kolaylaştırır ve daha iyi dokümantasyon sağlar.
Q: Prisma’nın avantajları nelerdir?
A: Prisma, tip-güvenli veritabanı sorguları, güçlü migration sistemi, farklı veritabanları için destek ve modern TypeScript geliştirme ortamlarıyla mükemmel entegrasyon sunar. Geliştirici üretkenliğini artırır ve yaygın veritabanı hatalarını azaltır.
Q: DigitalOcean App Platform’un faydaları nelerdir?
A: App Platform, altyapı yönetimi yükünü ortadan kaldıran bir PaaS çözümüdür. Otomatik dağıtım, ölçekleme, SSL sertifikaları, günlük kaydı ve izleme gibi özellikler sunarak geliştiricilerin sadece kod yazmaya odaklanmasını sağlar.
Q: API güvenliğini nasıl sağlayabilirim?
A: API güvenliği için kimlik doğrulama (örneğin JWT – JSON Web Tokens) ve yetkilendirme (rol tabanlı erişim kontrolü) mekanizmaları eklemeniz gerekir. Apollo Server, context içinde kullanıcı bilgilerini taşıyarak resolvers içinde kolayca yetkilendirme kontrolü yapmanızı sağlar. Rate limiting ve input validation da önemlidir.
Q: Uygulamamın ölçeklenebilirliğini nasıl artırabilirim?
A: DigitalOcean App Platform, uygulamanızı otomatik olarak ölçeklendirme yeteneğine sahiptir. Daha fazla isteği işlemek için daha fazla uygulama örneği ekleyebilir veya kaynakları (CPU, RAM) artırabilirsiniz. Ayrıca, veritabanı bağlantı havuzlama ve önbellekleme gibi teknikler de ölçeklenebilirliği artırır.
Q: Dağıtım sonrası hataları nasıl ayıklayabilirim?
A: DigitalOcean App Platform, uygulamanızın günlüklerini (logs) görüntülemenizi sağlar. Dağıtım sorunları veya çalışma zamanı hataları için bu günlükleri dikkatlice inceleyin. Ayrıca, hata izleme hizmetleri (Sentry, DataDog) entegre etmek de yardımcı olabilir.