gabrielb 8b5c37abe9
All checks were successful
Dev Build & Deploy Portal / build-deploy (push) Successful in 2m30s
feat(api): adicionar tratamento de erros e logging nas requisições
2026-05-19 20:58:14 -03:00

52 lines
2.0 KiB
TypeScript

import type { FetchOptions } from 'ofetch'
/**
* Wrapper para chamadas autenticadas ao core-api via BFF proxy.
*
* - Todas as requests passam por `/api/proxy/**` (que injeta Bearer + tenant headers no server)
* - Headers CSRF (`X-Requested-With: fetch`) sempre injetados — exigido pelo middleware do BFF em mutating methods
*
* Uso típico:
* const api = useApi()
* const debitos = await api.get<DebitoDTO[]>('portal/contribuinte/debitos')
* const novo = await api.post<DebitoDTO>('portal/contribuinte/debitos', payload)
*/
export function useApi() {
function buildUrl(path: string): string {
const clean = path.startsWith('/') ? path : `/${path}`
return `/api/proxy${clean}`
}
async function request<T>(path: string, options: FetchOptions = {}): Promise<T> {
try {
return await $fetch<T>(buildUrl(path), {
...options,
headers: {
'X-Requested-With': 'fetch',
...(options.headers ?? {}),
},
})
} catch (err: unknown) {
if (import.meta.dev) {
const e = err as { status?: number; data?: unknown }
console.error(`[api] ${(options.method ?? 'GET').toUpperCase()} ${path}${e.status}`, e.data)
}
throw err
}
}
return {
request,
get: <T>(path: string, opts?: FetchOptions) =>
request<T>(path, { ...opts, method: 'GET' }),
post: <T>(path: string, body?: unknown, opts?: FetchOptions) =>
request<T>(path, { ...opts, method: 'POST', body }),
put: <T>(path: string, body?: unknown, opts?: FetchOptions) =>
request<T>(path, { ...opts, method: 'PUT', body }),
patch: <T>(path: string, body?: unknown, opts?: FetchOptions) =>
request<T>(path, { ...opts, method: 'PATCH', body }),
delete: <T>(path: string, opts?: FetchOptions) =>
request<T>(path, { ...opts, method: 'DELETE' }),
}
}