@ido_kawaz/amqp-client 1.0.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 ADDED
@@ -0,0 +1,109 @@
1
+ # @ido_kawaz/amqp-client
2
+
3
+ [![CI](https://github.com/kawaz-video-streaming/amqp-client/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/kawaz-video-streaming/amqp-client/actions/workflows/ci.yml)
4
+
5
+ TypeScript Amqp client for RabbitMQ publishers and consumers.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @ido_kawaz/amqp-client
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```ts
16
+ import { AmqpClient, Consumer, AmqpConfig } from '@ido_kawaz/amqp-client';
17
+
18
+ const config: AmqpConfig = {
19
+ amqpConnectionString: 'localhost',
20
+ amqpUser: 'guest',
21
+ amqpPassword: 'guest',
22
+ };
23
+
24
+ async function bootstrap() {
25
+ const consumer = new Consumer(
26
+ 'orders.queue',
27
+ 'orders.exchange',
28
+ 'orders.created',
29
+ async (message) => {
30
+ if (!message) {
31
+ return;
32
+ }
33
+
34
+ const payload = JSON.parse(message.content.toString());
35
+ console.log('received:', payload);
36
+ },
37
+ );
38
+
39
+ const client = new AmqpClient(config, [consumer]);
40
+ await client.start();
41
+
42
+ client.publish('orders.exchange', 'orders.created', {
43
+ orderId: '123',
44
+ total: 45.5,
45
+ });
46
+
47
+ process.on('SIGTERM', async () => {
48
+ await client.stop();
49
+ });
50
+ }
51
+
52
+ bootstrap().catch(console.error);
53
+ ```
54
+
55
+ ## Configuration
56
+
57
+ `AmqpConfig`
58
+
59
+ - `amqpConnectionString`: RabbitMQ hostname
60
+ - `amqpUser`: RabbitMQ username
61
+ - `amqpPassword`: RabbitMQ password
62
+
63
+ ## API
64
+
65
+ ### `AmqpClient`
66
+
67
+ - `new AmqpClient(config: AmqpConfig, consumers: Consumer[])`
68
+ - `start(): Promise<void>`
69
+ - Connects to RabbitMQ and starts all consumer registrations.
70
+ - `publish<T>(exchange: string, topic: string, message: T): void`
71
+ - JSON serializes payload and publishes it.
72
+ - Throws `AmqpUninitializedError` if `start()` has not been called.
73
+ - Throws `AmqpPublisherError` if publish returns false.
74
+ - `stop(): Promise<void>`
75
+ - Closes channel and connection.
76
+
77
+ ### `Consumer`
78
+
79
+ - `new Consumer(queue, exchange, topic, handler)`
80
+ - Asserts queue and exchange and binds queue to topic.
81
+ - Calls handler for each message.
82
+ - `ack`s on success.
83
+ - `nack`s with requeue logic for `AmqpRetriableError`.
84
+ - `nack`s without requeue for all other errors.
85
+
86
+ ## Errors
87
+
88
+ - `AmqpError`
89
+ - `AmqpConnectionError`
90
+ - `AmqpUninitializedError`
91
+ - `AmqpPublisherError`
92
+ - `AmqpConsumerError`
93
+ - `AmqpRetriableError`
94
+ - `AmqpFatalError`
95
+
96
+ ## Development
97
+
98
+ - `npm run build` — clean and compile TypeScript
99
+ - `npm run build:watch` — compile TypeScript in watch mode
100
+ - `npm run clean` — remove build output
101
+ - `npm test` — run unit tests
102
+
103
+ ## Publish
104
+
105
+ - `npm run publish`
106
+ - Cleans workspace deeply
107
+ - Reinstalls dependencies
108
+ - Builds library
109
+ - Publishes with public access
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=amqpClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amqpClient.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/amqpClient.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
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
+ const amqplib_1 = __importDefault(require("amqplib"));
7
+ const amqpClient_1 = require("../amqpClient");
8
+ const errors_1 = require("../errors");
9
+ jest.mock('amqplib', () => ({
10
+ __esModule: true,
11
+ default: {
12
+ connect: jest.fn(),
13
+ },
14
+ }));
15
+ describe('AmqpClient', () => {
16
+ const baseConfig = {
17
+ amqpConnectionString: 'localhost',
18
+ amqpUser: 'guest',
19
+ amqpPassword: 'guest',
20
+ };
21
+ it('starts client and starts registered consumers', async () => {
22
+ const consumerStart = jest.fn().mockResolvedValue(undefined);
23
+ const consumer = { start: consumerStart };
24
+ const channel = {
25
+ publish: jest.fn().mockReturnValue(true),
26
+ close: jest.fn().mockResolvedValue(undefined),
27
+ };
28
+ const connection = {
29
+ createChannel: jest.fn().mockResolvedValue(channel),
30
+ close: jest.fn().mockResolvedValue(undefined),
31
+ };
32
+ amqplib_1.default.connect.mockResolvedValue(connection);
33
+ const client = new amqpClient_1.AmqpClient(baseConfig, [consumer]);
34
+ await client.start();
35
+ expect(amqplib_1.default.connect).toHaveBeenCalledWith({
36
+ username: 'guest',
37
+ password: 'guest',
38
+ hostname: 'localhost',
39
+ });
40
+ expect(connection.createChannel).toHaveBeenCalledTimes(1);
41
+ expect(consumerStart).toHaveBeenCalledWith(channel);
42
+ });
43
+ it('throws AmqpConnectionError when connect fails', async () => {
44
+ amqplib_1.default.connect.mockRejectedValue(new Error('boom'));
45
+ const client = new amqpClient_1.AmqpClient(baseConfig, []);
46
+ await expect(client.start()).rejects.toBeInstanceOf(errors_1.AmqpConnectionError);
47
+ });
48
+ it('throws AmqpUninitializedError when publishing before start', () => {
49
+ const client = new amqpClient_1.AmqpClient(baseConfig, []);
50
+ expect(() => client.publish('ex', 'topic', { x: 1 })).toThrow(errors_1.AmqpUninitializedError);
51
+ });
52
+ it('throws AmqpPublisherError when publish returns false', async () => {
53
+ const channel = {
54
+ publish: jest.fn().mockReturnValue(false),
55
+ close: jest.fn().mockResolvedValue(undefined),
56
+ };
57
+ const connection = {
58
+ createChannel: jest.fn().mockResolvedValue(channel),
59
+ close: jest.fn().mockResolvedValue(undefined),
60
+ };
61
+ amqplib_1.default.connect.mockResolvedValue(connection);
62
+ const client = new amqpClient_1.AmqpClient(baseConfig, []);
63
+ await client.start();
64
+ expect(() => client.publish('ex', 'rk', { ok: true })).toThrow(errors_1.AmqpPublisherError);
65
+ });
66
+ it('stops by closing channel and connection', async () => {
67
+ const channel = {
68
+ publish: jest.fn().mockReturnValue(true),
69
+ close: jest.fn().mockResolvedValue(undefined),
70
+ };
71
+ const connection = {
72
+ createChannel: jest.fn().mockResolvedValue(channel),
73
+ close: jest.fn().mockResolvedValue(undefined),
74
+ };
75
+ amqplib_1.default.connect.mockResolvedValue(connection);
76
+ const client = new amqpClient_1.AmqpClient(baseConfig, []);
77
+ await client.start();
78
+ await client.stop();
79
+ expect(channel.close).toHaveBeenCalledTimes(1);
80
+ expect(connection.close).toHaveBeenCalledTimes(1);
81
+ });
82
+ });
83
+ //# sourceMappingURL=amqpClient.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amqpClient.test.js","sourceRoot":"","sources":["../../src/__tests__/amqpClient.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=consumer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/consumer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const consumer_1 = require("../consumer");
4
+ const errors_1 = require("../errors");
5
+ describe('Consumer', () => {
6
+ function createMessage(deliveryCount) {
7
+ return {
8
+ properties: {
9
+ headers: deliveryCount === undefined ? {} : { 'x-delivery-count': deliveryCount },
10
+ },
11
+ content: Buffer.from(JSON.stringify({ id: '1' })),
12
+ };
13
+ }
14
+ function createChannel() {
15
+ return {
16
+ assertQueue: jest.fn().mockResolvedValue(undefined),
17
+ assertExchange: jest.fn().mockResolvedValue(undefined),
18
+ bindQueue: jest.fn().mockResolvedValue(undefined),
19
+ consume: jest.fn(),
20
+ ack: jest.fn(),
21
+ nack: jest.fn(),
22
+ };
23
+ }
24
+ it('binds queue and acknowledges message on success', async () => {
25
+ const handler = jest.fn().mockResolvedValue(undefined);
26
+ const consumer = new consumer_1.Consumer('orders.queue', 'orders.exchange', 'orders.created', handler);
27
+ const channel = createChannel();
28
+ const message = createMessage();
29
+ channel.consume.mockImplementation(async (_queue, onMessage) => {
30
+ await onMessage(message);
31
+ return { consumerTag: 'tag' };
32
+ });
33
+ await consumer.start(channel);
34
+ expect(channel.assertQueue).toHaveBeenCalledWith('orders.queue', {
35
+ durable: true,
36
+ arguments: { 'x-queue-type': 'quorum' },
37
+ });
38
+ expect(channel.assertExchange).toHaveBeenCalledWith('orders.exchange', 'topic', { durable: true });
39
+ expect(channel.bindQueue).toHaveBeenCalledWith('orders.queue', 'orders.exchange', 'orders.created');
40
+ expect(handler).toHaveBeenCalledWith(message);
41
+ expect(channel.ack).toHaveBeenCalledWith(message);
42
+ expect(channel.nack).not.toHaveBeenCalled();
43
+ });
44
+ it('requeues retriable error when delivery count is below retry limit', async () => {
45
+ const handler = jest.fn().mockRejectedValue(new errors_1.AmqpRetriableError(new Error('retry'), 3));
46
+ const consumer = new consumer_1.Consumer('q', 'ex', 'topic', handler);
47
+ const channel = createChannel();
48
+ const message = createMessage(1);
49
+ channel.consume.mockImplementation(async (_queue, onMessage) => {
50
+ await onMessage(message);
51
+ return { consumerTag: 'tag' };
52
+ });
53
+ await consumer.start(channel);
54
+ expect(channel.nack).toHaveBeenCalledWith(message, false, true);
55
+ });
56
+ it('does not requeue retriable error after retry limit', async () => {
57
+ const handler = jest.fn().mockRejectedValue(new errors_1.AmqpRetriableError(new Error('retry'), 2));
58
+ const consumer = new consumer_1.Consumer('q', 'ex', 'topic', handler);
59
+ const channel = createChannel();
60
+ const message = createMessage('2');
61
+ channel.consume.mockImplementation(async (_queue, onMessage) => {
62
+ await onMessage(message);
63
+ return { consumerTag: 'tag' };
64
+ });
65
+ await consumer.start(channel);
66
+ expect(channel.nack).toHaveBeenCalledWith(message, false, false);
67
+ });
68
+ it('nacks without requeue for non-retriable errors', async () => {
69
+ const handler = jest.fn().mockRejectedValue(new Error('bad-message'));
70
+ const consumer = new consumer_1.Consumer('q', 'ex', 'topic', handler);
71
+ const channel = createChannel();
72
+ const message = createMessage();
73
+ channel.consume.mockImplementation(async (_queue, onMessage) => {
74
+ await onMessage(message);
75
+ return { consumerTag: 'tag' };
76
+ });
77
+ await consumer.start(channel);
78
+ expect(channel.nack).toHaveBeenCalledWith(message, false, false);
79
+ });
80
+ });
81
+ //# sourceMappingURL=consumer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.test.js","sourceRoot":"","sources":["../../src/__tests__/consumer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Channel, ChannelModel } from 'amqplib';
2
+ import { AmqpConfig } from './config';
3
+ import { Consumer } from './consumer';
4
+ export declare class AmqpClient {
5
+ private readonly config;
6
+ private readonly consumers;
7
+ connection: ChannelModel | undefined;
8
+ channel: Channel | undefined;
9
+ constructor(config: AmqpConfig, consumers: Consumer[]);
10
+ start(): Promise<void>;
11
+ publish<T>(exchange: string, topic: string, message: T): void;
12
+ stop(): Promise<void>;
13
+ }
14
+ //# sourceMappingURL=amqpClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amqpClient.d.ts","sourceRoot":"","sources":["../src/amqpClient.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,qBAAa,UAAU;IAGP,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAc,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF3E,UAAU,EAAE,YAAY,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;gBACA,MAAM,EAAE,UAAU,EAAmB,SAAS,EAAE,QAAQ,EAAE;IAGjF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI;IAWvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ9B"}
@@ -0,0 +1,52 @@
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.AmqpClient = void 0;
7
+ const amqplib_1 = __importDefault(require("amqplib"));
8
+ const errors_1 = require("./errors");
9
+ const ramda_1 = require("ramda");
10
+ class AmqpClient {
11
+ constructor(config, consumers) {
12
+ this.config = config;
13
+ this.consumers = consumers;
14
+ }
15
+ async start() {
16
+ try {
17
+ const connection = await amqplib_1.default.connect({
18
+ username: this.config.amqpUser,
19
+ password: this.config.amqpPassword,
20
+ hostname: this.config.amqpConnectionString,
21
+ });
22
+ this.connection = connection;
23
+ this.channel = await connection.createChannel().then(async (channel) => {
24
+ await Promise.all(this.consumers.map((consumer) => consumer.start(channel)));
25
+ return channel;
26
+ });
27
+ }
28
+ catch (error) {
29
+ throw new errors_1.AmqpConnectionError(error.message, { amqpConnectionString: this.config.amqpConnectionString });
30
+ }
31
+ }
32
+ publish(exchange, topic, message) {
33
+ if ((0, ramda_1.isNil)(this.channel)) {
34
+ throw new errors_1.AmqpUninitializedError();
35
+ }
36
+ const messageData = Buffer.from(JSON.stringify(message));
37
+ const isPublished = this.channel.publish(exchange, topic, messageData);
38
+ if (!isPublished) {
39
+ throw new errors_1.AmqpPublisherError({ exchange, topic, message });
40
+ }
41
+ }
42
+ async stop() {
43
+ if ((0, ramda_1.isNotNil)(this.channel)) {
44
+ await this.channel.close();
45
+ }
46
+ if ((0, ramda_1.isNotNil)(this.connection)) {
47
+ await this.connection.close();
48
+ }
49
+ }
50
+ }
51
+ exports.AmqpClient = AmqpClient;
52
+ //# sourceMappingURL=amqpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amqpClient.js","sourceRoot":"","sources":["../src/amqpClient.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAsD;AAEtD,qCAA2F;AAC3F,iCAAwC;AAGxC,MAAa,UAAU;IAGnB,YAA6B,MAAkB,EAAmB,SAAqB;QAA1D,WAAM,GAAN,MAAM,CAAY;QAAmB,cAAS,GAAT,SAAS,CAAY;IACvF,CAAC;IAED,KAAK,CAAC,KAAK;QACP,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,iBAAI,CAAC,OAAO,CAAC;gBAClC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;gBAC9B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;gBAClC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB;aAC7C,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;YAC7B,IAAI,CAAC,OAAO,GAAG,MAAM,UAAU,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBACnE,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBAC7E,OAAO,OAAO,CAAC;YACnB,CAAC,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,4BAAmB,CAAE,KAAe,CAAC,OAAO,EAAE,EAAE,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACxH,CAAC;IACL,CAAC;IAED,OAAO,CAAI,QAAgB,EAAE,KAAa,EAAE,OAAU;QAClD,IAAI,IAAA,aAAK,EAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,+BAAsB,EAAE,CAAC;QACvC,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;QACvE,IAAI,CAAC,WAAW,EAAE,CAAC;YACf,MAAM,IAAI,2BAAkB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/D,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI;QACN,IAAI,IAAA,gBAAQ,EAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,IAAA,gBAAQ,EAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QAClC,CAAC;IACL,CAAC;CACJ;AA1CD,gCA0CC"}
@@ -0,0 +1,6 @@
1
+ export interface AmqpConfig {
2
+ amqpConnectionString: string;
3
+ amqpUser: string;
4
+ amqpPassword: string;
5
+ }
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACxB"}
package/dist/config.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import amqp, { Channel } from 'amqplib';
2
+ export declare class Consumer {
3
+ private readonly queue;
4
+ private readonly exchange;
5
+ private readonly topic;
6
+ private readonly handler;
7
+ constructor(queue: string, exchange: string, topic: string, handler: (message: amqp.Message | null) => Promise<void>);
8
+ start(channel: Channel): Promise<void>;
9
+ private shouldRequeue;
10
+ private getDeliveryCount;
11
+ private createAndBindQueue;
12
+ private assertQueue;
13
+ private assertExchange;
14
+ private bindQueue;
15
+ }
16
+ //# sourceMappingURL=consumer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.d.ts","sourceRoot":"","sources":["../src/consumer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxC,qBAAa,QAAQ;IAEb,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAHP,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC;IAGvE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB5C,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,gBAAgB;YAYV,kBAAkB;YAMlB,WAAW;YAIX,cAAc;YAId,SAAS;CAG1B"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Consumer = void 0;
4
+ const errors_1 = require("./errors");
5
+ class Consumer {
6
+ constructor(queue, exchange, topic, handler) {
7
+ this.queue = queue;
8
+ this.exchange = exchange;
9
+ this.topic = topic;
10
+ this.handler = handler;
11
+ }
12
+ async start(channel) {
13
+ await this.createAndBindQueue(channel, this.queue, this.exchange, this.topic);
14
+ await channel.consume(this.queue, async (message) => {
15
+ if (!message) {
16
+ return;
17
+ }
18
+ try {
19
+ await this.handler(message);
20
+ channel.ack(message);
21
+ }
22
+ catch (error) {
23
+ if (error instanceof errors_1.AmqpRetriableError) {
24
+ channel.nack(message, false, this.shouldRequeue(message, error.retryLimit));
25
+ }
26
+ else {
27
+ channel.nack(message, false, false);
28
+ }
29
+ }
30
+ });
31
+ }
32
+ shouldRequeue(message, retryLimit) {
33
+ return this.getDeliveryCount(message) < retryLimit;
34
+ }
35
+ getDeliveryCount(message) {
36
+ const deliveryCount = message.properties.headers?.['x-delivery-count'];
37
+ if (typeof deliveryCount === 'number') {
38
+ return deliveryCount;
39
+ }
40
+ else if (typeof deliveryCount === 'string') {
41
+ const parsedValue = Number(deliveryCount);
42
+ if (!Number.isNaN(parsedValue)) {
43
+ return parsedValue;
44
+ }
45
+ }
46
+ return 0;
47
+ }
48
+ async createAndBindQueue(channel, queue, exchange, topic) {
49
+ await this.assertQueue(channel, queue);
50
+ await this.assertExchange(channel, exchange);
51
+ await this.bindQueue(channel, queue, exchange, topic);
52
+ }
53
+ async assertQueue(channel, queue) {
54
+ await channel.assertQueue(queue, { durable: true, arguments: { 'x-queue-type': 'quorum' } });
55
+ }
56
+ async assertExchange(channel, exchange) {
57
+ await channel.assertExchange(exchange, "topic", { durable: true });
58
+ }
59
+ async bindQueue(channel, queue, exchange, topic) {
60
+ await channel.bindQueue(queue, exchange, topic);
61
+ }
62
+ }
63
+ exports.Consumer = Consumer;
64
+ //# sourceMappingURL=consumer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer.js","sourceRoot":"","sources":["../src/consumer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { AmqpConnectionArgs, AmqpPublishArgs } from "./types";
2
+ export declare class AmqpError extends Error {
3
+ constructor(message: string, args?: Object);
4
+ }
5
+ export declare class AmqpUninitializedError extends AmqpError {
6
+ constructor();
7
+ }
8
+ export declare class AmqpConnectionError extends AmqpError {
9
+ constructor(errorMessage: string, args: AmqpConnectionArgs);
10
+ }
11
+ export declare class AmqpPublisherError<T> extends AmqpError {
12
+ constructor(args: AmqpPublishArgs<T>);
13
+ }
14
+ export declare class AmqpConsumerError extends AmqpError {
15
+ constructor(error: Error);
16
+ }
17
+ export declare class AmqpRetriableError extends AmqpConsumerError {
18
+ readonly retryLimit: number;
19
+ constructor(error: Error, retryLimit?: number);
20
+ }
21
+ export declare class AmqpFatalError extends AmqpConsumerError {
22
+ constructor(error: Error);
23
+ }
24
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE9D,qBAAa,SAAU,SAAQ,KAAK;gBACpB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAG7C;AAED,qBAAa,sBAAuB,SAAQ,SAAS;;CAIpD;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBAClC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB;CAG7D;AAED,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,SAAS;gBACpC,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;CAGvC;AAED,qBAAa,iBAAkB,SAAQ,SAAS;gBAChC,KAAK,EAAE,KAAK;CAG3B;AAED,qBAAa,kBAAmB,SAAQ,iBAAiB;aACX,UAAU,EAAE,MAAM;gBAAhD,KAAK,EAAE,KAAK,EAAkB,UAAU,GAAE,MAAU;CAGnE;AAED,qBAAa,cAAe,SAAQ,iBAAiB;gBACrC,KAAK,EAAE,KAAK;CAG3B"}
package/dist/errors.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AmqpFatalError = exports.AmqpRetriableError = exports.AmqpConsumerError = exports.AmqpPublisherError = exports.AmqpConnectionError = exports.AmqpUninitializedError = exports.AmqpError = void 0;
4
+ class AmqpError extends Error {
5
+ constructor(message, args) {
6
+ super(`amqp error: ${message}, ${args ? JSON.stringify(args) : ''}`);
7
+ }
8
+ }
9
+ exports.AmqpError = AmqpError;
10
+ class AmqpUninitializedError extends AmqpError {
11
+ constructor() {
12
+ super("AMQP client is not initialized");
13
+ }
14
+ }
15
+ exports.AmqpUninitializedError = AmqpUninitializedError;
16
+ class AmqpConnectionError extends AmqpError {
17
+ constructor(errorMessage, args) {
18
+ super(`Failed to connect to AMQP server: ${errorMessage}`, args);
19
+ }
20
+ }
21
+ exports.AmqpConnectionError = AmqpConnectionError;
22
+ class AmqpPublisherError extends AmqpError {
23
+ constructor(args) {
24
+ super("Failed to publish message", args);
25
+ }
26
+ }
27
+ exports.AmqpPublisherError = AmqpPublisherError;
28
+ class AmqpConsumerError extends AmqpError {
29
+ constructor(error) {
30
+ super("Failed to consume message", { error });
31
+ }
32
+ }
33
+ exports.AmqpConsumerError = AmqpConsumerError;
34
+ class AmqpRetriableError extends AmqpConsumerError {
35
+ constructor(error, retryLimit = 0) {
36
+ super(error);
37
+ this.retryLimit = retryLimit;
38
+ }
39
+ }
40
+ exports.AmqpRetriableError = AmqpRetriableError;
41
+ class AmqpFatalError extends AmqpConsumerError {
42
+ constructor(error) {
43
+ super(error);
44
+ }
45
+ }
46
+ exports.AmqpFatalError = AmqpFatalError;
47
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAEA,MAAa,SAAU,SAAQ,KAAK;IAChC,YAAY,OAAe,EAAE,IAAa;QACtC,KAAK,CAAC,eAAe,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;CACJ;AAJD,8BAIC;AAED,MAAa,sBAAuB,SAAQ,SAAS;IACjD;QACI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC5C,CAAC;CACJ;AAJD,wDAIC;AAED,MAAa,mBAAoB,SAAQ,SAAS;IAC9C,YAAY,YAAoB,EAAE,IAAwB;QACtD,KAAK,CAAC,qCAAqC,YAAY,EAAE,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;CACJ;AAJD,kDAIC;AAED,MAAa,kBAAsB,SAAQ,SAAS;IAChD,YAAY,IAAwB;QAChC,KAAK,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC;CACJ;AAJD,gDAIC;AAED,MAAa,iBAAkB,SAAQ,SAAS;IAC5C,YAAY,KAAY;QACpB,KAAK,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC;CACJ;AAJD,8CAIC;AAED,MAAa,kBAAmB,SAAQ,iBAAiB;IACrD,YAAY,KAAY,EAAkB,aAAqB,CAAC;QAC5D,KAAK,CAAC,KAAK,CAAC,CAAC;QADyB,eAAU,GAAV,UAAU,CAAY;IAEhE,CAAC;CACJ;AAJD,gDAIC;AAED,MAAa,cAAe,SAAQ,iBAAiB;IACjD,YAAY,KAAY;QACpB,KAAK,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;CACJ;AAJD,wCAIC"}
@@ -0,0 +1,5 @@
1
+ export { AmqpClient } from './amqpClient';
2
+ export { AmqpConfig } from './config';
3
+ export { Consumer } from './consumer';
4
+ export { AmqpError, AmqpConnectionError, AmqpPublisherError, AmqpConsumerError, AmqpRetriableError, AmqpFatalError, } from './errors';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACH,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,GACjB,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AmqpFatalError = exports.AmqpRetriableError = exports.AmqpConsumerError = exports.AmqpPublisherError = exports.AmqpConnectionError = exports.AmqpError = exports.Consumer = exports.AmqpClient = void 0;
4
+ var amqpClient_1 = require("./amqpClient");
5
+ Object.defineProperty(exports, "AmqpClient", { enumerable: true, get: function () { return amqpClient_1.AmqpClient; } });
6
+ var consumer_1 = require("./consumer");
7
+ Object.defineProperty(exports, "Consumer", { enumerable: true, get: function () { return consumer_1.Consumer; } });
8
+ var errors_1 = require("./errors");
9
+ Object.defineProperty(exports, "AmqpError", { enumerable: true, get: function () { return errors_1.AmqpError; } });
10
+ Object.defineProperty(exports, "AmqpConnectionError", { enumerable: true, get: function () { return errors_1.AmqpConnectionError; } });
11
+ Object.defineProperty(exports, "AmqpPublisherError", { enumerable: true, get: function () { return errors_1.AmqpPublisherError; } });
12
+ Object.defineProperty(exports, "AmqpConsumerError", { enumerable: true, get: function () { return errors_1.AmqpConsumerError; } });
13
+ Object.defineProperty(exports, "AmqpRetriableError", { enumerable: true, get: function () { return errors_1.AmqpRetriableError; } });
14
+ Object.defineProperty(exports, "AmqpFatalError", { enumerable: true, get: function () { return errors_1.AmqpFatalError; } });
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AAEnB,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AACjB,mCAOkB;AANd,mGAAA,SAAS,OAAA;AACT,6GAAA,mBAAmB,OAAA;AACnB,4GAAA,kBAAkB,OAAA;AAClB,2GAAA,iBAAiB,OAAA;AACjB,4GAAA,kBAAkB,OAAA;AAClB,wGAAA,cAAc,OAAA"}
@@ -0,0 +1,9 @@
1
+ export interface AmqpConnectionArgs {
2
+ amqpConnectionString: string;
3
+ }
4
+ export interface AmqpPublishArgs<T> {
5
+ exchange: string;
6
+ topic: string;
7
+ message: T;
8
+ }
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IAC/B,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@ido_kawaz/amqp-client",
3
+ "version": "1.0.0",
4
+ "description": "AMQP client library for Kawaz Plus services",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "clean": "rimraf dist",
12
+ "clean:advanced": "rimraf dist node_modules package-lock.json",
13
+ "build": "npm run clean && tsc",
14
+ "build:watch": "tsc --watch",
15
+ "build:advanced": "npm run clean:advanced && npm i && tsc",
16
+ "test": "npm run build && jest --runInBand",
17
+ "publish": "npm run build:advanced && npm publish --access public"
18
+ },
19
+ "keywords": [
20
+ "amqp",
21
+ "rabbitmq",
22
+ "messaging"
23
+ ],
24
+ "author": "",
25
+ "license": "MIT",
26
+ "dependencies": {
27
+ "amqplib": "^0.10.9",
28
+ "ramda": "^0.32.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/amqplib": "^0.10.8",
32
+ "@types/jest": "^30.0.0",
33
+ "@types/node": "^20.0.0",
34
+ "@types/ramda": "^0.31.1",
35
+ "jest": "^30.0.0",
36
+ "rimraf": "^6.1.3",
37
+ "ts-jest": "^29.4.6",
38
+ "typescript": "^5.9.3"
39
+ }
40
+ }