ac-sqs 3.2.0 → 3.2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+
2
+ ## [3.2.1](https://github.com/admiralcloud/ac-sqs/compare/v3.2.0..v3.2.1) (2025-07-18 12:57:51)
3
+
4
+
5
+ ### Bug Fix
6
+
7
+ * **App:** Reduced code complexity | MP | [0313cc01d90d9e4d1ad3b7ef3136af7dfc72d717](https://github.com/admiralcloud/ac-sqs/commit/0313cc01d90d9e4d1ad3b7ef3136af7dfc72d717)
8
+ Create smaller functions
9
+ Related issues: [admiralcloud/ac-sqs#1](https://github.com/admiralcloud/ac-sqs/issues/1) [admiralcloud/ac-api-server#340](https://github.com/admiralcloud/ac-api-server/issues/340)
10
+ * **App:** Improved code quality | MP | [0d7e40518804f8c227cbc20c602510edada2e02e](https://github.com/admiralcloud/ac-sqs/commit/0d7e40518804f8c227cbc20c602510edada2e02e)
11
+ Separated huge function into smaller parts
12
+ Related issues: [admiralcloud/ac-sqs#1](https://github.com/admiralcloud/ac-sqs/issues/1) [admiralcloud/ac-api-server#340](https://github.com/admiralcloud/ac-api-server/issues/340)
13
+ * **App:** Improved code quality | MP | [cd9f5d3969d4aac9c3c87e7e84dd5788e9929cce](https://github.com/admiralcloud/ac-sqs/commit/cd9f5d3969d4aac9c3c87e7e84dd5788e9929cce)
14
+ Improved code quality
15
+ Related issues:
16
+ * **App:** Requested code changes | MP | [39aa6c33b9087fcb2c3cfa075716a5dd83e07550](https://github.com/admiralcloud/ac-sqs/commit/39aa6c33b9087fcb2c3cfa075716a5dd83e07550)
17
+ Improved code quality
18
+ Related issues:
19
+ * **App:** Improved visibility management | MP | [d45111846668fe3db268fd40987c726e82e1074c](https://github.com/admiralcloud/ac-sqs/commit/d45111846668fe3db268fd40987c726e82e1074c)
20
+ Add batch processing and throttling for visibility extension, better cleanup, graceful shutdown and stats
21
+ Related issues:
22
+ ### Chores
23
+
24
+ * **App:** Updated packages | MP | [c6a2d43081047626aa60d5cb5f97427760143880](https://github.com/admiralcloud/ac-sqs/commit/c6a2d43081047626aa60d5cb5f97427760143880)
25
+ Updated packages
26
+ Related issues:
1
27
 
2
28
  # [3.2.0](https://github.com/admiralcloud/ac-sqs/compare/v3.1.2..v3.2.0) (2025-05-11 11:56:57)
3
29
 
package/README.md CHANGED
@@ -120,7 +120,7 @@ Preparations you have to make before running the tests:
120
120
  + export the AWS profile to use for tests (if it is not your default profile) using **export AWS_PROFILE=development**
121
121
  + export the AWS account id using **export awsaccount=12345**
122
122
  + create a SQS list named "test_acsqs"
123
- + create a bucket and export the name using **export bucket=acsqs-test-bucket**
123
+ + create a bucket and export the name using **export bucket=sqstest.admiralcloud.com**
124
124
  + export the node test environment using **export NODE_ENV=test**
125
125
 
126
126
  **ATTENTION**: Tests may fail when checking the SQS length. This is a by-design failure:
package/index.js CHANGED
@@ -1,18 +1,24 @@
1
1
  const _ = require('lodash')
2
2
  const { v4: uuidV4 } = require('uuid')
3
+ const { setTimeout: sleep } = require('timers/promises')
3
4
 
4
- const { SQSClient, SendMessageCommand, SendMessageBatchCommand, ReceiveMessageCommand, DeleteMessageBatchCommand, GetQueueAttributesCommand, ChangeMessageVisibilityCommand } = require('@aws-sdk/client-sqs')
5
+ const { SQSClient, SendMessageCommand, SendMessageBatchCommand, ReceiveMessageCommand, DeleteMessageBatchCommand, GetQueueAttributesCommand, ChangeMessageVisibilityBatchCommand } = require('@aws-sdk/client-sqs')
5
6
  const { S3Client, GetObjectCommand, PutObjectCommand, DeleteObjectsCommand } = require("@aws-sdk/client-s3")
6
7
 
7
-
8
8
  class ACSQS {
9
- constructor({ region = 'eu-central-1', account, availableLists, useS3 = { enabled: true, bucket: undefined }, messageThreshold = 250e3, debug, logger=console, throwError = false }) {
9
+ constructor({ region = 'eu-central-1', account, availableLists, useS3 = { enabled: true, bucket: undefined }, messageThreshold = 250e3, debug, logger = console, throwError = false, maxConcurrentMessages = 3000 }) {
10
10
  this.region = region
11
11
  this.account = account
12
12
  this.availableLists = availableLists
13
13
  this.logger = logger
14
14
  this.throwError = throwError
15
- this.visibilityTimer = {}
15
+ this.maxConcurrentMessages = maxConcurrentMessages
16
+
17
+ // Improved visibility management
18
+ this.visibilityManagement = new Map()
19
+ this.batchExtendRunning = false
20
+ this.stopBatchExtend = false
21
+ this.batchExtendInterval = 5000 // Check every 5 seconds
16
22
 
17
23
  const awsConfig = {
18
24
  region,
@@ -26,6 +32,281 @@ class ACSQS {
26
32
  this.bucket = _.get(useS3, 'bucket')
27
33
  this.s3 = new S3Client(awsConfig)
28
34
  }
35
+
36
+ // Start batch extend loop
37
+ this.startBatchExtendTimer()
38
+ }
39
+
40
+ async startBatchExtendTimer() {
41
+ if (this.batchExtendRunning) return
42
+
43
+ this.batchExtendRunning = true
44
+ this.stopBatchExtend = false
45
+
46
+ while (true) {
47
+ try {
48
+ if (this.stopBatchExtend) break
49
+
50
+ await sleep(this.batchExtendInterval)
51
+
52
+ if (this.stopBatchExtend) break
53
+
54
+ await this.processBatchExtensions()
55
+ }
56
+ catch (error) {
57
+ this.logger.error('ACSQS | startBatchExtendTimer | Error in batch extend loop | %s', error?.message)
58
+ // Don't break the loop on errors, just log and continue
59
+ await sleep(1000) // Wait 1s on error before retrying
60
+ }
61
+ }
62
+
63
+ this.batchExtendRunning = false
64
+ }
65
+
66
+ stopBatchExtendTimer() {
67
+ this.stopBatchExtend = true
68
+ }
69
+
70
+ async processBatchExtensions() {
71
+ if (this.visibilityManagement.size === 0) return
72
+
73
+ // Group messages by queue for batch processing
74
+ const queueGroups = new Map()
75
+ const now = Date.now()
76
+
77
+ for (const [messageId, messageData] of this.visibilityManagement) {
78
+ // Check if message still exists in tracking (might have been deleted)
79
+ if (!this.visibilityManagement.has(messageId)) continue
80
+
81
+ // Check if message needs extension
82
+ if (now >= messageData.nextExtendTime) {
83
+ // Check max extensions
84
+ if (messageData.extensionCount >= messageData.maxExtensions) {
85
+ this.logger.warn('ACSQS | processBatchExtensions | Max extensions reached | %s | %s', messageData.queueName, messageId)
86
+ this.removeVisibilityTracking(messageId)
87
+ continue
88
+ }
89
+
90
+ if (!queueGroups.has(messageData.queueName)) {
91
+ queueGroups.set(messageData.queueName, [])
92
+ }
93
+ queueGroups.get(messageData.queueName).push(messageData)
94
+ }
95
+ }
96
+
97
+ // Process each queue's extensions in batch
98
+ for (const [queueName, messages] of queueGroups) {
99
+ await this.extendVisibilityBatch(queueName, messages)
100
+ }
101
+ }
102
+
103
+ async extendVisibilityBatch(queueName, messages) {
104
+ if (messages.length === 0) return
105
+
106
+ const config = _.find(this.availableLists, { name: queueName })
107
+ if (!config) return
108
+
109
+ const chunks = this.chunkMessages(messages)
110
+ await this.processAllChunks(queueName, chunks, config)
111
+ }
112
+
113
+ chunkMessages(messages) {
114
+ return _.chunk(messages, 10)
115
+ }
116
+
117
+ async processAllChunks(queueName, chunks, config) {
118
+ for (let i = 0; i < chunks.length; i++) {
119
+ const chunk = chunks[i]
120
+
121
+ // Add delay between chunks to avoid throttling (except for first chunk)
122
+ if (i > 0) {
123
+ await sleep(100)
124
+ }
125
+
126
+ await this.processChunk(queueName, chunk, config, i + 1, chunks.length)
127
+ }
128
+ }
129
+
130
+ async processChunk(queueName, chunk, config, chunkNumber, totalChunks) {
131
+ const validChunk = this.getValidChunk(chunk)
132
+ if (validChunk.length === 0) return
133
+
134
+ const sqsParams = await this.buildSQSParams(validChunk, config)
135
+ await this.executeChunkWithRetry(queueName, validChunk, sqsParams, config, chunkNumber, totalChunks)
136
+ }
137
+
138
+ getValidChunk(chunk) {
139
+ return chunk.filter(messageData => this.visibilityManagement.has(messageData.messageId))
140
+ }
141
+
142
+ async buildSQSParams(validChunk, config) {
143
+ const visibilityTimeout = _.get(config, 'visibilityTimeout', 30)
144
+ const entries = validChunk.map(messageData => ({
145
+ Id: messageData.messageId,
146
+ ReceiptHandle: messageData.receiptHandle,
147
+ VisibilityTimeout: visibilityTimeout
148
+ }))
149
+
150
+ return {
151
+ QueueUrl: await this.getQueueUrl(config),
152
+ Entries: entries
153
+ }
154
+ }
155
+
156
+ async executeChunkWithRetry(queueName, validChunk, sqsParams, config, chunkNumber, totalChunks) {
157
+ const maxRetries = 2
158
+ let lastError = null
159
+
160
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
161
+ if (attempt > 1) {
162
+ await this.handleRetryDelay(lastError, attempt, maxRetries, queueName, chunkNumber, totalChunks)
163
+ }
164
+
165
+ try {
166
+ const command = new ChangeMessageVisibilityBatchCommand(sqsParams)
167
+ const response = await this.sqs.send(command)
168
+
169
+ const visibilityTimeout = _.get(config, 'visibilityTimeout', 30)
170
+ this.handleChunkResponse(queueName, validChunk, response, config, visibilityTimeout)
171
+ return
172
+ }
173
+ catch (error) {
174
+ lastError = error
175
+
176
+ if (this.isPermanentError(error)) {
177
+ this.logger.warn('ACSQS | processChunk | Permanent error, not retrying | %s | %s', queueName, error.message)
178
+ break
179
+ }
180
+
181
+ if (attempt < maxRetries) {
182
+ this.logger.warn('ACSQS | processChunk | Attempt %s failed, will retry | %s | %s',
183
+ attempt, queueName, error.message)
184
+ }
185
+ }
186
+ }
187
+
188
+ this.handleAllRetriesFailed(queueName, validChunk, lastError)
189
+ }
190
+
191
+ async handleRetryDelay(lastError, attempt, maxRetries, queueName, chunkNumber, totalChunks) {
192
+ const isThrottled = lastError?.message?.includes('throttled')
193
+ const delayMs = isThrottled ? 500 : 200
194
+
195
+ this.logger.warn('ACSQS | processChunk | Retry attempt %s/%s | %s | Chunk %s/%s | Waiting %sms',
196
+ attempt, maxRetries, queueName, chunkNumber, totalChunks, delayMs)
197
+
198
+ await sleep(delayMs)
199
+ }
200
+
201
+ isPermanentError(error) {
202
+ return error.message?.includes('ReceiptHandleIsInvalid') ||
203
+ error.message?.includes('MessageNotInflight')
204
+ }
205
+
206
+ handleAllRetriesFailed(queueName, validChunk, lastError) {
207
+ this.logger.error('ACSQS | processChunk | All retries failed | %s | Chunk size: %s | %s',
208
+ queueName, validChunk.length, lastError?.message)
209
+
210
+ for (const messageData of validChunk) {
211
+ this.removeVisibilityTracking(messageData.messageId)
212
+ }
213
+ }
214
+
215
+ handleChunkResponse(queueName, validChunk, response, config, visibilityTimeout) {
216
+ const successful = new Set((response.Successful || []).map(s => s.Id))
217
+ const failed = new Set((response.Failed || []).map(f => f.Id))
218
+
219
+ for (const messageData of validChunk) {
220
+ // Check again if message still exists (might have been deleted during AWS call)
221
+ if (!this.visibilityManagement.has(messageData.messageId)) continue
222
+
223
+ if (successful.has(messageData.messageId)) {
224
+ this.updateSuccessfulMessage(messageData, visibilityTimeout, queueName, config)
225
+ }
226
+ else if (failed.has(messageData.messageId)) {
227
+ this.handleFailedMessage(messageData, response.Failed, queueName, config)
228
+ }
229
+ }
230
+ }
231
+
232
+ updateSuccessfulMessage(messageData, visibilityTimeout, queueName, config) {
233
+ messageData.extensionCount++
234
+ messageData.nextExtendTime = Date.now() + (visibilityTimeout * 0.8 * 1000)
235
+
236
+ if (config.debug) {
237
+ this.logger.debug('ACSQS | extendVisibilityBatch | Success | %s | M %s | %ss | Count: %s',
238
+ queueName, messageData.messageId, visibilityTimeout, messageData.extensionCount)
239
+ }
240
+ }
241
+
242
+ handleFailedMessage(messageData, failedItems, queueName, config) {
243
+ const failedItem = failedItems.find(f => f.Id === messageData.messageId)
244
+
245
+ // Log only if it's not an expired receipt handle (which is normal)
246
+ if (failedItem?.Code === 'ReceiptHandleIsInvalid') {
247
+ if (config.debug) {
248
+ this.logger.debug('ACSQS | extendVisibilityBatch | Receipt handle expired (normal) | %s | M %s',
249
+ queueName, messageData.messageId)
250
+ }
251
+ }
252
+ else {
253
+ this.logger.warn('ACSQS | extendVisibilityBatch | Failed | %s | M %s | %s',
254
+ queueName, messageData.messageId, failedItem?.Message || 'Unknown error')
255
+ }
256
+
257
+ // Remove from tracking if receipt handle expired or other permanent error
258
+ if (failedItem?.Code === 'ReceiptHandleIsInvalid' || failedItem?.Code === 'MessageNotInflight') {
259
+ this.removeVisibilityTracking(messageData.messageId)
260
+ }
261
+ }
262
+
263
+ addVisibilityTracking(messageId, queueName, receiptHandle, config) {
264
+ // Check if we're at max capacity
265
+ if (this.visibilityManagement.size >= this.maxConcurrentMessages) {
266
+ this.logger.warn('ACSQS | addVisibilityTracking | Max concurrent messages reached | %s', this.maxConcurrentMessages)
267
+ return false
268
+ }
269
+
270
+ const visibilityTimeout = _.get(config, 'visibilityTimeout', 30)
271
+ const maxExtensions = _.get(config, 'maxVisibilityExtensions', 12)
272
+
273
+ this.visibilityManagement.set(messageId, {
274
+ messageId,
275
+ queueName,
276
+ receiptHandle,
277
+ extensionCount: 0,
278
+ maxExtensions,
279
+ nextExtendTime: Date.now() + (visibilityTimeout * 0.8 * 1000),
280
+ createdAt: Date.now()
281
+ })
282
+
283
+ return true
284
+ }
285
+
286
+ removeVisibilityTracking(messageId) {
287
+ this.visibilityManagement.delete(messageId)
288
+ }
289
+
290
+ // Legacy method for backwards compatibility - now uses batch processing
291
+ async extendVisibility({ name, message, throwError }) {
292
+ const config = _.find(this.availableLists, { name })
293
+ if (!config) {
294
+ this.logger.error('AWS | extendVisibility | configurationMissing | %s', name)
295
+ throw new Error('configurationForListMissing')
296
+ }
297
+
298
+ const { MessageId: messageId } = message
299
+
300
+ // Check if message is already being tracked
301
+ if (this.visibilityManagement.has(messageId)) {
302
+ // Force immediate extension by setting nextExtendTime to now
303
+ const messageData = this.visibilityManagement.get(messageId)
304
+ messageData.nextExtendTime = Date.now()
305
+ return
306
+ }
307
+
308
+ // Add to tracking if not already present
309
+ this.addVisibilityTracking(messageId, name, message.ReceiptHandle, config)
29
310
  }
30
311
 
31
312
  async getAllLists({ throwError = false } = {}) {
@@ -68,7 +349,6 @@ class ACSQS {
68
349
  }
69
350
  }
70
351
 
71
-
72
352
  async sendSQSMessage({ name, message, messageGroupId, deDuplicationId, delay, throwError, debug }) {
73
353
  const config = _.find(this.availableLists, { name })
74
354
  if (!config) {
@@ -165,62 +445,6 @@ class ACSQS {
165
445
  }
166
446
  }
167
447
 
168
- async extendVisibility({ name, message, throwError }) {
169
- const config = _.find(this.availableLists, { name })
170
- if (!config) {
171
- this.logger.error('AWS | extendVisibility | configurationMissing | %s', name)
172
- throw new Error('configurationForListMissing')
173
- }
174
-
175
- const visibilityTimeout = _.get(config, 'visibilityTimeout', 15)
176
- const maxVisibilityExtensions = _.get(config, 'maxVisibilityExtensions', 12) // max number of times the extension can me made (12 x 15s = 3min)
177
-
178
- const { MessageId: messageId, ReceiptHandle: receiptHandle } = message
179
-
180
- // Check if we've reached maximum extensions
181
- if (this.visibilityTimer[messageId] && this.visibilityTimer[messageId].visibilityExtensionCount >= maxVisibilityExtensions) {
182
- this.logger.warn('ACSQS | extendVisibility | %s | M %s | Max extensions reached | %s | %j', name, messageId, maxVisibilityExtensions, message)
183
- this.deleteVisibilityTimer({ messageId })
184
- return
185
- }
186
-
187
- // Track extension count
188
- if (this.visibilityTimer[messageId]) {
189
- this.visibilityTimer[messageId].visibilityExtensionCount++
190
- }
191
-
192
- const sqsParams = {
193
- QueueUrl: await this.getQueueUrl(config),
194
- ReceiptHandle: receiptHandle,
195
- VisibilityTimeout: visibilityTimeout
196
- }
197
- const command = new ChangeMessageVisibilityCommand(sqsParams)
198
- try {
199
- const response = await this.sqs.send(command)
200
- if (config.debug) {
201
- const visibilityExtensionCount = this.visibilityTimer[messageId] ? this.visibilityTimer[messageId].visibilityExtensionCount : 0
202
- this.logger.debug('ACSQS | extendVisibility | %s | M %s | %ss | %s | %j', name, messageId, visibilityTimeout, visibilityExtensionCount, message)
203
- }
204
-
205
- return response
206
- }
207
- catch(e) {
208
- this.logger.error('ACSQS | extendVisibility | %s | %s', name, e?.message)
209
- this.deleteVisibilityTimer({ messageId })
210
- if (this.throwError || throwError) throw e
211
- }
212
- }
213
-
214
- deleteVisibilityTimer({ messageId }) {
215
- if (this.visibilityTimer[messageId]) {
216
- clearTimeout(this.visibilityTimer[messageId].timer)
217
- const self = this
218
- setTimeout(() => {
219
- delete self.visibilityTimer[messageId]
220
- }, 1000)
221
- }
222
- }
223
-
224
448
  async receiveSQSMessages({ name, throwError, debug }) {
225
449
  const config = _.find(this.availableLists, { name })
226
450
  if (!config) {
@@ -241,7 +465,6 @@ class ACSQS {
241
465
  const result = await this.sqs.send(command)
242
466
  if (!_.size(result.Messages)) return
243
467
 
244
- // Benutze Arrow-Funktion, um `this` beizubehalten
245
468
  const messages = await Promise.all(result.Messages.map(async (message) => {
246
469
  if (message.Body.startsWith('s3:')) {
247
470
  const key = message.Body.replace('s3:', '')
@@ -251,27 +474,14 @@ class ACSQS {
251
474
  message.s3key = key
252
475
  }
253
476
  catch(e) {
254
- this.logger.error('ACSQS | receiveSQSMessages | s3KeyInvalid | %s', name, key)
477
+ this.logger.error('ACSQS | receiveSQSMessages | s3KeyInvalid | %s | %s', name, key)
255
478
  }
256
479
  }
257
480
 
258
481
  if (visibilityTimeout > 0) {
259
- // start visibility timer that automatically extends visibility of the message if required
260
- const { MessageId: messageId } = message
261
- const timeoutMs = Math.floor(visibilityTimeout * 0.8 * 1000)
262
- const self = this // `this` als lokale Variable speichern
263
-
264
- this.visibilityTimer[messageId] = {
265
- // Arrow-Funktion für setInterval damit `this` erhalten bleibt,
266
- // oder verwende die lokale Variable `self`
267
- timer: setInterval(() => {
268
- this.extendVisibility({ name, message })
269
- .catch(e => {
270
- this.logger.error('ACSQS | AutoExtendVisibility | Failed %s', e.message)
271
- })
272
- }, timeoutMs),
273
- visibilityExtensionCount: 0
274
- }
482
+ // Add to visibility tracking instead of individual timers
483
+ const { MessageId: messageId, ReceiptHandle: receiptHandle } = message
484
+ this.addVisibilityTracking(messageId, name, receiptHandle, config)
275
485
  }
276
486
 
277
487
  return message
@@ -305,12 +515,10 @@ class ACSQS {
305
515
  if (item.s3key) {
306
516
  s3keys.push({ Key: item.s3key })
307
517
  }
308
- if (this.visibilityTimer[messageId]) {
309
- this.deleteVisibilityTimer({ messageId })
310
- }
518
+ // Remove from visibility tracking
519
+ this.removeVisibilityTracking(messageId)
311
520
  }
312
521
 
313
-
314
522
  let sqsParams = {
315
523
  QueueUrl: await this.getQueueUrl(config),
316
524
  Entries: entries
@@ -327,7 +535,7 @@ class ACSQS {
327
535
  Objects: s3keys,
328
536
  }
329
537
  }
330
- const command = new DeleteObjectsCommand(input);
538
+ const command = new DeleteObjectsCommand(input)
331
539
  this.s3.send(command)
332
540
  }
333
541
  return response
@@ -338,6 +546,54 @@ class ACSQS {
338
546
  }
339
547
  }
340
548
 
549
+ // Cleanup method for graceful shutdown
550
+ async shutdown() {
551
+ this.stopBatchExtendTimer()
552
+
553
+ // Wait for batch extend loop to finish
554
+ while (this.batchExtendRunning) {
555
+ await sleep(100)
556
+ }
557
+
558
+ this.visibilityManagement.clear()
559
+ this.logger.info('ACSQS | shutdown | Visibility management stopped and cleared')
560
+ }
561
+
562
+ // Get visibility tracking stats for monitoring
563
+ getVisibilityStats() {
564
+ const stats = {
565
+ totalTracked: this.visibilityManagement.size,
566
+ queueBreakdown: {},
567
+ oldestMessage: null,
568
+ avgExtensions: 0
569
+ }
570
+
571
+ let totalExtensions = 0
572
+ let oldestTime = Date.now()
573
+
574
+ for (const [messageId, data] of this.visibilityManagement) {
575
+ if (!stats.queueBreakdown[data.queueName]) {
576
+ stats.queueBreakdown[data.queueName] = 0
577
+ }
578
+ stats.queueBreakdown[data.queueName]++
579
+ totalExtensions += data.extensionCount
580
+
581
+ if (data.createdAt < oldestTime) {
582
+ oldestTime = data.createdAt
583
+ stats.oldestMessage = {
584
+ messageId,
585
+ age: Date.now() - data.createdAt,
586
+ extensions: data.extensionCount
587
+ }
588
+ }
589
+ }
590
+
591
+ if (this.visibilityManagement.size > 0) {
592
+ stats.avgExtensions = totalExtensions / this.visibilityManagement.size
593
+ }
594
+
595
+ return stats
596
+ }
341
597
 
342
598
  // helpers
343
599
  async fetchS3Object({ key }) {
@@ -356,7 +612,6 @@ class ACSQS {
356
612
  throw e
357
613
  }
358
614
  }
359
-
360
615
  }
361
616
 
362
617
  module.exports = ACSQS
package/package.json CHANGED
@@ -3,24 +3,24 @@
3
3
  "author": "Mark Poepping (https://www.admiralcloud.com)",
4
4
  "license": "MIT",
5
5
  "repository": "admiralcloud/ac-sqs",
6
- "version": "3.2.0",
6
+ "version": "3.2.1",
7
7
  "dependencies": {
8
- "@aws-sdk/client-s3": "^3.806.0",
9
- "@aws-sdk/client-sqs": "^3.806.0",
8
+ "@aws-sdk/client-s3": "^3.846.0",
9
+ "@aws-sdk/client-sqs": "^3.846.0",
10
10
  "lodash": "^4.17.21",
11
11
  "uuid": "^11.1.0"
12
12
  },
13
13
  "devDependencies": {
14
14
  "ac-semantic-release": "^0.4.6",
15
15
  "chai": "^4.5.0",
16
- "eslint": "^9.26.0",
17
- "mocha": "^11.2.2"
16
+ "eslint": "^9.31.0",
17
+ "mocha": "^11.7.1"
18
18
  },
19
19
  "scripts": {
20
20
  "test": "mocha --reporter spec"
21
21
  },
22
22
  "engines": {
23
- "node": ">=16.0.0"
23
+ "node": ">=20.0.0"
24
24
  },
25
25
  "resolutions": {
26
26
  "mocha/chokidar/braces": "^3.0.3"