import { buildApiUrl } from '@/constants/Api'; import AsyncStorage from '@react-native-async-storage/async-storage'; type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; let inMemoryToken: string | null = null; export async function setAuthToken(token: string | null): Promise { inMemoryToken = token; } export function getAuthToken(): string | null { return inMemoryToken; } export type ApiRequestOptions = { method?: HttpMethod; headers?: Record; body?: any; signal?: AbortSignal; }; export type ApiResponse = { data: T; }; async function doFetch(path: string, options: ApiRequestOptions = {}): Promise { const url = buildApiUrl(path); const headers: Record = { 'Content-Type': 'application/json', ...(options.headers || {}), }; const token = getAuthToken(); if (token) { headers['Authorization'] = `Bearer ${token}`; } const response = await fetch(url, { method: options.method ?? 'GET', headers, body: options.body != null ? JSON.stringify(options.body) : undefined, signal: options.signal, }); const text = await response.text(); let json: any = null; try { json = text ? JSON.parse(text) : null; } catch { // 非 JSON 响应 } if (!response.ok) { const errorMessage = (json && (json.message || json.error)) || `HTTP ${response.status}`; const error = new Error(errorMessage); // @ts-expect-error augment error.status = response.status; throw error; } // 支持后端返回 { data: ... } 或直接返回对象 return (json && (json.data ?? json)) as T; } export const api = { get: (path: string, options?: ApiRequestOptions) => doFetch(path, { ...options, method: 'GET' }), post: (path: string, body?: any, options?: ApiRequestOptions) => doFetch(path, { ...options, method: 'POST', body }), put: (path: string, body?: any, options?: ApiRequestOptions) => doFetch(path, { ...options, method: 'PUT', body }), patch: (path: string, body?: any, options?: ApiRequestOptions) => doFetch(path, { ...options, method: 'PATCH', body }), delete: (path: string, options?: ApiRequestOptions) => doFetch(path, { ...options, method: 'DELETE' }), }; export const STORAGE_KEYS = { authToken: '@auth_token', userProfile: '@user_profile', } as const; export async function loadPersistedToken(): Promise { try { const t = await AsyncStorage.getItem(STORAGE_KEYS.authToken); return t || null; } catch { return null; } }