import type { Resp } from '@/types' export async function useFetchJson(url: string, opt?: RequestInit): Promise> { const prefix = import.meta.env.VITE_API_URL ?? '' const urlFull = join(prefix, url) const headers = new Headers(opt?.headers) if (!headers.has('Content-Type')) { headers.set('Content-Type', 'application/json') } const fetchOptions: RequestInit = { ...opt, headers, // Always include cookies so the backend can read the HTTPOnly access_token credentials: 'same-origin', } try { const res = await fetch(urlFull, fetchOptions) const contentType = res.headers.get('content-type') ?? '' if (!contentType.includes('application/json')) { throw { message: 'this is not proper json format' } as Resp } const data = await res.json() // Handle 401 — access token expired; try to refresh via the HTTPOnly refresh_token cookie if (res.status === 401) { const { useAuthStore } = await import('@/stores/user/auth') const authStore = useAuthStore() const refreshed = await authStore.refreshAccessToken() if (refreshed) { // Retry the original request — cookies are updated by the refresh endpoint const retryRes = await fetch(urlFull, fetchOptions) const retryContentType = retryRes.headers.get('content-type') ?? '' if (!retryContentType.includes('application/json')) { throw { message: 'this is not proper json format' } as Resp } const retryData = await retryRes.json() if (!retryRes.ok) { throw retryData as Resp } return retryData as Resp } // Refresh failed — logout and propagate the error authStore.logout() throw data as Resp } if (!res.ok) { throw data as Resp } return data as Resp } catch (error) { throw error as Resp } } export function join(...parts: string[]): string { const path = parts .filter(Boolean) .join('/') .replace(/\/{2,}/g, '/') return path.startsWith('/') ? path : `/${path}` }