npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adatechnology/http-client

v0.0.2

Published

Este módulo fornece uma interface HTTP completa e flexível para fazer requisições HTTP em aplicações NestJS. Suporta tanto APIs Promise quanto Observable (RxJS), oferecendo máxima flexibilidade para diferentes casos de uso.

Downloads

198

Readme

HTTP Provider

Este módulo fornece uma interface HTTP completa e flexível para fazer requisições HTTP em aplicações NestJS. Suporta tanto APIs Promise quanto Observable (RxJS), oferecendo máxima flexibilidade para diferentes casos de uso.

Quick start

  1. Instale as dependências necessárias no monorepo (axios + rxjs):

Quick start

  1. Instale as dependências necessárias no monorepo (axios + rxjs):
pnpm add -w axios rxjs
  1. Configure o módulo no seu AppModule usando forRoot para fornecer uma instância Axios configurada (baseURL, timeout, headers etc.). O pacote publica o namespace @adatechnology/http-client.
import { Module } from "@nestjs/common";
import { HttpModule } from "@adatechnology/http-client";

@Module({
  imports: [
    // conveniência: importa a implementação Axios internamente
    HttpModule.forRoot({ baseURL: "https://api.example.com", timeout: 10000 }),
  ],
})
export class AppModule {}

Após isso, injete o provider padrão HTTP_PROVIDER no seu serviço:

import { Inject, Injectable } from "@nestjs/common";
import {
  HTTP_PROVIDER,
  HttpProviderInterface,
} from "@adatechnology/http-client";

@Injectable()
export class MeuServico {
  constructor(
    @Inject(HTTP_PROVIDER) private readonly http: HttpProviderInterface,
  ) {}

  async getUsers() {
    const res = await this.http.get("/users");
    return res.data;
  }
}

O pacote também exporta os tokens HTTP_AXIOS_PROVIDER e HTTP_AXIOS_CONNECTION caso precise da instância Axios original ou queira controlar a implementação diretamente. O módulo também exporta os tokens HTTP_AXIOS_PROVIDER e HTTP_AXIOS_CONNECTION caso precise da instância Axios original ou queira criar instâncias adicionais.

Implementation modules

A implementação específica (Axios) foi isolada em implementations/axios. Existem duas formas de usar o pacote:

  1. Usar o shim de conveniência HttpModule.forRoot(...) — já importa a implementação Axios internamente e registra o HTTP_PROVIDER:
// simples - importa a implementação Axios por baixo dos panos
imports: [HttpModule.forRoot({ baseURL: "https://api.example.com" })];
  1. Importar explicitamente o módulo de implementação quando precisar de controle fino ou quiser trocar de driver:
import { HttpImplementationAxiosModule } from "@adatechnology/http-client";

imports: [
  // registra a conexão e o provider Axios
  HttpImplementationAxiosModule.forRoot({ baseURL: "https://api.example.com" }),
  // registra o provider genérico que usa a implementação registrada
  HttpModule.forRoot(),
];

Nesse modo explícito, HttpImplementationAxiosModule.forRoot registra os tokens HTTP_AXIOS_CONNECTION (a instância Axios) e HTTP_AXIOS_PROVIDER (o provider baseado em Axios). O HttpModule registra apenas o HTTP_PROVIDER que delega à implementação registrada.

