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

@dexcode-components/helpers

v0.2.2

Published

Funções utilitárias compartilhadas para projetos Next.js e React

Readme

Gateway e HttpClient

Este pacote expõe dois utilitários principais:

  • gatewayHandler: um handler pronto para ser usado como Route Handler do Next.js (App Router) para encaminhar requisições.
  • HttpClient: um cliente HTTP baseado em fetch, com suporte a chamadas diretas, via gateway e para rotas internas (/api/...).

Como usar o Gateway (Next.js App Router)

Para usar, basta criar a rota do gateway no App Router.

Caminho:

  • app/api/gateway/route.ts

Conteúdo (precisa estar assim):

import { gatewayHandler } from "@dexcode-components/helpers";

export const GET = gatewayHandler;
export const POST = gatewayHandler;
export const PUT = gatewayHandler;
export const PATCH = gatewayHandler;
export const DELETE = gatewayHandler;

O gateway:

  • Lê a URL de destino em ?url=... e faz o fetch para essa URL.
  • Valida a chave interna via header x-internal-key (comparando com process.env.GATEWAY_KEY).
  • Se houver authorization no request, usa esse valor; caso contrário tenta ler de cookie (configurável) e repassar como Authorization para o destino.

Variáveis de ambiente

Configure as variáveis abaixo no seu projeto (use valores reais apenas no seu .env local/infra):

  • process.env.GATEWAY_KEY
    • Server-only.
    • Deve bater com o valor enviado no header x-internal-key.
  • process.env.NEXT_PUBLIC_GATEWAY_KEY
    • Usada como fallback pelo HttpClient quando você chama via gateway e não informa a chave explicitamente.
    • Por ser NEXT_PUBLIC_*, considere esse valor como “chave interna” e não como segredo.
  • process.env.TOKEN_NAME ou process.env.NEXT_PUBLIC_TOKEN_NAME (opcional)
    • Nome do cookie onde o gateway tenta ler o token quando não existir authorization no header.
    • Se não definir, o padrão é token.
  • process.env.NEXT_PUBLIC_API_BASE_URL
    • Base URL do serviço que seu Service vai consumir (ex.: https://api.exemplo.com).

Como configurar um Service com HttpClient

Exemplo de interface (opcional):

export interface IEquipeService {
  getAll(): Promise<unknown>;
}

Exemplo de implementação usando Base URL via env (sem expor sua API real):

import { HttpClient } from "@dexcode-components/helpers";

export class EquipeService implements IEquipeService {
  private httpClient: HttpClient;

  constructor() {
    this.httpClient = new HttpClient();
    this.httpClient.baseUrl(process.env.NEXT_PUBLIC_API_BASE_URL!);
  }

  async getAll(): Promise<unknown> {
    return await this.httpClient.get({
      url: "/api/Equipe",
    });
  }
}

export const _equipeService = new EquipeService();

Chamadas diretas vs via gateway

Por padrão, o HttpClient usa serverSide: true (via gateway). Para desativar, passe serverSide: false.

O HttpClient pode operar em 3 modos:

1) Via gateway (serverSide: true) (padrão)

Usa a rota interna do gateway (por padrão /api/gateway) para encaminhar chamadas para uma URL absoluta, passando a URL final em ?url=....

Requisitos:

  • baseUrl(...) precisa ser absoluto (https://...) ou você precisa passar url absoluto.
  • A rota app/api/gateway/route.ts precisa existir.
return await this.httpClient.get({
  url: "/api/Equipe",
});

2) Chamada direta (serverSide: false)

Faz o fetch direto na URL resolvida (Base URL + url).

return await this.httpClient.get({
  url: "/api/Equipe",
  serverSide: false,
});

Você também pode passar uma URL absoluta diretamente:

return await this.httpClient.get({
  url: "https://api.exemplo.com/api/Equipe",
  serverSide: false,
});

3) Chamar rota interna do Next (/api/...) (client-side)

