@palmetto/pubsub 1.0.2 → 1.0.4

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.
@@ -1,4 +1,4 @@
1
- import { MessageContext, PubSubConfiguration } from "../interfaces";
1
+ import { MessageContext, PubSubConfiguration } from "../interfaces.js";
2
2
  export interface BullMqQueueConfiguration extends PubSubConfiguration {
3
3
  /**
4
4
  * The name of the queue
@@ -1,6 +1,6 @@
1
1
  import type * as bullmq from "bullmq";
2
- import { Logger, PublisherProvider } from "../interfaces";
3
- import { BullMqQueueConfiguration } from "./config";
2
+ import { Logger, PublisherProvider } from "../interfaces.js";
3
+ import { BullMqQueueConfiguration } from "./config.js";
4
4
  export declare class BullMqPublisher implements PublisherProvider {
5
5
  private readonly connection;
6
6
  private readonly logger;
@@ -10,14 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BullMqPublisher = void 0;
13
- const connection_1 = require("./connection");
14
- const lazy_load_1 = require("../lazy-load");
13
+ const connection_js_1 = require("./connection.js");
14
+ const lazy_load_js_1 = require("../lazy-load.js");
15
15
  class BullMqPublisher {
16
16
  constructor(connection, logger) {
17
17
  this.connection = connection;
18
18
  this.logger = logger;
19
19
  this.queues = new Map();
20
- this.transport = connection_1.BULLMQ_TRANSPORT;
20
+ this.transport = connection_js_1.BULLMQ_TRANSPORT;
21
21
  }
22
22
  getQueue(config) {
23
23
  return __awaiter(this, void 0, void 0, function* () {
@@ -25,7 +25,7 @@ class BullMqPublisher {
25
25
  if (queue) {
26
26
  return queue;
27
27
  }
28
- const BullMqPackage = yield (0, lazy_load_1.lazyLoad)({
28
+ const BullMqPackage = yield (0, lazy_load_js_1.lazyLoad)({
29
29
  packageName: "bullmq",
30
30
  context: "BullMqPublisher",
31
31
  });
@@ -41,7 +41,7 @@ class BullMqPublisher {
41
41
  var _a, _b;
42
42
  const queue = yield this.getQueue(config);
43
43
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publishing message to ${queue.name} - ${message}`);
44
- yield queue.add(config.job || connection_1.BULLMQ_DEFAULTJOB, message, {
44
+ yield queue.add(config.job || connection_js_1.BULLMQ_DEFAULTJOB, message, {
45
45
  attempts: config.retries,
46
46
  backoff: {
47
47
  type: "fixed",
@@ -1,5 +1,5 @@
1
- import { Logger, MessageContext, MessageResult, PubSubProvider, StopSubscribe } from "../interfaces";
2
- import { BullMqQueueConfiguration } from "./config";
1
+ import { Logger, MessageContext, MessageResult, PubSubProvider, StopSubscribe } from "../interfaces.js";
2
+ import { BullMqQueueConfiguration } from "./config.js";
3
3
  import type { ConnectionOptions } from "bullmq";
4
4
  export declare class BullMqPubSubProvider implements PubSubProvider {
5
5
  private readonly publisher;
@@ -10,14 +10,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BullMqPubSubProvider = void 0;
13
- const connection_1 = require("./connection");
14
- const publisher_1 = require("./publisher");
15
- const subscriber_1 = require("./subscriber");
13
+ const connection_js_1 = require("./connection.js");
14
+ const publisher_js_1 = require("./publisher.js");
15
+ const subscriber_js_1 = require("./subscriber.js");
16
16
  class BullMqPubSubProvider {
17
17
  constructor(connection, logger) {
18
- this.transport = connection_1.BULLMQ_TRANSPORT;
19
- this.publisher = new publisher_1.BullMqPublisher(connection, logger);
20
- this.subscriber = new subscriber_1.BullMqSubscriber(connection, logger);
18
+ this.transport = connection_js_1.BULLMQ_TRANSPORT;
19
+ this.publisher = new publisher_js_1.BullMqPublisher(connection, logger);
20
+ this.subscriber = new subscriber_js_1.BullMqSubscriber(connection, logger);
21
21
  }
22
22
  publish(config, message) {
23
23
  return this.publisher.publish(config, message);
@@ -1,6 +1,6 @@
1
1
  import type * as bullmq from "bullmq";
2
- import { Logger, MessageResult, StopSubscribe, SubscriberProvider } from "../interfaces";
3
- import { BullMqMessageContext, BullMqQueueConfiguration } from "./config";
2
+ import { Logger, MessageResult, StopSubscribe, SubscriberProvider } from "../interfaces.js";
3
+ import { BullMqMessageContext, BullMqQueueConfiguration } from "./config.js";
4
4
  declare class SubscribedMessage {
5
5
  private readonly owner;
6
6
  private readonly worker;
@@ -10,9 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BullMqSubscriber = exports.MessageRetryError = exports.MessageFailError = void 0;
13
- const interfaces_1 = require("../interfaces");
14
- const connection_1 = require("./connection");
15
- const lazy_load_1 = require("../lazy-load");
13
+ const interfaces_js_1 = require("../interfaces.js");
14
+ const connection_js_1 = require("./connection.js");
15
+ const lazy_load_js_1 = require("../lazy-load.js");
16
+ const create_log_error_payload_js_1 = require("../create-log-error-payload.js");
16
17
  class SubscribedMessage {
17
18
  constructor(owner, worker, logger) {
18
19
  this.owner = owner;
@@ -45,7 +46,7 @@ class BullMqSubscriber {
45
46
  this.connection = connection;
46
47
  this.logger = logger;
47
48
  this.stops = new Map();
48
- this.transport = connection_1.BULLMQ_TRANSPORT;
49
+ this.transport = connection_js_1.BULLMQ_TRANSPORT;
49
50
  }
50
51
  removeSubscriber(subscribedMessage) {
51
52
  for (const [key, value] of this.stops) {
@@ -58,7 +59,7 @@ class BullMqSubscriber {
58
59
  startSubscribe(config, onMessage) {
59
60
  return __awaiter(this, void 0, void 0, function* () {
60
61
  var _a, _b, _c, _d;
61
- const BullMqPackage = yield (0, lazy_load_1.lazyLoad)({
62
+ const BullMqPackage = yield (0, lazy_load_js_1.lazyLoad)({
62
63
  packageName: "bullmq",
63
64
  context: "BullMqSubscriber",
64
65
  });
@@ -70,10 +71,10 @@ class BullMqSubscriber {
70
71
  // lastSent: new Date(job.attemptsStarted),
71
72
  };
72
73
  const result = yield onMessage(job.data, context);
73
- if (result === interfaces_1.MessageResult.Ok) {
74
+ if (result === interfaces_js_1.MessageResult.Ok) {
74
75
  return context.reply;
75
76
  }
76
- if (result === interfaces_1.MessageResult.Retry) {
77
+ if (result === interfaces_js_1.MessageResult.Retry) {
77
78
  throw new MessageRetryError();
78
79
  }
79
80
  throw new BullMqPackage.UnrecoverableError("Handler asked to fail this job");
@@ -98,7 +99,10 @@ class BullMqSubscriber {
98
99
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `BullMq PubSub subscriber stopped for ${worker.name}`);
99
100
  })
100
101
  .catch((err) => {
101
- this.logger.error(`BullMq PubSub subscriber crashed for ${worker.name}`, err);
102
+ this.logger.error({
103
+ message: `BullMq PubSub subscriber crashed for ${worker.name}`,
104
+ error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
105
+ });
102
106
  });
103
107
  const subscribedMessage = new SubscribedMessage(this, worker, this.logger);
104
108
  this.stops.set(config, subscribedMessage);
@@ -0,0 +1,8 @@
1
+ export interface LogErrorPayload {
2
+ message: string;
3
+ kind: string;
4
+ stack?: string;
5
+ cause?: unknown;
6
+ statusCode?: number;
7
+ }
8
+ export declare function createLogErrorPayload(error: unknown): LogErrorPayload;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /* compare to code in @palmetto/nestjs-logger */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.createLogErrorPayload = createLogErrorPayload;
5
+ function createLogErrorPayload(error) {
6
+ if (error instanceof Error) {
7
+ const statusCode = "statusCode" in error && typeof error.statusCode === "number"
8
+ ? error.statusCode
9
+ : undefined;
10
+ return {
11
+ kind: error.name,
12
+ message: error.message,
13
+ stack: error.stack,
14
+ cause: error.cause,
15
+ statusCode,
16
+ };
17
+ }
18
+ if (typeof error === "object" && error !== null) {
19
+ let kind;
20
+ let message;
21
+ let stack;
22
+ let cause;
23
+ let statusCode;
24
+ if ("name" in error && typeof error.name === "string") {
25
+ kind = error.name;
26
+ }
27
+ else {
28
+ kind = "Error";
29
+ }
30
+ if ("message" in error && typeof error.message === "string") {
31
+ message = error.message;
32
+ }
33
+ else {
34
+ message = JSON.stringify(error);
35
+ }
36
+ if ("stack" in error && typeof error.stack === "string") {
37
+ stack = error.stack;
38
+ }
39
+ if ("cause" in error) {
40
+ cause = error.cause;
41
+ }
42
+ if ("statusCode" in error && typeof error.statusCode === "number") {
43
+ statusCode = error.statusCode;
44
+ }
45
+ return { kind, message, stack, cause, statusCode };
46
+ }
47
+ return { kind: "Error", message: String(error) };
48
+ }
@@ -1,4 +1,4 @@
1
- import { BaseMessage, Logger, PublisherProvider, PubSubConfiguration } from "./interfaces";
1
+ import { BaseMessage, Logger, PublisherProvider, PubSubConfiguration } from "./interfaces.js";
2
2
  export declare class Publisher {
3
3
  private readonly logger;
4
4
  private readonly hashes;
package/dist/publisher.js CHANGED
@@ -13,7 +13,7 @@ exports.Publisher = void 0;
13
13
  const v4_1 = require("zod/v4");
14
14
  const uuid_1 = require("uuid");
15
15
  const crypto_hash_1 = require("crypto-hash");
16
- const errors_1 = require("./errors");
16
+ const errors_js_1 = require("./errors.js");
17
17
  class Publisher {
18
18
  constructor(logger, providers) {
19
19
  this.logger = logger;
@@ -67,7 +67,7 @@ class Publisher {
67
67
  const json = JSON.stringify(message);
68
68
  const check = schema.safeParse(JSON.parse(json));
69
69
  if (!check.success) {
70
- throw new errors_1.SchemaValidationError(`Schema did not accept the published message: ${check.error.message}`);
70
+ throw new errors_js_1.SchemaValidationError(`Schema did not accept the published message: ${check.error.message}`);
71
71
  }
72
72
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publisher publishing message for ${provider.transport}`);
73
73
  yield provider.publish(config, json);
@@ -84,7 +84,7 @@ class Publisher {
84
84
  const { transport } = config;
85
85
  const provider = this.publisherProviders.get(transport);
86
86
  if (!provider) {
87
- throw new errors_1.MissingPubSubProviderError(`No provider configured for ${transport}`);
87
+ throw new errors_js_1.MissingPubSubProviderError(`No provider configured for ${transport}`);
88
88
  }
89
89
  return provider;
90
90
  }
@@ -1,4 +1,4 @@
1
- import { MessageContext, PubSubConfiguration } from "../interfaces";
1
+ import { MessageContext, PubSubConfiguration } from "../interfaces.js";
2
2
  export interface RabbitMqConnectionConfig {
3
3
  /**
4
4
  * The URL to the RabbitMQ host
@@ -6,7 +6,7 @@ exports.getExchangeName = getExchangeName;
6
6
  exports.getQueueType = getQueueType;
7
7
  exports.getRoutingKey = getRoutingKey;
8
8
  exports.getExchangeType = getExchangeType;
9
- const errors_1 = require("../errors");
9
+ const errors_js_1 = require("../errors.js");
10
10
  /**
11
11
  * Default binding key for all messages
12
12
  */
@@ -26,7 +26,7 @@ function getQueueName(config) {
26
26
  let queueName = config.name;
27
27
  if (config.exchangeType === "topic") {
28
28
  if (!config.topicSubscriberName) {
29
- throw new errors_1.ConfigurationError("Topic queues must have a subscriber name");
29
+ throw new errors_js_1.ConfigurationError("Topic queues must have a subscriber name");
30
30
  }
31
31
  queueName += "." + config.topicSubscriberName;
32
32
  }
@@ -58,7 +58,7 @@ function getExchangeName(config) {
58
58
  if (["dead-letter", "retry"].includes(queueType)) {
59
59
  if (config.exchangeType === "topic") {
60
60
  if (!config.topicSubscriberName) {
61
- throw new errors_1.ConfigurationError(`Topic ${queueType} exchanges must have a subscriber name`);
61
+ throw new errors_js_1.ConfigurationError(`Topic ${queueType} exchanges must have a subscriber name`);
62
62
  }
63
63
  exchangeName += "." + config.topicSubscriberName;
64
64
  }
@@ -1,7 +1,7 @@
1
1
  import type * as amqpmgr from "amqp-connection-manager";
2
2
  import type { Channel } from "amqplib";
3
- import { RabbitQueueExchangeConfiguration, RabbitMqConnectionConfig } from "./config";
4
- import { Logger } from "../interfaces";
3
+ import { RabbitQueueExchangeConfiguration, RabbitMqConnectionConfig } from "./config.js";
4
+ import { Logger } from "../interfaces.js";
5
5
  export declare class SocketError extends Error {
6
6
  readonly code: string;
7
7
  readonly error: unknown;
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RabbitMqConnection = exports.RABBITMQ_TRANSPORT = exports.SocketError = void 0;
13
- const config_1 = require("./config");
14
- const lazy_load_1 = require("../lazy-load");
13
+ const config_js_1 = require("./config.js");
14
+ const lazy_load_js_1 = require("../lazy-load.js");
15
15
  class SocketError extends Error {
16
16
  constructor(code, error) {
17
17
  super(`Socket error: ${code}`);
@@ -27,7 +27,7 @@ exports.RABBITMQ_TRANSPORT = "rabbitmq";
27
27
  class RabbitMqConnection {
28
28
  static create(config, logger) {
29
29
  return __awaiter(this, void 0, void 0, function* () {
30
- const AmqpMgrPackage = yield (0, lazy_load_1.lazyLoad)({
30
+ const AmqpMgrPackage = yield (0, lazy_load_js_1.lazyLoad)({
31
31
  packageName: "amqp-connection-manager",
32
32
  context: "RabbitMqConnection",
33
33
  });
@@ -59,7 +59,7 @@ class RabbitMqConnection {
59
59
  assertExchange(channel, config) {
60
60
  return __awaiter(this, void 0, void 0, function* () {
61
61
  var _a, _b;
62
- const { exchange } = yield channel.assertExchange((0, config_1.getExchangeName)(config), (0, config_1.getExchangeType)(config), {
62
+ const { exchange } = yield channel.assertExchange((0, config_js_1.getExchangeName)(config), (0, config_js_1.getExchangeType)(config), {
63
63
  autoDelete: !!config.temporary,
64
64
  });
65
65
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Asserted exchange ${exchange}`);
@@ -74,14 +74,14 @@ class RabbitMqConnection {
74
74
  const exchangeName = yield this.assertExchange(channel, config);
75
75
  const dlExchangeName = yield this.assertExchange(channel, dlConfig);
76
76
  const retryExchangeName = yield this.assertExchange(channel, retryConfig);
77
- const queueName = (0, config_1.getQueueName)(config);
78
- const dlQueueName = (0, config_1.getQueueName)(dlConfig);
79
- const retryQueueName = (0, config_1.getQueueName)(retryConfig);
77
+ const queueName = (0, config_js_1.getQueueName)(config);
78
+ const dlQueueName = (0, config_js_1.getQueueName)(dlConfig);
79
+ const retryQueueName = (0, config_js_1.getQueueName)(retryConfig);
80
80
  const autoDelete = !!config.temporary;
81
81
  // special case to ensure the retry dead-letter only reverts to the original queue,
82
82
  // regardless of original exchange type [that is, not re-using the original queue exchange here]
83
83
  const retryDlExchangeName = ((_a = config.overrides) === null || _a === void 0 ? void 0 : _a.retryQueueExchangeName) ||
84
- `${queueName}${config_1.QueueNameExtensions["dead-letter"]}${config_1.QueueNameExtensions["retry"]}`;
84
+ `${queueName}${config_js_1.QueueNameExtensions["dead-letter"]}${config_js_1.QueueNameExtensions["retry"]}`;
85
85
  yield channel.assertExchange(retryDlExchangeName, "direct", {
86
86
  autoDelete: !!config.temporary,
87
87
  });
@@ -93,13 +93,13 @@ class RabbitMqConnection {
93
93
  // create the default queue using the dead-letter exchange as the DLX
94
94
  yield this.assertQueue(channel, queueName, autoDelete, dlExchangeName);
95
95
  // bind the default queue using the default exchange and default routing key
96
- yield this.bindQueue(channel, queueName, exchangeName, ((_e = (_d = config.overrides) === null || _d === void 0 ? void 0 : _d.names.default) === null || _e === void 0 ? void 0 : _e.routingKey) || config_1.DEFAULT_BINDING_KEY);
96
+ yield this.bindQueue(channel, queueName, exchangeName, ((_e = (_d = config.overrides) === null || _d === void 0 ? void 0 : _d.names.default) === null || _e === void 0 ? void 0 : _e.routingKey) || config_js_1.DEFAULT_BINDING_KEY);
97
97
  // bind the dead-letter queue to the dead-letter exchange and dead-letter routing key
98
- yield this.bindQueue(channel, dlQueueName, dlExchangeName, ((_g = (_f = config.overrides) === null || _f === void 0 ? void 0 : _f.names["dead-letter"]) === null || _g === void 0 ? void 0 : _g.routingKey) || config_1.DEFAULT_BINDING_KEY);
98
+ yield this.bindQueue(channel, dlQueueName, dlExchangeName, ((_g = (_f = config.overrides) === null || _f === void 0 ? void 0 : _f.names["dead-letter"]) === null || _g === void 0 ? void 0 : _g.routingKey) || config_js_1.DEFAULT_BINDING_KEY);
99
99
  // bind the retry queue to the retry exchange and retry routing key
100
- yield this.bindQueue(channel, retryQueueName, retryExchangeName, ((_j = (_h = config.overrides) === null || _h === void 0 ? void 0 : _h.names.retry) === null || _j === void 0 ? void 0 : _j.routingKey) || config_1.DEFAULT_BINDING_KEY);
100
+ yield this.bindQueue(channel, retryQueueName, retryExchangeName, ((_j = (_h = config.overrides) === null || _h === void 0 ? void 0 : _h.names.retry) === null || _j === void 0 ? void 0 : _j.routingKey) || config_js_1.DEFAULT_BINDING_KEY);
101
101
  // bind the queue to the retry dead-letter exchange and default routing key
102
- yield this.bindQueue(channel, queueName, retryDlExchangeName, ((_l = (_k = config.overrides) === null || _k === void 0 ? void 0 : _k.names.default) === null || _l === void 0 ? void 0 : _l.routingKey) || config_1.DEFAULT_BINDING_KEY);
102
+ yield this.bindQueue(channel, queueName, retryDlExchangeName, ((_l = (_k = config.overrides) === null || _k === void 0 ? void 0 : _k.names.default) === null || _l === void 0 ? void 0 : _l.routingKey) || config_js_1.DEFAULT_BINDING_KEY);
103
103
  return {
104
104
  exchangeName,
105
105
  dlExchangeName,
@@ -1,6 +1,6 @@
1
- import { Logger, PublisherProvider } from "../interfaces";
2
- import { RabbitMqConnection } from "./connection";
3
- import { RabbitQueueExchangeConfiguration } from "./config";
1
+ import { Logger, PublisherProvider } from "../interfaces.js";
2
+ import { RabbitMqConnection } from "./connection.js";
3
+ import { RabbitQueueExchangeConfiguration } from "./config.js";
4
4
  export declare class RabbitMqPublisher implements PublisherProvider {
5
5
  private readonly connection;
6
6
  private readonly logger;
@@ -10,17 +10,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RabbitMqPublisher = void 0;
13
- const errors_1 = require("../errors");
14
- const connection_1 = require("./connection");
15
- const config_1 = require("./config");
16
- const utility_1 = require("./utility");
13
+ const errors_js_1 = require("../errors.js");
14
+ const connection_js_1 = require("./connection.js");
15
+ const config_js_1 = require("./config.js");
16
+ const utility_js_1 = require("./utility.js");
17
17
  class RabbitMqPublisher {
18
18
  constructor(connection, logger) {
19
19
  this.connection = connection;
20
20
  this.logger = logger;
21
21
  this.inited = new Set();
22
22
  this.connected = false;
23
- this.transport = connection_1.RABBITMQ_TRANSPORT;
23
+ this.transport = connection_js_1.RABBITMQ_TRANSPORT;
24
24
  }
25
25
  init(config) {
26
26
  return __awaiter(this, void 0, void 0, function* () {
@@ -57,7 +57,7 @@ class RabbitMqPublisher {
57
57
  yield this.channel.addSetup((channel) => __awaiter(this, void 0, void 0, function* () {
58
58
  yield this.connection.assertExchange(channel, config);
59
59
  }));
60
- (_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `RabbitMq created setup for publisher for ${(0, config_1.getExchangeName)(config)}`);
60
+ (_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `RabbitMq created setup for publisher for ${(0, config_js_1.getExchangeName)(config)}`);
61
61
  this.inited.add(config);
62
62
  }
63
63
  return this.channel;
@@ -66,7 +66,7 @@ class RabbitMqPublisher {
66
66
  if (new Date() >= timeoutAfter) {
67
67
  throw err;
68
68
  }
69
- yield (0, utility_1.delay)(delayMs);
69
+ yield (0, utility_js_1.delay)(delayMs);
70
70
  }
71
71
  }
72
72
  });
@@ -82,16 +82,16 @@ class RabbitMqPublisher {
82
82
  return __awaiter(this, void 0, void 0, function* () {
83
83
  var _a, _b, _c, _d;
84
84
  const channel = yield this.getChannel(config);
85
- (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publishing message to ${(0, config_1.getExchangeName)(config)} - ${message} [starting]`);
86
- const exchangeName = (0, config_1.getExchangeName)(config);
87
- const ok = yield channel.publish(exchangeName, (0, config_1.getRoutingKey)(config), Buffer.from(message, "utf8"), {
85
+ (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Publishing message to ${(0, config_js_1.getExchangeName)(config)} - ${message} [starting]`);
86
+ const exchangeName = (0, config_js_1.getExchangeName)(config);
87
+ const ok = yield channel.publish(exchangeName, (0, config_js_1.getRoutingKey)(config), Buffer.from(message, "utf8"), {
88
88
  contentType: "application/json",
89
89
  timestamp: new Date().valueOf(),
90
90
  persistent: true,
91
91
  });
92
- (_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `Published message to ${(0, config_1.getExchangeName)(config)} - ${message} [${ok}]`);
92
+ (_d = (_c = this.logger).debug) === null || _d === void 0 ? void 0 : _d.call(_c, `Published message to ${(0, config_js_1.getExchangeName)(config)} - ${message} [${ok}]`);
93
93
  if (!ok) {
94
- throw new errors_1.PublishError(`RabbitMq publish to ${exchangeName} failed`);
94
+ throw new errors_js_1.PublishError(`RabbitMq publish to ${exchangeName} failed`);
95
95
  }
96
96
  });
97
97
  }
@@ -1,6 +1,6 @@
1
- import { Logger, MessageContext, MessageResult, PubSubProvider, StopSubscribe } from "../interfaces";
2
- import { RabbitQueueExchangeConfiguration } from "./config";
3
- import { RabbitMqConnection } from "./connection";
1
+ import { Logger, MessageContext, MessageResult, PubSubProvider, StopSubscribe } from "../interfaces.js";
2
+ import { RabbitQueueExchangeConfiguration } from "./config.js";
3
+ import { RabbitMqConnection } from "./connection.js";
4
4
  /**
5
5
  * Combines a RabbitMqPublisher and RabbitMqSubscriber into a single instance
6
6
  */
@@ -10,17 +10,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RabbitMqPubSubProvider = void 0;
13
- const connection_1 = require("./connection");
14
- const publisher_1 = require("./publisher");
15
- const subscriber_1 = require("./subscriber");
13
+ const connection_js_1 = require("./connection.js");
14
+ const publisher_js_1 = require("./publisher.js");
15
+ const subscriber_js_1 = require("./subscriber.js");
16
16
  /**
17
17
  * Combines a RabbitMqPublisher and RabbitMqSubscriber into a single instance
18
18
  */
19
19
  class RabbitMqPubSubProvider {
20
20
  constructor(connection, logger) {
21
- this.transport = connection_1.RABBITMQ_TRANSPORT;
22
- this.publisher = new publisher_1.RabbitMqPublisher(connection, logger);
23
- this.subscriber = new subscriber_1.RabbitMqSubscriber(connection, logger);
21
+ this.transport = connection_js_1.RABBITMQ_TRANSPORT;
22
+ this.publisher = new publisher_js_1.RabbitMqPublisher(connection, logger);
23
+ this.subscriber = new subscriber_js_1.RabbitMqSubscriber(connection, logger);
24
24
  }
25
25
  publish(config, message) {
26
26
  return this.publisher.publish(config, message);
@@ -1,8 +1,8 @@
1
1
  import type { ConsumeMessage } from "amqplib";
2
2
  import type { ChannelWrapper } from "amqp-connection-manager";
3
- import { Logger, MessageResult, StopSubscribe, SubscriberProvider } from "../interfaces";
4
- import { RabbitMqMessageContext, RabbitQueueExchangeConfiguration } from "./config";
5
- import { RabbitMqConnection } from "./connection";
3
+ import { Logger, MessageResult, StopSubscribe, SubscriberProvider } from "../interfaces.js";
4
+ import { RabbitMqMessageContext, RabbitQueueExchangeConfiguration } from "./config.js";
5
+ import { RabbitMqConnection } from "./connection.js";
6
6
  declare class SubscribedMessage {
7
7
  private readonly owner;
8
8
  private readonly logger;
@@ -10,10 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RabbitMqSubscriber = void 0;
13
- const interfaces_1 = require("../interfaces");
14
- const errors_1 = require("../errors");
15
- const config_1 = require("./config");
16
- const connection_1 = require("./connection");
13
+ const interfaces_js_1 = require("../interfaces.js");
14
+ const errors_js_1 = require("../errors.js");
15
+ const config_js_1 = require("./config.js");
16
+ const connection_js_1 = require("./connection.js");
17
+ const create_log_error_payload_js_1 = require("../create-log-error-payload.js");
17
18
  class SubscribedMessage {
18
19
  constructor(owner, logger, config, onMessage, stop) {
19
20
  this.owner = owner;
@@ -55,7 +56,7 @@ class RabbitMqSubscriber {
55
56
  this.connection = connection;
56
57
  this.logger = logger;
57
58
  this.subscribers = new Map();
58
- this.transport = connection_1.RABBITMQ_TRANSPORT;
59
+ this.transport = connection_js_1.RABBITMQ_TRANSPORT;
59
60
  }
60
61
  removeSubscriber(subscribedMessage) {
61
62
  for (const [key, value] of this.subscribers) {
@@ -66,10 +67,10 @@ class RabbitMqSubscriber {
66
67
  }
67
68
  }
68
69
  startSubscribe(config, onMessage) {
69
- const queueName = (0, config_1.getQueueName)(config);
70
+ const queueName = (0, config_js_1.getQueueName)(config);
70
71
  let subscribedMessage = this.subscribers.get(queueName);
71
72
  if (subscribedMessage) {
72
- throw new errors_1.AlreadySubscribingError(queueName);
73
+ throw new errors_js_1.AlreadySubscribingError(queueName);
73
74
  }
74
75
  subscribedMessage = new SubscribedMessage(this, this.logger, config, onMessage);
75
76
  this.subscribers.set(queueName, subscribedMessage);
@@ -120,19 +121,22 @@ class RabbitMqSubscriber {
120
121
  messageResult = yield subscribedMessage.onMessage(json, context);
121
122
  }
122
123
  catch (err) {
123
- messageResult = interfaces_1.MessageResult.Retry;
124
- this.logger.error(`RabbitMq consumer unhandled exception, retrying message to ${retryExchangeName} ${msg.fields.routingKey}`, err);
124
+ messageResult = interfaces_js_1.MessageResult.Retry;
125
+ this.logger.error({
126
+ message: `RabbitMq consumer unhandled exception, retrying message to ${retryExchangeName} ${msg.fields.routingKey}`,
127
+ error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
128
+ });
125
129
  }
126
- if (messageResult === interfaces_1.MessageResult.Ok) {
130
+ if (messageResult === interfaces_js_1.MessageResult.Ok) {
127
131
  channel.ack(msg);
128
132
  return;
129
133
  }
130
- if (messageResult === interfaces_1.MessageResult.Retry &&
134
+ if (messageResult === interfaces_js_1.MessageResult.Retry &&
131
135
  subscribedMessage.config.retries &&
132
136
  retries >= subscribedMessage.config.retries) {
133
- messageResult = interfaces_1.MessageResult.Fail;
137
+ messageResult = interfaces_js_1.MessageResult.Fail;
134
138
  }
135
- if (messageResult === interfaces_1.MessageResult.Fail) {
139
+ if (messageResult === interfaces_js_1.MessageResult.Fail) {
136
140
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `RabbitMq retry count exceeded - sending message to DLQ`);
137
141
  channel.nack(msg, undefined, false);
138
142
  return;
@@ -167,12 +171,18 @@ class RabbitMqSubscriber {
167
171
  subscribedMessage.busy++;
168
172
  onRabbitMessage(m)
169
173
  .catch((err) => {
170
- this.logger.error("Unexpected error handling RabbitMq message", err);
174
+ this.logger.error({
175
+ message: "Unexpected error handling RabbitMq message",
176
+ error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err),
177
+ });
171
178
  try {
172
179
  channel.nack(m, undefined, true);
173
180
  }
174
181
  catch (err2) {
175
- this.logger.error("Unexpected error handling RabbitMq message during NACK attempt", err2);
182
+ this.logger.error({
183
+ message: "Unexpected error handling RabbitMq message during NACK attempt",
184
+ error: (0, create_log_error_payload_js_1.createLogErrorPayload)(err2),
185
+ });
176
186
  }
177
187
  })
178
188
  .finally(() => {
@@ -1,4 +1,4 @@
1
- import { BaseMessage, Logger, MessageContext, MessageResult, PubSubConfiguration, SubscriberProvider } from "./interfaces";
1
+ import { BaseMessage, Logger, MessageContext, MessageResult, PubSubConfiguration, SubscriberProvider } from "./interfaces.js";
2
2
  export interface SubscriberEventContext {
3
3
  message: string;
4
4
  context: MessageContext;
@@ -20,7 +20,17 @@ export declare class Subscriber {
20
20
  private readonly subscribedMessages;
21
21
  constructor(logger: Logger, providers?: SubscriberProvider[]);
22
22
  on<TU extends keyof SubscriberEvents>(event: TU, listener: SubscriberEvents[TU]): this;
23
- subscribe<TMessage extends BaseMessage>(config: PubSubConfiguration, onMessage: (msg: TMessage, context: MessageContext) => Promise<MessageResult> | MessageResult): Promise<void>;
23
+ /**
24
+ * Starts the subscriber for the given configuration. Depending on the protocol, the subscriber may not be started immediately.
25
+ *
26
+ * @param config The pubsub configuration to use for this subscriber
27
+ * @param onMessage The function to execute when a message arrives
28
+ * @returns An async function that will unsubscribe the subscriber when called
29
+ */
30
+ subscribe<TMessage extends BaseMessage>(config: PubSubConfiguration, onMessage: (msg: TMessage, context: MessageContext) => Promise<MessageResult> | MessageResult): Promise<() => Promise<void>>;
31
+ /**
32
+ * Unsubscribes all active subscribers.
33
+ */
24
34
  unsubscribe(): Promise<void>;
25
35
  addProvider(provider: SubscriberProvider): void;
26
36
  removeProvider(providerOrTransport: SubscriberProvider | string): boolean;
@@ -10,8 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.Subscriber = void 0;
13
- const interfaces_1 = require("./interfaces");
14
- const errors_1 = require("./errors");
13
+ const interfaces_js_1 = require("./interfaces.js");
14
+ const errors_js_1 = require("./errors.js");
15
15
  const events_1 = require("events");
16
16
  class SubscribedMessage {
17
17
  constructor(stop) {
@@ -32,6 +32,13 @@ class Subscriber {
32
32
  this.events.on(event, listener);
33
33
  return this;
34
34
  }
35
+ /**
36
+ * Starts the subscriber for the given configuration. Depending on the protocol, the subscriber may not be started immediately.
37
+ *
38
+ * @param config The pubsub configuration to use for this subscriber
39
+ * @param onMessage The function to execute when a message arrives
40
+ * @returns An async function that will unsubscribe the subscriber when called
41
+ */
35
42
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
36
43
  subscribe(config, onMessage) {
37
44
  return __awaiter(this, void 0, void 0, function* () {
@@ -39,12 +46,12 @@ class Subscriber {
39
46
  let subscribedMessage = this.subscribedMessages.get(config);
40
47
  const schema = config.schema;
41
48
  if (subscribedMessage) {
42
- throw new errors_1.AlreadySubscribingError(typeof config);
49
+ throw new errors_js_1.AlreadySubscribingError(typeof config);
43
50
  }
44
51
  (_b = (_a = this.logger).debug) === null || _b === void 0 ? void 0 : _b.call(_a, `Initializing subscriber for provider ${config.transport}:${config.name}`);
45
52
  const provider = this.subscriberProvdiers.get(config.transport);
46
53
  if (!provider) {
47
- throw new errors_1.MissingPubSubProviderError(`No provider configured for ${config.transport}`);
54
+ throw new errors_js_1.MissingPubSubProviderError(`No provider configured for ${config.transport}`);
48
55
  }
49
56
  const transform = (jsonStr, context) => __awaiter(this, void 0, void 0, function* () {
50
57
  var _a;
@@ -52,7 +59,7 @@ class Subscriber {
52
59
  const jsonObject = JSON.parse(jsonStr);
53
60
  const r = schema.safeParse(jsonObject);
54
61
  if (!r.success) {
55
- const id = interfaces_1.IdMetaSchema.safeParse(jsonObject);
62
+ const id = interfaces_js_1.IdMetaSchema.safeParse(jsonObject);
56
63
  if (id.success) {
57
64
  this.logger.warn(`Unable to parse message ${id.data.id} created at ${(_a = id.data.meta) === null || _a === void 0 ? void 0 : _a.createdAt} for ${config.transport}:${config.name} - schemaError`);
58
65
  }
@@ -64,11 +71,11 @@ class Subscriber {
64
71
  context,
65
72
  config,
66
73
  durationMs: new Date().valueOf() - start,
67
- result: interfaces_1.MessageResult.Fail,
74
+ result: interfaces_js_1.MessageResult.Fail,
68
75
  };
69
76
  this.events.emit("schemaError", handledEventContext);
70
77
  this.events.emit("messageHandled", handledEventContext);
71
- return interfaces_1.MessageResult.Fail;
78
+ return interfaces_js_1.MessageResult.Fail;
72
79
  }
73
80
  try {
74
81
  const result = yield onMessage(r.data, context);
@@ -98,8 +105,17 @@ class Subscriber {
98
105
  subscribedMessage = new SubscribedMessage(yield provider.startSubscribe(config, transform));
99
106
  this.subscribedMessages.set(config, subscribedMessage);
100
107
  this.logger.log(`Started subscriber for ${config.transport}:${config.name}`);
108
+ return () => __awaiter(this, void 0, void 0, function* () {
109
+ this.logger.log(`Stopping subscriber for ${config.transport}:${config.name}`);
110
+ this.subscribedMessages.delete(config);
111
+ yield subscribedMessage.stop();
112
+ this.logger.log(`Stopped subscriber for ${config.transport}:${config.name}`);
113
+ });
101
114
  });
102
115
  }
116
+ /**
117
+ * Unsubscribes all active subscribers.
118
+ */
103
119
  unsubscribe() {
104
120
  return __awaiter(this, void 0, void 0, function* () {
105
121
  this.logger.log(`Stopping all ${this.subscribedMessages.size} subscribers`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palmetto/pubsub",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "main": "./dist/main.js",
5
5
  "scripts": {
6
6
  "lint": "yarn run -T eslint --fix ./src",