feat(arayüz): API istemcisi, TanStack Query, ts-rs tip üretimi ve oturum durumu
- Backend: ts-rs ile DTO'lardan TypeScript tipleri (frontend/src/types, npm run types) - Hata ve health yanıtları tipli yapılara çevrildi - lib/api.ts: tek API istemcisi, Türkçe ApiError, ağ hatası mesajı - lib/query.ts: QueryClient (4xx tekrar denenmez, 401 → oturum kapanır) - lib/auth.ts: useMe, useLogin, useRegister, useLogout - Vitest: 7 API istemcisi testi (toplam 29) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* TanStack Query ayarları: sunucu verisinin önbelleği, yeniden deneme, yenileme.
|
||||
*/
|
||||
import { QueryCache, QueryClient } from '@tanstack/react-query'
|
||||
import { ApiError } from './api'
|
||||
|
||||
/** Önbellek anahtarları tek yerde (yazım hatası olmasın) */
|
||||
export const queryKeys = {
|
||||
me: ['me'] as const,
|
||||
health: ['health'] as const,
|
||||
household: ['household'] as const,
|
||||
categories: (includeInactive = false) => ['categories', { includeInactive }] as const,
|
||||
paymentMethods: (includeInactive = false) => ['payment-methods', { includeInactive }] as const,
|
||||
}
|
||||
|
||||
/** 4xx hataları tekrar denemenin anlamı yok (yanlış istek / yetki); ağ ve 5xx için 2 kez dene. */
|
||||
function shouldRetry(failureCount: number, error: unknown) {
|
||||
if (error instanceof ApiError && error.status >= 400 && error.status < 500) return false
|
||||
return failureCount < 2
|
||||
}
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
queryCache: new QueryCache({
|
||||
onError: (error) => {
|
||||
// Herhangi bir istek 401 alırsa oturum bitmiş demektir → "me" boşaltılır,
|
||||
// korumalı sayfalar (Adım 4) kullanıcıyı giriş ekranına yönlendirir.
|
||||
if (error instanceof ApiError && error.isUnauthorized) {
|
||||
queryClient.setQueryData(queryKeys.me, null)
|
||||
}
|
||||
},
|
||||
}),
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
retry: shouldRetry,
|
||||
staleTime: 30_000, // 30 sn içinde aynı veri tekrar istenmez
|
||||
refetchOnWindowFocus: true, // sekmeye dönünce güncel veri (ör. eşin eklediği harcama)
|
||||
},
|
||||
mutations: {
|
||||
retry: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user