Use a forma explícita se for adicionar múltiplos drivers (fetch, node-http) no futuro — cada driver teria seu próprio implementations/* com forRoot.

Características

  • ✅ Suporte completo a todos os métodos HTTP (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
  • ✅ APIs duplas: Promise e Observable (RxJS)
  • ✅ Cache automático com TTL configurável
  • ✅ Invalidação de cache
  • ✅ Interceptors para tratamento de erros
  • ✅ Configuração de timeout, headers globais
  • ✅ Instâncias múltiplas com configurações diferentes
  • ✅ Tipagem TypeScript completa
  • ✅ Baseado em Axios (robusto e bem testado)

Instalação e Configuração

O provider HTTP já está integrado no sistema de providers do projeto. Para usar, basta injetar o HTTP_PROVIDER no seu serviço:

import { Inject, Injectable } from "@nestjs/common";
import {
  HTTP_PROVIDER,
  HttpProviderInterface,
} from "@modules/shared/infrastructure/providers/http";

@Injectable()
export class MeuServico {
  constructor(
    @Inject(HTTP_PROVIDER)
    private readonly httpProvider: HttpProviderInterface,
  ) {}
}

Exemplos de Uso

Requisições Básicas

GET Request

// Promise API
const response = await this.httpProvider.get<User[]>("/api/users");
console.log(response.data); // Array de usuários
console.log(response.status); // 200

// Observable API
this.httpProvider.get$<User[]>("/api/users").subscribe({
  next: (response) => console.log("Usuários:", response.data),
  error: (error) => console.error("Erro:", error),
  complete: () => console.log("Requisição completa"),
});

POST Request

const newUser = { name: "João", email: "[email protected]" };

// Promise API
const response = await this.httpProvider.post<User>("/api/users", newUser);
console.log("Usuário criado:", response.data);

// Observable API
this.httpProvider.post$<User>("/api/users", newUser).subscribe({
  next: (response) => console.log("Usuário criado:", response.data),
  error: (error) => console.error("Erro ao criar usuário:", error),
});

PUT/PATCH Request

const updatedUser = { name: "João Silva", email: "[email protected]" };

// PUT - substitui completamente o recurso
const putResponse = await this.httpProvider.put<User>(
  "/api/users/1",
  updatedUser,
);

// PATCH - atualiza parcialmente o recurso
const patchResponse = await this.httpProvider.patch<User>("/api/users/1", {
  name: "João Silva",
});

DELETE Request

// Promise API
await this.httpProvider.delete("/api/users/1");
console.log("Usuário deletado");

// Observable API
this.httpProvider.delete$("/api/users/1").subscribe({
  next: () => console.log("Usuário deletado"),
  error: (error) => console.error("Erro ao deletar:", error),
});

Cache

O provider inclui cache automático para requisições GET com limpeza automática de entradas expiradas. Por padrão, as respostas são cacheadas por 5 minutos e o cache é limpo automaticamente a cada 5 minutos.

// Requisição com cache (padrão)
const response1 = await this.httpProvider.get("/api/users");
const response2 = await this.httpProvider.get("/api/users"); // Retorna do cache

// Desabilitar cache para uma requisição específica
const response = await this.httpProvider.get("/api/users", { cache: false });

// Cache customizado (30 segundos)
const response = await this.httpProvider.get("/api/users", {
  cache: true,
  cacheTtl: 30000,
});

Invalidação de Cache

// Limpar cache específico
this.httpProvider.clearCache("/api/users");

// Limpar todo o cache
this.httpProvider.clearCache();

// Ver estatísticas do cache
const stats = this.httpProvider.getCacheStats();
console.log(`Cache tem ${stats.size} entradas`);

Configuração de Headers e Autenticação

Headers Personalizados

// Definir headers para todas as requisições
this.httpProvider.setHeaders({
  "X-API-Key": "your-api-key",
  "X-Custom-Header": "custom-value",
});

// Ou definir headers por requisição
const response = await this.httpProvider.get("/api/data", {
  headers: {
    Authorization: "Bearer token",
    "Content-Type": "application/json",
  },
});

Autenticação Bearer Token

// Definir token de autenticação (Bearer por padrão)
this.httpProvider.setAuthToken("your-jwt-token");

// Ou especificar tipo de token
this.httpProvider.setAuthToken("your-token", "Basic");

// Limpar token
this.httpProvider.clearAuthToken();

// Definir token de autenticação this.httpProvider.setAuthToken('your-jwt-token');

// Ou especificar o tipo de token this.httpProvider.setAuthToken('your-token', 'Basic');

// Remover token this.httpProvider.clearAuthToken();


### Timeout e Base URL

#### Configurar Timeout

```typescript
// Definir timeout global (30 segundos)
this.httpProvider.setTimeout(30000);

// Ou por requisição
const response = await this.httpProvider.get('/api/slow-endpoint', {
  timeout: 5000, // 5 segundos
});

Base URL

// Definir base URL para todas as requisições
this.httpProvider.setBaseURL("https://api.example.com");

// Agora as requisições são relativas
const users = await this.httpProvider.get<User[]>("/users"); // https://api.example.com/users
const posts = await this.httpProvider.get<Post[]>("/posts"); // https://api.example.com/posts

Interceptors

Request Interceptor

// Adicionar interceptor de request
const requestInterceptorId = this.httpProvider.addRequestInterceptor(
  (config) => {
    // Modificar config antes de enviar
    config.headers["X-Request-ID"] = generateRequestId();
    config.headers["X-Timestamp"] = Date.now().toString();
    return config;
  },
  (error) => {
    // Tratar erro na configuração da requisição
    console.error("Erro no request interceptor:", error);
    return Promise.reject(error);
  },
);

// Remover interceptor
this.httpProvider.removeRequestInterceptor(requestInterceptorId);

Response Interceptor

// Adicionar interceptor de response
const responseInterceptorId = this.httpProvider.addResponseInterceptor(
  (response) => {
    // Processar resposta antes de retornar
    console.log(
      `Request to ${response.config.url} took ${Date.now() - response.config.timestamp}ms`,
    );
    return response;
  },
  (error) => {
    // Tratar erros de resposta
    if (error.response?.status === 401) {
      // Token expirado - redirecionar para login
      this.authService.logout();
    }
    return Promise.reject(error);
  },
);

// Remover interceptor
this.httpProvider.removeResponseInterceptor(responseInterceptorId);

Requisições Customizadas

Usando o método request

// Requisição customizada com Promise
const response = await this.httpProvider.request<User>({
  method: "GET",
  url: "/api/users",
  params: { page: 1, limit: 10 },
  headers: { "Custom-Header": "value" },
});

// Com Observable
this.httpProvider
  .request$<User>({
    method: "POST",
    url: "/api/users",
    data: { name: "João", email: "[email protected]" },
  })
  .subscribe((response) => console.log(response.data));

Instâncias Múltiplas

Criar instância separada

// Criar instância com configuração específica
const apiClient = this.httpProvider.createInstance({
  baseURL: "https://external-api.com",
  timeout: 10000,
  headers: {
    Authorization: "Bearer external-token",
    "X-API-Version": "v2",
  },
});

// Usar a instância específica
const externalData = await apiClient.get("/data");

Tratamento de Erros

Com Promises

try {
  const response = await this.httpProvider.get("/api/users");
  console.log("Dados:", response.data);
} catch (error) {
  if (error.response) {
    // Erro da API (4xx, 5xx)
    console.error("Erro da API:", error.response.status, error.response.data);
  } else if (error.request) {
    // Erro de rede
    console.error("Erro de rede:", error.message);
  } else {
    // Outro erro
    console.error("Erro:", error.message);
  }
}

Com Observables

this.httpProvider.get$<User[]>("/api/users").subscribe({
  next: (response) => {
    console.log("Usuários carregados:", response.data);
  },
  error: (error) => {
    if (error.response) {
      // Erro da API
      this.notificationService.showError(
        `Erro ${error.response.status}: ${error.response.data.message}`,
      );
    } else {
      // Erro de rede
      this.notificationService.showError("Erro de conexão");
    }
  },
  complete: () => {
    console.log("Requisição finalizada");
  },
});

Casos de Uso Avançados

Retry com Observable

import { retry, delay } from "rxjs/operators";

this.httpProvider
  .get$<Data>("/api/unstable-endpoint")
  .pipe(
    retry({
      count: 3,
      delay: (error, retryCount) => {
        console.log(`Tentativa ${retryCount} falhou, tentando novamente...`);
        return timer(1000 * retryCount); // Delay crescente
      },
    }),
  )
  .subscribe({
    next: (response) => console.log("Dados:", response.data),
    error: (error) => console.error("Falhou após 3 tentativas:", error),
  });

Cache com Interceptors

// Interceptor para cache simples
const cache = new Map();

this.httpProvider.addResponseInterceptor((response) => {
  // Cache GET requests
  if (response.config.method?.toLowerCase() === "get") {
    cache.set(response.config.url, {
      data: response.data,
      timestamp: Date.now(),
    });
  }
  return response;
});

this.httpProvider.addRequestInterceptor((config) => {
  // Verificar cache para GET requests
  if (config.method?.toLowerCase() === "get") {
    const cached = cache.get(config.url);
    if (cached && Date.now() - cached.timestamp < 300000) {
      // 5 minutos
      // Retornar dados do cache (isso cancelará a requisição real)
      return Promise.reject({
        __cached: true,
        data: cached.data,
        config,
      });
    }
  }
  return config;
});

Upload de Arquivos

const formData = new FormData();
formData.append("file", file);
formData.append("metadata", JSON.stringify({ name: "document.pdf" }));

const response = await this.httpProvider.post<UploadResult>(
  "/api/upload",
  formData,
  {
    headers: {
      "Content-Type": "multipart/form-data",
    },
    onUploadProgress: (progressEvent) => {
      const percentCompleted = Math.round(
        (progressEvent.loaded * 100) / progressEvent.total,
      );
      console.log(`Upload: ${percentCompleted}%`);
    },
  },
);

Interface Completa

interface HttpProviderInterface {
  // Métodos HTTP Promise-based
  get<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
  post<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Promise<HttpResponse<T>>;
  put<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Promise<HttpResponse<T>>;
  patch<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Promise<HttpResponse<T>>;
  delete<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
  head<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
  options<T>(url: string, config?: HttpRequestConfig): Promise<HttpResponse<T>>;
  request<T>(config: HttpRequestConfig): Promise<HttpResponse<T>>;

  // Métodos HTTP Observable-based
  get$<T>(url: string, config?: HttpRequestConfig): Observable<HttpResponse<T>>;
  post$<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  put$<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  patch$<T>(
    url: string,
    data?: any,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  delete$<T>(
    url: string,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  head$<T>(
    url: string,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  options$<T>(
    url: string,
    config?: HttpRequestConfig,
  ): Observable<HttpResponse<T>>;
  request$<T>(config: HttpRequestConfig): Observable<HttpResponse<T>>;

  // Interceptors
  addRequestInterceptor(onFulfilled?, onRejected?): number;
  addResponseInterceptor(onFulfilled?, onRejected?): number;
  removeRequestInterceptor(interceptorId: number): void;
  removeResponseInterceptor(interceptorId: number): void;

  // Configuração
  createInstance(config?: HttpClientConfig): HttpProviderInterface;
  setBaseURL(baseURL: string): void;
  setTimeout(timeout: number): void;
  setHeaders(headers: Record<string, string>): void;
  setAuthToken(token: string, type?: string): void;
  clearAuthToken(): void;
}

Boas Práticas

  1. Use Observables para operações complexas: Quando precisar de retry, cancelamento, ou combinação com outras streams.

  2. Configure timeouts apropriados: Defina timeouts realistas baseados na natureza da API.

  3. Centralize configuração: Use interceptors para adicionar headers comuns, logging, etc.

  4. Trate erros adequadamente: Implemente tratamento de erro específico para diferentes tipos de falha.

  5. Use instâncias separadas: Para APIs externas com configurações diferentes.

  6. Documente suas APIs: Use JSDoc nos métodos que consomem o HTTP provider.

  7. Considere cache: Para dados que não mudam frequentemente, implemente cache com interceptors.

Este provider oferece uma base sólida e flexível para todas as suas necessidades de comunicação HTTP!