Quando você quer chamar uma rota interna do próprio Next (ex.: um route handler em /api/...) e reaproveitar cookies automaticamente.

Requisitos:

  • Defina gateway.path com o caminho da rota interna.
  • Não informe url.
return await this.httpClient.post({
  serverSide: false,
  data: { exemplo: true },
  gateway: { path: "/api/minha-rota" },
});

Configurações personalizadas (IHttpClientProps)

Cada chamada do HttpClient recebe um IHttpClientProps, permitindo ajustar comportamento por endpoint.

Assinatura:

export interface IHttpClientProps {
  url?: string;
  config?: RequestInit;
  data?: unknown;
  contentType?: string;
  serverSide?: boolean;
  gateway?: {
    path?: string;
    internalKeyHeader?: string;
    internalKey?: string;
  };
}

Regras rápidas:

  • Se serverSide: true: informe url (URL absoluta, ou relativa com baseUrl absoluto) ou informe gateway.path (para chamar um gateway custom).
  • Se serverSide estiver falso/omitido: informe url ou então informe gateway.path para chamar uma rota interna do Next.

config?: RequestInit

Usado para configurar o fetch no modo direto e no modo de rota interna (ex.: headers, credentials, cache, redirect, mode, signal).

Exemplo com credentials e AbortController:

const controller = new AbortController();

return await this.httpClient.get({
  url: "/api/Equipe",
  config: {
    credentials: "include",
    signal: controller.signal,
  },
});

No modo serverSide: true, o config é enviado no body para o gateway, e o gateway usa config.headers para montar headers de saída. Outros campos do RequestInit não impactam a chamada externa.

data?: unknown

Payload para métodos com body (POST/PUT/PATCH). Em GET/DELETE não envia body.

return await this.httpClient.post({
  url: "/api/Equipe",
  data: { nome: "Nova Equipe" },
});

contentType?: string

Permite sobrescrever o Content-Type por chamada.

  • Se o Content-Type incluir application/json, o body é JSON.stringify(data).
  • Caso contrário, o data é enviado como BodyInit (ex.: FormData, Blob, string).
const form = new FormData();
form.append("arquivo", file);

return await this.httpClient.post({
  url: "/api/upload",
  data: form,
  contentType: "multipart/form-data",
});

Observação importante no modo gateway (serverSide: true):

  • O HttpClient sempre envia para o gateway um body JSON no formato { data, config }.
  • Por isso, payloads como FormData/Blob não podem ser encaminhados “como estão” via gateway. Para upload/multipart, use chamada direta (sem serverSide) ou implemente um gateway custom que suporte isso.

gateway?: { ... }

Configurações específicas do gateway:

  • path:
    • com serverSide: true: caminho do endpoint do gateway (default: /api/gateway).
    • com serverSide falso/omitido e sem url: caminho de uma rota interna do Next (ex.: /api/minha-rota).
  • internalKeyHeader: muda o nome do header enviado com a chave (default: x-internal-key).
  • internalKey: define a chave para essa chamada (se não passar, usa HttpClient.gateway(...).internalKey e por fim process.env.NEXT_PUBLIC_GATEWAY_KEY).

Configuração padrão no client:

this.httpClient
  .baseUrl(process.env.NEXT_PUBLIC_API_BASE_URL!)
  .gateway({
    path: "/api/gateway",
    internalKeyHeader: "x-internal-key",
    internalKey: process.env.NEXT_PUBLIC_GATEWAY_KEY,
  });

Override por request:

return await this.httpClient.get({
  url: "/api/Equipe",
  serverSide: true,
  gateway: {
    path: "/api/gateway",
    internalKeyHeader: "x-internal-key",
    internalKey: "SUA_CHAVE_INTERNA_AQUI",
  },
});

Se você alterar internalKeyHeader, o gatewayHandler padrão continuará validando apenas x-internal-key. Nesse caso, adapte o seu gateway (ou crie um handler próprio) para validar o mesmo header que você está enviando.