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

@ecdt/events-engine

v1.1.0

Published

Publicador de eventos para o coletor do motor de eventos, sem dependencias e sem API exclusiva do Node

Downloads

464

Readme

@ecdt/events-engine

Publicador de eventos para o coletor do motor de eventos. Não tem dependências nem usa API exclusiva do Node, então roda no servidor e no browser.


Instalação

npm install @ecdt/events-engine

criarMotorEventos(options)

Cria o publicador de um produtor, uma vez, na inicialização do serviço.

const { criarMotorEventos } = require('@ecdt/events-engine');

const motor = criarMotorEventos({ produtor: 'meu-servico', chave: process.env.MOTOR_EVENTOS_CHAVE });

motor.publicarEventoDaRequisicao(req, {
  tipo: 'meu_evento',
  payload: { campo: 'valor' },
});

| Opção | Default | Descrição | |---|---|---| | produtor | desconhecido | Identificador de quem publica, no formato ^[a-z0-9-]+$ | | chave | MOTOR_EVENTOS_CHAVE | Chave do produtor, enviada em x-ecdt-produtor-chave | | url | MOTOR_EVENTOS_URL | URL completa do coletor; a lib não monta caminho nenhum | | cookieVisitante | MOTOR_EVENTOS_COOKIE_VISITANTE | Nome do cookie que guarda o identificador anônimo | | timeoutMs | 2000 | Aborta a requisição | | aoFalhar | console.error | Recebe a mensagem quando a publicação não acontece |

O produtor vai no header x-ecdt-produtor de toda publicação. Informe-o como constante no código: fora do formato, a lib avisa com console.warn e publica como desconhecido, sem lançar. Ele só se define na inicialização; a chamada não consegue trocá-lo.

A chave identifica o produtor para o coletor e vai no header x-ecdt-produtor-chave, como foi recebida. Ela é segredo: guarde em variável de ambiente ou num gerenciador de segredos e use só no servidor, porque qualquer valor no código do browser fica público. Como o produtor, só se define na inicialização, e o objeto devolvido não a expõe. Sem chave, o header não é enviado.

As demais opções valem de padrão para toda publicação, e a chamada prevalece sobre elas. As variáveis de ambiente são lidas a cada publicação, e só quando existe process; no browser, passe url na inicialização.

O objeto devolvido expõe produtor (o valor efetivo, já validado), publicarEvento e publicarEventoDaRequisicao.


publicarEvento(options)

Envia um evento para o coletor, sem bloquear o fluxo que o gerou.

motor.publicarEvento({
  tipo: 'meu_evento',
  autorizacao: req.headers.authorization,
  payload: { campo: 'valor' },
});

| Opção | Default | Descrição | |---|---|---| | tipo | — | Nome do evento, em snake_case | | autorizacao | — | Header Authorization da requisição que originou o evento | | idVisitante | — | Identificador anônimo, para quando não há token | | payload | {} | Campos do evento | | url, timeoutMs, aoFalhar | os da inicialização | Sobrescrevem o padrão só nesta chamada |

A identidade do usuário sai do token, nunca do corpo: o coletor a resolve a partir do Authorization repassado. Quando não há token — rota pública, visitante anônimo — vale o idVisitante, que vai no corpo como id_visitante. Ele não é identidade autenticada, é um identificador de correlação, e por isso pode vir do corpo da requisição. Basta um dos dois.

Sem tipo, ou sem nenhum dos dois identificadores, a função não faz nada; sem url ela ainda registra um console.warn, porque url ausente é configuração faltando e não um evento que não se aplica.

A função nunca lança e nunca devolve promise. O evento é secundário ao fluxo que o gerou — falha de publicação não pode virar erro de quem chamou, e o retorno undefined impede que alguém consiga dar await e acoplar a latência do request ao coletor.


publicarEventoDaRequisicao(req, options)

O mesmo publish, montado a partir da requisição que gerou o evento. Resolve o token pelo header Authorization e o identificador anônimo pelo corpo (id_visitante) ou pelo cookie, nessa ordem.

| Opção | Default | Descrição | |---|---|---| | tipo, payload, url, timeoutMs, aoFalhar | — | Idênticos ao publicarEvento | | cookieVisitante | o da inicialização | Nome do cookie que guarda o identificador anônimo |

Sem cookieVisitante configurado, só o corpo alimenta o id_visitante. Também não lança em nenhuma hipótese, inclusive com req sem headers nem body.


lerCookie, idDoCookie e sanitizarId

Leitura do header Cookie, sem dependência de framework.

const { idDoCookie } = require('@ecdt/events-engine');

const idVisitante = idDoCookie(req.headers.cookie, 'nome_do_cookie');

| Função | Devolve | |---|---| | lerCookie(cabecalho, nome) | Valor cru do cookie, ou null | | idDoCookie(cabecalho, nome, { maxLen }) | O identificador: aceita o cookie como string simples ou como JSON com campo id, decodifica o valor e corta em maxLen (100 por padrão) | | sanitizarId(valor, maxLen) | O mesmo corte e validação, para identificador que veio de outro lugar |

O match do nome é exato, então nome_antigo não casa com nome. Nenhuma das três lança: entrada que não é string vira null.


Migrando do @ecdt/server-common

O publicador e as funções de cookie saíram do @ecdt/server-common na 2.0.0. As assinaturas das chamadas não mudaram; o que muda é criar o publicador antes, com o produtor.

-const { publicarEventoDaRequisicao } = require('@ecdt/server-common');
+const { criarMotorEventos } = require('@ecdt/events-engine');
+
+const { publicarEventoDaRequisicao } = criarMotorEventos({ produtor: 'meu-servico' });

 publicarEventoDaRequisicao(req, { tipo, payload, cookieVisitante });

lerCookie, idDoCookie e sanitizarId só trocam de pacote no require.


TypeScript

O pacote publica os tipos em src/index.d.ts. As interfaces exportadas são OpcoesDoMotor, MotorEventos, PublicarEventoOptions, PublicarEventoDaRequisicaoOptions e IdDoCookieOptions.