Pular para o conteúdo principal

@cactus-agents/api-client

HTTP client framework-agnostic baseado em fetch. Gerencia headers de tenant, idioma, autorização e callbacks de erro.

Instalação

pnpm add @cactus-agents/api-client

Uso básico

import { createApiClient } from '@cactus-agents/api-client';

const client = createApiClient({
baseUrl: 'https://api.example.com/v2',
tenant: 'my-tenant',
language: 'pt-br',
});

const response = await client.get<MyData>('/endpoint');
// response.data, response.status, response.headers

ApiClientConfig

interface ApiClientConfig {
baseUrl: string; // URL base da API
tenant: string; // Header tenant
language: string; // Idioma fallback

// Opcionais
buildId?: string; // ID do build
debug?: boolean; // Habilita header DEBUG

// Callbacks de dados
getAccessToken?: () => string | null;
getLocale?: () => string;
getOriginAccess?: () => OriginAccess;
getReferrerInfo?: () => ReferrerInfo | null;
getExtraHeaders?: () => Record<string, string>;

// Hooks de erro
onUnauthorized?: (url: string) => void; // 401
onChallenge?: () => void; // 429
onTimeoutLimit?: (url: string) => void; // 202
}

Métodos

MétodoDescrição
get<T>(path, options?)GET com headers internos
post<T>(path, body?, options?)POST com headers internos
put<T>(path, body?, options?)PUT com headers internos
patch<T>(path, body?, options?)PATCH com headers internos
delete<T>(path, options?)DELETE com headers internos
getExternal<T>(url, options?)GET para URLs externas (sem headers internos)

Headers automáticos

Em toda request interna, o client adiciona:

  • tenant — valor do config
  • lang / language — do getLocale() ou fallback
  • version — buildId
  • origin-domain — hostname
  • X-LOG-INFO — JSON com metadata
  • Authorization: Bearer {token} — se getAccessToken() retorna token
  • X-ORIGIN-ACCESS — se getOriginAccess() retorna valor

Tratamento de status

StatusComportamento
200-299Resolve com ApiResponse<T>
202Resolve (não throw) + chama onTimeoutLimit
401Chama onUnauthorized + throw
429Chama onChallenge + throw
Outros non-okThrow

ApiResponse

interface ApiResponse<T> {
data: T;
status: number;
statusText: string;
headers: Headers;
}

OriginAccess

enum OriginAccess {
Unknown,
App,
Desktop,
DesktopApp,
Mobile,
MobileApp,
}

Helpers

O pacote exporta helpers de conveniência para quem consome o ApiClient junto com outros pacotes do SDK.

createFetcherFromClient(client)

Converte um ApiClient (ou qualquer objeto com get/post que retorna { data }) no formato de fetcher plano esperado por @cactus-agents/auth e @cactus-agents/brand:

import { createApiClient, createFetcherFromClient } from '@cactus-agents/api-client';
import { createAuthService } from '@cactus-agents/auth';

const client = createApiClient({ baseUrl, tenant, language });
const fetcher = createFetcherFromClient(client);
const auth = createAuthService(fetcher);

Na maioria dos casos, prefira usar createAuthFromClient ou createBrandFromClient diretamente — eles fazem essa conversão internamente.

createFullFetcherFromClient(client)

Versão estendida do createFetcherFromClient que expõe todos os 5 métodos HTTP (get, post, put, patch, delete). Usado por pacotes que precisam de mais do que get/post, como @cactus-agents/user:

import { createApiClient, createFullFetcherFromClient } from '@cactus-agents/api-client';
import { createUserService } from '@cactus-agents/user';

const client = createApiClient({ baseUrl, tenant, language });
const fetcher = createFullFetcherFromClient(client);
const user = createUserService(fetcher);

Na maioria dos casos, prefira usar createUserFromClient diretamente — ele faz essa conversão internamente.

extractApiError(err)

Normaliza erros do ApiClient (que não são instâncias de Error) em uma estrutura consistente para logging e respostas HTTP:

import { extractApiError } from '@cactus-agents/api-client';

try {
await client.post('/endpoint', body);
} catch (err) {
const { status, data, message, isApiError } = extractApiError(err);
// status: number | undefined
// data: response body (se API error)
// message: string (para logging)
// isApiError: boolean
}

Tipos

interface ClientLike {
get<T>(path: string): Promise<{ data: T }>;
post<T>(path: string, body?: unknown): Promise<{ data: T }>;
}

interface FullClientLike extends ClientLike {
put<T>(path: string, payload?: unknown): Promise<{ data: T }>;
patch<T>(path: string, payload?: unknown): Promise<{ data: T }>;
delete<T>(path: string, payload?: unknown): Promise<{ data: T }>;
}

interface ExtractedApiError {
status: number | undefined;
data: unknown;
message: string;
isApiError: boolean;
}