npm package: @rebound-dlq/node
Description: [![NPM Version](https://img.shields.io/npm/v/@rebound-dlq/node)](https://www.npmjs.com/package/@rebound-dlq/node) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
Author: Codify Labs
Latest version: 0.2.8

# Rebound DLQ — Node.js SDK

[![NPM Version](https://img.shields.io/npm/v/@rebound-dlq/node)](https://www.npmjs.com/package/@rebound-dlq/node)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

SDK oficial em Node.js para integrar sua aplicação com a plataforma **[Rebound DLQ](https://rebound-dlq.com)**.

Capture falhas, registre eventos de erro e garanta rastreabilidade das suas filas mortas — tudo sem impactar a performance da sua aplicação.

---

## Por que usar?

- **Zero latência no fluxo principal** — o evento é enfileirado em memória e a aplicação segue sem esperar resposta de rede.
- **Criptografia local AES-256** — o payload é criptografado antes de sair do seu processo.
- **Entrega resiliente** — retry automático com backoff exponencial em caso de falha de rede.
- **Sem config extra** — o comportamento de retry, buffer e retomada é totalmente automático, determinado pela configuração da conta na plataforma.

> **Pré-requisito:** uma conta e um projeto ativos em [rebound-dlq.com](https://rebound-dlq.com).

---

## Instalação

```bash
npm install @rebound-dlq/node
```

---

## Configuração

A única configuração obrigatória é o `projectSecret`, obtido no painel da plataforma Rebound DLQ.

Nunca exponha a chave no código-fonte. Use variáveis de ambiente:

```env
REBOUND_PROJECT_SECRET="seu_project_secret_aqui"
```

---

## Agrupamento por fluxo

Agora o SDK também pode ajudar a agrupar eventos DLQ por **fluxo de integração** na plataforma.

Isso é útil quando o seu cliente quer enxergar, por exemplo, apenas os erros do fluxo `Pagarme`, `ERP`, `Webhook de pedidos` ou qualquer outro processo operacional.

Os campos usados pela plataforma são:

| Campo | Obrigatório | Descrição |
|---|---|---|
| `flowKey` | ✅ Sim | Identificador técnico e estável do fluxo. Ex.: `pagarme-payments`. |
| `flowLabel` | Não | Nome amigável exibido no painel. Ex.: `Integração Pagarme`. |
| `flowStep` | Não | Etapa específica do fluxo. Ex.: `create_charge`, `payment_webhook`, `capture_receivables`. |

### Regra de agrupamento

- Se chegar um evento com um `flowKey` já existente naquele projeto, ele é agrupado no mesmo fluxo.
- Se o `flowKey` ainda não existir, a plataforma cria o fluxo automaticamente.
- Se o evento não enviar dados de fluxo, ele continua funcionando normalmente, como já funciona hoje.

### Exemplo recomendado de nomenclatura

```ts
{
  flowKey: 'pagarme-payments',
  flowLabel: 'Integração Pagarme',
  flowStep: 'payment_webhook'
}
```

> Dica: trate `flowKey` como identificador estável. Evite usar textos que mudam com frequência.

---

## Interfaces disponíveis

### `DlqWrapper` — recomendado

Encapsula qualquer função assíncrona. Se ela lançar uma exceção, o evento de erro é capturado, criptografado e enviado automaticamente em background.

```ts
import { DlqWrapper } from '@rebound-dlq/node';

const dlq = new DlqWrapper({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});
```

**Parâmetros:**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `projectSecret` | ✅ Sim | Chave secreta do projeto, usada para autenticação e criptografia local. |

**Uso:**

```ts
const resultado = await dlq.execute(() => minhaFuncaoQuePodefFalhar(dados), dados);
```

O erro original é sempre relançado para o seu tratamento normal. O SDK apenas captura, criptografa e envia o evento em background.

**Exemplo completo:**

```ts
import { DlqWrapper } from '@rebound-dlq/node';

const dlq = new DlqWrapper({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});

async function processarPagamento(dados: { userId: string; valor: number }) {
  if (dados.valor > 10000) {
    throw new Error('Limite excedido na operadora');
  }
  return 'aprovado';
}

try {
  const resultado = await dlq.execute(
    () => processarPagamento({ userId: 'u-123', valor: 15000 }),
    { userId: 'u-123', valor: 15000 },
  );
} catch (err) {
  // erro relançado normalmente — o SDK já registrou o evento
  console.error((err as Error).message);
}
```

### `DlqWrapper` com fluxo

Se você quiser agrupar o evento por fluxo usando o `DlqWrapper`, passe um terceiro parâmetro opcional com o contexto do fluxo.

```ts
import { DlqWrapper } from '@rebound-dlq/node';

const dlq = new DlqWrapper({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});

await dlq.execute(
  () => processarPagamento({ userId: 'u-123', valor: 15000 }),
  {
    userId: 'u-123',
    valor: 15000,
  },
  {
    flowKey: 'pagarme-payments',
    flowLabel: 'Integração Pagarme',
    flowStep: 'create_charge',
  },
);
```

> Se você não passar o terceiro parâmetro, o evento continua sendo enviado normalmente, sem vínculo com fluxo.

---

### `ReboundClient` + adapters — uso avançado

Para enviar eventos manualmente ou usar com adapters (HTTP, Kafka etc.).

```ts
import { ReboundClient, HTTPAdapter } from '@rebound-dlq/node';

const client = new ReboundClient({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});

const httpDlq = new HTTPAdapter(client);

await httpDlq.sendToDLQ({
  payload: { orderId: 'ORD-1001', amount: 99.9 },
  error: new Error('Payment gateway timeout'),
  flowKey: 'checkout-payments',
  flowLabel: 'Checkout de pagamentos',
  flowStep: 'gateway_authorization',
  metadata: {
    endpoint: '/api/payments',
    method: 'POST',
    tenantId: 'acme',
  }
});
```

**Parâmetros do `ReboundClient`:**

| Campo | Obrigatório | Descrição |
|---|---|---|
| `projectSecret` | ✅ Sim | Chave secreta do projeto, usada para autenticação e criptografia local. |

### Exemplo com fluxo usando `HTTPAdapter`

```ts
import { ReboundClient, HTTPAdapter } from '@rebound-dlq/node';

const client = new ReboundClient({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});

const httpDlq = new HTTPAdapter(client);

await httpDlq.sendToDLQ({
  payload: {
    orderId: 'ORD-1001',
    amount: 99.9,
    customerId: 'cus_123',
  },
  error: new Error('Payment gateway timeout'),
  flowKey: 'pagarme-payments',
  flowLabel: 'Integração Pagarme',
  flowStep: 'create_charge',
  metadata: {
    endpoint: '/api/payments',
    method: 'POST',
    tenantId: 'acme',
  },
});
```

### Exemplo com fluxo usando `KafkaAdapter`

```ts
import { ReboundClient, KafkaAdapter } from '@rebound-dlq/node';

const client = new ReboundClient({
  projectSecret: process.env.REBOUND_PROJECT_SECRET!,
});

const kafkaDlq = new KafkaAdapter(client);

await kafkaDlq.sendToDLQ({
  payload: {
    topic: 'payments.events',
    partition: 2,
    key: 'order-1001',
    message: { orderId: 'ORD-1001', status: 'failed' },
  },
  error: new Error('Kafka publish timeout'),
  flowKey: 'pagarme-payments',
  flowLabel: 'Integração Pagarme',
  flowStep: 'payment_webhook',
  metadata: {
    topic: 'payments.events',
    consumerGroup: 'payments-worker',
  },
});
```

### Resumo prático de uso

- Use `DlqWrapper` quando quiser a integração mais simples possível.
- Use `ReboundClient` + adapters quando quiser separar melhor `payload` e `metadata`.
- Para agrupamento por fluxo, envie `flowKey`, `flowLabel` e `flowStep` como campos opcionais separados do payload.
- `metadata` continua existindo para contexto técnico adicional, sem misturar regra de agrupamento com o payload do usuário.

---

## Comportamento automático

O SDK gerencia entrega, retry e limites de plano de forma totalmente automática, sem configuração adicional.

| Situação | O que o SDK faz |
|---|---|
| Sucesso na entrega | Remove o evento da fila |
| Falha de rede / erro transiente | Retry com backoff exponencial |
| Conta no limite (sem cobrança extra) | Descarta eventos e reconsulta o estado periodicamente |
| Conta no limite (com cobrança extra ativa) | Mantém eventos em buffer por até 15 min e retenta quando liberado |
| Conta desbloqueada / upgrade | Retoma o envio automaticamente, sem reiniciar o processo |

> A política de limite e cobrança extra é definida na sua conta na plataforma, não no SDK.

---

## Observações operacionais

- A fila é **in-memory**: eventos não sobrevivem a restart do processo.
- Para workloads efêmeros, prefira processos com **shutdown gracioso**.
- O SDK emite logs no console ao entrar em modo de retry, buffer ou descarte.

---

## Suporte

Dúvidas de integração ou comportamento? Abra um chamado pela plataforma oficial em [rebound-dlq.com](https://rebound-dlq.com).

---

Feito por **Codify Labs / Rebound DLQ**.