/** * Auth API client for login, register, me, refresh. * Uses NEXT_PUBLIC_BASE_API_URL on client (defaults to same as BASE_API_URL for server). */ const getBaseUrl = () => typeof window !== "undefined" ? process.env.NEXT_PUBLIC_BASE_API_URL ?? "http://127.0.0.1:8080" : process.env.BASE_API_URL ?? process.env.NEXT_PUBLIC_BASE_API_URL ?? "http://127.0.0.1:8080"; const API_PREFIX = "/api/v1/auth"; export interface AuthUser { id: number; email: string; first_name: string; last_name: string; username?: string; is_admin: boolean; email_verified?: boolean; } export interface LoginResponse { access_token: string; refresh_token: string; user: AuthUser; } export interface RegisterResponse { message: string; user: AuthUser; } export interface RefreshResponse { access_token: string; refresh_token: string; } /** POST /api/v1/auth/login – doğrudan backend (token client’ta; cookie için loginViaCookie kullanın) */ export async function login( email: string, password: string ): Promise { const base = getBaseUrl(); const res = await fetch(`${base}${API_PREFIX}/login`, { method: "POST", headers: { "Content-Type": "application/json", accept: "application/json" }, body: JSON.stringify({ email, password }), }); if (!res.ok) { const err = await res.json().catch(() => ({})); throw new Error((err as { detail?: string }).detail ?? "Giriş başarısız"); } return res.json(); } /** Cookie tabanlı giriş – token’lar HTTP-only secure cookie’de saklanır */ export async function loginViaCookie( email: string, password: string ): Promise<{ user: AuthUser }> { const res = await fetch("/api/auth/cookie-login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: email.trim(), password }), credentials: "include", }); const data = await res.json().catch(() => ({})); if (!res.ok) { throw new Error((data as { error?: string }).error ?? "Giriş başarısız"); } return data as { user: AuthUser }; } /** Cookie tabanlı çıkış */ export async function logoutViaCookie(): Promise { await fetch("/api/auth/cookie-logout", { method: "POST", credentials: "include", }); } /** Cookie oturumunu kontrol et (client tarafında oturum bilgisi için) */ export async function getCookieSession(): Promise<{ loggedIn: boolean; user?: AuthUser; }> { const res = await fetch("/api/auth/cookie-session", { credentials: "include" }); const data = await res.json().catch(() => ({ loggedIn: false })); return data as { loggedIn: boolean; user?: AuthUser }; } /** POST /api/v1/auth/register */ export async function register(body: { email: string; first_name: string; last_name: string; password: string; username: string; }): Promise { const base = getBaseUrl(); const res = await fetch(`${base}${API_PREFIX}/register`, { method: "POST", headers: { "Content-Type": "application/json", accept: "application/json" }, body: JSON.stringify(body), }); if (!res.ok) { const err = await res.json().catch(() => ({})); const detail = (err as { detail?: string | string[] }).detail; const message = Array.isArray(detail) ? detail.join(" ") : detail ?? "Kayıt başarısız"; throw new Error(message); } return res.json(); } /** GET /api/v1/auth/me */ export async function me(accessToken: string): Promise<{ user: AuthUser }> { const base = getBaseUrl(); const res = await fetch(`${base}${API_PREFIX}/me`, { headers: { accept: "application/json", Authorization: `Bearer ${accessToken}`, }, }); if (!res.ok) throw new Error("Oturum bilgisi alınamadı"); return res.json(); } /** POST /api/v1/auth/refresh */ export async function refresh(refreshToken: string): Promise { const base = getBaseUrl(); const res = await fetch(`${base}${API_PREFIX}/refresh`, { method: "POST", headers: { "Content-Type": "application/json", accept: "application/json" }, body: JSON.stringify({ refresh_token: refreshToken }), }); if (!res.ok) throw new Error("Token yenilenemedi"); return res.json(); } const ACCESS_KEY = "auth_access_token"; const REFRESH_KEY = "auth_refresh_token"; const AUTH_CHANGE_EVENT = "auth-change"; /** Header vb. bileşenlerin oturum değişikliğini algılaması için tetiklenir. */ export function notifyAuthChange(): void { if (typeof window === "undefined") return; window.dispatchEvent(new Event(AUTH_CHANGE_EVENT)); } export function setTokens(access: string, refreshToken: string): void { if (typeof window === "undefined") return; localStorage.setItem(ACCESS_KEY, access); localStorage.setItem(REFRESH_KEY, refreshToken); notifyAuthChange(); } export function getAccessToken(): string | null { if (typeof window === "undefined") return null; return localStorage.getItem(ACCESS_KEY); } export function getRefreshToken(): string | null { if (typeof window === "undefined") return null; return localStorage.getItem(REFRESH_KEY); } export function clearTokens(): void { if (typeof window === "undefined") return; localStorage.removeItem(ACCESS_KEY); localStorage.removeItem(REFRESH_KEY); notifyAuthChange(); } export { AUTH_CHANGE_EVENT };