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

@ruanlopes1350/hermes-client

v1.2.1

Published

SDK oficial para comunicação com o microsserviço de e-mails Hermes.

Readme

Hermes Client SDK

SDK oficial em Node.js/TypeScript para integrar com o Hermes - Gateway de E-mails Transacionais. Este SDK fornece uma interface moderna e encadeada (Builder pattern) para o envio de e-mails, além de gerenciar automaticamente a rotação de API Keys em tempo real usando Webhooks assinados com HMAC-SHA256.

📦 Instalação

npm install @ruanlopes1350/hermes-client

🚀 Como Usar

1. Inicialização

O SDK precisa de um endereço do seu servidor Hermes e de uma estratégia de armazenamento para a chave (Storage Adapter).

import { HermesClient, MemoryAdapter } from '@ruanlopes1350/hermes-client';

const hermes = new HermesClient({
  baseUrl: 'https://seu-hermes-api.com',
  timeoutMs: 30000,          // Opcional: timeout para os requests (padrão: 30000ms)
  logLevel: 'warn',          // Opcional: 'debug' | 'info' | 'warn' | 'error' | 'silent' (padrão)
  storageAdapter: new MemoryAdapter('hm_sua_chave_inicial_aqui'),
});

Nota: A chave inicial pode ser passada diretamente ao MemoryAdapter ou via initialApiKey na configuração:

const hermes = new HermesClient({
  baseUrl: 'https://seu-hermes-api.com',
  initialApiKey: 'hm_sua_chave_inicial_aqui',
});

2. Enviando E-mails (Builder Pattern — Recomendado)

// Com template do Hermes e variáveis dinâmicas
await hermes.email()
  .to('[email protected]')
  .subject('Bem-vindo ao Sistema!')
  .useTemplate('uuid-do-template', { nome: 'João da Silva' })
  .priority('high')            // Opcional: 'high' | 'medium' | 'low'
  .credential('credencial-id') // Opcional: substitui a credencial padrão da key
  .send();

// Com body HTML direto (sem template)
await hermes.email()
  .to('[email protected]')
  .subject('Alerta de Segurança')
  .body('<h1>Aviso</h1><p>Houve uma tentativa de login.</p>')
  .send();

// Com envio agendado
await hermes.email()
  .to('[email protected]')
  .subject('Newsletter Mensal')
  .useTemplate('newsletter-tpl', { mes: 'Julho' })
  .scheduledAt(new Date('2026-08-01T09:00:00Z'))
  .send();

Retrocompatibilidade: O método legado hermes.sendEmail(payload) ainda é suportado.

3. Enviando E-mails em Bulk

// Builder fluido
await hermes.bulk()
  .email()
    .to('[email protected]')
    .subject('Bem-vinda!')
    .useTemplate('onboarding-tpl', { name: 'Alice' })
    .done()
  .email()
    .to('[email protected]')
    .subject('Bem-vindo!')
    .useTemplate('onboarding-tpl', { name: 'Bob' })
    .done()
  .send();

// Forma direta com array
await hermes.sendBulkEmails([
  { recipient_to: '[email protected]', subject: 'Olá', template_id: 'tpl-1', variables: { name: 'Alice' } },
  { recipient_to: '[email protected]',   subject: 'Olá', template_id: 'tpl-1', variables: { name: 'Bob' } },
]);

4. Health Check

const status = await hermes.healthCheck();
console.log(status.status); // "ok"

5. Tratamento de Erros Tipados

O SDK expõe classes de erro específicas para tratamento granular:

import { HermesRateLimitError, HermesAuthError, HermesNetworkError } from '@ruanlopes1350/hermes-client';

try {
  await hermes.email()
    .to('[email protected]')
    .subject('Recuperação de Senha')
    .useTemplate('recovery-template', { link: 'https://...' })
    .send();
} catch (err) {
  if (err instanceof HermesRateLimitError) {
    console.warn(`Rate limit atingido. Tente novamente em ${err.retryAfterMs}ms`);
  } else if (err instanceof HermesAuthError) {
    console.error('API Key inválida ou expirada');
  } else if (err instanceof HermesNetworkError) {
    console.error('Problema de conectividade ao chamar a API');
  }
}

Retry automático: O SDK retenta automaticamente em erros de indisponibilidade (502, 503, 504) e Rate Limit com backoff exponencial. Configure via retry em HermesClientConfig.

