değişiklikler

ulufe projesinin ai tarafında oluşturulan değişiklik günlüğü kayıtları.

Tüm güncellemeler
Müşteri Yönetim Sistemi
29 Aralık 2025 %9
Bu değişiklik günlüğü Claude tarafından oluşturuldu.

Tam özellikli bir müşteri (contacts) yönetim sistemi geliştirildi. Sistem, veritabanı şeması, API endpoint’leri, validasyon, tip güvenliği ve geliştirici araçlarını içeriyor.

Tamamlanan işler

  • CRUD operasyonları - Müşteri oluşturma, listeleme, güncelleme ve silme endpoint’leri
  • Çok kiracılı mimari - Kullanıcıya özel veri izolasyonu ile güvenli erişim
  • Tip güvenliği - Frontend ve backend arasında paylaşımlı TypeScript tipleri
  • Validasyon - Zod şemaları ile otomatik veri doğrulama
  • Sayfalama (pagination) - Özelleştirilebilir sayfa boyutu ve sayfa numarası
  • Filtreleme - Aktif/pasif durum filtreleme desteği
  • Geliştirici araçları - Bruno API collection ile test ortamı

Mimari kararlar

Paket yapısı

Tip ve şemaların nerede yaşayacağına dair bilinçli kararlar alındı:

  • @ulufe/models - İstemci tarafı TypeScript interface’leri (sıfır bağımlılık)
  • @ulufe/schema - Zod validasyon şemaları (istek/yanıt doğrulama)
  • apps/api/src/db/schema.ts - Drizzle ORM şemaları (minimal tip export’u)

Neden bu yaklaşım?

  • Endişelerin temiz ayrımı
  • İstemci bundle’ına veritabanı bağımlılıklarının girmemesi
  • API’nin veritabanı şemasından bağımsız evrilebilmesi
  • Frontend için stabil, dokümante edilmiş tip kontratları

API Endpoint’leri

Müşteri yönetimi için 5 RESTful endpoint oluşturuldu. Tüm endpoint’ler kimlik doğrulama gerektiriyor ve kullanıcılar sadece kendi müşterilerine erişebiliyor. Oluşturma, listeleme (sayfalı), tekil getirme, güncelleme ve silme işlemleri destekleniyor. Güvenlik için sahiplik doğrulaması yapılıyor ve bilgi sızıntısını önlemek amacıyla yetkisiz erişimlerde 404 hatası dönülüyor.

Pagination (Sayfalama)

Yeniden kullanılabilir sayfalama yardımcı fonksiyonu oluşturuldu:

Kullanım:

const contacts = await withPagination(
  query.$dynamic(),
  desc(contact.createdAt), // En yeniler önce
  page,
  limit
);

Özellikler:

  • Tüm endpoint’lerde tutarlı sayfalama
  • Otomatik offset hesaplaması
  • Özelleştirilebilir sıralama
  • Drizzle sorguları ile tip güvenli

Validasyon Middleware

@hono/standard-validator entegre edildi:

Öncesi:

const body = await c.req.json();
const validation = schema.safeParse(body);
if (!validation.success) {
  return c.json({ error: "Doğrulama başarısız" }, 400);
}

Sonrası:

sValidator("json", SchemaRequestCreateContact),
async (c) => {
  const data = c.req.valid("json"); // Zaten doğrulanmış!
}

Bruno API Collection

Test için eksiksiz bir Bruno koleksiyonu oluşturuldu:

  • 6 hazır endpoint dosyası
  • Örnek payload’lar
  • Dokümantasyon
  • Yerel ortam konfigürasyonu
  • Sorgu/path parametreleri

Kullanım:

  1. usebruno.com adresinden Bruno’yu indir
  2. .bruno klasörünü koleksiyon olarak aç
  3. “local” ortamını seç
  4. Test etmeye başla!

Oluşturulan/Değiştirilen dosyalar

Yeni paketler

  • @ulufe/models - İstemci tarafı tip tanımları (Contact, User)
  • @ulufe/schema - Validasyon şemaları (create, update, list)

API dosyaları

  • apps/api/src/routes/contacts.ts - CRUD route handler’ları
  • apps/api/src/helpers/pagination.ts - Sayfalama yardımcı fonksiyonu
  • apps/api/src/db/schema.ts - Contact tablosu eklendi

Geliştirici araçları

  • .bruno/ - Tam Bruno API koleksiyonu (6 endpoint)

Toplam: 18 dosya oluşturuldu, 3 dosya değiştirildi

Öğrenimler

1. Query parametre dönüşümü

URL query parametreleri her zaman string’dir. z.coerce.boolean() ve z.coerce.number() kullanarak otomatik tip dönüşümü sağlandı.

2. Sayfa tabanlı vs Offset tabanlı sayfalama

Sayfa tabanlı yaklaşımı seçildi çünkü:

  • Daha sezgisel: /contacts?page=2&limit=50
  • UI sayfalama kontrolleri için daha kolay
  • Kullanıcılar “sayfalar” olarak düşünür

3. Endişelerin ayrılması

Üç katmanlı tip sistemi:

  • Veritabanı katmanı - Drizzle şema tanımları
  • Validasyon katmanı - Zod şemaları
  • Model katmanı - TypeScript interface’leri

Bu yaklaşım bağlantıyı önler ve her katmanın bağımsız gelişmesine izin verir.

4. Yetkilendirme ile güvenlik

Her sorgu kullanıcı kapsamı içerir:

// Yanlış: Tüm müşterileri döndürür
const contacts = await db.select().from(contact);

// Doğru: Sadece kullanıcının müşterileri
const contacts = await db
  .select()
  .from(contact)
  .where(eq(contact.userId, user.id));

Performans değerlendirmeleri

İndeksleme

Mevcut şema şu indekslere sahip:

  • id (primary key - otomatik)
  • userId (foreign key - otomatik)

Gelecek optimizasyon: Yaygın sorgular için kompozit indeks düşünülebilir.

Sayfalama performansı

LIMIT ve OFFSET kullanımı büyük veri setleri için yavaş olabilir.

Gelecek optimizasyon: Cursor tabanlı sayfalama

Count sorgusu optimizasyonu

Sayfalama metadata için ayrı count sorgusu çalıştırılıyor.

Gelecek optimizasyon:

  • Çok müşterisi olan kullanıcılar için count cache’leme
  • Çok büyük veri setleri için yaklaşık count kullanımı
Ana sayfaya dön