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

ti-hooks

v1.3.3

Published

ti-hooks: proxy de webhooks com túnel WebSocket — recebe eventos em URL pública e entrega em apps locais, com fila, ack e histórico

Readme

ti-hooks

Receba webhooks de produção/sandbox (Asaas etc.) na sua máquina local, sem ngrok e sem mexer no painel da origem a cada dev.

Funciona como pub/sub: cada hook tem uma URL pública única (cadastrada uma vez na origem) e N assinantes. Todo evento é entregue a todos os assinantes (fan-out), cada um com fila, retry e histórico independentes — a entrega em localhost atravessa um túnel WebSocket que o CLI abre da sua máquina.

Origem (Asaas etc.) ──▶ https://<proxy>/webhook/<hook>/<token>
                              │  fan-out
              ┌───────────────┼────────────────┐
        túnel do joão   túnel da maria    fila do CI (offline)
              ▼                ▼
     localhost:4000     localhost:3300      entrega quando abrir

Se o seu túnel estiver fechado, os eventos ficam na fila e descem quando você conectar. Se a sua app recusar (500, caiu), o proxy re-tenta com backoff até 10 vezes e depois guarda como failed — reprocessável com um comando.

Começar (dev)

O admin vai te passar três coisas: a URL do proxy da equipe (ex.: wss://hooks.ti.dev.br), o nome do hook (ex.: asaas) e o joinCode (código de convite). Com elas em mãos, na pasta em que for trabalhar:

npm i -g ti-hooks     # requer Node 20.17+ — recomendado 22 LTS (Mac, Windows ou Linux)
ti-hooks              # primeiro uso: o assistente pergunta as 3 coisas + seu nome
                      # e a URL da sua app local, grava o .env e já abre o túnel

Prefere sem assistente? O mesmo, em uma linha:

PROXY_URL=wss://hooks.ti.dev.br ti-hooks subscribe asaas <joinCode> seu-nome http://localhost:4000/webhooks

Nos dois casos tudo fica salvo no .env da pasta — daqui em diante os comandos não pedem mais nada. Dia a dia:

Navegação do menu: ⏎ seleciona · esc volta · ctrl+c sai — em qualquer tela.

ti-hooks                     # menu interativo (túnel, log, eventos, teste)
ti-hooks tunnel-bg           # abre o túnel em segundo plano
ti-hooks logs -f             # acompanha as entregas ao vivo
ti-hooks events <hook>       # histórico do seu hook: ✓ entregues · ● fila · ✗ falhos
ti-hooks resend <hook> <id>  # reprocessa um evento seu
ti-hooks test <hook>         # dispara um evento de teste
ti-hooks stop                # fecha o túnel
ti-hooks unsubscribe <hook> <seu-nome>   # cancela sua assinatura

Sem ADMIN_TOKEN no .env, o CLI opera em modo dev: o token da sua assinatura autentica você nos comandos do seu hook; assinaturas de outros devs e administração ficam bloqueadas. Estado do túnel: ~/.ti-hooks/.

Administrar (admin)

Com ADMIN_TOKEN no .env (o mesmo do servidor), o CLI libera tudo. Para promover alguém a admin, envie o token por canal seguro e a pessoa roda:

ti-hooks admin <ADMIN_TOKEN>    # valida no servidor e grava no .env da pasta

⚠️ O token é único e dá poder total (criar/remover hooks, ver tokens de todos). Revogar alguém = trocar o ADMIN_TOKEN no servidor e reenviar aos demais admins.

ti-hooks add <hook> [targetUrl]        # cria hook → retorna webhookUrl (p/ origem) e joinCode (p/ devs)
ti-hooks list                          # hooks, assinantes, joinCodes, filas
ti-hooks list-con                      # só os túneis conectados
ti-hooks events <hook>                 # histórico com o status POR assinante
ti-hooks resend <hook> <id> [assinante]
ti-hooks unsubscribe <hook> <nome>     # remove assinatura de qualquer dev
ti-hooks delete <hook>                 # remove o hook inteiro
ti-hooks tunnel-bg                     # seu túnel (usa sua assinatura "default", criada com o hook)

Regra do targetUrl: a entrega usa sempre o destino do assinante; o do hook (raiz) é só o padrão herdado por quem assina sem informar o seu.

API

| Método | Rota | Auth | Descrição | |---|---|---|---| | POST | /registrations | x-admin-token | Cria hook; gera inboundToken e joinCode | | GET | /registrations | x-admin-token | Lista hooks e assinantes | | POST | /hooks/:slug/join-info | joinCode no body | Valida o código e revela o destino padrão do hook | | POST | /hooks/:slug/subscribe | joinCode no body | Cria assinatura; retorna o token do assinante | | DELETE | /hooks/:slug/subscribers/:name | admin ou o próprio | Remove assinatura (descarta a fila dela) | | POST | /registrations/:slug/test | admin ou x-tunnel-token | Evento de teste pelo caminho real | | GET | /registrations/:slug/events | admin ou x-tunnel-token | Histórico (admin: por assinante; dev: só o seu) | | POST | /registrations/:slug/events/:id/resend | admin ou x-tunnel-token | Reprocessa (?subscriber= p/ um só) | | DELETE | /registrations/:slug | x-admin-token | Remove o hook inteiro | | POST/PUT/PATCH | /webhook/:slug/:inboundToken | token na URL | Recebe o webhook e faz o fan-out | | GET | /health | — | { ok, agents: ["hook/assinante", ...] } |

slug é o identificador técnico do hook na API. O proxy repassa todos os headers intactos — validação fim-a-fim (ex.: asaas-access-token) é da aplicação destino.

Garantia de entrega

At-least-once por assinante: o proxy só marca delivered com confirmação 2xx (ack do agent pelo túnel). Falha ou 30s sem ack → volta pra fila com backoff, até 10 tentativas → failed (dead letter), reprocessável via resend. Fila aguardando túnel fechado não gasta tentativas.

Rodar o seu próprio proxy

O pacote inclui o servidor: npm run server (ou pm2 via npm run deploy). Persistência em JSON no data/ (registrations, filas por assinante e histórico com retenção de 200 eventos/30 dias por hook).

Variáveis do servidor (.env): PORT (3207), HOST, ADMIN_TOKEN (obrigatória), DATA_DIR e as opcionais MAX_ATTEMPTS (10), ACK_TIMEOUT_MS (30000), RETRY_SWEEP_MS (30000), HISTORY_RETENTION_DAYS (30). Na máquina local: PROXY_URL, ADMIN_TOKEN (admin) ou TUNNELS=hook:token[,...] (dev — o subscribe preenche sozinho).

Guia completo de operação (infra, deploy, troubleshooting) e collection do Bruno: no repositório, em docs/.

Licença

MIT