47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
// Wrapper sobre $fetch que injeta o Authorization header automaticamente.
|
|
// Em caso de 401, tenta renovar o token via refresh e repete a requisição.
|
|
export function useApi() {
|
|
const { public: { apiBase } } = useRuntimeConfig()
|
|
const token = useCookie<string | null>('auth_token')
|
|
const refreshToken = useCookie<string | null>('refresh_token')
|
|
|
|
async function tryRefresh(): Promise<boolean> {
|
|
if (!refreshToken.value) return false
|
|
try {
|
|
const res = await $fetch<{ access_token: string; refresh_token: string }>(
|
|
`${apiBase}/auth/refresh`,
|
|
{ method: 'POST', body: { refresh_token: refreshToken.value } }
|
|
)
|
|
token.value = res.access_token
|
|
refreshToken.value = res.refresh_token
|
|
return true
|
|
} catch {
|
|
token.value = null
|
|
refreshToken.value = null
|
|
navigateTo('/login')
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function apiFetch<T>(path: string, options: Parameters<typeof $fetch>[1] = {}): Promise<T> {
|
|
const doFetch = () => $fetch<T>(`${apiBase}${path}`, {
|
|
...options,
|
|
headers: {
|
|
...(options.headers as Record<string, string> || {}),
|
|
...(token.value ? { Authorization: `Bearer ${token.value}` } : {}),
|
|
},
|
|
})
|
|
|
|
try {
|
|
return await doFetch()
|
|
} catch (err: any) {
|
|
if (err?.status === 401 && await tryRefresh()) {
|
|
return await doFetch()
|
|
}
|
|
throw err
|
|
}
|
|
}
|
|
|
|
return { apiFetch }
|
|
}
|