@fgiova/fastify-sqs-consumer 2.0.1 → 3.0.1

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 CHANGED
@@ -1,5 +1,5 @@
1
1
  # fastify sqs-consumer
2
- [![NPM version](https://img.shields.io/npm/v/@fgiova/fastify-sqs-consumer.svg?style=flat)](https://www.npmjs.com/package/@fgiova/fastify-rest-gateway)
2
+ [![NPM version](https://img.shields.io/npm/v/@fgiova/fastify-sqs-consumer.svg?style=flat)](https://www.npmjs.com/package/@fgiova/fastify-sqs-consumer)
3
3
  ![CI workflow](https://github.com/fgiova/fastify-sqs-consumer/actions/workflows/node.js.yml/badge.svg)
4
4
  [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)
5
5
  [![Linted with Biome](https://img.shields.io/badge/Linted_with-Biome-60a5fa?style=flat&logo=biome)](https://biomejs.dev)
@@ -18,11 +18,34 @@ This plugin uses [@fgiova/mini-sqs-client](https://www.npmjs.com/package/@fgiova
18
18
  ```bash
19
19
  npm i @fgiova/fastify-sqs-consumer
20
20
  ```
21
- ### Usage
21
+
22
+ ## Usage
23
+
24
+ ### ESM
25
+ ```js
26
+ import fastify from "fastify";
27
+ import sqsConsumer from "@fgiova/fastify-sqs-consumer";
28
+
29
+ const app = fastify();
30
+
31
+ app.register(sqsConsumer, [
32
+ {
33
+ arn: "arn:aws:sqs:eu-central-1:000000000000:MyQueue",
34
+ waitTimeSeconds: 20,
35
+ timeout: 10_000,
36
+ batchSize: 10,
37
+ handlerFunction: async (message, fastify) => {
38
+ return true;
39
+ }
40
+ }
41
+ ]);
42
+ ```
43
+
44
+ ### CommonJS
22
45
  ```js
23
- const fastify = require("fastify")()
46
+ const fastify = require("fastify")();
24
47
 
25
- fastify.register(require("fastify-sqs-consumer"), [
48
+ fastify.register(require("@fgiova/fastify-sqs-consumer").default, [
26
49
  {
27
50
  arn: "arn:aws:sqs:eu-central-1:000000000000:MyQueue",
28
51
  waitTimeSeconds: 20,
@@ -34,30 +57,38 @@ fastify.register(require("fastify-sqs-consumer"), [
34
57
  }
35
58
  ]);
36
59
  ```
37
- ### Options
38
- Options are an array of objects with the following properties (one more for each queue):
39
60
 
40
- | Option | Type | Description |
41
- |-----------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
42
- | arn* | string | The ARN of the Amazon SQS queue from which messages are received. |
43
- | handlerFunction* | function | The function that will be called for each message. |
44
- | name | string | An optional name for the consumer (useful for add [hooks](https://github.com/fgiova/sqs-consumer?tab=readme-ov-file#hooks) post config). If not provided, uuid is assigned. |
45
- | waitTimeSeconds | number | The duration (in seconds, default 20s) for which the call waits for a message to arrive in the queue before returning. If a message is available, the call returns sooner than WaitTimeSeconds. If no messages are available and the wait time expires, the call returns successfully with an empty list of messages. |
46
- | timeout | number | The duration before the message is considered as failed: default 90000ms. |
47
- | batchSize | number | The maximum number of messages to return. Amazon SQS never returns more messages than this value (however, fewer messages might be returned). Valid values: 1 to 10. Default: 1. |
48
- | messageAttributeNames | string[] | Array of caught message's attributes for each message |
49
- | events | object | Events functions for the consumer (detail in next table) |
50
- | sqs | SQSClient | Initialized SQS Client (useful for testing sessions) |
61
+ ## Options
62
+ Options are an array of objects with the following properties (one for each queue):
63
+
64
+ | Option | Type | Description |
65
+ |-----------------------|-------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
66
+ | arn* | string | The ARN of the Amazon SQS queue from which messages are received. |
67
+ | handlerFunction* | function | The function that will be called for each message. |
68
+ | name | string | An optional name for the consumer (useful for add [hooks](https://github.com/fgiova/sqs-consumer?tab=readme-ov-file#hooks) post config). If not provided, uuid is assigned. |
69
+ | waitTimeSeconds | number | The duration (in seconds, default 20s) for which the call waits for a message to arrive in the queue before returning. If a message is available, the call returns sooner than WaitTimeSeconds. If no messages are available and the wait time expires, the call returns successfully with an empty list of messages. |
70
+ | timeout | number | The duration before the message is considered as failed: default 90000ms. |
71
+ | batchSize | number | The maximum number of messages to return. Amazon SQS never returns more messages than this value (however, fewer messages might be returned). Valid values: 1 to 10. Default: 1. |
72
+ | attributeNames | string[] | Array of message system attributes to retrieve for each message. |
73
+ | messageAttributeNames | string[] | Array of custom message attributes to retrieve for each message. |
74
+ | parallelExecution | boolean | Enable parallel execution of message handlers. |
75
+ | credentials | {accessKeyId, secretAccessKey} | Explicit AWS credentials (alternative to environment configuration). |
76
+ | events | object | Events functions for the consumer (detail in next table). |
77
+ | sqs | MiniSQSClient | Initialized [@fgiova/mini-sqs-client](https://www.npmjs.com/package/@fgiova/mini-sqs-client) instance (useful for testing sessions). |
78
+
79
+ \* required
80
+
81
+ ## Decorator
51
82
 
52
- * required
83
+ The plugin decorates the Fastify instance with `sqsConsumers`, a `Record<string, { consumer: SQSConsumer, meta: { pendingMessages: number } }>` that provides access to the registered consumers and their metadata.
53
84
 
54
- ### handlerFunction
85
+ ## handlerFunction
55
86
 
56
87
  Handler function is an async function called for each message received from the queue.
57
88
  Each Error thrown by the function is caught and the message is not deleted from the queue.
58
- Otherwise, the message is deleted from the queue.
89
+ Otherwise, the message is deleted from the queue.
59
90
 
60
- #### Events
91
+ ### Events
61
92
 
62
93
  | Option | Type | Description |
63
94
  |------------------|-----------------------------------------------------------------------|---------------------------------------------------------------------|
@@ -72,4 +103,4 @@ Otherwise, the message is deleted from the queue.
72
103
  | onSQSError | (error: Error, message?: Message) => Promise<void> | Called when the consumer receives an error from the SQS service |
73
104
 
74
105
  ## License
75
- Licensed under [MIT](./LICENSE).
106
+ Licensed under [MIT](./LICENSE).
@@ -3,11 +3,20 @@ import { type HooksOptions, SQSConsumer } from "@fgiova/sqs-consumer";
3
3
  import type { FastifyInstance } from "fastify";
4
4
  declare module "fastify" {
5
5
  interface FastifyInstance {
6
- sqsConsumers: Record<string, SQSConsumer>;
6
+ sqsConsumers: Record<string, {
7
+ consumer: SQSConsumer;
8
+ meta: {
9
+ pendingMessages: number;
10
+ };
11
+ }>;
7
12
  }
8
13
  }
9
14
  declare function sqsConsumerPlugin(fastify: FastifyInstance, options: {
10
15
  arn: string;
16
+ credentials?: {
17
+ accessKeyId: string;
18
+ secretAccessKey: string;
19
+ };
11
20
  name?: string;
12
21
  handlerFunction: (message: Message, fastify: FastifyInstance) => Promise<unknown>;
13
22
  timeout?: number;
package/dist/cjs/index.js CHANGED
@@ -6,70 +6,101 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.fastifyPlugin = void 0;
7
7
  const node_crypto_1 = require("node:crypto");
8
8
  const sqs_consumer_1 = require("@fgiova/sqs-consumer");
9
+ // @ts-expect-error
10
+ const unpromise_1 = require("@watchable/unpromise");
9
11
  const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
10
- function createConsumer(fastify, queueArn, handlerFunction, meta, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs) {
11
- return new sqs_consumer_1.SQSConsumer({
12
- queueARN: queueArn,
13
- autostart: false,
14
- consumerOptions: {
15
- waitTimeSeconds,
16
- itemsPerRequest: batchSize,
17
- attributeNames,
18
- messageAttributeNames,
19
- visibilityTimeout: timeout / 1000,
20
- },
21
- handlerOptions: {
22
- executionTimeout: timeout,
23
- parallelExecution,
24
- },
25
- hooks,
26
- clientOptions: {
27
- sqsClient: sqs,
28
- },
29
- handler: async function handleMessageFunction(message) {
30
- meta.pendingMessages++;
31
- try {
32
- await handlerFunction(message, fastify);
33
- meta.pendingMessages--;
34
- }
35
- catch (e) {
36
- meta.pendingMessages--;
37
- fastify.log.error(e);
38
- throw e;
39
- }
40
- return;
41
- },
42
- });
12
+ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs, credentials) {
13
+ const meta = { pendingMessages: 0 };
14
+ return {
15
+ consumer: new sqs_consumer_1.SQSConsumer({
16
+ queueARN: queueArn,
17
+ autostart: false,
18
+ consumerOptions: {
19
+ waitTimeSeconds,
20
+ itemsPerRequest: batchSize,
21
+ attributeNames,
22
+ messageAttributeNames,
23
+ visibilityTimeout: timeout / 1000,
24
+ },
25
+ handlerOptions: {
26
+ executionTimeout: timeout,
27
+ parallelExecution,
28
+ },
29
+ hooks,
30
+ clientOptions: {
31
+ sqsClient: sqs,
32
+ /* c8 ignore next 1 */
33
+ signer: credentials ? { credentials } : undefined,
34
+ },
35
+ handler: async function handleMessageFunction(message) {
36
+ let timeoutId;
37
+ meta.pendingMessages++;
38
+ try {
39
+ return await unpromise_1.Unpromise.race([
40
+ handlerFunction(message, fastify),
41
+ new Promise((_, reject) => {
42
+ timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000);
43
+ }),
44
+ ]);
45
+ }
46
+ catch (e) {
47
+ fastify.log.error(e);
48
+ throw e;
49
+ /* c8 ignore next */
50
+ }
51
+ finally {
52
+ // biome-ignore lint/style/noNonNullAssertion: TimeoutId is always set before this line is reached
53
+ clearTimeout(timeoutId);
54
+ meta.pendingMessages--;
55
+ }
56
+ },
57
+ }),
58
+ meta,
59
+ };
43
60
  }
44
61
  function sqsConsumerPlugin(fastify, options, done) {
45
- const metaData = {
46
- pendingMessages: 0,
47
- };
48
62
  const consumers = {};
63
+ let maxExecutionTimeout = 90000;
49
64
  fastify.decorate("sqsConsumers", consumers);
50
65
  for (const handler of options) {
51
- const { name, arn: queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, events, sqs, parallelExecution, } = handler;
66
+ maxExecutionTimeout = Math.max(maxExecutionTimeout, handler.timeout ?? 0);
67
+ const { name, arn: queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, events, sqs, parallelExecution, credentials, } = handler;
52
68
  try {
53
- consumers[name || (0, node_crypto_1.randomUUID)()] = createConsumer(fastify, queueArn, handlerFunction, metaData, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, parallelExecution, events, sqs);
69
+ consumers[name || (0, node_crypto_1.randomUUID)()] = createConsumer(fastify, queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, parallelExecution, events, sqs, credentials);
54
70
  } /* c8 ignore next 3 */
55
71
  catch (e) {
56
72
  fastify.log.error(e);
57
73
  }
58
74
  }
59
75
  fastify.addHook("onReady", (done) => {
60
- for (const consumer of Object.values(consumers)) {
61
- consumer.start().catch((e) => fastify.log.error(e));
76
+ for (const consumerName of Object.keys(consumers)) {
77
+ consumers[consumerName].consumer.start().catch(async (e) => {
78
+ fastify.log.error(e);
79
+ await consumers[consumerName].consumer
80
+ .stop()
81
+ .catch((stopErr) => fastify.log.error(stopErr));
82
+ delete consumers[consumerName];
83
+ });
62
84
  }
63
85
  done();
64
86
  });
65
- let allStopped = false;
66
- fastify.addHook("onClose", async (fastify) => {
87
+ fastify.addHook("onClose", (fastify, done) => {
88
+ let allStopped = false;
67
89
  const arrayConsumers = Object.values(consumers);
90
+ const timeStart = Date.now();
68
91
  for (const consumer of arrayConsumers) {
69
- await consumer.stop();
92
+ consumer.consumer
93
+ .stop()
94
+ .catch((e) => fastify.log.error(`[fastify-sqs-consumer] Error stopping consumer: ${e}`));
70
95
  }
71
96
  const interval = setInterval(() => {
72
- const isRunning = arrayConsumers.some((consumer) => consumer.isRunning);
97
+ const isRunning = arrayConsumers.some((consumer) => consumer.consumer.isRunning);
98
+ const pendingMessages = arrayConsumers.reduce((acc, consumer) => acc + consumer.meta.pendingMessages, 0);
99
+ if (Date.now() - timeStart > maxExecutionTimeout + 2000) {
100
+ fastify.log.warn("[fastify-sqs-consumer] Consumers are taking too long to stop... forcing shutdown");
101
+ clearInterval(interval);
102
+ return done();
103
+ }
73
104
  /* c8 ignore next 5 */
74
105
  if (isRunning) {
75
106
  fastify.log.debug("[fastify-sqs-consumer] Some consumers still running... please wait");
@@ -79,14 +110,14 @@ function sqsConsumerPlugin(fastify, options, done) {
79
110
  allStopped = true;
80
111
  fastify.log.debug("[fastify-sqs-consumer] All consumers are stopped");
81
112
  }
82
- if (metaData.pendingMessages <= 0) {
113
+ if (pendingMessages <= 0) {
83
114
  clearInterval(interval);
84
115
  return done();
85
116
  }
86
117
  else {
87
- fastify.log.debug(`[fastify-sqs-consumer] ${metaData.pendingMessages} pending messages`);
118
+ fastify.log.debug(`[fastify-sqs-consumer] ${pendingMessages} pending messages`);
88
119
  }
89
- }, 50);
120
+ }, 500);
90
121
  });
91
122
  done();
92
123
  }
@@ -3,11 +3,20 @@ import { type HooksOptions, SQSConsumer } from "@fgiova/sqs-consumer";
3
3
  import type { FastifyInstance } from "fastify";
4
4
  declare module "fastify" {
5
5
  interface FastifyInstance {
6
- sqsConsumers: Record<string, SQSConsumer>;
6
+ sqsConsumers: Record<string, {
7
+ consumer: SQSConsumer;
8
+ meta: {
9
+ pendingMessages: number;
10
+ };
11
+ }>;
7
12
  }
8
13
  }
9
14
  declare function sqsConsumerPlugin(fastify: FastifyInstance, options: {
10
15
  arn: string;
16
+ credentials?: {
17
+ accessKeyId: string;
18
+ secretAccessKey: string;
19
+ };
11
20
  name?: string;
12
21
  handlerFunction: (message: Message, fastify: FastifyInstance) => Promise<unknown>;
13
22
  timeout?: number;
@@ -1,69 +1,100 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { SQSConsumer } from "@fgiova/sqs-consumer";
3
+ // @ts-expect-error
4
+ import { Unpromise } from "@watchable/unpromise";
3
5
  import fp from "fastify-plugin";
4
- function createConsumer(fastify, queueArn, handlerFunction, meta, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs) {
5
- return new SQSConsumer({
6
- queueARN: queueArn,
7
- autostart: false,
8
- consumerOptions: {
9
- waitTimeSeconds,
10
- itemsPerRequest: batchSize,
11
- attributeNames,
12
- messageAttributeNames,
13
- visibilityTimeout: timeout / 1000,
14
- },
15
- handlerOptions: {
16
- executionTimeout: timeout,
17
- parallelExecution,
18
- },
19
- hooks,
20
- clientOptions: {
21
- sqsClient: sqs,
22
- },
23
- handler: async function handleMessageFunction(message) {
24
- meta.pendingMessages++;
25
- try {
26
- await handlerFunction(message, fastify);
27
- meta.pendingMessages--;
28
- }
29
- catch (e) {
30
- meta.pendingMessages--;
31
- fastify.log.error(e);
32
- throw e;
33
- }
34
- return;
35
- },
36
- });
6
+ function createConsumer(fastify, queueArn, handlerFunction, timeout = 90000, waitTimeSeconds = 20, batchSize = 1, attributeNames = [], messageAttributeNames = [], parallelExecution, hooks, sqs, credentials) {
7
+ const meta = { pendingMessages: 0 };
8
+ return {
9
+ consumer: new SQSConsumer({
10
+ queueARN: queueArn,
11
+ autostart: false,
12
+ consumerOptions: {
13
+ waitTimeSeconds,
14
+ itemsPerRequest: batchSize,
15
+ attributeNames,
16
+ messageAttributeNames,
17
+ visibilityTimeout: timeout / 1000,
18
+ },
19
+ handlerOptions: {
20
+ executionTimeout: timeout,
21
+ parallelExecution,
22
+ },
23
+ hooks,
24
+ clientOptions: {
25
+ sqsClient: sqs,
26
+ /* c8 ignore next 1 */
27
+ signer: credentials ? { credentials } : undefined,
28
+ },
29
+ handler: async function handleMessageFunction(message) {
30
+ let timeoutId;
31
+ meta.pendingMessages++;
32
+ try {
33
+ return await Unpromise.race([
34
+ handlerFunction(message, fastify),
35
+ new Promise((_, reject) => {
36
+ timeoutId = setTimeout(() => reject(new Error("Handler execution timed out")), timeout + 1000);
37
+ }),
38
+ ]);
39
+ }
40
+ catch (e) {
41
+ fastify.log.error(e);
42
+ throw e;
43
+ /* c8 ignore next */
44
+ }
45
+ finally {
46
+ // biome-ignore lint/style/noNonNullAssertion: TimeoutId is always set before this line is reached
47
+ clearTimeout(timeoutId);
48
+ meta.pendingMessages--;
49
+ }
50
+ },
51
+ }),
52
+ meta,
53
+ };
37
54
  }
38
55
  function sqsConsumerPlugin(fastify, options, done) {
39
- const metaData = {
40
- pendingMessages: 0,
41
- };
42
56
  const consumers = {};
57
+ let maxExecutionTimeout = 90000;
43
58
  fastify.decorate("sqsConsumers", consumers);
44
59
  for (const handler of options) {
45
- const { name, arn: queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, events, sqs, parallelExecution, } = handler;
60
+ maxExecutionTimeout = Math.max(maxExecutionTimeout, handler.timeout ?? 0);
61
+ const { name, arn: queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, events, sqs, parallelExecution, credentials, } = handler;
46
62
  try {
47
- consumers[name || randomUUID()] = createConsumer(fastify, queueArn, handlerFunction, metaData, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, parallelExecution, events, sqs);
63
+ consumers[name || randomUUID()] = createConsumer(fastify, queueArn, handlerFunction, timeout, waitTimeSeconds, batchSize, attributeNames, messageAttributeNames, parallelExecution, events, sqs, credentials);
48
64
  } /* c8 ignore next 3 */
49
65
  catch (e) {
50
66
  fastify.log.error(e);
51
67
  }
52
68
  }
53
69
  fastify.addHook("onReady", (done) => {
54
- for (const consumer of Object.values(consumers)) {
55
- consumer.start().catch((e) => fastify.log.error(e));
70
+ for (const consumerName of Object.keys(consumers)) {
71
+ consumers[consumerName].consumer.start().catch(async (e) => {
72
+ fastify.log.error(e);
73
+ await consumers[consumerName].consumer
74
+ .stop()
75
+ .catch((stopErr) => fastify.log.error(stopErr));
76
+ delete consumers[consumerName];
77
+ });
56
78
  }
57
79
  done();
58
80
  });
59
- let allStopped = false;
60
- fastify.addHook("onClose", async (fastify) => {
81
+ fastify.addHook("onClose", (fastify, done) => {
82
+ let allStopped = false;
61
83
  const arrayConsumers = Object.values(consumers);
84
+ const timeStart = Date.now();
62
85
  for (const consumer of arrayConsumers) {
63
- await consumer.stop();
86
+ consumer.consumer
87
+ .stop()
88
+ .catch((e) => fastify.log.error(`[fastify-sqs-consumer] Error stopping consumer: ${e}`));
64
89
  }
65
90
  const interval = setInterval(() => {
66
- const isRunning = arrayConsumers.some((consumer) => consumer.isRunning);
91
+ const isRunning = arrayConsumers.some((consumer) => consumer.consumer.isRunning);
92
+ const pendingMessages = arrayConsumers.reduce((acc, consumer) => acc + consumer.meta.pendingMessages, 0);
93
+ if (Date.now() - timeStart > maxExecutionTimeout + 2000) {
94
+ fastify.log.warn("[fastify-sqs-consumer] Consumers are taking too long to stop... forcing shutdown");
95
+ clearInterval(interval);
96
+ return done();
97
+ }
67
98
  /* c8 ignore next 5 */
68
99
  if (isRunning) {
69
100
  fastify.log.debug("[fastify-sqs-consumer] Some consumers still running... please wait");
@@ -73,14 +104,14 @@ function sqsConsumerPlugin(fastify, options, done) {
73
104
  allStopped = true;
74
105
  fastify.log.debug("[fastify-sqs-consumer] All consumers are stopped");
75
106
  }
76
- if (metaData.pendingMessages <= 0) {
107
+ if (pendingMessages <= 0) {
77
108
  clearInterval(interval);
78
109
  return done();
79
110
  }
80
111
  else {
81
- fastify.log.debug(`[fastify-sqs-consumer] ${metaData.pendingMessages} pending messages`);
112
+ fastify.log.debug(`[fastify-sqs-consumer] ${pendingMessages} pending messages`);
82
113
  }
83
- }, 50);
114
+ }, 500);
84
115
  });
85
116
  done();
86
117
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fgiova/fastify-sqs-consumer",
3
3
  "description": "sqs-consumer fastify plugin",
4
- "version": "2.0.1",
4
+ "version": "3.0.1",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "types": "./dist/cjs/index.d.ts",
7
7
  "exports": {
@@ -49,7 +49,7 @@
49
49
  "access": "public"
50
50
  },
51
51
  "engines": {
52
- "node": ">=20.14.1"
52
+ "node": "^22.14.0 || >= 24.10.0"
53
53
  },
54
54
  "tap": {
55
55
  "show-full-coverage": true,
@@ -70,20 +70,23 @@
70
70
  "@fgiova/cjs-esm-ts-builder": "^1.2.0",
71
71
  "@semantic-release/changelog": "^6.0.3",
72
72
  "@semantic-release/git": "^10.0.1",
73
+ "@semantic-release/npm": "^13.1.4",
73
74
  "@tsconfig/node20": "^20.1.6",
74
75
  "@types/dotenv": "^6.1.1",
75
76
  "@types/node": "^20.19.11",
76
- "conventional-changelog-conventionalcommits": "^8.0.0",
77
+ "clock-mock": "^2.0.4",
78
+ "conventional-changelog-conventionalcommits": "^9.1.0",
77
79
  "dotenv": "^10.0.0",
78
- "fastify": "^5.5.0",
79
- "semantic-release": "^24.2.3",
80
+ "fastify": "^5.8.5",
81
+ "semantic-release": "^25.0.3",
80
82
  "tap": "^21.1.0",
81
83
  "testcontainers": "^11.5.1",
82
84
  "ts-node": "^10.9.2",
83
85
  "typescript": "^5.1.6"
84
86
  },
85
87
  "dependencies": {
86
- "@fgiova/sqs-consumer": "^2.1.3",
87
- "fastify-plugin": "^5.0.1"
88
+ "@fgiova/sqs-consumer": "^3.2.0",
89
+ "@watchable/unpromise": "^1.0.2",
90
+ "fastify-plugin": "^5.1.0"
88
91
  }
89
92
  }