@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 emfetch, 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 ofetchpara essa URL. - Valida a chave interna via header
x-internal-key(comparando comprocess.env.GATEWAY_KEY). - Se houver
authorizationno request, usa esse valor; caso contrário tenta ler de cookie (configurável) e repassar comoAuthorizationpara 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
HttpClientquando 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.
- Usada como fallback pelo
process.env.TOKEN_NAMEouprocess.env.NEXT_PUBLIC_TOKEN_NAME(opcional)- Nome do cookie onde o gateway tenta ler o token quando não existir
authorizationno header. - Se não definir, o padrão é
token.
- Nome do cookie onde o gateway tenta ler o token quando não existir
process.env.NEXT_PUBLIC_API_BASE_URL- Base URL do serviço que seu Service vai consumir (ex.:
https://api.exemplo.com).
- Base URL do serviço que seu Service vai consumir (ex.:
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 passarurlabsoluto.- A rota
app/api/gateway/route.tsprecisa 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.pathcom 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: informeurl(URL absoluta, ou relativa combaseUrlabsoluto) ou informegateway.path(para chamar um gateway custom). - Se
serverSideestiver falso/omitido: informeurlou então informegateway.pathpara 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-Typeincluirapplication/json, o body éJSON.stringify(data). - Caso contrário, o
dataé enviado comoBodyInit(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
HttpClientsempre envia para o gateway um body JSON no formato{ data, config }. - Por isso, payloads como
FormData/Blobnão podem ser encaminhados “como estão” via gateway. Para upload/multipart, use chamada direta (semserverSide) 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
serverSidefalso/omitido e semurl: caminho de uma rota interna do Next (ex.:/api/minha-rota).
- com
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, usaHttpClient.gateway(...).internalKeye por fimprocess.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.
