@gleissonneves/liz-api-client
v1.3.3
Published
Cliente HTTP baseado em fetch, com suporte a interceptadores, retry automático, timeout e tratamento de erros.
Maintainers
Readme
liz-api-client
Cliente HTTP moderno e extensível baseado em fetch, com suporte a interceptadores, retry automático, timeout configurável e tratamento de erros avançado.
Sumário
- Recursos
- Instalação
- Uso básico
- Métodos disponíveis
- Formato de resposta
- Tratamento de erros
- Interceptadores
- Configurações do construtor
- Classe ApiError
- Uso avançado
- Roadmap
- Contribuindo
- Licença
✨ Recursos
- Base URL configurável por instância
- Timeout nativo por requisição (com
AbortController) - Retry automático em erros de rede (configurável)
- Interceptadores de request, response e erro
- Classe
ApiErrorpara erros HTTP estruturados - Parsing automático de JSON e texto
- Query params em requisições GET com valores nulos ignorados
- Suporte ao método PATCH
- Extensível para middlewares e caching
📦 Instalação
npm install @gleissonneves/liz-api-client🚀 Uso básico
import { Api } from '@gleissonneves/liz-api-client';
const api = new Api({
baseUrl: 'https://api.meuservico.com',
timeout: 10000, // padrão: 15000 ms
maxRetries: 2, // padrão: 0
});📖 Métodos disponíveis
get(endpoint, queryParams?, config?)
const { data } = await api.get('/usuarios', { ativo: true, pagina: 1 });
console.log(data);post(endpoint, body?, config?)
const { data } = await api.post('/usuarios', {
nome: 'João',
email: '[email protected]',
});put(endpoint, body?, config?)
await api.put('/usuarios/42', { nome: 'João Silva' });patch(endpoint, body?, config?)
await api.patch('/usuarios/42', { ativo: false });delete(endpoint, config?)
await api.delete('/usuarios/42');setInterceptors({ request?, response?, error? })
Registra interceptadores globais. Veja a seção Interceptadores.
📬 Formato de resposta
Todos os métodos resolvem com um objeto no seguinte formato:
| Campo | Tipo | Descrição |
| ---------- | ------------------ | ------------------------------------- |
| data | object \| string | Corpo da resposta (JSON ou texto) |
| status | number | Código HTTP |
| ok | boolean | true se status entre 200–299 |
| headers | Headers | Cabeçalhos da resposta |
| response | Response | Objeto Response original do fetch |
⚠️ Tratamento de erros
Respostas com status fora de 2xx lançam uma instância de ApiError:
import { Api, ApiError } from '@gleissonneves/liz-api-client';
try {
const { data } = await api.get('/protegido');
} catch (error) {
if (error instanceof ApiError) {
console.error(`Erro ${error.status}:`, error.data);
} else {
console.error('Erro inesperado:', error);
}
}Erros de timeout são lançados com status 408.
🔥 Interceptadores
Use setInterceptors para adicionar lógica transversal às requisições.
api.setInterceptors({
request: async (config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
response: async (response) => {
// Manipule a resposta antes de ela chegar ao chamador
return response;
},
error: async (error) => {
// Centralize o tratamento de erros
if (error instanceof ApiError && error.status === 401) {
// redirecionar para login, por exemplo
}
throw error;
},
});⚙️ Configurações do construtor
| Propriedade | Tipo | Descrição | Padrão |
| ------------ | -------- | ------------------------------------------------ | ---------------------------------------- |
| baseUrl | string | URL base prefixada em todos os endpoints | '' |
| timeout | number | Tempo limite em ms antes de abortar a requisição | 15000 |
| maxRetries | number | Tentativas extras em erros de rede | 0 |
| headers | object | Cabeçalhos padrão mesclados em cada requisição | { 'Content-Type': 'application/json' } |
maxRetriespode ser sobrescrito por requisição viaconfig.maxRetries.
🧩 Classe ApiError
Todos os erros HTTP são lançados como ApiError extends Error.
| Atributo | Tipo | Descrição |
| ---------- | ------------------ | -------------------------- |
| status | number | Código HTTP da resposta |
| data | object \| string | Corpo da resposta |
| response | Response \| null | Objeto Response original |
🔬 Uso avançado
Singleton com autenticação
Em aplicações reais, é comum exportar uma instância única configurada com interceptadores de autenticação. O exemplo abaixo mostra um padrão de singleton com injeção de token e tenant header, e tratamento centralizado de sessão expirada.
// src/api/index.js
import { Api, ApiError } from '@gleissonneves/liz-api-client';
export { Api };
const apiInstance = new Api({
baseUrl: 'https://api.meuservico.com',
credentials: 'include',
});
apiInstance.setInterceptors({
request: async (config) => {
const token = localStorage.getItem('token');
config.headers = {
...config.headers,
...(token && { Authorization: `Bearer ${token}` }),
};
return config;
},
response: async (res) => res,
error: async (error) => {
if (error instanceof ApiError && error.status === 401) {
// Dispara logout global sem acoplamento direto ao roteador
window.dispatchEvent(new Event('auth:logout'));
}
throw error;
},
});
export { apiInstance };// Em qualquer módulo da aplicação — sem recriar instâncias
import { apiInstance } from '@/api';
const { data } = await apiInstance.get('/usuarios');Por que singleton?
- Garante que interceptadores (token, tenant) sejam aplicados em todas as requisições sem configuração repetida.
- Evita múltiplas instâncias com estados de interceptador divergentes.
- Centraliza o ponto de logout por sessão expirada (
auth:logout), desacoplando a lógica de autenticação dos componentes.
🛡️ Roadmap
- [ ] Cache de respostas (Cache-First / stale-while-revalidate)
- [ ] Middlewares encadeáveis (
use(middleware)) - [ ] Retentativas inteligentes baseadas em tipo de erro (
retryIf) - [ ] Upload progress (
onUploadProgress)
🤝 Contribuindo
- Faça um fork do repositório
- Crie uma branch:
git checkout -b feat/minha-feature - Faça commits seguindo o Conventional Commits
- Abra um Pull Request
Bugs e sugestões: issues
📄 Licença
MIT © Gleisson Neves
