@hd-agent-kit/cli 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +9 -2
- package/package.json +1 -1
- package/templates/AGENTS.md +535 -15
- package/templates/skills/analyze/SKILL.md +177 -21
- package/templates/skills/api-design/SKILL.md +454 -0
- package/templates/skills/performance-check/SKILL.md +117 -16
- package/templates/skills/security-scan/SKILL.md +67 -16
- package/templates/skills/write-tests/SKILL.md +190 -12
|
@@ -24,6 +24,41 @@ description: Analyze the project structure, tech stack, and conventions to gener
|
|
|
24
24
|
- İşlem öncesi kontrol sırasında `project-rules.md` bulunamadıysa → Kullanıcıya "Analiz yapayım mı?" sor.
|
|
25
25
|
- **Önemli:** Kullanıcı `/analyze` yazmamışsa ve `project-rules.md` mevcutsa → Bu süreci ATLAMA.
|
|
26
26
|
|
|
27
|
+
### Sıfırdan Proje Başlatma Modu
|
|
28
|
+
|
|
29
|
+
Kullanıcı yeni bir proje başlatacağını bildirirse (package.json yok, kaynak kod boş, "sıfırdan X yapmak istiyorum" gibi ifadeler varsa):
|
|
30
|
+
|
|
31
|
+
**1. Analiz değil, tasarım moduna geç** — Mevcut kod taramak yerine mimari kararları netleştir.
|
|
32
|
+
|
|
33
|
+
**2. Şu soruları tek mesajda sor:**
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Projeyi başlatmadan önce birkaç şeyi netleştirelim:
|
|
37
|
+
|
|
38
|
+
1. Proje tipi? (Frontend SPA / Fullstack / Standalone API / CLI / Kütüphane)
|
|
39
|
+
2. Framework? (Next.js, Vite+React, Express, Hono, Electron, vs.)
|
|
40
|
+
3. TypeScript kullanılacak mı?
|
|
41
|
+
4. Kimlik doğrulama (auth) gerekiyor mu?
|
|
42
|
+
5. Stil: Tailwind, CSS Modules, styled-components, başka?
|
|
43
|
+
6. UI kit: shadcn/ui, MUI, Radix, özel tasarım sistemi mi?
|
|
44
|
+
7. Test: Vitest, Jest, Playwright, Cypress, yoksa test yok mu?
|
|
45
|
+
8. Monorepo mu, tek repo mu?
|
|
46
|
+
9. Deployment target? (Vercel, Railway, VPS, npm publish)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**3. Cevaplar alındıktan sonra:**
|
|
50
|
+
|
|
51
|
+
- `project-rules.md` dosyasını **mevcut kodu analiz etmeden, belirlenen stack ile proaktif olarak oluştur**
|
|
52
|
+
- Önerilen proje iskeletini listele: hangi klasörler oluşturulmalı, hangi config dosyaları kurulmalı, hangi paketler kurulmalı
|
|
53
|
+
- Kullanıcı onayladıktan sonra kuruluma başla
|
|
54
|
+
|
|
55
|
+
**4. İskeleti kurarken mimari prensipleri uygula:**
|
|
56
|
+
|
|
57
|
+
- Feature-based klasör yapısı öner (type-based değil)
|
|
58
|
+
- Atomic Design hiyerarşisine uygun component klasörleri kur (`components/ui/`, `components/`, `features/`)
|
|
59
|
+
- Smart/Dumb ayrımını gözetecek klasör yapısı oluştur
|
|
60
|
+
- Backend için katmanlı yapı: `routes/` → `controllers/` → `services/`
|
|
61
|
+
|
|
27
62
|
---
|
|
28
63
|
|
|
29
64
|
## Analiz Adımları
|
|
@@ -70,9 +105,26 @@ package.json + config dosyalarından tespit et:
|
|
|
70
105
|
└── Diğer: Monorepo tooling, deployment config, analytics
|
|
71
106
|
```
|
|
72
107
|
|
|
73
|
-
### Adım 3:
|
|
108
|
+
### Adım 3: Proje Tipi Tespiti & Kod Stili Analizi
|
|
109
|
+
|
|
110
|
+
Mevcut kaynak kodunu **en az 10-15 dosya** üzerinden örnekleyerek analiz et.
|
|
111
|
+
|
|
112
|
+
**Önce Proje Tipini Tespit Et:**
|
|
74
113
|
|
|
75
|
-
|
|
114
|
+
```
|
|
115
|
+
Proje tipleri ve tespiti:
|
|
116
|
+
├── Frontend SPA → React/Vue/Svelte, src/components, src/pages, no server
|
|
117
|
+
├── Fullstack → Next.js/Remix/Nuxt, hem UI hem API/server katmanı
|
|
118
|
+
├── Standalone API → Express/Fastify/Hono, routes/, controllers/, no UI
|
|
119
|
+
├── CLI Araç → bin/ klasörü veya package.json#bin, terminal çıktısı
|
|
120
|
+
└── NPM Kütüphanesi → package.json#main|module|exports, src/, dist/, no bin
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Tespit edilen proje tipine göre aşağıdaki uygun alt bölümleri uygula:**
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
#### Frontend / Fullstack UI Analizi *(SPA, Next.js, Remix vs. için)*
|
|
76
128
|
|
|
77
129
|
**Component Yapısı:**
|
|
78
130
|
- Arrow function mı, function declaration mı?
|
|
@@ -91,26 +143,68 @@ Mevcut kaynak kodunu **en az 10-15 dosya** üzerinden örnekleyerek analiz et:
|
|
|
91
143
|
- CSS Modules ise: Adlandırma convention'ı ne?
|
|
92
144
|
- Theme/token sistemi var mı?
|
|
93
145
|
|
|
146
|
+
**Hata Yönetimi (UI):**
|
|
147
|
+
- Error boundary kullanılıyor mu?
|
|
148
|
+
- API hataları nasıl handle ediliyor?
|
|
149
|
+
- Toast/notification sistemi var mı?
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
#### Backend / API Analizi *(Standalone API, Next.js API Routes, fullstack backend için)*
|
|
154
|
+
|
|
155
|
+
**Route & Controller Yapısı:**
|
|
156
|
+
- Route yapısı nasıl? (Express Router, Next.js App Router, Fastify plugin vs.)
|
|
157
|
+
- Controller ve service ayrımı var mı?
|
|
158
|
+
- Middleware zinciri nasıl kurulmuş? (auth, validation, logging sırası)
|
|
159
|
+
|
|
160
|
+
**Validation & Error Handling:**
|
|
161
|
+
- Validation nerede yapılıyor? (middleware, handler içinde, Zod schema)
|
|
162
|
+
- Hata response formatı tutarlı mı? (`code`, `message`, `details` yapısı)
|
|
163
|
+
- Global hata middleware'i var mı?
|
|
164
|
+
|
|
165
|
+
**Auth & Güvenlik:**
|
|
166
|
+
- Auth middleware var mı? Nasıl uygulanıyor? (JWT, session, API key)
|
|
167
|
+
- Rate limiting uygulanmış mı?
|
|
168
|
+
- Input sanitization yapılıyor mu?
|
|
169
|
+
|
|
170
|
+
**Veri Erişimi:**
|
|
171
|
+
- DB query'leri nerede yazılıyor? (service layer, doğrudan handler'da, repository pattern)
|
|
172
|
+
- ORM/query builder nasıl kullanılıyor? (Prisma, Drizzle, Knex)
|
|
173
|
+
- Transaction kullanım pattern'ı nasıl?
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
#### CLI Araç Analizi *(bin/ olan projeler için)*
|
|
178
|
+
|
|
179
|
+
- Argüman ayrıştırma nasıl yapılıyor? (manuel `process.argv`, commander, yargs)
|
|
180
|
+
- Komut/sub-komut yapısı nasıl?
|
|
181
|
+
- Kullanıcı geri bildirim formatı nasıl? (log prefix'leri, renkler, emoji'ler)
|
|
182
|
+
- `--force` / `--dry-run` / `--verbose` gibi ortak flag'ler var mı?
|
|
183
|
+
- Cross-platform uyum nasıl sağlanmış?
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
#### Library / NPM Paket Analizi *(package.json#exports olan projeler için)*
|
|
188
|
+
|
|
189
|
+
- Public API nerede tanımlı? (`index.ts`, `src/index.ts`)
|
|
190
|
+
- Internal vs. public export ayrımı var mı?
|
|
191
|
+
- CJS ve ESM dual çıktı üretiliyor mu?
|
|
192
|
+
- `d.ts` tip tanımları üretiliyor mu?
|
|
193
|
+
- Semver politikası ve changelog tutma convention'ı nasıl?
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
**Tüm Proje Tipleri için Ortak Analiz:**
|
|
198
|
+
|
|
94
199
|
**Import Sıralaması:**
|
|
95
|
-
- Mevcut koddaki import sıralamasını tespit et (
|
|
96
|
-
- Absolute import path alias var mı? (`@/`, `~/`,
|
|
200
|
+
- Mevcut koddaki import sıralamasını tespit et (stdlib, 3rd party, internal, types vs.)
|
|
201
|
+
- Absolute import path alias var mı? (`@/`, `~/`, `#/`, `src/`)
|
|
97
202
|
|
|
98
203
|
**Tip Tanımları:**
|
|
99
|
-
- Type'lar nerede tanımlanıyor? (
|
|
204
|
+
- Type'lar nerede tanımlanıyor? (kaynak dosyanın yanında, ayrı `types/` klasörü, global `types.d.ts`?)
|
|
100
205
|
- `interface` mi `type` mı daha yaygın?
|
|
101
206
|
- Zod/Valibot schema'dan tip türetme var mı?
|
|
102
207
|
|
|
103
|
-
**Hata Yönetimi:**
|
|
104
|
-
- Error boundary kullanılıyor mu?
|
|
105
|
-
- API hataları nasıl handle ediliyor?
|
|
106
|
-
- Toast/notification sistemi var mı?
|
|
107
|
-
|
|
108
|
-
**Backend/API Katmanı (varsa):**
|
|
109
|
-
- API route yapısı nasıl? (Next.js App Router, Pages Router, Express router vs.)
|
|
110
|
-
- Validation nerede yapılıyor? (Middleware, handler içinde, Zod schema)
|
|
111
|
-
- Auth middleware var mı? Nasıl uygulanıyor?
|
|
112
|
-
- DB query'leri nerede yazılıyor? (Service layer, doğrudan handler'da)
|
|
113
|
-
|
|
114
208
|
### Adım 4: Konfigürasyon Analizi
|
|
115
209
|
|
|
116
210
|
```
|
|
@@ -206,15 +300,16 @@ Analiz tamamlandıktan sonra aşağıdaki formatta `project-rules.md` oluştur:
|
|
|
206
300
|
|
|
207
301
|
```markdown
|
|
208
302
|
# [Proje Adı] — Proje Kuralları
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
303
|
+
<!-- Bu dosya otomatik analiz ile oluşturulmuştur. -->
|
|
304
|
+
<!-- Son analiz tarihi: [TARİH] -->
|
|
305
|
+
<!-- Analiz tetikleyicisi: [/analyze komutu / Otomatik tespit] -->
|
|
212
306
|
|
|
213
307
|
## Proje Özeti
|
|
308
|
+
- **Tür:** [Frontend SPA / Fullstack / Standalone API / CLI Araç / NPM Kütüphanesi]
|
|
214
309
|
- **Framework:** [tespit edilen]
|
|
215
310
|
- **Dil:** [TypeScript/JavaScript] | Strict: [Evet/Hayır]
|
|
216
|
-
- **Styling:** [tespit edilen]
|
|
217
|
-
- **State Yönetimi:** [tespit edilen]
|
|
311
|
+
- **Styling:** [tespit edilen veya "Yok"]
|
|
312
|
+
- **State Yönetimi:** [tespit edilen veya "Yok"]
|
|
218
313
|
- **Test:** [tespit edilen]
|
|
219
314
|
- **Build Tool:** [tespit edilen]
|
|
220
315
|
- **Monorepo:** [Evet/Hayır]
|
|
@@ -267,6 +362,65 @@ Analiz tamamlandıktan sonra aşağıdaki formatta `project-rules.md` oluştur:
|
|
|
267
362
|
## Git Kuralları
|
|
268
363
|
[Commit format, branch naming — projeden tespit edilen]
|
|
269
364
|
|
|
365
|
+
## Temel Dosya Haritası
|
|
366
|
+
|
|
367
|
+
> AI asistanın yeni kod yazarken direkt başvuracağı dosya konumları.
|
|
368
|
+
> Analiz sırasında tespit edilen kritik dosyaları domain'e göre listele.
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
[domain] : [dosya yolu]
|
|
372
|
+
HTTP Client : src/lib/api.ts
|
|
373
|
+
Auth Service : src/services/auth.ts
|
|
374
|
+
Tipler : src/types/index.ts
|
|
375
|
+
Env Config : src/config/env.ts
|
|
376
|
+
Router : src/router/index.ts
|
|
377
|
+
Store/State : src/store/index.ts
|
|
378
|
+
Theme/Tokens : tailwind.config.ts / src/styles/tokens.ts
|
|
379
|
+
Test Utility : src/test/utils.tsx
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
*Yalnızca projede gerçekten var olan dosyaları ekle. Olmayan alan için satırı dahil etme.*
|
|
383
|
+
|
|
384
|
+
## Kod Örüntü Örnekleri
|
|
385
|
+
|
|
386
|
+
> Bu projedeki gerçek kod pattern'larından alınan 3-5 kısa snippet.
|
|
387
|
+
> AI asistanın yeni kod yazarken birebir taklit edeceği referans örnekler.
|
|
388
|
+
|
|
389
|
+
### [Örnek: Component]
|
|
390
|
+
```typescript
|
|
391
|
+
// Buraya projeden alınmış gerçek bir component örneği
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### [Örnek: API İsteği / Data Fetching]
|
|
395
|
+
```typescript
|
|
396
|
+
// Buraya projeden alınmış gerçek bir data fetching örneği
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### [Örnek: Tip Tanımı]
|
|
400
|
+
```typescript
|
|
401
|
+
// Buraya projeden alınmış gerçek bir type/interface örneği
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
*Her snippet ~10-20 satır olmalı — pattern'ı gösterecek kadar, fazla değil.*
|
|
405
|
+
|
|
406
|
+
## Varsayılan Tercihler
|
|
407
|
+
|
|
408
|
+
> AI asistanın her prompt için otomatik başvuracağı hızlı referans tablosu.
|
|
409
|
+
> Projede aktif kullanılan tercihler yazılır; kullanılmayan alan için "Yok" yaz.
|
|
410
|
+
|
|
411
|
+
| Alan | Bu Projede Kullanılan |
|
|
412
|
+
| --- | --- |
|
|
413
|
+
| Form | [React Hook Form + Zod / Formik / Yup / Yok] |
|
|
414
|
+
| HTTP İstek | [TanStack Query / SWR / axios / fetch / Yok] |
|
|
415
|
+
| Bildirim/Toast | [sonner / react-hot-toast / shadcn/Toaster / Yok] |
|
|
416
|
+
| Modal/Dialog | [shadcn/Dialog / Radix / Headless UI / Yok] |
|
|
417
|
+
| Tablo/Liste | [TanStack Table / shadcn/Table / Yok] |
|
|
418
|
+
| İkon Seti | [lucide-react / heroicons / react-icons / Yok] |
|
|
419
|
+
| Tarih Formatlama | [date-fns / dayjs / Intl API / Yok] |
|
|
420
|
+
| Validation Şeması | [Zod / Yup / Valibot / Yok] |
|
|
421
|
+
| Ortam Değişkeni | [NEXT_PUBLIC_ / VITE_ / process.env / Yok] |
|
|
422
|
+
| Test Utility | [Testing Library / supertest / Yok] |
|
|
423
|
+
|
|
270
424
|
## Proje-Spesifik Notlar
|
|
271
425
|
[Projeye özel convention'lar, dikkat edilmesi gereken noktalar, bilinen teknik borçlar]
|
|
272
426
|
```
|
|
@@ -278,6 +432,8 @@ Yukarıdaki bölümlerin hepsi her projede geçerli olmayabilir. Analiz sonucund
|
|
|
278
432
|
- Sadece frontend → "Backend/Server Kuralları" eklenmez.
|
|
279
433
|
- i18n yoksa → "i18n Kuralları" eklenmez.
|
|
280
434
|
|
|
435
|
+
**"Varsayılan Tercihler" tablosu her projede zorunludur** — frontend ya da backend, her tür proje için ilgili satırlar doldurulur. Kullanılmayan alanlar için "Yok" değerini yaz.
|
|
436
|
+
|
|
281
437
|
Sadece projede aktif olarak kullanılan teknolojilere ve pattern'lara dair bölümleri yaz.
|
|
282
438
|
|
|
283
439
|
---
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: Design REST/GraphQL API endpoints, define request/response schemas, and generate OpenAPI documentation
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /api-design — API Tasarım Skill'i
|
|
7
|
+
|
|
8
|
+
> **Tetikleyici:** `/api-design [kaynak/modül]`
|
|
9
|
+
> **Amaç:** REST veya GraphQL API endpoint'lerini tasarlamak, request/response şemalarını tanımlamak ve OpenAPI/Swagger belgesi oluşturmak.
|
|
10
|
+
> **Çıktı:** Endpoint tasarımı + Zod/TypeScript şemaları + OpenAPI YAML/JSON taslağı
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Kullanım Formatları
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/api-design users ← users kaynağı için tam CRUD API tasarımı
|
|
18
|
+
/api-design orders checkout ← checkout akışı endpoint tasarımı
|
|
19
|
+
/api-design --graphql products ← GraphQL schema tasarımı
|
|
20
|
+
/api-design --openapi ← Mevcut route'lardan OpenAPI belgesi oluştur
|
|
21
|
+
/api-design auth ← Auth endpoint'leri (login, logout, refresh)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Uygulama Adımları
|
|
27
|
+
|
|
28
|
+
### Adım 1: Bağlam Analizi
|
|
29
|
+
|
|
30
|
+
Mevcut projeyi incele ve şunları tespit et:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
📋 Proje Bağlamı:
|
|
34
|
+
├── API tipi: [REST / GraphQL / tRPC / mixed]
|
|
35
|
+
├── Framework: [Express, Fastify, Hono, Next.js, Nest.js]
|
|
36
|
+
├── Auth yöntemi: [JWT, session, API key, OAuth2]
|
|
37
|
+
├── Validation: [Zod, Yup, Joi, class-validator]
|
|
38
|
+
├── DB/ORM: [Prisma, Drizzle, Mongoose, TypeORM]
|
|
39
|
+
├── Mevcut API convention'ı: [versiyonlama, prefix, naming]
|
|
40
|
+
└── Mevcut endpoint örnekleri: [varsa örnek route'lar]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Adım 2: Kaynak & Endpoint Tasarımı
|
|
44
|
+
|
|
45
|
+
Belirtilen kaynak için RESTful endpoint seti tasarla:
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## REST API Tasarım Kuralları
|
|
50
|
+
|
|
51
|
+
### URL Yapısı
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Kaynak adları: çoğul isim, kebab-case
|
|
55
|
+
✅ /api/users
|
|
56
|
+
✅ /api/blog-posts
|
|
57
|
+
❌ /api/getUser
|
|
58
|
+
❌ /api/user_list
|
|
59
|
+
|
|
60
|
+
Hiyerarşik ilişkiler: iç içe kaynak
|
|
61
|
+
/api/users/:userId/orders ← Kullanıcının siparişleri
|
|
62
|
+
/api/orders/:orderId/items ← Sipariş kalemleri
|
|
63
|
+
|
|
64
|
+
Versiyon prefix'i (gerekirse):
|
|
65
|
+
/api/v1/users
|
|
66
|
+
/api/v2/users
|
|
67
|
+
|
|
68
|
+
Filtre/sayfalama: query parameter
|
|
69
|
+
/api/users?page=2&limit=20&sort=createdAt:desc&status=active
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### HTTP Method Eşleşmesi
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
GET /api/resources → Liste (sayfalı)
|
|
76
|
+
GET /api/resources/:id → Tekil kaynak
|
|
77
|
+
POST /api/resources → Yeni oluştur
|
|
78
|
+
PUT /api/resources/:id → Tamamını güncelle (tüm alanlar)
|
|
79
|
+
PATCH /api/resources/:id → Kısmen güncelle (değişen alanlar)
|
|
80
|
+
DELETE /api/resources/:id → Sil
|
|
81
|
+
|
|
82
|
+
Özel aksiyonlar (action endpoint):
|
|
83
|
+
POST /api/orders/:id/cancel → İptal et (fiil + kaynak kombinasyonu)
|
|
84
|
+
POST /api/users/:id/verify → Doğrula
|
|
85
|
+
POST /api/auth/refresh → Token yenile
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Standart CRUD Tasarım Şablonu
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
📋 [Kaynak] API Endpoint'leri:
|
|
92
|
+
|
|
93
|
+
┌─────────────────────────────────┬────────┬──────────────────────────────────┐
|
|
94
|
+
│ Endpoint │ Method │ Açıklama │
|
|
95
|
+
├─────────────────────────────────┼────────┼──────────────────────────────────┤
|
|
96
|
+
│ /api/[resources] │ GET │ Liste (filtreleme + sayfalama) │
|
|
97
|
+
│ /api/[resources]/:id │ GET │ Tekil kaynak │
|
|
98
|
+
│ /api/[resources] │ POST │ Yeni oluştur │
|
|
99
|
+
│ /api/[resources]/:id │ PATCH │ Kısmi güncelleme │
|
|
100
|
+
│ /api/[resources]/:id │ DELETE │ Sil (soft veya hard) │
|
|
101
|
+
└─────────────────────────────────┴────────┴──────────────────────────────────┘
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Request/Response Şema Tasarımı
|
|
107
|
+
|
|
108
|
+
### Zod Şema Örüntüsü
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { z } from 'zod';
|
|
112
|
+
|
|
113
|
+
// ── Base schema (DB'den dönen tam nesne) ──────────────────
|
|
114
|
+
export const UserSchema = z.object({
|
|
115
|
+
id: z.string().uuid(),
|
|
116
|
+
name: z.string().min(1).max(100),
|
|
117
|
+
email: z.string().email(),
|
|
118
|
+
role: z.enum(['admin', 'user', 'guest']),
|
|
119
|
+
createdAt: z.string().datetime(),
|
|
120
|
+
updatedAt: z.string().datetime(),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ── Create request (id ve timestamp'ler yok) ─────────────
|
|
124
|
+
export const CreateUserSchema = UserSchema.omit({
|
|
125
|
+
id: true,
|
|
126
|
+
createdAt: true,
|
|
127
|
+
updatedAt: true,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// ── Update request (tüm alanlar opsiyonel) ────────────────
|
|
131
|
+
export const UpdateUserSchema = CreateUserSchema.partial();
|
|
132
|
+
|
|
133
|
+
// ── List query parameters ─────────────────────────────────
|
|
134
|
+
export const UserListQuerySchema = z.object({
|
|
135
|
+
page: z.coerce.number().int().min(1).default(1),
|
|
136
|
+
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
137
|
+
sort: z.enum(['createdAt', 'name', 'email']).default('createdAt'),
|
|
138
|
+
order: z.enum(['asc', 'desc']).default('desc'),
|
|
139
|
+
search: z.string().optional(),
|
|
140
|
+
role: z.enum(['admin', 'user', 'guest']).optional(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// ── TypeScript tipleri (şemadan türetme) ──────────────────
|
|
144
|
+
export type User = z.infer<typeof UserSchema>;
|
|
145
|
+
export type CreateUserDto = z.infer<typeof CreateUserSchema>;
|
|
146
|
+
export type UpdateUserDto = z.infer<typeof UpdateUserSchema>;
|
|
147
|
+
export type UserListQuery = z.infer<typeof UserListQuerySchema>;
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Tutarlı Response Formatı
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// ✅ Tekil kaynak response
|
|
154
|
+
type SingleResponse<T> = {
|
|
155
|
+
data: T;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// ✅ Liste response (sayfalama meta verisi ile)
|
|
159
|
+
type ListResponse<T> = {
|
|
160
|
+
data: T[];
|
|
161
|
+
meta: {
|
|
162
|
+
total: number;
|
|
163
|
+
page: number;
|
|
164
|
+
limit: number;
|
|
165
|
+
totalPages: number;
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// ✅ Hata response
|
|
170
|
+
type ErrorResponse = {
|
|
171
|
+
code: string; // "VALIDATION_ERROR", "NOT_FOUND", "UNAUTHORIZED"
|
|
172
|
+
message: string; // Kullanıcıya gösterilebilir mesaj
|
|
173
|
+
details?: unknown; // Validation hataları (sadece dev/staging)
|
|
174
|
+
requestId?: string; // Correlation ID (production'da önemli)
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### HTTP Status Code Kılavuzu
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
200 OK → Başarılı GET, PATCH, PUT
|
|
182
|
+
201 Created → Başarılı POST (Location header ekle)
|
|
183
|
+
204 No Content → Başarılı DELETE (body yok)
|
|
184
|
+
400 Bad Request → Validation hatası
|
|
185
|
+
401 Unauthorized → Token yok veya geçersiz
|
|
186
|
+
403 Forbidden → Token geçerli ama yetki yetersiz
|
|
187
|
+
404 Not Found → Kaynak bulunamadı
|
|
188
|
+
409 Conflict → Duplicate kayıt, eşzamanlılık çakışması
|
|
189
|
+
422 Unprocessable → Semantik validasyon hatası (formatı doğru ama mantıksal hata)
|
|
190
|
+
429 Too Many Req. → Rate limit aşıldı (Retry-After header ekle)
|
|
191
|
+
500 Internal Error → Beklenmeyen sunucu hatası (detayı logla, kullanıcıya gösterme)
|
|
192
|
+
503 Unavailable → Servis geçici olarak kullanılamıyor
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Sayfalama & Filtreleme Tasarımı
|
|
198
|
+
|
|
199
|
+
### Sayfalama Stratejileri
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// ── Offset tabanlı (basit, küçük-orta veri setleri) ───────
|
|
203
|
+
GET /api/users?page=2&limit=20
|
|
204
|
+
// → { data: [...], meta: { total: 150, page: 2, limit: 20, totalPages: 8 } }
|
|
205
|
+
|
|
206
|
+
// ── Cursor tabanlı (büyük veri setleri, real-time feed) ───
|
|
207
|
+
GET /api/posts?cursor=eyJpZCI6IjEyMyJ9&limit=20
|
|
208
|
+
// → { data: [...], nextCursor: "eyJpZCI6IjE0MyJ9" | null }
|
|
209
|
+
|
|
210
|
+
// Tercih kuralı:
|
|
211
|
+
// Küçük-orta, sıralı liste → offset
|
|
212
|
+
// Büyük veri, sosyal feed, real-time → cursor
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Filtreleme & Sıralama Convention'ı
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
Filtreleme: query param = alan adı
|
|
219
|
+
/api/users?status=active&role=admin
|
|
220
|
+
|
|
221
|
+
Çoklu değer: virgülle ayrılmış
|
|
222
|
+
/api/users?role=admin,moderator
|
|
223
|
+
|
|
224
|
+
Aralık filtreleri: _gte / _lte suffix
|
|
225
|
+
/api/orders?createdAt_gte=2024-01-01&createdAt_lte=2024-12-31
|
|
226
|
+
/api/products?price_gte=100&price_lte=500
|
|
227
|
+
|
|
228
|
+
Arama: q veya search parametresi
|
|
229
|
+
/api/products?q=laptop
|
|
230
|
+
|
|
231
|
+
Sıralama: sort=alan:yön
|
|
232
|
+
/api/users?sort=createdAt:desc,name:asc
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Auth Endpoint Tasarımı
|
|
238
|
+
|
|
239
|
+
### Standart Auth Akışı
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
POST /api/auth/register → Kayıt ol
|
|
243
|
+
body: { name, email, password }
|
|
244
|
+
response 201: { user: {...}, accessToken, refreshToken }
|
|
245
|
+
|
|
246
|
+
POST /api/auth/login → Giriş yap
|
|
247
|
+
body: { email, password }
|
|
248
|
+
response 200: { user: {...}, accessToken, refreshToken }
|
|
249
|
+
|
|
250
|
+
POST /api/auth/refresh → Access token yenile
|
|
251
|
+
body: { refreshToken }
|
|
252
|
+
response 200: { accessToken, refreshToken }
|
|
253
|
+
|
|
254
|
+
POST /api/auth/logout → Çıkış yap (token iptal)
|
|
255
|
+
headers: Authorization: Bearer <token>
|
|
256
|
+
response 204
|
|
257
|
+
|
|
258
|
+
GET /api/auth/me → Mevcut kullanıcı bilgisi
|
|
259
|
+
headers: Authorization: Bearer <token>
|
|
260
|
+
response 200: { user: {...} }
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Token Güvenlik Kuralları
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
Access token: kısa ömürlü (15dk - 1sa), stateless JWT
|
|
267
|
+
Refresh token: uzun ömürlü (7-30gün), DB'de sakla (iptal için)
|
|
268
|
+
Storage: httpOnly cookie (XSS koruması) veya memory (localStorage değil)
|
|
269
|
+
Rotation: Refresh token her kullanımda yenile
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## GraphQL Şema Tasarımı *(GraphQL projeler için)*
|
|
275
|
+
|
|
276
|
+
```graphql
|
|
277
|
+
# Tip tanımları
|
|
278
|
+
type User {
|
|
279
|
+
id: ID!
|
|
280
|
+
name: String!
|
|
281
|
+
email: String!
|
|
282
|
+
role: UserRole!
|
|
283
|
+
createdAt: DateTime!
|
|
284
|
+
orders: [Order!]! # İlişki — lazy load
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
enum UserRole {
|
|
288
|
+
ADMIN
|
|
289
|
+
USER
|
|
290
|
+
GUEST
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# Query'ler
|
|
294
|
+
type Query {
|
|
295
|
+
user(id: ID!): User
|
|
296
|
+
users(
|
|
297
|
+
page: Int = 1
|
|
298
|
+
limit: Int = 20
|
|
299
|
+
filter: UserFilter
|
|
300
|
+
): UserConnection!
|
|
301
|
+
me: User # Auth gerektiren
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
# Mutation'lar
|
|
305
|
+
type Mutation {
|
|
306
|
+
createUser(input: CreateUserInput!): CreateUserPayload!
|
|
307
|
+
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
|
|
308
|
+
deleteUser(id: ID!): DeleteUserPayload!
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
# Input tipleri
|
|
312
|
+
input CreateUserInput {
|
|
313
|
+
name: String!
|
|
314
|
+
email: String!
|
|
315
|
+
password: String!
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
# Cursor-based pagination
|
|
319
|
+
type UserConnection {
|
|
320
|
+
edges: [UserEdge!]!
|
|
321
|
+
pageInfo: PageInfo!
|
|
322
|
+
totalCount: Int!
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## OpenAPI / Swagger Dokümantasyonu
|
|
329
|
+
|
|
330
|
+
### Temel Yapı (YAML)
|
|
331
|
+
|
|
332
|
+
```yaml
|
|
333
|
+
openapi: 3.1.0
|
|
334
|
+
info:
|
|
335
|
+
title: [Proje Adı] API
|
|
336
|
+
version: 1.0.0
|
|
337
|
+
description: |
|
|
338
|
+
[API açıklaması]
|
|
339
|
+
|
|
340
|
+
servers:
|
|
341
|
+
- url: http://localhost:3000/api
|
|
342
|
+
description: Development
|
|
343
|
+
- url: https://api.example.com
|
|
344
|
+
description: Production
|
|
345
|
+
|
|
346
|
+
components:
|
|
347
|
+
securitySchemes:
|
|
348
|
+
bearerAuth:
|
|
349
|
+
type: http
|
|
350
|
+
scheme: bearer
|
|
351
|
+
bearerFormat: JWT
|
|
352
|
+
|
|
353
|
+
schemas:
|
|
354
|
+
User:
|
|
355
|
+
type: object
|
|
356
|
+
required: [id, name, email, role]
|
|
357
|
+
properties:
|
|
358
|
+
id:
|
|
359
|
+
type: string
|
|
360
|
+
format: uuid
|
|
361
|
+
name:
|
|
362
|
+
type: string
|
|
363
|
+
minLength: 1
|
|
364
|
+
maxLength: 100
|
|
365
|
+
email:
|
|
366
|
+
type: string
|
|
367
|
+
format: email
|
|
368
|
+
role:
|
|
369
|
+
type: string
|
|
370
|
+
enum: [admin, user, guest]
|
|
371
|
+
|
|
372
|
+
Error:
|
|
373
|
+
type: object
|
|
374
|
+
required: [code, message]
|
|
375
|
+
properties:
|
|
376
|
+
code:
|
|
377
|
+
type: string
|
|
378
|
+
message:
|
|
379
|
+
type: string
|
|
380
|
+
details:
|
|
381
|
+
type: object
|
|
382
|
+
|
|
383
|
+
paths:
|
|
384
|
+
/users:
|
|
385
|
+
get:
|
|
386
|
+
summary: Kullanıcı listesi
|
|
387
|
+
security:
|
|
388
|
+
- bearerAuth: []
|
|
389
|
+
parameters:
|
|
390
|
+
- in: query
|
|
391
|
+
name: page
|
|
392
|
+
schema:
|
|
393
|
+
type: integer
|
|
394
|
+
minimum: 1
|
|
395
|
+
default: 1
|
|
396
|
+
- in: query
|
|
397
|
+
name: limit
|
|
398
|
+
schema:
|
|
399
|
+
type: integer
|
|
400
|
+
minimum: 1
|
|
401
|
+
maximum: 100
|
|
402
|
+
default: 20
|
|
403
|
+
responses:
|
|
404
|
+
'200':
|
|
405
|
+
description: Başarılı
|
|
406
|
+
content:
|
|
407
|
+
application/json:
|
|
408
|
+
schema:
|
|
409
|
+
type: object
|
|
410
|
+
properties:
|
|
411
|
+
data:
|
|
412
|
+
type: array
|
|
413
|
+
items:
|
|
414
|
+
$ref: '#/components/schemas/User'
|
|
415
|
+
meta:
|
|
416
|
+
$ref: '#/components/schemas/PaginationMeta'
|
|
417
|
+
'401':
|
|
418
|
+
$ref: '#/components/responses/Unauthorized'
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## API Versiyonlama Stratejisi
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
Versiyonlama yöntemleri:
|
|
427
|
+
|
|
428
|
+
1. URL prefix (önerilen — en açık)
|
|
429
|
+
/api/v1/users
|
|
430
|
+
/api/v2/users
|
|
431
|
+
|
|
432
|
+
2. Header (temiz URL, karmaşık routing)
|
|
433
|
+
Accept: application/vnd.api+json;version=2
|
|
434
|
+
|
|
435
|
+
3. Query parameter (öneri değil — cache sorunları)
|
|
436
|
+
/api/users?version=2
|
|
437
|
+
|
|
438
|
+
Kural:
|
|
439
|
+
- Breaking change → yeni major versiyon (v2)
|
|
440
|
+
- Geri uyumlu ekleme → aynı versiyonda
|
|
441
|
+
- Eski versiyon → deprecation uyarısı + sunset tarihi
|
|
442
|
+
- En az iki major versiyon paralel desteklenmeli
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Çıktı Formatı
|
|
448
|
+
|
|
449
|
+
1. **Endpoint tablosu** — Method, path, açıklama, auth gereksinimleri
|
|
450
|
+
2. **Request/Response şemaları** — Zod veya TypeScript tiplemesiyle
|
|
451
|
+
3. **HTTP status code haritası** — Her endpoint için beklenen response'lar
|
|
452
|
+
4. **OpenAPI taslağı** — YAML formatında (isteğe bağlı)
|
|
453
|
+
5. **Örnek istekler** — curl veya fetch ile test edilebilir örnekler
|
|
454
|
+
6. **Tasarım kararları** — Neden bu yapı seçildi, alternatifleri neydi
|