ac-support-connector 1.0.12 → 1.0.14

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.
@@ -16,21 +16,15 @@ jobs:
16
16
 
17
17
  strategy:
18
18
  matrix:
19
- node-version: [20.x, 22.x]
19
+ node-version: [22.x, 24.x]
20
20
  # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
21
- redis-version: [6]
22
21
 
23
22
  steps:
24
- - uses: actions/checkout@v3
23
+ - uses: actions/checkout@v5
25
24
  - name: Use Node.js ${{ matrix.node-version }}
26
- uses: actions/setup-node@v3
25
+ uses: actions/setup-node@v5
27
26
  with:
28
27
  node-version: ${{ matrix.node-version }}
29
-
30
- - name: Start Redis
31
- uses: supercharge/redis-github-action@1.4.0
32
- with:
33
- redis-version: ${{ matrix.redis-version }}
34
28
 
35
29
  - run: yarn install
36
30
  - run: yarn run test
package/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ ## [1.0.14](https://github.com/admiralcloud/ac-support-connector/compare/v1.0.13..v1.0.14) (2026-04-09 11:27:07)
2
+
3
+
4
+ ### Bug Fix
5
+
6
+
7
+ * **Connector:** Improvements after CoPilot review | MP | [e09a77aa4871c89a05383f0f03b076a6ef2f63c3](https://github.com/admiralcloud/ac-support-connector/commit/e09a77aa4871c89a05383f0f03b076a6ef2f63c3)
8
+ Improvements after CoPilot review
9
+ Related issues:
10
+ * **Connector:** Add 2 new parameters - throwError, logger | MP | [982c057541f6e3cef22a661c0eb51403a899b2ef](https://github.com/admiralcloud/ac-support-connector/commit/982c057541f6e3cef22a661c0eb51403a899b2ef)
11
+ Set throwError as true per default, so errors are propagated. Allow custom loggers, default to console (as before)
12
+ Related issues:
13
+ ## [1.0.13](https://github.com/admiralcloud/ac-support-connector/compare/v1.0.12..v1.0.13) (2026-04-04 10:19:59)
14
+
15
+
16
+ ### Bug Fix
17
+
18
+
19
+ * **Connector:** Package updaets | MP | [1bd12738508d496c03b217445bc7ce33e3e1b3bd](https://github.com/admiralcloud/ac-support-connector/commit/1bd12738508d496c03b217445bc7ce33e3e1b3bd)
20
+ Package updates
21
+ Related issues:
22
+ * **Connector:** Package updates | MP | [a616f404236d18ab8d1afa9cc21f8d07bbcc1fb6](https://github.com/admiralcloud/ac-support-connector/commit/a616f404236d18ab8d1afa9cc21f8d07bbcc1fb6)
23
+ Package updates
24
+ Related issues:
25
+ ### Tests
26
+
27
+
28
+ * **Connector:** Remove real Redis from test | MP | [f50d09c6e5f2959216dfb7454f2733e0fb2dfc4e](https://github.com/admiralcloud/ac-support-connector/commit/f50d09c6e5f2959216dfb7454f2733e0fb2dfc4e)
29
+ Mock Redis in test
30
+ Related issues:
31
+ ### Chores
32
+
33
+
34
+ * **Connector:** Updated Github actions | MP | [b779c602f162af94547c968e267bafb611b6af8f](https://github.com/admiralcloud/ac-support-connector/commit/b779c602f162af94547c968e267bafb611b6af8f)
35
+ Updated Github actions
36
+ Related issues:
1
37
 
2
38
  ## [1.0.12](https://github.com/admiralcloud/ac-support-connector/compare/v1.0.11..v1.0.12) (2026-03-21 11:21:38)
3
39
 
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # AC Support Connector
2
2
  This module sends unified support payloads to SQS. A dedicated service (not part of the connector) then processes those SQS messages and delivers the support messages to different channels (e.g. Teams, a helpdesk, etc)
3
3
 
4
- [![Node.js CI](https://github.com/AdmiralCloud/ac-geoip/actions/workflows/node.js.yml/badge.svg)](https://github.com/AdmiralCloud/ac-support-connector/actions/workflows/node.js.yml)
4
+ [![Node.js CI](https://github.com/AdmiralCloud/ac-geoip/actions/workflows/node.js.yml/badge.svg)](https://github.com/AdmiralCloud/ac-support-connector/actions/workflows/node.js.yml) [![CodeQL](https://github.com/AdmiralCloud/ac-support-connector/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/AdmiralCloud/ac-support-connector/actions/workflows/github-code-scanning/codeql)
5
5
 
6
6
  # Breaking changes
7
7
  ## Version 1
package/index.js CHANGED
@@ -9,7 +9,7 @@ module.exports = {
9
9
 
10
10
  aws: {},
11
11
 
12
- init: async function({ serviceName, instanceId, sqsQueue = 'AC-SupportQueue', bucket, redisInstance, region = 'eu-central-1', profile = process.env['profile'], debug } = {}) {
12
+ init: async function({ serviceName, instanceId, sqsQueue = 'AC-SupportQueue', bucket, redisInstance, region = 'eu-central-1', profile = process.env['profile'], debug, logger = console, throwError = true } = {}) {
13
13
 
14
14
  this.sqsQueue = sqsQueue
15
15
  this.serviceName = serviceName || 'SupportConnector'
@@ -17,6 +17,12 @@ module.exports = {
17
17
  this.redisInstance = redisInstance
18
18
  this.cache = new NodeCache()
19
19
  this.debugMode = debug
20
+ this.logger = {
21
+ info: logger?.info?.bind(logger) ?? console.info.bind(console),
22
+ warn: logger?.warn?.bind(logger) ?? console.warn.bind(console),
23
+ error: logger?.error?.bind(logger) ?? console.error.bind(console),
24
+ }
25
+ this.throwError = throwError
20
26
 
21
27
  if (!debug) {
22
28
  const client = new STSClient({
@@ -31,7 +37,8 @@ module.exports = {
31
37
  availableLists: [{
32
38
  name: sqsQueue,
33
39
  fifo: true
34
- }]
40
+ }],
41
+ throwError
35
42
  }
36
43
  if (profile) { sqsParams.profile = profile } // Optional AWS profile, see below
37
44
  if (bucket) {
@@ -61,7 +68,7 @@ module.exports = {
61
68
  })
62
69
  }
63
70
  await this.createMessage(ticket)
64
- console.warn(`Test Message ${identifier} sent`)
71
+ this.logger.warn(`Test Message ${identifier} sent`)
65
72
  process.exit(0)
66
73
  }
67
74
  }
@@ -111,11 +118,14 @@ module.exports = {
111
118
  }
112
119
  try {
113
120
  const response = await this.acsqs.sendSQSMessage({ name: this.sqsQueue, message: JSON.stringify(messagePayload), messageGroupId: (messageGroupId || this.serviceName) })
114
- if (this.debugMode) { console.warn(response) }
121
+ if (this.debugMode) { this.logger.info(response) }
115
122
  return response
116
123
  }
117
124
  catch(e) {
118
- console.error('%s | Subject %s | Failed %j', functionName, subject, e?.message)
125
+ this.logger.error('%s | Subject %s | Failed %j', functionName, subject, e?.message)
126
+ if (this.throwError) {
127
+ throw e
128
+ }
119
129
  }
120
130
  }
121
131
  }
package/package.json CHANGED
@@ -3,19 +3,18 @@
3
3
  "author": "Mark Poepping (https://www.admiralcloud.com)",
4
4
  "license": "MIT",
5
5
  "repository": "admiralcloud/ac-support-connector",
6
- "version": "1.0.12",
6
+ "version": "1.0.14",
7
7
  "dependencies": {
8
- "@aws-sdk/client-sts": "^3.1014.0",
9
- "ac-sqs": "^4.0.5",
8
+ "@aws-sdk/client-sts": "^3.1024.0",
9
+ "ac-sqs": "^4.0.6",
10
10
  "node-cache": "^5.1.2"
11
11
  },
12
12
  "devDependencies": {
13
- "ac-semantic-release": "^0.4.10",
13
+ "ac-semantic-release": "^1.0.1",
14
14
  "chai": "^4.5.0",
15
- "eslint": "^10.1.0",
15
+ "eslint": "^10.2.0",
16
16
  "expect": "^30.3.0",
17
17
  "globals": "^17.4.0",
18
- "ioredis": "^5.10.1",
19
18
  "mocha": "^11.7.5"
20
19
  },
21
20
  "scripts": {
package/test/test.js CHANGED
@@ -1,11 +1,24 @@
1
1
  const { expect } = require('chai');
2
2
 
3
- const Redis = require("ioredis");
4
- const redisInstance = new Redis()
5
-
6
3
  const supCon = require('../index')
7
4
 
8
- const string1001 = new Array(512000).join('b')
5
+ // Minimal Redis stub – no real connection needed
6
+ function createFakeRedis() {
7
+ const store = new Map()
8
+ return {
9
+ async set(key, _value, exFlag, seconds, nxFlag) {
10
+ if (nxFlag === 'nx' && store.has(key)) { return null }
11
+ store.set(key, true)
12
+ setTimeout(() => store.delete(key), seconds * 1000)
13
+ return 'OK'
14
+ },
15
+ quit() {}
16
+ }
17
+ }
18
+
19
+ const redisInstance = createFakeRedis()
20
+
21
+ const string1001 = new Array(1100000).join('b')
9
22
 
10
23
  function timeout(ms) {
11
24
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -25,7 +38,7 @@ describe('Basic tests', () => {
25
38
  expect(response.message[0]).to.have.property('content', params.text)
26
39
  })
27
40
 
28
- it('Check truncated payload > 256KB - should not throw an error', async() => {
41
+ it('Check truncated payload > 1MB - should not throw an error', async() => {
29
42
  const params = {
30
43
  subject: 'Failed',
31
44
  message: [{
@@ -140,6 +153,116 @@ describe('Block with Memory', () => {
140
153
  })
141
154
 
142
155
 
156
+ describe('throwError behavior', () => {
157
+ const originalEnv = process.env.NODE_ENV
158
+ let fakeLogger
159
+
160
+ before(async() => {
161
+ fakeLogger = { errors: [], warns: [], error(...args) { this.errors.push(args) }, warn(...args) { this.warns.push(args) } }
162
+ await supCon.init({ debug: true, logger: fakeLogger })
163
+ process.env.NODE_ENV = 'production' // bypass early return in createMessage
164
+ supCon.acsqs = {
165
+ async sendSQSMessage() {
166
+ throw new Error('SQS failed')
167
+ }
168
+ }
169
+ })
170
+
171
+ after(() => {
172
+ process.env.NODE_ENV = originalEnv
173
+ delete supCon.acsqs
174
+ })
175
+
176
+ it('throwError: true - should throw on SQS failure', async() => {
177
+ supCon.throwError = true
178
+ fakeLogger.errors = []
179
+ let threw = false
180
+ try {
181
+ await supCon.createMessage({ subject: 'Test', text: 'Error' })
182
+ }
183
+ catch(e) {
184
+ threw = true
185
+ expect(e.message).to.equal('SQS failed')
186
+ }
187
+ expect(threw).to.be.true
188
+ expect(fakeLogger.errors).to.have.lengthOf(1)
189
+ })
190
+
191
+ it('throwError: false - should not throw on SQS failure', async() => {
192
+ supCon.throwError = false
193
+ fakeLogger.errors = []
194
+ const response = await supCon.createMessage({ subject: 'Test', text: 'Error' })
195
+ expect(response).to.be.undefined
196
+ expect(fakeLogger.errors).to.have.lengthOf(1)
197
+ })
198
+ })
199
+
200
+ describe('custom logger', () => {
201
+ const originalEnv = process.env.NODE_ENV
202
+ let fakeLogger
203
+
204
+ before(async() => {
205
+ fakeLogger = { infos: [], info(...args) { this.infos.push(args) } }
206
+ await supCon.init({ debug: true, logger: fakeLogger })
207
+ process.env.NODE_ENV = 'production'
208
+ supCon.acsqs = {
209
+ async sendSQSMessage() { return { MessageId: 'abc123' } }
210
+ }
211
+ })
212
+
213
+ after(() => {
214
+ process.env.NODE_ENV = originalEnv
215
+ delete supCon.acsqs
216
+ })
217
+
218
+ it('logger.info is called on successful send in debug mode', async() => {
219
+ const response = await supCon.createMessage({ subject: 'Test', text: 'Hello' })
220
+ expect(response).to.deep.equal({ MessageId: 'abc123' })
221
+ expect(fakeLogger.infos).to.have.lengthOf(1)
222
+ })
223
+ })
224
+
225
+
226
+ describe('logger normalization', () => {
227
+ const originalEnv = process.env.NODE_ENV
228
+
229
+ before(() => {
230
+ process.env.NODE_ENV = 'production'
231
+ })
232
+
233
+ after(() => {
234
+ process.env.NODE_ENV = originalEnv
235
+ delete supCon.acsqs
236
+ })
237
+
238
+ it('null logger - falls back to console without throwing', async() => {
239
+ await supCon.init({ debug: true, logger: null })
240
+ supCon.acsqs = { async sendSQSMessage() { throw new Error('boom') } }
241
+ supCon.throwError = false
242
+ // must not throw a TypeError about this.logger.error
243
+ await supCon.createMessage({ subject: 'Test', text: 'Hello' })
244
+ })
245
+
246
+ it('partial logger (missing warn/error) - fills gaps without throwing', async() => {
247
+ const partial = { infos: [], info(...args) { this.infos.push(args) } }
248
+ await supCon.init({ debug: true, logger: partial })
249
+ supCon.acsqs = { async sendSQSMessage() { throw new Error('boom') } }
250
+ supCon.throwError = false
251
+ // error method is missing on partial — must not throw a TypeError
252
+ await supCon.createMessage({ subject: 'Test', text: 'Hello' })
253
+ })
254
+
255
+ it('partial logger (missing info) - successful send does not throw', async() => {
256
+ const partial = { errors: [], error(...args) { this.errors.push(args) } }
257
+ await supCon.init({ debug: true, logger: partial })
258
+ supCon.acsqs = { async sendSQSMessage() { return { MessageId: 'xyz' } } }
259
+ // info method is missing — must not throw a TypeError on success path
260
+ const response = await supCon.createMessage({ subject: 'Test', text: 'Hello' })
261
+ expect(response).to.deep.equal({ MessageId: 'xyz' })
262
+ })
263
+ })
264
+
265
+
143
266
  describe('Cleanup', () => {
144
267
  it('Close Redis', async() => {
145
268
  redisInstance.quit()