6. Helpers para Templates

import { templateHelpers } from '@ruanlopes1350/hermes-client';

await hermes.email()
  .to('[email protected]')
  .subject('Pedido confirmado')
  .useTemplate('order-confirmation', {
    greeting:  templateHelpers.greeting('João'),         // "Boa tarde, João"
    orderDate: templateHelpers.formatDate(new Date()),   // "20 de maio de 2026"
    total:     templateHelpers.formatCurrency(149.90),   // "R$ 149,90"
  })
  .send();

🔄 Rotação Automática de Chaves (Webhooks)

O Hermes enviará um Webhook assinado com HMAC-SHA256 sempre que uma API Key estiver prestes a expirar, contendo a nova chave. O SDK oferece middlewares plug-and-play para os principais frameworks:

Express.js

import express from 'express';
import { expressWebhookHandler } from '@ruanlopes1350/hermes-client/express';

const app = express();

// IMPORTANTE: use express.raw() para que a assinatura HMAC seja validada corretamente
app.post(
  '/webhook/hermes',
  express.raw({ type: 'application/json' }),
  expressWebhookHandler(hermes, process.env.HERMES_WEBHOOK_SECRET!),
);

Next.js (App Router)

Crie app/api/webhook/hermes/route.ts:

import { nextWebhookHandler } from '@ruanlopes1350/hermes-client/next';
import { hermes } from '@/lib/hermes'; // a instância criada anteriormente

export const POST = nextWebhookHandler(hermes, process.env.HERMES_WEBHOOK_SECRET!);

Fastify

import fastify from 'fastify';
import { fastifyWebhookHandler } from '@ruanlopes1350/hermes-client/fastify';

const app = fastify();

app.post(
  '/webhook/hermes',
  fastifyWebhookHandler(hermes, process.env.HERMES_WEBHOOK_SECRET!),
);

📡 Eventos (Ciclo de Vida)

O HermesClient é um emissor de eventos leve, 100% compatível com Edge Runtimes:

hermes.on('keyRotated', (newKey, oldKey) => {
  console.log('✅ Chave rotacionada automaticamente pelo Hermes!');
});

hermes.on('error', (err) => {
  console.error('❌ Erro no cliente Hermes:', err);
});

🛠️ Storage Adapters

Quando o webhook chega e a chave muda, o SDK atualiza a chave via o Storage Adapter configurado:

MemoryAdapter (padrão)

Guarda a chave na RAM da instância. Simples e ideal para testes rápidos.

import { HermesClient, MemoryAdapter } from '@ruanlopes1350/hermes-client';

const hermes = new HermesClient({
  baseUrl: 'https://seu-hermes-api.com',
  storageAdapter: new MemoryAdapter('hm_chave_inicial'),
});

Atenção: Em ambientes com múltiplas instâncias (load balancers), a MemoryAdapter não propaga a nova chave entre processos. Use EnvAdapter ou um adapter customizado (ex: RedisAdapter).

EnvAdapter

Lê e escreve a chave diretamente em um arquivo .env físico. Ideal para servidores VPS/Bare Metal.

import { HermesClient, EnvAdapter } from '@ruanlopes1350/hermes-client';

const hermes = new HermesClient({
  baseUrl: 'https://seu-hermes-api.com',
  // Procura a variável HERMES_API_KEY no arquivo .env da raiz do projeto
  storageAdapter: new EnvAdapter('.env', 'HERMES_API_KEY'),
});

Adapter Customizado (ex: Redis — para multi-instância)

import { StorageAdapter, HermesClient } from '@ruanlopes1350/hermes-client';
import redis from './redis-client';

export class RedisAdapter implements StorageAdapter {
  async getApiKey() {
    return await redis.get('hermes_api_key');
  }

  async setApiKey(key: string) {
    await redis.set('hermes_api_key', key);
  }
}

const hermes = new HermesClient({
  baseUrl: 'https://seu-hermes-api.com',
  storageAdapter: new RedisAdapter(),
});

📦 Build e Distribuição

O SDK é construído com tsup e distribuído em formato dual:

| Formato | Arquivo | |---|---| | ESM | dist/index.mjs | | CJS | dist/index.js | | Types | dist/index.d.ts |

Handlers de webhook são exportados como sub-pacotes separados (/express, /next, /fastify) para tree-shaking eficiente.


📄 Licença

ISC — Ruan Lopes