Kod Standartları ve Kuralları
LibreChat'e katkıda bulunmak için kodlama standartları, çalışma alanı sınırları ve kurallar.
Çalışma Alanı Sınırları
LibreChat bir monorepo'dur. Tüm yeni kodlar doğru çalışma alanını hedeflemelidir:
| Çalışma Alanı | Dil | Taraf | Amaç |
|---|---|---|---|
/api | JS (eski) | Backend | Express sunucusu — buradaki değişiklikleri en aza indirin |
/packages/api | TypeScript | Backend | Yeni backend kodu burada yer alır (sadece TS, /api tarafından tüketilir) |
/packages/data-schemas | TypeScript | Backend | Veritabanı modelleri/şemaları ve veritabanına özgü paylaşılan mantık |
/packages/data-provider | TypeScript | Paylaşılan | API tipleri, endpoint'ler, veri servisi — frontend ve backend tarafından kullanılır |
/client | TypeScript/React | Frontend | Frontend SPA |
/packages/client | TypeScript | Frontend | Paylaşılan frontend araçları |
/packages/apiiçindeki tüm yeni backend kodları TypeScript olmalıdır./apideğişikliklerini mutlak minimumda tutun (/packages/apidizinini çağıran ince JS sarmalayıcıları).- Veritabanına özgü paylaşılan mantık
/packages/data-schemasiçinde yer alır. - Frontend/backend paylaşımlı API mantığı (endpoint'ler, tipler, data-service)
/packages/data-providerdizininde yer alır. - Proje kök dizininden tüm derlenmiş kodları oluşturun:
npm run build. - API/tip değişikliklerinden sonra paylaşılan data-provider kodunu yeniden derleyin:
npm run build:data-provider.
Genel Kılavuzlar
- "Clean code" (temiz kod) prensiplerini kullanın: fonksiyonları ve modülleri küçük tutun, tek sorumluluk ilkesine (single responsibility principle) bağlı kalın ve ifade edici, okunabilir kod yazın.
- Anlamlı ve açıklayıcı değişken ve fonksiyon isimleri kullanın.
- Kodun okunabilirliğini ve sürdürülebilirliğini kısalığa tercih edin.
- Tutarlı kod biçimlendirmesi için sağlanan
.eslintrcve.prettierrcdosyalarını kullanın. - Mümkün olduğunda otomatik düzeltmeyi kullanarak tüm biçimlendirme lint hatalarını giderin. Tüm TypeScript/ESLint uyarıları ve hataları çözülmelidir.
Adlandırma ve Dosya Organizasyonu
- Mümkün olduğunda
permissions.ts,capabilities.tsveyaservice.tsgibi tek kelimelik dosya adları kullanın. - Birden fazla kelime gerektiğinde,
adminCapabilities.tsyerineadmin/capabilities.tsgibi dosya bağlamını veren tek kelimelik bir dizini tercih edin. - Dizinin bağlam sağlamasına izin verin.
app/appConfigService.tsyerineapp/service.tstercih edin.
Kod Yapısı
- İç içe geçmekten kaçının (Never-nesting): erken dönüşler (early returns), düz kod yapısı ve minimum girinti kullanın. Karmaşık işlemleri, iyi adlandırılmış yardımcı fonksiyonlara bölün.
- İşlevsel öncelikli: saf işlevler, değiştirilemez veri, zorunlu döngüler yerine
map/filter/reduce. Yalnızca alan modellemesini veya durum kapsüllemeyi açıkça iyileştirdiği durumlarda OOP'ye başvurun. - Dinamik içe aktarma (dynamic imports) kullanmayın, kesinlikle gerekli olmadığı sürece.
- Tekrarlanan mantığı özel yardımcı işlevlere (DRY) ayırın. Neredeyse aynı uygulamalar yerine parametreli yardımcıları, sabitleri, paylaşılan doğrulayıcıları, merkezi hata yönetimini ve paylaşılan tipleri tercih edin.
Yineleme ve Performans
- Döngüleri en aza indirin — özellikle mesaj dizileri gibi sıkça yinelenen paylaşılan veri yapıları üzerinde. Ölçek büyüdükçe her ek geçiş maliyeti artırır.
- Mümkün olduğunda ardışık O(n) işlemlerini tek bir geçişte birleştirin; iş birleştirilebiliyorsa aynı koleksiyon üzerinde asla iki kez döngü kurmayın.
- Yinelemeye olan ihtiyacı azaltan veri yapılarını seçin (örneğin,
Array.find/Array.includesyerine aramalar içinMap/Setkullanın). - Gereksiz nesne oluşturmaktan kaçının; zaman-mekan ödünleşimlerini (space-time tradeoffs) göz önünde bulundurun.
- Bellek sızıntılarını önleyin: closure'lara (kapanışlar) dikkat edin, kaynakları/olay dinleyicilerini (event listeners) temizleyin, döngüsel referanslardan kaçının.
Tip Güvenliği
- Asla
anykullanmayın. Tüm parametreler, dönüş değerleri ve değişkenler için açık türler (explicit types) kullanın. unknownkullanımını sınırlayın —unknown,Record<string, unknown>veas unknown as Tiddialarından kaçının. BirRecord<string, unknown>kullanımı neredeyse her zaman eksik bir açık tip tanımına işaret eder.- Türleri kopyalamayın — yeni bir tür tanımlamadan önce projenin içinde (özellikle
packages/data-providerdizininde) halihazırda bir türün var olup olmadığını kontrol edin. Mevcut türleri yeniden kullanın ve genişletin. - Union tiplerini, generic yapıları ve interface'leri uygun şekilde kullanın.
Yorumlar ve Dokümantasyon
- Kendi kendini belgeleyen kodlar yazın; kodun ne yaptığını anlatan satır içi yorumlar kullanmayın.
- Yalnızca karmaşık/belirgin olmayan mantık veya genel API'lerdeki intellisense için JSDoc kullanın.
- Kısa dokümantasyon için tek satırlık JSDoc, karmaşık durumlar için çok satırlı JSDoc kullanın.
- Kesinlikle gerekli olmadıkça tek satırlık
//yorumlarından kaçının.
İçe Aktarma Sırası
İçe aktarmalar (imports) üç bölüm halinde (sırasıyla) düzenlenmiştir:
- Paket içe aktarımları — en kısa satır uzunluğundan en uzuna doğru sıralanmıştır (
reacther zaman ilk içe aktarımdır). import typeiçe aktarmaları — en uzundan en kısaya doğru sıralanmıştır (önce paket türleri, ardından yerel türler; uzunluk sıralaması alt gruplar arasında sıfırlanır).- Yerel/proje içe aktarımları — en uzundan en kısaya doğru sıralanmıştır.
- Aynı modülden gelen değer içe aktarımlarını mümkün olduğunca birleştirin.
- Tip içe aktarmaları için her zaman bağımsız
import type { ... }kullanın; değer içe aktarmalarının içinde asla satır içitypeanahtar sözcüğünü kullanmayın (örneğin,import { Foo, type Bar }yanlıştır).
Döngü Tercihleri
- Döngüleri mümkün olduğunca sınırlandırın. Tek geçişli (single-pass) dönüşümleri tercih edin ve aynı verinin üzerinden tekrar tekrar geçmekten kaçının.
- performans açısından kritik veya dizin bağımlı işlemler için
for (let i = 0; ...)kullanın. - Basit dizi yinelemesi için
for...of. for...inyalnızca nesne özelliği numaralandırması içindir.
Node.js API Sunucusu
API Tasarımı
- API'leri tasarlarken RESTful prensiplerini takip edin.
- Rotalar, denetleyiciler, servisler ve modeller için anlamlı ve açıklayıcı isimler kullanın.
- Her rota için uygun HTTP yöntemlerini (GET, POST, PUT, DELETE) kullanın.
- Tutarlı API yanıtları için uygun durum kodlarını ve yanıt yapılarını kullanın (başarı için 2xx, istemciden gelen hatalı istekler için 4xx, sunucu hatası için 5xx).
- İstisnaları yakalamak ve düzgün bir şekilde yönetmek için try-catch bloklarını kullanın.
- Uygun hata yönetimini uygulayın ve tutarlı bir şekilde uygun hata yanıtları döndürün.
- Önemli olayları ve hataları günlüğe kaydetmek için
utilsdizininde bulunan günlük kaydı sistemini kullanın. requireJWTAuthara yazılımını (middleware) kullanarak JWT tabanlı, durumsuz (stateless) kimlik doğrulaması yapın.
Dosya Yapısı
Yeni backend kodu, TypeScript olarak /packages/api dizinine eklenir. Eski /api dizini şu yapıyı takip eder:
Rotalar
Her bir HTTP istek yöntemini, kullanılacak ara yazılımları ve her rota için çağrılacak denetleyici işlevini belirtir.
- Her bir kaynak veya mantıksal gruplandırma için ayrı dosyalarda Express Router kullanarak rotaları tanımlayın.
- Açıklayıcı rota isimleri kullanın ve RESTful kurallarına uyun.
- Rotaları kısa tutun ve tek bir sorumluluğa odaklanın.
- Tüm rotaların başına
/apiad alanını ekleyin.
Denetleyiciler
Uygun servis fonksiyonlarını çağırmak ve ilgili yanıt durum kodunu ve JSON gövdesini döndürmek dahil olmak üzere, her rota için mantığı içerir.
- İstek/yanıt mantığını yönetmek için her rota için ayrı bir kontrolcü dosyası oluşturun.
- Controller dosyalarını PascalCase kuralını kullanarak adlandırın ve dosya adının sonuna "Controller" ekleyin (örneğin,
UserController.js). - Karmaşık işlemleri servis veya model dosyalarına devrederek controller'ları ince tutun.
Servisler
Birden fazla controller arasında paylaşılan karmaşık iş mantığını veya işlemleri içerir.
- Servis dosyalarını PascalCase kuralını kullanarak adlandırın ve dosya adının sonuna "Service" ekleyin (örneğin,
AuthService.js). - Daha iyi yeniden kullanılabilirlik için servisleri belirli modellere veya veritabanlarına sıkı bir şekilde bağlamaktan kaçının.
- Her servis içinde tek sorumluluk ilkesini koruyun.
Modeller
Veri varlıklarını ve bunların ilişkilerini temsil etmek için Mongoose modellerini tanımlar.
- Model dosyaları ve bunlarla ilişkili koleksiyonlar için tekil, PascalCase isimler kullanın (örneğin,
User.jsveuserskoleksiyonu). - Modellerde yalnızca gerekli alanları, indeksleri ve doğrulamaları dahil edin.
- İstek/yanıt nesnelerine doğrudan referans vermekten kaçınarak modelleri API katmanından bağımsız tutun.
Veritabanı Erişimi (MongoDB ve Mongoose)
- MongoDB ODM'si olarak Mongoose (https://mongoosejs.com) kullanın.
- Her bir varlık için ayrı model dosyaları oluşturun ve sorumlulukların net bir şekilde ayrıldığından emin olun.
- Veri bütünlüğünü sağlamak için Mongoose şema doğrulamasını kullanın.
- Veritabanı bağlantılarını verimli bir şekilde yönetin ve bağlantı sızıntılarından kaçının.
- Kısa ve okunabilir veritabanı sorguları oluşturmak için Mongoose sorgu oluşturucularını (query builders) kullanın.
React Client
Genel TypeScript ve React En İyi Uygulamaları
- Statik tiplemeden ve geliştirilmiş araçlardan yararlanmak için TypeScript best practices kullanın.
- İlgili dosyaları özellik dizinleri içinde gruplandırın (örneğin,
SidePanel/Memories/). - Bileşenleri PascalCase kuralını kullanarak adlandırın.
- Bileşenin amacını doğru bir şekilde yansıtan kısa ve açıklayıcı isimler kullanın.
- Karmaşık bileşenleri uygun olduğunda daha küçük, yeniden kullanılabilir bileşenlere bölün.
- Bileşenler içindeki işleme (rendering) mantığını minimumda tutun.
- Yeniden kullanılabilir parçaları ayrı fonksiyonlara veya hook'lara ayırın.
- TypeScript türlerini veya arayüzlerini kullanarak prop türü tanımlarını uygulayın.
- Uygun olan yerlerde form doğrulama kullanın (form doğrulama ve gönderimi için React Hook Form kullanıyoruz).
Yerelleştirme
- İstemciye yönelik tüm metinler
useLocalize()hook'u kullanılarak yerelleştirilmelidir. - Yalnızca
client/src/locales/en/translation.jsondosyasındaki İngilizce anahtarları güncelleyin (diğer diller harici olarak otomatikleştirilmiştir). - Anlamsal yerelleştirme anahtarı önekleri kullanın:
com_ui_,com_assistants_vb. - Yeni yerelleştirme anahtarları için her zaman anlamlı bir yedek metin sağlayın.
Veri Servisleri
client/src/data-provider/[Feature]/queries.tsdosyasında veri sağlayıcı kancaları (hooks) oluşturun.client/src/data-provider/[Feature]/index.tsdosyasındaki tüm hook'ları dışa aktarın.client/src/data-provider/index.tsdosyasına özellik dışa aktarımlarını (feature exports) ekleyin.- Tüm API etkileşimleri için React Query (
@tanstack/react-query) kullanın. - Mutasyonlarda uygun sorgu geçersiz kılma (query invalidation) işlemini uygulayın.
packages/data-provider/src/keys.tsdosyasına QueryKeys ve MutationKeys ekleyin.
Paylaşılan API entegrasyonunu eklerken şunları güncelleyin:
packages/data-provider/src/api-endpoints.ts(endpoint'ler)packages/data-provider/src/data-service.ts(veri hizmeti işlevleri)packages/data-provider/src/types/queries.ts(TypeScript türleri)
Performans
- Ölçekte bellek ve hız verimliliğine öncelik verin.
- Büyük veri kümeleri için uygun imleç (cursor) sayfalama yöntemini uygulayın.
- Uygun bağımlılık dizileri (dependency arrays) ile gereksiz yeniden oluşturmalardan (re-renders) kaçının.
- React Query'nin önbelleğe alma ve arka planda yeniden getirme (refetching) özelliklerinden yararlanın.
Test Etme ve Dokümantasyon
- Jest kullanarak tüm kritik ve karmaşık işlevler için birim testleri yazın.
- Supertest kullanarak tüm API endpoint'leri için entegrasyon testleri yazın.
- Playwright kullanarak tüm istemci tarafı işlevleri için uçtan uca testler yazın.
- Testin amacını net bir şekilde ifade etmek için açıklayıcı test durumu ve fonksiyon isimleri kullanın.
- Testleri kendi çalışma dizinlerinden çalıştırın:
cd api && npx jest <pattern>,cd packages/api && npx jest <pattern>vb. - UI/veri akışları için yükleme, başarı ve hata durumlarını kapsayın.
- Frontend testlerinde bileşenleri render etmek için
test/layout-test-utilskullanın. - Mock'lar yerine gerçek mantığı tercih edin. Yalnızca harici HTTP API'leri, hız sınırlamalı servisler ve deterministik olmayan sistem çağrıları gibi yerel olarak kontrol edilemeyen durumları mock'layın.
- Temel uygulamayı değiştirmeden çağrıları doğrulamak (assert) gerektiğinde spy'ları kullanın.
- Sorguların ve şema doğrulamanın gerçek veritabanı davranışını sergilemesi için MongoDB destekli testlerde
mongodb-memory-serverkullanın.
Bu rehber nasıl?