Cliente HTTP para requisições API com tratamento de erros e respostas padronizadas.
# NPM
npm install @wmmz/fn-api-client
# Yarn
yarn add @wmmz/fn-api-client
# PNPM
pnpm add @wmmz/fn-api-client
✨ Principais Características :
🔄 Tratamento padronizado de erros
📝 Tipagem forte com TypeScript
🎯 Callbacks para sucesso e erro
🌐 Suporte a REST e GraphQL
⚡ Integração com Cube
⏱️ Timeout configurável
🔑 Headers customizáveis
📦 Zero dependências extras
import { ApiClient } from '@wmmz/fn-api-client' ;
// Configuração do cliente
const client = new ApiClient ( {
baseURL : 'https://api.exemplo.com' ,
timeout : 5000 ,
headers : {
'Authorization' : 'Bearer seu-token'
}
} ) ;
// Interceptador para adicionar token dinâmico
client . addRequestInterceptor ( ( config ) => {
const tokens = storage . getTokens ( ) ;
if ( tokens ?. accessToken ) {
config . headers = {
...config . headers ,
Authorization : `Bearer ${ tokens . accessToken } `
} ;
}
return config ;
} ) ;
// Interceptador para refresh token automático
client . addErrorInterceptor ( async ( error ) => {
if ( error . status === 401 ) {
await refreshToken ( ) ;
return {
data : { message : 'Token renovado' } ,
status : 200 ,
message : 'Autenticação renovada'
} ;
}
return error ;
} ) ;
// GET com tipagem
interface Usuario {
id : number ;
nome : string ;
email : string ;
}
client . get < Usuario > ( '/usuarios/1' , {
onSuccess : ( response ) => {
console . log ( 'Dados:' , response . data ) ;
console . log ( 'Status:' , response . status ) ;
console . log ( 'Mensagem:' , response . message ) ;
} ,
onError : ( error ) => {
console . error ( 'Erro:' , error . message ) ;
console . error ( 'Status:' , error . status ) ;
console . error ( 'Detalhes:' , error . details ) ;
}
} ) ;
// POST com dados
const novoUsuario = {
nome : 'João Silva' ,
email : 'joao@exemplo.com'
} ;
client . post < Usuario > ( '/usuarios' , novoUsuario , {
onSuccess : ( response ) => console . log ( 'Criado:' , response . data ) ,
onError : ( error ) => console . error ( 'Erro:' , error . message )
} ) ;
// GET com parâmetros
client . get < UserVote > ( '/votos' , { userId : '123' , agendaId : '456' } , {
onSuccess : ( response ) => console . log ( 'Voto:' , response . data ) ,
onError : ( error ) => {
if ( error . status === 404 ) {
console . log ( 'Usuário não votou ainda' ) ;
}
}
} ) ;
import { GraphQLClient } from '@wmmz/fn-api-client' ;
const client = new GraphQLClient ( {
baseURL : 'https://api.exemplo.com/graphql' ,
headers : {
'Authorization' : 'Bearer seu-token'
}
} ) ;
// Query com variáveis
const query = `
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
posts {
id
title
}
}
}
` ;
client . query ( query , { id : '123' } , {
onSuccess : ( response ) => {
const user = response . data . user ;
console . log ( 'Usuário:' , user . name ) ;
console . log ( 'Posts:' , user . posts . length ) ;
} ,
onError : ( error ) => console . error ( 'Erro:' , error . message )
} ) ;
// Mutation
const mutation = `
mutation CreateUser($input: UserInput!) {
createUser(input: $input) {
id
name
email
}
}
` ;
const variables = {
input : {
name : 'João Silva' ,
email : 'joao@exemplo.com'
}
} ;
client . mutate ( mutation , variables , {
onSuccess : ( response ) => console . log ( 'Criado:' , response . data . createUser ) ,
onError : ( error ) => console . error ( 'Erro:' , error . message )
} ) ;
import { CubeGraphQLClient } from '@wmmz/fn-api-client' ;
const client = new CubeGraphQLClient ( {
baseURL : 'http://localhost:4000' ,
headers : {
'Authorization' : 'Bearer seu-token'
}
} ) ;
// Consulta com filtros e campos
await client . query ( '/cubejs-api/graphql' , {
limit : 20 ,
offset : 0 ,
where : {
vendas : {
total : { greaterThan : 1000 } ,
status : { in : [ 'APROVADA' , 'CONCLUIDA' ] }
} ,
cliente : {
tipo : { equals : 'PJ' }
}
} ,
fields : {
vendas : {
id : true ,
total : true ,
status : true
} ,
cliente : {
nome : true ,
tipo : true
}
}
} , {
onSuccess : ( response ) => console . log ( 'Dados:' , response . data ) ,
onError : ( error ) => console . error ( 'Erro:' , error . message )
} ) ;
1. Interceptadores para Autenticação
const client = new ApiClient ( {
baseURL : 'https://api.exemplo.com'
} ) ;
// Interceptador de requisição para token dinâmico
client . addRequestInterceptor ( ( config ) => {
const tokens = storage . getTokens ( ) ;
if ( tokens ?. accessToken ) {
config . headers = {
...config . headers ,
Authorization : `Bearer ${ tokens . accessToken } `
} ;
}
return config ;
} ) ;
// Interceptador de erro para refresh token automático
client . addErrorInterceptor ( async ( error ) => {
if ( error . status === 401 ) {
try {
const newTokens = await refreshToken ( ) ;
storage . setTokens ( newTokens ) ;
return {
data : { message : 'Token renovado automaticamente' } ,
status : 200 ,
message : 'Autenticação renovada com sucesso'
} ;
} catch ( refreshError ) {
return {
...error ,
message : 'Sessão expirada. Faça login novamente.'
} ;
}
}
return error ;
} ) ;
// Interceptador de resposta para logging
client . addResponseInterceptor ( ( response ) => {
console . log ( `✅ ${ response . status } : ${ response . message } ` ) ;
return response ;
} ) ;
const formData = new FormData ( ) ;
formData . append ( 'file' , file ) ;
client . post ( '/upload' , formData , {
headers : {
'Content-Type' : 'multipart/form-data'
} ,
onSuccess : ( response ) => console . log ( 'Upload concluído:' , response . data ) ,
onError : ( error ) => console . error ( 'Erro no upload:' , error . message )
} ) ;
3. Consultas Cube com Agregações
const client = new CubeGraphQLClient ( {
baseURL : 'http://localhost:4000'
} ) ;
await client . query ( '/cubejs-api/graphql' , {
where : {
vendas : {
data : { between : [ '2024-01-01' , '2024-12-31' ] }
}
} ,
fields : {
vendas : {
total_vendas : true ,
media_ticket : true ,
count_pedidos : true
}
}
} , {
onSuccess : ( response ) => console . log ( 'Métricas:' , response . data ) ,
onError : ( error ) => console . error ( 'Erro:' , error . message )
} ) ;
Método
Descrição
Parâmetros
constructor
Cria uma instância do cliente
config: ApiClientConfig
get
Realiza requisição GET
url: string, paramsOrCallbacks?: QueryParams | RequestCallbacks<T>, callbacks?: RequestCallbacks<T>
post
Realiza requisição POST
url: string, data: unknown, callbacks?: RequestCallbacks<T>
put
Realiza requisição PUT
url: string, data: unknown, callbacks?: RequestCallbacks<T>
delete
Realiza requisição DELETE
url: string, paramsOrCallbacks?: QueryParams | RequestCallbacks<T>, callbacks?: RequestCallbacks<T>
addRequestInterceptor
Adiciona interceptador de requisição
interceptor: RequestInterceptor
addResponseInterceptor
Adiciona interceptador de resposta
interceptor: ResponseInterceptor
addErrorInterceptor
Adiciona interceptador de erro
interceptor: ErrorInterceptor
removeRequestInterceptor
Remove interceptador de requisição
interceptor: RequestInterceptor
removeResponseInterceptor
Remove interceptador de resposta
interceptor: ResponseInterceptor
removeErrorInterceptor
Remove interceptador de erro
interceptor: ErrorInterceptor
clearInterceptors
Remove todos os interceptadores
void
Método
Descrição
Parâmetros
constructor
Cria uma instância do cliente GraphQL
config: GraphQLConfig
query
Executa uma query GraphQL
query: string, variables?: GraphQLVariables, callbacks?: RequestCallbacks<T>
mutate
Executa uma mutation GraphQL
mutation: string, variables?: GraphQLVariables, callbacks?: RequestCallbacks<T>
Método
Descrição
Parâmetros
constructor
Cria uma instância do cliente Cube
config: CubeGraphQLConfig
query
Executa uma query Cube
url: string, options?: CubeQueryOptions, callbacks?: RequestCallbacks<T>
interface ApiClientConfig {
baseURL : string ;
timeout ?: number ;
headers ?: Record < string , string > ;
}
interface GraphQLConfig extends ApiClientConfig { }
interface CubeGraphQLConfig extends ApiClientConfig { }
interface ApiResponse < T > {
data : T ;
status : number ;
message : string ;
}
interface ApiError {
message : string ;
status : number ;
code ?: string ;
details ?: unknown ;
}
interface RequestCallbacks < T > {
onSuccess ?: ( response : ApiResponse < T > ) => void ;
onError ?: ( error : ApiError ) => void ;
}
interface RequestConfig {
url ?: string ;
method ?: string ;
headers ?: Record < string , string > ;
data ?: unknown ;
params ?: Record < string , unknown > ;
timeout ?: number ;
}
interface QueryParams {
[ key : string ] : string | number | boolean | undefined ;
}
type RequestInterceptor = ( config : RequestConfig ) => RequestConfig ;
type ResponseInterceptor = < T > ( response : ApiResponse < T > ) => ApiResponse < T > ;
type ErrorInterceptor = ( error : ApiError ) => ApiError | Promise < ApiResponse < unknown > > ;
}
interface CubeQueryOptions {
limit ?: number ;
offset ?: number ;
where ?: CubeQueryWhere ;
fields ?: CubeQueryFields ;
defaultEntity ?: string ;
defaultFields ?: string [ ] ;
}
Fork o projeto
Crie sua branch (git checkout -b feature/AmazingFeature)
Commit suas mudanças (git commit -m 'feat: Adicionar nova funcionalidade')
Push para a branch (git push origin feature/AmazingFeature)
Abra um Pull Request
Changelog (em desenvolvimento | versão 1.0.1)