Files
kakeibo/frontend/src/lib/query.ts
T

73 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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,
registration: ['registration'] 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,
/** Dönem listesi; `currentPeriod` da bu önekle başlar (birlikte yenilenir) */
periods: ['periods'] as const,
currentPeriod: ['periods', 'current'] as const,
/** Panel: son dönemler + toplam birikim (dönem listesiyle birlikte yenilenir) */
stats: ['periods', 'stats'] as const,
/** Bir döneme bağlı tüm veriler bu önekle başlar → `invalidateQueries({ queryKey: period(id) })` */
/** Birikimler: portföy ve varlık işlemleri bu önekle başlar (birlikte yenilenir) */
portfolio: ['portfolio'] as const,
assetTxs: (assetId: string) => ['portfolio', 'txs', assetId] as const,
pendingSavings: ['portfolio', 'pending'] as const,
/** Rapor kırılımı (`query` = sunucu sorgu metni); kayıt değişince `reports` öneki yenilenir */
reportBreakdown: (query: string) => ['reports', 'breakdown', query] as const,
reports: ['reports'] as const,
/** JSON yedeği: son yedek zamanı + geri dönüş noktaları */
backup: ['backup'] as const,
period: (id: string) => ['period', id] as const,
planItems: (id: string) => ['period', id, 'plan-items'] as const,
summary: (id: string) => ['period', id, 'summary'] as const,
review: (id: string) => ['period', id, 'review'] as const,
/** Panel grafiği: günlük harcama (kayıt değişince dönem önekiyle yenilenir) */
daily: (id: string) => ['period', id, 'daily'] as const,
/** Aylık değerlendirme raporu (Markdown); kayıt değişince dönem önekiyle yenilenir */
monthlyReport: (id: string) => ['period', id, 'report'] as const,
budget: (id: string) => ['period', id, 'budget'] as const,
suggestion: (id: string, method: string) => ['period', id, 'suggestion', method] as const,
notes: (id: string, context: string) => ['period', id, 'notes', context] as const,
/** Harcamalar; `range` verilmezse tüm dönem (`entries(id)` → tüm aralıkların öneki) */
entries: (id: string, range?: { from: string; to: string }) =>
range ? (['period', id, 'entries', range] as const) : (['period', id, 'entries'] 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,
},
},
})