@rebound-dlq/node 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/dist/adapters/base.adapter.d.ts +8 -0
- package/dist/adapters/base.adapter.js +36 -0
- package/dist/adapters/http.adapter.d.ts +5 -0
- package/dist/adapters/http.adapter.js +17 -0
- package/dist/adapters/kafka.adapter.d.ts +5 -0
- package/dist/adapters/kafka.adapter.js +17 -0
- package/dist/core/client.d.ts +7 -0
- package/dist/core/client.js +25 -0
- package/dist/core/constants.d.ts +4 -0
- package/dist/core/constants.js +7 -0
- package/dist/core/errors.d.ts +7 -0
- package/dist/core/errors.js +18 -0
- package/dist/core/queue.d.ts +12 -0
- package/dist/core/queue.js +74 -0
- package/dist/core/wrapper.d.ts +17 -0
- package/dist/core/wrapper.js +73 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +14 -0
- package/dist/models/payload.d.ts +23 -0
- package/dist/models/payload.js +2 -0
- package/package.json +18 -0
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Rebound DLQ SDK 🚀
|
|
2
|
+
|
|
3
|
+
O **Rebound DLQ SDK** é uma solução de altíssima performance (Zero Gargalos e Fila em Memória) para capturar falhas em integrações, proteger sua regra de negócio e fazer o reprocessamento de DLQs (Dead Letter Queues) de forma transparente para sua aplicação Node.js.
|
|
4
|
+
|
|
5
|
+
Sua aplicação original não vai travar nem ficar lenta, mesmo se a nossa API cair ou a rede oscilar.
|
|
6
|
+
|
|
7
|
+
## 📦 1. Instalação
|
|
8
|
+
|
|
9
|
+
Abra o terminal do seu projeto Node.js e instale o pacote:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @rebound/dlq-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
*(Nota: Se você está rodando um pacote em testes local via `.tgz`, use: `npm install ./caminho/do/seu/rebound-dlq-sdk-0.1.0.tgz`)*
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ⚙️ 2. Como Configurar e Usar na Prática
|
|
20
|
+
|
|
21
|
+
A forma ideal de utilizar o SDK é "abraçando" (envolvendo) as funções de risco do seu sistema (pagamentos, cadastros em APIs externas, envio de emails, etc) através do `DlqWrapper`.
|
|
22
|
+
|
|
23
|
+
### Passo A: Importar e Configurar o SDK
|
|
24
|
+
|
|
25
|
+
No topo do seu arquivo principal (ou no seu arquivo de injeção de dependências), inicialize o Wrapper passando suas credenciais:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// Se você usa CommonJS (require):
|
|
29
|
+
const { DlqWrapper } = require('@rebound/dlq-sdk');
|
|
30
|
+
|
|
31
|
+
// Se você usa ES Modules (import):
|
|
32
|
+
// import { DlqWrapper } from '@rebound/dlq-sdk';
|
|
33
|
+
|
|
34
|
+
const dlqWrapper = new DlqWrapper({
|
|
35
|
+
projectId: "seu-project-id", // Pegue no painel do Rebound
|
|
36
|
+
projectSecret: "sk_dev_sua_chave_secreta", // Use sk_dev_ para testes ou sk_live_ para produção
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Passo B: Proteger sua Função
|
|
41
|
+
|
|
42
|
+
Em vez de chamar sua função diretamente, chame ela *dentro* do método `.execute()` do SDK.
|
|
43
|
+
|
|
44
|
+
Sempre que a sua função der erro, o SDK silenciosamente vai capturar o payload e enviar pra Rebound em backgroud, enquanto sua aplicação segue a vida imediatamente e de forma limpa.
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
// Uma função sua que costuma falhar ou chamar serviços externos
|
|
48
|
+
async function minhaFuncaoDeRisco(dados) {
|
|
49
|
+
console.log("Iniciando pagamento...");
|
|
50
|
+
if (dados.valor > 1000) {
|
|
51
|
+
throw new Error("Saldo insuficiente na operadora do cartão");
|
|
52
|
+
}
|
|
53
|
+
return "Sucesso!";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function run() {
|
|
57
|
+
// 1. Defina os dados que você quer salvar caso essa rotina falhe
|
|
58
|
+
const payloadQueSeraSalvoNaDLQ = {
|
|
59
|
+
userId: "123",
|
|
60
|
+
valor: 5000,
|
|
61
|
+
tentativa: 1,
|
|
62
|
+
modulo: "Checkout"
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
// 2. Execute a sua função DENTRO da proteção do SDK
|
|
67
|
+
const resultado = await dlqWrapper.execute(
|
|
68
|
+
() => minhaFuncaoDeRisco(payloadQueSeraSalvoNaDLQ), // Sua função de negócio
|
|
69
|
+
payloadQueSeraSalvoNaDLQ // O Payload que vai pra nuvem em caso de erro
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
console.log("Deu tudo certo:", resultado);
|
|
73
|
+
|
|
74
|
+
} catch (erro) {
|
|
75
|
+
// 3. Trate o erro localmente como você sempre fez (o App NÃO morre)
|
|
76
|
+
console.log("Erro na aplicação:", erro.message);
|
|
77
|
+
|
|
78
|
+
// 🚀 A MÁGICA:
|
|
79
|
+
// Nesse exato momento, o SDK já pegou esse erro e despachou para o Rebound na nuvem.
|
|
80
|
+
// Se a internet falhou, ele salvou na memória RAM e ficará tentando de novo em background
|
|
81
|
+
// sem travar ou deixar sua API mais lenta!
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
run();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## ⚡ Por que usar nossa DLQ Engine?
|
|
91
|
+
|
|
92
|
+
1. **In-Memory Zero-Latency**: A comunicação com nossos servidores não engargala os verbos HTTP da sua aplicação. Assim que a exceção bater e você usar o wrapper, ele joga o payload rápido (`O(1)`) pra uma fila inteligente em Memória RAM da sua máquina.
|
|
93
|
+
2. **Entrega Garantida**: Se a sua infra ou nossa nuvem apresentar lentidão, sua requisição fica salva temporariamente no Node Event Loop da sua aplicação fazendo "Retry Exponencial" silencioso.
|
|
94
|
+
3. **Criptografia Automática**: Todas as requisições enviadas ao Painel são criptografadas (AES-256) com sua `projectSecret` ainda na sua infraestrutura. Ninguém acessa do outro lado além de você.
|
|
95
|
+
|
|
96
|
+
### Modos suportados
|
|
97
|
+
|
|
98
|
+
- `sk_dev_*` conectará automaticamente na Sandbox / Local (Porta 3001)
|
|
99
|
+
- `sk_live_*` conectará aos endpoints oficiais estabilizados de produção.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
**Suporte Rebound**
|
|
103
|
+
Dúvidas ou problemas? Acesse seu dashboard e abra um chamado com nosso time de engenharia.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReboundClient } from '../core/client';
|
|
2
|
+
import { DLQPayload, SendToDLQOptions } from '../models/payload';
|
|
3
|
+
export declare abstract class BaseAdapter {
|
|
4
|
+
protected client: ReboundClient;
|
|
5
|
+
constructor(client: ReboundClient);
|
|
6
|
+
sendToDLQ(options: SendToDLQOptions): Promise<void>;
|
|
7
|
+
protected normalizeError(error?: Error | string): DLQPayload['error'];
|
|
8
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseAdapter = void 0;
|
|
4
|
+
class BaseAdapter {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
async sendToDLQ(options) {
|
|
9
|
+
const { payload, error, source = 'unknown', metadata = {} } = options;
|
|
10
|
+
const dlqPayload = {
|
|
11
|
+
payload,
|
|
12
|
+
source,
|
|
13
|
+
error: this.normalizeError(error),
|
|
14
|
+
metadata,
|
|
15
|
+
timestamp: Date.now()
|
|
16
|
+
};
|
|
17
|
+
return this.client.send(dlqPayload);
|
|
18
|
+
}
|
|
19
|
+
normalizeError(error) {
|
|
20
|
+
if (!error)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (typeof error === 'string') {
|
|
23
|
+
return {
|
|
24
|
+
message: error,
|
|
25
|
+
name: 'Error'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
message: error.message,
|
|
30
|
+
stack: error.stack,
|
|
31
|
+
name: error.name,
|
|
32
|
+
code: error.code
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.BaseAdapter = BaseAdapter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HTTPAdapter = void 0;
|
|
4
|
+
const base_adapter_1 = require("./base.adapter");
|
|
5
|
+
class HTTPAdapter extends base_adapter_1.BaseAdapter {
|
|
6
|
+
async sendToDLQ(options) {
|
|
7
|
+
return super.sendToDLQ({
|
|
8
|
+
...options,
|
|
9
|
+
source: options.source || 'http',
|
|
10
|
+
metadata: {
|
|
11
|
+
...options.metadata,
|
|
12
|
+
type: 'http'
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.HTTPAdapter = HTTPAdapter;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KafkaAdapter = void 0;
|
|
4
|
+
const base_adapter_1 = require("./base.adapter");
|
|
5
|
+
class KafkaAdapter extends base_adapter_1.BaseAdapter {
|
|
6
|
+
async sendToDLQ(options) {
|
|
7
|
+
return super.sendToDLQ({
|
|
8
|
+
...options,
|
|
9
|
+
source: options.source || 'kafka',
|
|
10
|
+
metadata: {
|
|
11
|
+
...options.metadata,
|
|
12
|
+
type: 'kafka'
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.KafkaAdapter = KafkaAdapter;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReboundClient = void 0;
|
|
4
|
+
const constants_1 = require("./constants");
|
|
5
|
+
const queue_1 = require("./queue");
|
|
6
|
+
class ReboundClient {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
const isTest = config.apiKey.startsWith('sk_test_');
|
|
10
|
+
this.baseUrl = config.endpoint ||
|
|
11
|
+
(isTest
|
|
12
|
+
? constants_1.REBOUND_API_ENDPOINTS.TEST
|
|
13
|
+
: constants_1.REBOUND_API_ENDPOINTS.PRODUCTION);
|
|
14
|
+
}
|
|
15
|
+
async send(payload) {
|
|
16
|
+
const endpoint = `${this.baseUrl}/dlq-injestion`;
|
|
17
|
+
const enrichedPayload = {
|
|
18
|
+
...payload,
|
|
19
|
+
timestamp: payload.timestamp || Date.now(),
|
|
20
|
+
};
|
|
21
|
+
// Enqueue directly in memory so the application doesn't block on network responses
|
|
22
|
+
queue_1.MemoryQueue.getInstance().enqueue(endpoint, this.config.apiKey, enrichedPayload);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.ReboundClient = ReboundClient;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReboundAPIError = exports.ReboundError = void 0;
|
|
4
|
+
class ReboundError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "ReboundError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.ReboundError = ReboundError;
|
|
11
|
+
class ReboundAPIError extends ReboundError {
|
|
12
|
+
constructor(statusCode, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.statusCode = statusCode;
|
|
15
|
+
this.name = "ReboundAPIError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.ReboundAPIError = ReboundAPIError;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class MemoryQueue {
|
|
2
|
+
private static instance;
|
|
3
|
+
private queue;
|
|
4
|
+
private isProcessing;
|
|
5
|
+
private baseDelayMs;
|
|
6
|
+
private maxDelayMs;
|
|
7
|
+
private constructor();
|
|
8
|
+
static getInstance(): MemoryQueue;
|
|
9
|
+
enqueue(endpoint: string, apiKey: string, payload: any): void;
|
|
10
|
+
private processQueue;
|
|
11
|
+
private applyBackoff;
|
|
12
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoryQueue = void 0;
|
|
4
|
+
class MemoryQueue {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.queue = [];
|
|
7
|
+
this.isProcessing = false;
|
|
8
|
+
this.baseDelayMs = 1000;
|
|
9
|
+
this.maxDelayMs = 60000; // max 60 seconds between retries
|
|
10
|
+
}
|
|
11
|
+
static getInstance() {
|
|
12
|
+
if (!MemoryQueue.instance) {
|
|
13
|
+
MemoryQueue.instance = new MemoryQueue();
|
|
14
|
+
}
|
|
15
|
+
return MemoryQueue.instance;
|
|
16
|
+
}
|
|
17
|
+
enqueue(endpoint, apiKey, payload) {
|
|
18
|
+
this.queue.push({
|
|
19
|
+
endpoint,
|
|
20
|
+
apiKey,
|
|
21
|
+
payload,
|
|
22
|
+
retryCount: 0
|
|
23
|
+
});
|
|
24
|
+
if (!this.isProcessing) {
|
|
25
|
+
// Offload to Event Loop so it returns instantly for the main application thread
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
this.processQueue().catch((err) => {
|
|
28
|
+
console.error('[Rebound SDK] Unexpected queue error:', err);
|
|
29
|
+
});
|
|
30
|
+
}, 0);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async processQueue() {
|
|
34
|
+
this.isProcessing = true;
|
|
35
|
+
while (this.queue.length > 0) {
|
|
36
|
+
const item = this.queue[0]; // FIFO
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(item.endpoint, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
'x-api-key': `Bearer ${item.apiKey}`
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify(item.payload),
|
|
45
|
+
});
|
|
46
|
+
if (response.ok) {
|
|
47
|
+
if (item.retryCount > 0) {
|
|
48
|
+
console.log(`[Rebound SDK] Event successfully delivered after ${item.retryCount} retries.`);
|
|
49
|
+
}
|
|
50
|
+
// Success: Remove item from memory queue
|
|
51
|
+
this.queue.shift();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// API error (ex 429, 500)
|
|
55
|
+
await this.applyBackoff(item);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// Network unstable / Connection refused
|
|
60
|
+
await this.applyBackoff(item);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
this.isProcessing = false;
|
|
64
|
+
}
|
|
65
|
+
async applyBackoff(item) {
|
|
66
|
+
item.retryCount++;
|
|
67
|
+
const delay = Math.min(this.baseDelayMs * Math.pow(2, item.retryCount), this.maxDelayMs);
|
|
68
|
+
if (item.retryCount === 1) {
|
|
69
|
+
console.warn(`[Rebound SDK] Connectivity issue sending DLQ event. Retrying in background to guarantee delivery...`);
|
|
70
|
+
}
|
|
71
|
+
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.MemoryQueue = MemoryQueue;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface DlqServiceConfig {
|
|
2
|
+
projectId: string;
|
|
3
|
+
projectSecret: string;
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
maxFailures?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class DlqWrapper {
|
|
8
|
+
private projectId;
|
|
9
|
+
private projectSecret;
|
|
10
|
+
private readonly endpoint;
|
|
11
|
+
constructor(config: DlqServiceConfig);
|
|
12
|
+
execute<T>(fn: () => Promise<T>, payload: any): Promise<T>;
|
|
13
|
+
private reportError;
|
|
14
|
+
private generateFingerprint;
|
|
15
|
+
private encrypt;
|
|
16
|
+
private sendToApi;
|
|
17
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DlqWrapper = void 0;
|
|
7
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
8
|
+
const constants_1 = require("./constants");
|
|
9
|
+
const queue_1 = require("./queue");
|
|
10
|
+
class DlqWrapper {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.projectId = config.projectId;
|
|
13
|
+
this.projectSecret = config.projectSecret;
|
|
14
|
+
// Identifica se é ambiente de teste através do projectSecret (mesma lógica da apiKey no ReboundClient)
|
|
15
|
+
const isTest = config.projectSecret.startsWith('sk_dev_');
|
|
16
|
+
this.endpoint = config.endpoint ||
|
|
17
|
+
(isTest
|
|
18
|
+
? constants_1.REBOUND_API_ENDPOINTS.TEST
|
|
19
|
+
: constants_1.REBOUND_API_ENDPOINTS.PRODUCTION) + '/dlq-injestion'; // Usar o sufixo apropriado
|
|
20
|
+
}
|
|
21
|
+
async execute(fn, payload) {
|
|
22
|
+
try {
|
|
23
|
+
return await fn();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
// MemoryQueue handles retries in the background, making this instant
|
|
27
|
+
this.reportError(error, payload).catch(e => {
|
|
28
|
+
// Silently fail if reportError fails, so we don't block the client logic
|
|
29
|
+
console.error("[Rebound SDK] Error building payload to DLQ", e);
|
|
30
|
+
});
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async reportError(error, payload) {
|
|
35
|
+
const fingerprint = this.generateFingerprint(error);
|
|
36
|
+
const encryptedPayload = this.encrypt(payload);
|
|
37
|
+
const data = {
|
|
38
|
+
projectId: this.projectId,
|
|
39
|
+
fingerprint,
|
|
40
|
+
error: {
|
|
41
|
+
name: error.name,
|
|
42
|
+
message: error.message,
|
|
43
|
+
stack: error.stack
|
|
44
|
+
},
|
|
45
|
+
payload: encryptedPayload
|
|
46
|
+
};
|
|
47
|
+
return this.sendToApi(data);
|
|
48
|
+
}
|
|
49
|
+
generateFingerprint(error) {
|
|
50
|
+
const stack = (error.stack || "").split("\n").slice(0, 3).join("");
|
|
51
|
+
return crypto_1.default.createHash('sha256')
|
|
52
|
+
.update(`${error.name}${stack}`)
|
|
53
|
+
.digest('hex');
|
|
54
|
+
}
|
|
55
|
+
encrypt(payload) {
|
|
56
|
+
const algorithm = 'aes-256-cbc';
|
|
57
|
+
// Use projectSecret to derive a 32-byte key.
|
|
58
|
+
// If it's not 32 bytes, we hash it to ensure it is.
|
|
59
|
+
const key = crypto_1.default.createHash('sha256').update(String(this.projectSecret)).digest('base64').substring(0, 32);
|
|
60
|
+
const iv = crypto_1.default.randomBytes(16);
|
|
61
|
+
const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
|
|
62
|
+
const cipher = crypto_1.default.createCipheriv(algorithm, Buffer.from(key), iv);
|
|
63
|
+
let encrypted = cipher.update(payloadString, 'utf8', 'hex');
|
|
64
|
+
encrypted += cipher.final('hex');
|
|
65
|
+
// We return iv and encrypted data together, maybe separated by a colon
|
|
66
|
+
return `${iv.toString('hex')}:${encrypted}`;
|
|
67
|
+
}
|
|
68
|
+
async sendToApi(data) {
|
|
69
|
+
// Rely on MemoryQueue to guarantee delivery and offload network bottlenecks
|
|
70
|
+
queue_1.MemoryQueue.getInstance().enqueue(this.endpoint, this.projectSecret, data);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.DlqWrapper = DlqWrapper;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ReboundClient } from './core/client';
|
|
2
|
+
export { DlqWrapper } from './core/wrapper';
|
|
3
|
+
export type { DlqServiceConfig } from './core/wrapper';
|
|
4
|
+
export { HTTPAdapter } from './adapters/http.adapter';
|
|
5
|
+
export { KafkaAdapter } from './adapters/kafka.adapter';
|
|
6
|
+
export { ReboundError, ReboundAPIError } from './core/errors';
|
|
7
|
+
export type { DLQPayload, ReboundConfig, SendToDLQOptions } from './models/payload';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReboundAPIError = exports.ReboundError = exports.KafkaAdapter = exports.HTTPAdapter = exports.DlqWrapper = exports.ReboundClient = void 0;
|
|
4
|
+
var client_1 = require("./core/client");
|
|
5
|
+
Object.defineProperty(exports, "ReboundClient", { enumerable: true, get: function () { return client_1.ReboundClient; } });
|
|
6
|
+
var wrapper_1 = require("./core/wrapper");
|
|
7
|
+
Object.defineProperty(exports, "DlqWrapper", { enumerable: true, get: function () { return wrapper_1.DlqWrapper; } });
|
|
8
|
+
var http_adapter_1 = require("./adapters/http.adapter");
|
|
9
|
+
Object.defineProperty(exports, "HTTPAdapter", { enumerable: true, get: function () { return http_adapter_1.HTTPAdapter; } });
|
|
10
|
+
var kafka_adapter_1 = require("./adapters/kafka.adapter");
|
|
11
|
+
Object.defineProperty(exports, "KafkaAdapter", { enumerable: true, get: function () { return kafka_adapter_1.KafkaAdapter; } });
|
|
12
|
+
var errors_1 = require("./core/errors");
|
|
13
|
+
Object.defineProperty(exports, "ReboundError", { enumerable: true, get: function () { return errors_1.ReboundError; } });
|
|
14
|
+
Object.defineProperty(exports, "ReboundAPIError", { enumerable: true, get: function () { return errors_1.ReboundAPIError; } });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface DLQPayload {
|
|
2
|
+
payload: any;
|
|
3
|
+
source: string;
|
|
4
|
+
error?: {
|
|
5
|
+
message: string;
|
|
6
|
+
stack?: string;
|
|
7
|
+
code?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
};
|
|
10
|
+
metadata?: Record<string, any>;
|
|
11
|
+
timestamp?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ReboundConfig {
|
|
14
|
+
apiKey: string;
|
|
15
|
+
endpoint?: string;
|
|
16
|
+
timeout?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SendToDLQOptions {
|
|
19
|
+
payload: any;
|
|
20
|
+
error?: Error | string;
|
|
21
|
+
source?: string;
|
|
22
|
+
metadata?: Record<string, any>;
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rebound-dlq/node",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"files": ["dist"],
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"dev": "tsc --watch",
|
|
10
|
+
"json-server": "npx json-server --watch mock-server.json --port 3005",
|
|
11
|
+
"test:wrapper": "npx ts-node examples/wrapper-example.ts"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/node": "^20.0.0",
|
|
15
|
+
"json-server": "^1.0.0-beta.3",
|
|
16
|
+
"typescript": "^5.0.0"
|
|
17
|
+
}
|
|
18
|
+
}
|