sqs-producer 3.4.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,13 +5,18 @@ on:
5
5
  pull_request_target:
6
6
  types: [opened,closed,synchronize]
7
7
 
8
+ permissions:
9
+ contents: write
10
+ issues: write
11
+ pull-requests: write
12
+
8
13
  jobs:
9
14
  CLAAssistant:
10
15
  runs-on: ubuntu-latest
11
16
  steps:
12
17
  - name: "CLA Check"
13
18
  if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
14
- uses: contributor-assistant/github-action@v2.2.1
19
+ uses: contributor-assistant/github-action@v2.3.1
15
20
  env:
16
21
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17
22
  PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
@@ -40,7 +40,7 @@ jobs:
40
40
 
41
41
  steps:
42
42
  - name: Checkout repository
43
- uses: actions/checkout@v3
43
+ uses: actions/checkout@v4
44
44
 
45
45
  # Initializes the CodeQL tools for scanning.
46
46
  - name: Initialize CodeQL
@@ -17,10 +17,10 @@ jobs:
17
17
  node-version: [18.x]
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v3
20
+ - uses: actions/checkout@v4
21
21
 
22
22
  - name: Use Node.js ${{ matrix.node-version }}
23
- uses: actions/setup-node@v3
23
+ uses: actions/setup-node@v4
24
24
  with:
25
25
  node-version: ${{ matrix.node-version }}
26
26
 
@@ -28,7 +28,7 @@ jobs:
28
28
  run: npm ci
29
29
 
30
30
  - name: Report Coverage
31
- uses: paambaati/codeclimate-action@v3.2.0
31
+ uses: paambaati/codeclimate-action@v5.0.0
32
32
  env:
33
33
  CC_TEST_REPORTER_ID: b7dd7a17709f29e70a936a1a9482a9d7c0da56915aec94382436d4e8f9bcb78e
34
34
  with:
@@ -0,0 +1,14 @@
1
+ name: 'Dependency Review'
2
+ on: [pull_request]
3
+
4
+ permissions:
5
+ contents: read
6
+
7
+ jobs:
8
+ dependency-review:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: 'Checkout Repository'
12
+ uses: actions/checkout@v4
13
+ - name: 'Dependency Review'
14
+ uses: actions/dependency-review-action@v3
@@ -0,0 +1,59 @@
1
+ # Simple workflow for deploying static content to GitHub Pages
2
+ name: Deploy static content to Pages
3
+
4
+ on:
5
+ # Runs on pushes targeting the default branch
6
+ push:
7
+ branches: ["main"]
8
+
9
+ # Allows you to run this workflow manually from the Actions tab
10
+ workflow_dispatch:
11
+
12
+ # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13
+ permissions:
14
+ contents: read
15
+ pages: write
16
+ id-token: write
17
+
18
+ # Allow one concurrent deployment
19
+ concurrency:
20
+ group: "pages"
21
+ cancel-in-progress: true
22
+
23
+ jobs:
24
+ # Single deploy job since we're just deploying
25
+ deploy:
26
+ environment:
27
+ name: github-pages
28
+ url: ${{ steps.deployment.outputs.page_url }}
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - name: Checkout
32
+ uses: actions/checkout@v4
33
+
34
+ - name: Setup Node.js
35
+ uses: actions/setup-node@v4
36
+ with:
37
+ node-version: 18.x
38
+ cache: 'npm'
39
+
40
+ - name: NPM Audit
41
+ run: npx audit-ci
42
+
43
+ - name: Install Node Modules
44
+ run: npm ci
45
+
46
+ - name: Build Docs
47
+ run: npm run generate-docs
48
+
49
+ - name: Setup Pages
50
+ uses: actions/configure-pages@v3
51
+
52
+ - name: Upload artifact
53
+ uses: actions/upload-pages-artifact@v2
54
+ with:
55
+ path: './public'
56
+
57
+ - name: Deploy to GitHub Pages
58
+ id: deployment
59
+ uses: actions/deploy-pages@v2
@@ -0,0 +1,29 @@
1
+ name: "Lock Threads"
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 * * * *" # Once a day, at midnight UTC
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ issues: write
10
+ pull-requests: write
11
+
12
+ concurrency:
13
+ group: lock
14
+
15
+ jobs:
16
+ action:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: dessant/lock-threads@v4
20
+ with:
21
+ github-token: ${{ secrets.GITHUB_TOKEN }}
22
+ issue-inactive-days: "30" # Lock issues after 30 days of being closed
23
+ pr-inactive-days: "5" # Lock closed PRs after 5 days. This ensures that issues that stem from a PR are opened as issues, rather than comments on the recently merged PR.
24
+ add-issue-labels: "outdated"
25
+ exclude-issue-created-before: "2023-01-01"
26
+ issue-comment: >
27
+ This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.
28
+ pr-comment: >
29
+ This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.
@@ -0,0 +1,26 @@
1
+ name: Publish Package to npmjs
2
+ on:
3
+ workflow_dispatch:
4
+ jobs:
5
+ build:
6
+ runs-on: ubuntu-latest
7
+ permissions:
8
+ contents: write
9
+ issues: write
10
+ pull-requests: write
11
+ id-token: write
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20.x'
17
+ cache: 'npm'
18
+ registry-url: 'https://registry.npmjs.org'
19
+ - run: npm ci
20
+ - name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
21
+ run: npm audit signatures
22
+ - name: Release
23
+ env:
24
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
26
+ run: npx semantic-release
@@ -7,7 +7,7 @@ jobs:
7
7
  stale:
8
8
  runs-on: ubuntu-latest
9
9
  steps:
10
- - uses: actions/stale@v6
10
+ - uses: actions/stale@v8
11
11
  with:
12
12
  stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
13
13
  stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
@@ -16,4 +16,9 @@ jobs:
16
16
  days-before-issue-stale: 30
17
17
  days-before-pr-stale: 45
18
18
  days-before-issue-close: 5
19
- days-before-pr-close: 10
19
+ days-before-pr-close: 10
20
+ operations-per-run: 90
21
+ exempt-issue-labels: keep
22
+ exempt-pr-labels: keep
23
+ exempt-all-assignees: true
24
+ exempt-all-milestones: true
@@ -17,10 +17,10 @@ jobs:
17
17
  node-version: [18.x, 20.x]
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v3
20
+ - uses: actions/checkout@v4
21
21
 
22
22
  - name: Use Node.js ${{ matrix.node-version }}
23
- uses: actions/setup-node@v3
23
+ uses: actions/setup-node@v4
24
24
  with:
25
25
  node-version: ${{ matrix.node-version }}
26
26
 
package/.prettierignore CHANGED
@@ -1,4 +1,5 @@
1
1
  node_modules
2
2
  coverage
3
3
  bake-scripts
4
- dist
4
+ dist
5
+ public
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ ## [5.0.0](https://github.com/bbc/sqs-producer/compare/v4.0.0...v5.0.0) (2024-03-11)
2
+
3
+
4
+ ### Features
5
+
6
+ * updating ProducerOptions to use QueueUrl hostname ([#102](https://github.com/bbc/sqs-producer/issues/102)) ([370c363](https://github.com/bbc/sqs-producer/commit/370c3637ff161ee72bb2058b0e0dea7f77f9112f))
7
+
8
+
9
+ ### Chores
10
+
11
+ * add documentation ([#106](https://github.com/bbc/sqs-producer/issues/106)) ([96dcb3b](https://github.com/bbc/sqs-producer/commit/96dcb3b4bce2882830568555206196dbb8875503))
12
+ * **deps:** upgrading dependencies - march 24 ([#105](https://github.com/bbc/sqs-producer/issues/105)) ([4daa21b](https://github.com/bbc/sqs-producer/commit/4daa21b0b82a0f97321823f3537afe45c116df73))
13
+ * downgrading @semantic-release/npm ([7836f3a](https://github.com/bbc/sqs-producer/commit/7836f3a5b6b4e887a727a98e476ac0dd97f26daf))
14
+ * handle breaking changes ([4509173](https://github.com/bbc/sqs-producer/commit/4509173bfe38be97b5e4b1a3b2a56881109e8c84))
15
+ * improve and update ci cd ([#107](https://github.com/bbc/sqs-producer/issues/107)) ([fe7e708](https://github.com/bbc/sqs-producer/commit/fe7e708435c0f1680ab060383f6edd0c00e9abee))
package/README.md CHANGED
@@ -5,10 +5,12 @@
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/5220635a4598c9f1a546/maintainability)](https://codeclimate.com/github/bbc/sqs-producer/maintainability)
6
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/5220635a4598c9f1a546/test_coverage)](https://codeclimate.com/github/bbc/sqs-producer/test_coverage)
7
7
 
8
- Enqueues messages onto a given SQS queue
8
+ Enqueues messages onto a given SQS queue.
9
9
 
10
10
  ## Installation
11
11
 
12
+ To install this package, enter the following command into your terminal (or the variant of whatever package manager you are using):
13
+
12
14
  ```
13
15
  npm install sqs-producer
14
16
  ```
@@ -24,6 +26,10 @@ npm install sqs-producer
24
26
 
25
27
  We will only support Node versions that are actively or security supported by the Node team. If you are still using an Node 14, please use a version of this library before the v3.2.1 release, if you are using Node 16, please use a version before the v3.3.0 release.
26
28
 
29
+ ## Documentation
30
+
31
+ Visit [https://bbc.github.io/sqs-producer/](https://bbc.github.io/sqs-producer/) for the full API documentation.
32
+
27
33
  ## Usage
28
34
 
29
35
  ```js
@@ -78,7 +84,7 @@ await producer.send([
78
84
  //
79
85
  // deduplicationId can be excluded if content-based deduplication is enabled
80
86
  //
81
- // http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queue-recommendations.html
87
+ // https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queue-recommendations.html
82
88
  await producer.send({
83
89
  id: 'testId',
84
90
  body: 'Hello world from our FIFO queue!',
@@ -89,7 +95,7 @@ await producer.send({
89
95
 
90
96
  ### Credentials
91
97
 
92
- By default the consumer will look for AWS credentials in the places [specified by the AWS SDK](http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html#Setting_AWS_Credentials). The simplest option is to export your credentials as environment variables:
98
+ By default the consumer will look for AWS credentials in the places [specified by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-configuring.html#Setting_AWS_Credentials). The simplest option is to export your credentials as environment variables:
93
99
 
94
100
  ```bash
95
101
  export AWS_SECRET_ACCESS_KEY=...
@@ -123,7 +129,7 @@ await producer.send(['msg1', 'msg2']);
123
129
 
124
130
  ### Test
125
131
 
126
- ```
132
+ ```bash
127
133
  npm test
128
134
  ```
129
135
 
@@ -131,7 +137,7 @@ npm test
131
137
 
132
138
  For coverage report, run the command:
133
139
 
134
- ```
140
+ ```bash
135
141
  npm run coverage
136
142
  ```
137
143
 
@@ -139,10 +145,16 @@ npm run coverage
139
145
 
140
146
  To check for problems using ESLint
141
147
 
142
- ```
148
+ ```bash
143
149
  npm run lint
144
150
  ```
145
151
 
146
152
  ## Contributing
147
153
 
148
- See [contributing guildlines](./.github/CONTRIBUTING.md)
154
+ We welcome and appreciate contributions for anyone who would like to take the time to fix a bug or implement a new feature.
155
+
156
+ But before you get started, [please read the contributing guidelines](https://github.com/bbc/sqs-producer/blob/main/.github/CONTRIBUTING.md) and [code of conduct](https://github.com/bbc/sqs-producer/blob/main/.github/CODE_OF_CONDUCT.md).
157
+
158
+ ## License
159
+
160
+ SQS Producer is distributed under the Apache License, Version 2.0, see [LICENSE](./LICENSE) for more information.
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Error thrown when a message fails to send.
3
+ */
4
+ export declare class FailedMessagesError extends Error {
5
+ /** Ids of messages that failed to send. */
6
+ failedMessages: string[];
7
+ /**
8
+ * @param failedMessages Ids of messages that failed to send.
9
+ */
10
+ constructor(failedMessages: string[]);
11
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FailedMessagesError = void 0;
4
+ /**
5
+ * Error thrown when a message fails to send.
6
+ */
7
+ class FailedMessagesError extends Error {
8
+ /**
9
+ * @param failedMessages Ids of messages that failed to send.
10
+ */
11
+ constructor(failedMessages) {
12
+ super(`Failed to send messages: ${failedMessages.join(', ')}`);
13
+ this.failedMessages = failedMessages;
14
+ }
15
+ }
16
+ exports.FailedMessagesError = FailedMessagesError;
package/dist/format.d.ts CHANGED
@@ -1,3 +1,8 @@
1
1
  import { SendMessageBatchRequestEntry } from '@aws-sdk/client-sqs';
2
2
  import { Message } from './types';
3
+ /**
4
+ * Converts a message to a SendMessageBatchRequestEntry using the appropriate method
5
+ * depending on if the message is a string or an object
6
+ * @param message The message to convert
7
+ */
3
8
  export declare function toEntry(message: string | Message): SendMessageBatchRequestEntry;
package/dist/format.js CHANGED
@@ -2,6 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toEntry = void 0;
4
4
  const validation_1 = require("./validation");
5
+ /**
6
+ * Converts a message object to a SendMessageBatchRequestEntry
7
+ * @param message - The message to convert
8
+ * @returns The SendMessageBatchRequestEntry
9
+ * @throws Will throw an error if the message is invalid
10
+ */
5
11
  function entryFromObject(message) {
6
12
  if (!message.body) {
7
13
  throw new Error(`Object messages must have 'body' prop`);
@@ -50,12 +56,21 @@ function entryFromObject(message) {
50
56
  }
51
57
  return entry;
52
58
  }
59
+ /**
60
+ * Converts a message string to a SendMessageBatchRequestEntry
61
+ * @param message The message to convert
62
+ */
53
63
  function entryFromString(message) {
54
64
  return {
55
65
  Id: message,
56
66
  MessageBody: message
57
67
  };
58
68
  }
69
+ /**
70
+ * Converts a message to a SendMessageBatchRequestEntry using the appropriate method
71
+ * depending on if the message is a string or an object
72
+ * @param message The message to convert
73
+ */
59
74
  function toEntry(message) {
60
75
  if ((0, validation_1.isString)(message)) {
61
76
  return entryFromString(message);
@@ -1,5 +1,8 @@
1
1
  import { SQSClient, SendMessageBatchResultEntry } from '@aws-sdk/client-sqs';
2
2
  import { Message, ProducerOptions } from './types';
3
+ /**
4
+ * [Usage](https://bbc.github.io/sqs-producer/index.html#usage)
5
+ */
3
6
  export declare class Producer {
4
7
  static create: (options: ProducerOptions) => Producer;
5
8
  queueUrl: string;
@@ -7,8 +10,31 @@ export declare class Producer {
7
10
  sqs: SQSClient;
8
11
  region?: string;
9
12
  constructor(options: ProducerOptions);
13
+ /**
14
+ * Returns the number of messages in the queue.
15
+ * @returns A promise that resolves to the number of messages in the queue.
16
+ */
10
17
  queueSize(): Promise<number>;
18
+ /**
19
+ * Send a message to the queue.
20
+ * @param messages - A single message or an array of messages.
21
+ * @returns A promise that resolves to the result of the send operation.
22
+ */
11
23
  send(messages: string | Message | (string | Message)[]): Promise<SendMessageBatchResultEntry[]>;
24
+ /**
25
+ * Validate the producer options.
26
+ * @param options - The producer options to validate.
27
+ * @throws Error if any required options are missing or invalid.
28
+ */
12
29
  private validate;
30
+ /**
31
+ * Send a batch of messages to the queue.
32
+ * @param failedMessages - An array of failed message IDs.
33
+ * @param successfulMessages - An array of successful message results.
34
+ * @param messages - An array of messages to send.
35
+ * @param startIndex - The index of the first message in the batch.
36
+ * @returns A promise that resolves to the result of the send operation.
37
+ * @throws FailedMessagesError
38
+ */
13
39
  private sendBatch;
14
40
  }
package/dist/producer.js CHANGED
@@ -3,16 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Producer = void 0;
4
4
  const client_sqs_1 = require("@aws-sdk/client-sqs");
5
5
  const format_1 = require("./format");
6
+ const errors_1 = require("./errors");
6
7
  const requiredOptions = ['queueUrl'];
8
+ /**
9
+ * [Usage](https://bbc.github.io/sqs-producer/index.html#usage)
10
+ */
7
11
  class Producer {
8
12
  constructor(options) {
13
+ var _a;
9
14
  this.validate(options);
10
15
  this.queueUrl = options.queueUrl;
11
16
  this.batchSize = options.batchSize || 10;
12
17
  this.sqs =
13
18
  options.sqs ||
14
- new client_sqs_1.SQSClient(Object.assign(Object.assign({}, options), { region: options.region || process.env.AWS_REGION || 'eu-west-1' }));
19
+ new client_sqs_1.SQSClient(Object.assign(Object.assign({}, options), { useQueueUrlAsEndpoint: (_a = options.useQueueUrlAsEndpoint) !== null && _a !== void 0 ? _a : true, region: options.region || process.env.AWS_REGION || 'eu-west-1' }));
15
20
  }
21
+ /**
22
+ * Returns the number of messages in the queue.
23
+ * @returns A promise that resolves to the number of messages in the queue.
24
+ */
16
25
  async queueSize() {
17
26
  const command = new client_sqs_1.GetQueueAttributesCommand({
18
27
  QueueUrl: this.queueUrl,
@@ -23,6 +32,11 @@ class Producer {
23
32
  result.Attributes &&
24
33
  result.Attributes.ApproximateNumberOfMessages);
25
34
  }
35
+ /**
36
+ * Send a message to the queue.
37
+ * @param messages - A single message or an array of messages.
38
+ * @returns A promise that resolves to the result of the send operation.
39
+ */
26
40
  async send(messages) {
27
41
  const failedMessages = [];
28
42
  const successfulMessages = [];
@@ -30,6 +44,11 @@ class Producer {
30
44
  const messagesArr = !Array.isArray(messages) ? [messages] : messages;
31
45
  return this.sendBatch(failedMessages, successfulMessages, messagesArr, startIndex);
32
46
  }
47
+ /**
48
+ * Validate the producer options.
49
+ * @param options - The producer options to validate.
50
+ * @throws Error if any required options are missing or invalid.
51
+ */
33
52
  validate(options) {
34
53
  for (const option of requiredOptions) {
35
54
  if (!options[option]) {
@@ -40,6 +59,15 @@ class Producer {
40
59
  throw new Error('SQS batchSize option must be between 1 and 10.');
41
60
  }
42
61
  }
62
+ /**
63
+ * Send a batch of messages to the queue.
64
+ * @param failedMessages - An array of failed message IDs.
65
+ * @param successfulMessages - An array of successful message results.
66
+ * @param messages - An array of messages to send.
67
+ * @param startIndex - The index of the first message in the batch.
68
+ * @returns A promise that resolves to the result of the send operation.
69
+ * @throws FailedMessagesError
70
+ */
43
71
  async sendBatch(failedMessages, successfulMessages, messages, startIndex) {
44
72
  var _a;
45
73
  const endIndex = startIndex + this.batchSize;
@@ -58,10 +86,14 @@ class Producer {
58
86
  if (failedMessagesBatch.length === 0) {
59
87
  return successfulMessagesBatch;
60
88
  }
61
- throw new Error(`Failed to send messages: ${failedMessagesBatch.join(', ')}`);
89
+ throw new errors_1.FailedMessagesError(failedMessagesBatch);
62
90
  }
63
91
  }
64
92
  exports.Producer = Producer;
93
+ /**
94
+ * Creates a new producer.
95
+ * @param options - The producer options.
96
+ */
65
97
  Producer.create = (options) => {
66
98
  return new Producer(options);
67
99
  };
package/dist/types.d.ts CHANGED
@@ -1,16 +1,64 @@
1
1
  import { MessageAttributeValue, SQSClient } from '@aws-sdk/client-sqs';
2
2
  export interface ProducerOptions {
3
+ /**
4
+ * The URL of the queue to send messages to.
5
+ */
3
6
  queueUrl: string;
7
+ /**
8
+ * The number of messages to send in a single batch.
9
+ */
4
10
  batchSize?: number;
11
+ /**
12
+ * The SQS client to use. If not provided, a new client will be created.
13
+ */
5
14
  sqs?: SQSClient;
15
+ /**
16
+ * The AWS region to use. If not provided, the region will be determined
17
+ * from the `AWS_REGION` environment variable or will default to `eu-west-1.
18
+ */
6
19
  region?: string;
20
+ /**
21
+ * In cases where a QueueUrl is given as input, that
22
+ * will be preferred as the request endpoint.
23
+ *
24
+ * Set this value to false to ignore the QueueUrl and use the
25
+ * client's resolved endpoint, which may be a custom endpoint.
26
+ */
27
+ useQueueUrlAsEndpoint?: boolean;
7
28
  }
8
29
  export interface Message {
30
+ /**
31
+ * An identifier for the message. This must be unique within
32
+ * the batch of messages.
33
+ */
9
34
  id: string;
35
+ /**
36
+ * The messages contents.
37
+ */
10
38
  body: string;
39
+ /**
40
+ * This parameter applies only to FIFO (first-in-first-out) queues.
41
+ * When set messages that belong to the same message group are processed
42
+ * in a FIFO manner
43
+ */
11
44
  groupId?: string;
45
+ /**
46
+ * This parameter applies only to FIFO (first-in-first-out) queues.
47
+ * The token used for deduplication of messages within a 5-minute minimum
48
+ * deduplication interval. If a message with a particular id is sent successfully,
49
+ * subsequent messages with the same id are accepted
50
+ * successfully but aren't delivered.
51
+ */
12
52
  deduplicationId?: string;
53
+ /**
54
+ * The length of time, in seconds, for which to delay a specific message.
55
+ * Valid values: 0 to 900. Maximum: 15 minutes.
56
+ */
13
57
  delaySeconds?: number;
58
+ /**
59
+ * Each message attribute consists of a Name, Type, and Value. For more
60
+ * information, see [Amazon SQS message attributes](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-attributes.html).
61
+ */
14
62
  messageAttributes?: {
15
63
  [key: string]: MessageAttributeValue;
16
64
  };
@@ -1,3 +1,15 @@
1
+ /**
2
+ * Checks if the value is a string
3
+ * @param value - The value to check
4
+ */
1
5
  export declare function isString(value: any): boolean;
6
+ /**
7
+ * Checks if the value is an object
8
+ * @param value - The value to check
9
+ */
2
10
  export declare function isObject(value: any): boolean;
11
+ /**
12
+ * Checks if a MessageAttribute is valid
13
+ * @param messageAttribute - The MessageAttribute to check
14
+ */
3
15
  export declare function isMessageAttributeValid(messageAttribute: any): boolean;
@@ -1,14 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isMessageAttributeValid = exports.isObject = exports.isString = void 0;
4
+ /**
5
+ * Checks if the value is a string
6
+ * @param value - The value to check
7
+ */
4
8
  function isString(value) {
5
9
  return typeof value === 'string' || value instanceof String;
6
10
  }
7
11
  exports.isString = isString;
12
+ /**
13
+ * Checks if the value is an object
14
+ * @param value - The value to check
15
+ */
8
16
  function isObject(value) {
9
17
  return value && typeof value === 'object' && value instanceof Object;
10
18
  }
11
19
  exports.isObject = isObject;
20
+ /**
21
+ * Checks if a MessageAttribute is valid
22
+ * @param messageAttribute - The MessageAttribute to check
23
+ */
12
24
  function isMessageAttributeValid(messageAttribute) {
13
25
  if (!messageAttribute.DataType) {
14
26
  throw new Error('A MessageAttribute must have a DataType key');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqs-producer",
3
- "version": "3.4.0",
3
+ "version": "5.0.0",
4
4
  "description": "Enqueues messages onto a given SQS queue",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -11,13 +11,14 @@
11
11
  "lcov": "c8 mocha && c8 report --reporter=lcov",
12
12
  "lint": "eslint . --ext .ts",
13
13
  "lint:fix": "eslint . --fix",
14
- "format": "prettier --loglevel warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
14
+ "format": "prettier --log-level warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
15
15
  "format:check": "prettier --check \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
16
16
  "build": "npm run clean && tsc",
17
17
  "prepublishOnly": "npm run build",
18
18
  "pretest": "npm run build",
19
19
  "watch": "tsc --watch",
20
- "clean": "rm -fr dist/*"
20
+ "clean": "rm -fr dist/*",
21
+ "generate-docs": "typedoc"
21
22
  },
22
23
  "engines": {
23
24
  "node": ">=18.0.0"
@@ -36,29 +37,125 @@
36
37
  "producer",
37
38
  "queue"
38
39
  ],
39
- "homepage": "https://github.com/bbc/sqs-producer",
40
+ "homepage": "https://bbc.github.io/sqs-producer/",
41
+ "publishConfig": {
42
+ "provenance": true
43
+ },
44
+ "release": {
45
+ "branches": [
46
+ "main",
47
+ {
48
+ "name": "canary",
49
+ "prerelease": true
50
+ }
51
+ ],
52
+ "plugins": [
53
+ [
54
+ "@semantic-release/commit-analyzer",
55
+ {
56
+ "preset": "conventionalcommits",
57
+ "releaseRules": [
58
+ {
59
+ "type": "breaking",
60
+ "release": "major"
61
+ },
62
+ {
63
+ "type": "feat",
64
+ "release": "minor"
65
+ },
66
+ {
67
+ "type": "chore",
68
+ "release": "patch"
69
+ },
70
+ {
71
+ "type": "fix",
72
+ "release": "patch"
73
+ },
74
+ {
75
+ "type": "docs",
76
+ "release": "patch"
77
+ },
78
+ {
79
+ "type": "refactor",
80
+ "release": "patch"
81
+ },
82
+ {
83
+ "type": "test",
84
+ "release": "patch"
85
+ }
86
+ ]
87
+ }
88
+ ],
89
+ [
90
+ "@semantic-release/release-notes-generator",
91
+ {
92
+ "preset": "conventionalcommits",
93
+ "presetConfig": {
94
+ "types": [
95
+ {
96
+ "type": "feat",
97
+ "section": "Features"
98
+ },
99
+ {
100
+ "type": "fix",
101
+ "section": "Bug Fixes"
102
+ },
103
+ {
104
+ "type": "chore",
105
+ "section": "Chores"
106
+ },
107
+ {
108
+ "type": "docs",
109
+ "section": "Documentation"
110
+ },
111
+ {
112
+ "type": "refactor",
113
+ "section": "Refactors"
114
+ },
115
+ {
116
+ "type": "test",
117
+ "section": "Tests"
118
+ }
119
+ ]
120
+ }
121
+ }
122
+ ],
123
+ "@semantic-release/changelog",
124
+ "@semantic-release/github",
125
+ "@semantic-release/npm"
126
+ ]
127
+ },
40
128
  "devDependencies": {
41
- "@types/chai": "^4.3.9",
42
- "@types/debug": "^4.1.10",
43
- "@types/mocha": "^10.0.3",
44
- "@types/node": "^20.8.7",
45
- "@types/sinon": "^10.0.20",
46
- "chai": "^4.3.10",
47
- "eslint": "^8.52.0",
48
- "eslint-config-iplayer": "^9.1.0",
49
- "eslint-config-prettier": "^9.0.0",
50
- "mocha": "^10.2.0",
51
- "c8": "^8.0.1",
52
- "prettier": "^3.0.3",
53
- "sinon": "^17.0.0",
54
- "ts-node": "^10.9.1",
55
- "typescript": "^5.2.2"
129
+ "@semantic-release/changelog": "^6.0.3",
130
+ "@semantic-release/commit-analyzer": "^11.1.0",
131
+ "@semantic-release/git": "^10.0.1",
132
+ "@semantic-release/github": "^9.2.6",
133
+ "@semantic-release/npm": "11.0.2",
134
+ "@semantic-release/release-notes-generator": "^12.1.0",
135
+ "@types/chai": "^4.3.12",
136
+ "@types/debug": "^4.1.12",
137
+ "@types/mocha": "^10.0.6",
138
+ "@types/node": "^20.11.25",
139
+ "@types/sinon": "^17.0.3",
140
+ "chai": "^4.4.1",
141
+ "conventional-changelog-conventionalcommits": "^7.0.2",
142
+ "eslint": "^8.57.0",
143
+ "eslint-config-iplayer": "^9.2.0",
144
+ "eslint-config-prettier": "^9.1.0",
145
+ "mocha": "^10.3.0",
146
+ "c8": "^9.1.0",
147
+ "prettier": "^3.2.5",
148
+ "semantic-release": "^23.0.0",
149
+ "sinon": "^17.0.1",
150
+ "ts-node": "^10.9.2",
151
+ "typedoc": "^0.25.12",
152
+ "typescript": "^5.4.2"
56
153
  },
57
154
  "dependencies": {
58
- "@aws-sdk/client-sqs": "^3.428.0"
155
+ "@aws-sdk/client-sqs": "^3.529.1"
59
156
  },
60
157
  "peerDependencies": {
61
- "@aws-sdk/client-sqs": "^3.428.0"
158
+ "@aws-sdk/client-sqs": "^3.529.1"
62
159
  },
63
160
  "mocha": {
64
161
  "spec": "test/**/**/*.test.ts",
package/src/errors.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Error thrown when a message fails to send.
3
+ */
4
+ export class FailedMessagesError extends Error {
5
+ /** Ids of messages that failed to send. */
6
+ public failedMessages: string[];
7
+ /**
8
+ * @param failedMessages Ids of messages that failed to send.
9
+ */
10
+ constructor(failedMessages: string[]) {
11
+ super(`Failed to send messages: ${failedMessages.join(', ')}`);
12
+ this.failedMessages = failedMessages;
13
+ }
14
+ }
package/src/format.ts CHANGED
@@ -2,6 +2,12 @@ import { SendMessageBatchRequestEntry } from '@aws-sdk/client-sqs';
2
2
  import { Message } from './types';
3
3
  import { isObject, isString, isMessageAttributeValid } from './validation';
4
4
 
5
+ /**
6
+ * Converts a message object to a SendMessageBatchRequestEntry
7
+ * @param message - The message to convert
8
+ * @returns The SendMessageBatchRequestEntry
9
+ * @throws Will throw an error if the message is invalid
10
+ */
5
11
  function entryFromObject(message: Message): SendMessageBatchRequestEntry {
6
12
  if (!message.body) {
7
13
  throw new Error(`Object messages must have 'body' prop`);
@@ -69,6 +75,10 @@ function entryFromObject(message: Message): SendMessageBatchRequestEntry {
69
75
  return entry;
70
76
  }
71
77
 
78
+ /**
79
+ * Converts a message string to a SendMessageBatchRequestEntry
80
+ * @param message The message to convert
81
+ */
72
82
  function entryFromString(message: string): SendMessageBatchRequestEntry {
73
83
  return {
74
84
  Id: message,
@@ -76,6 +86,11 @@ function entryFromString(message: string): SendMessageBatchRequestEntry {
76
86
  };
77
87
  }
78
88
 
89
+ /**
90
+ * Converts a message to a SendMessageBatchRequestEntry using the appropriate method
91
+ * depending on if the message is a string or an object
92
+ * @param message The message to convert
93
+ */
79
94
  export function toEntry(
80
95
  message: string | Message
81
96
  ): SendMessageBatchRequestEntry {
package/src/producer.ts CHANGED
@@ -6,9 +6,13 @@ import {
6
6
  } from '@aws-sdk/client-sqs';
7
7
  import { Message, ProducerOptions } from './types';
8
8
  import { toEntry } from './format';
9
+ import { FailedMessagesError } from './errors';
9
10
 
10
11
  const requiredOptions = ['queueUrl'];
11
12
 
13
+ /**
14
+ * [Usage](https://bbc.github.io/sqs-producer/index.html#usage)
15
+ */
12
16
  export class Producer {
13
17
  static create: (options: ProducerOptions) => Producer;
14
18
  queueUrl: string;
@@ -24,10 +28,15 @@ export class Producer {
24
28
  options.sqs ||
25
29
  new SQSClient({
26
30
  ...options,
31
+ useQueueUrlAsEndpoint: options.useQueueUrlAsEndpoint ?? true,
27
32
  region: options.region || process.env.AWS_REGION || 'eu-west-1'
28
33
  });
29
34
  }
30
35
 
36
+ /**
37
+ * Returns the number of messages in the queue.
38
+ * @returns A promise that resolves to the number of messages in the queue.
39
+ */
31
40
  async queueSize(): Promise<number> {
32
41
  const command = new GetQueueAttributesCommand({
33
42
  QueueUrl: this.queueUrl,
@@ -43,6 +52,11 @@ export class Producer {
43
52
  );
44
53
  }
45
54
 
55
+ /**
56
+ * Send a message to the queue.
57
+ * @param messages - A single message or an array of messages.
58
+ * @returns A promise that resolves to the result of the send operation.
59
+ */
46
60
  async send(
47
61
  messages: string | Message | (string | Message)[]
48
62
  ): Promise<SendMessageBatchResultEntry[]> {
@@ -59,6 +73,11 @@ export class Producer {
59
73
  );
60
74
  }
61
75
 
76
+ /**
77
+ * Validate the producer options.
78
+ * @param options - The producer options to validate.
79
+ * @throws Error if any required options are missing or invalid.
80
+ */
62
81
  private validate(options: ProducerOptions): void {
63
82
  for (const option of requiredOptions) {
64
83
  if (!options[option]) {
@@ -70,6 +89,15 @@ export class Producer {
70
89
  }
71
90
  }
72
91
 
92
+ /**
93
+ * Send a batch of messages to the queue.
94
+ * @param failedMessages - An array of failed message IDs.
95
+ * @param successfulMessages - An array of successful message results.
96
+ * @param messages - An array of messages to send.
97
+ * @param startIndex - The index of the first message in the batch.
98
+ * @returns A promise that resolves to the result of the send operation.
99
+ * @throws FailedMessagesError
100
+ */
73
101
  private async sendBatch(
74
102
  failedMessages?: string[],
75
103
  successfulMessages?: SendMessageBatchResultEntry[],
@@ -104,12 +132,14 @@ export class Producer {
104
132
  if (failedMessagesBatch.length === 0) {
105
133
  return successfulMessagesBatch;
106
134
  }
107
- throw new Error(
108
- `Failed to send messages: ${failedMessagesBatch.join(', ')}`
109
- );
135
+ throw new FailedMessagesError(failedMessagesBatch);
110
136
  }
111
137
  }
112
138
 
139
+ /**
140
+ * Creates a new producer.
141
+ * @param options - The producer options.
142
+ */
113
143
  Producer.create = (options: ProducerOptions): Producer => {
114
144
  return new Producer(options);
115
145
  };
package/src/types.ts CHANGED
@@ -1,17 +1,65 @@
1
1
  import { MessageAttributeValue, SQSClient } from '@aws-sdk/client-sqs';
2
2
 
3
3
  export interface ProducerOptions {
4
+ /**
5
+ * The URL of the queue to send messages to.
6
+ */
4
7
  queueUrl: string;
8
+ /**
9
+ * The number of messages to send in a single batch.
10
+ */
5
11
  batchSize?: number;
12
+ /**
13
+ * The SQS client to use. If not provided, a new client will be created.
14
+ */
6
15
  sqs?: SQSClient;
16
+ /**
17
+ * The AWS region to use. If not provided, the region will be determined
18
+ * from the `AWS_REGION` environment variable or will default to `eu-west-1.
19
+ */
7
20
  region?: string;
21
+ /**
22
+ * In cases where a QueueUrl is given as input, that
23
+ * will be preferred as the request endpoint.
24
+ *
25
+ * Set this value to false to ignore the QueueUrl and use the
26
+ * client's resolved endpoint, which may be a custom endpoint.
27
+ */
28
+ useQueueUrlAsEndpoint?: boolean;
8
29
  }
9
30
 
10
31
  export interface Message {
32
+ /**
33
+ * An identifier for the message. This must be unique within
34
+ * the batch of messages.
35
+ */
11
36
  id: string;
37
+ /**
38
+ * The messages contents.
39
+ */
12
40
  body: string;
41
+ /**
42
+ * This parameter applies only to FIFO (first-in-first-out) queues.
43
+ * When set messages that belong to the same message group are processed
44
+ * in a FIFO manner
45
+ */
13
46
  groupId?: string;
47
+ /**
48
+ * This parameter applies only to FIFO (first-in-first-out) queues.
49
+ * The token used for deduplication of messages within a 5-minute minimum
50
+ * deduplication interval. If a message with a particular id is sent successfully,
51
+ * subsequent messages with the same id are accepted
52
+ * successfully but aren't delivered.
53
+ */
14
54
  deduplicationId?: string;
55
+ /**
56
+ * The length of time, in seconds, for which to delay a specific message.
57
+ * Valid values: 0 to 900. Maximum: 15 minutes.
58
+ */
15
59
  delaySeconds?: number;
60
+ /**
61
+ * Each message attribute consists of a Name, Type, and Value. For more
62
+ * information, see [Amazon SQS message attributes](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-attributes.html).
63
+ */
16
64
  messageAttributes?: { [key: string]: MessageAttributeValue };
17
65
  }
package/src/validation.ts CHANGED
@@ -1,11 +1,23 @@
1
+ /**
2
+ * Checks if the value is a string
3
+ * @param value - The value to check
4
+ */
1
5
  export function isString(value: any): boolean {
2
6
  return typeof value === 'string' || value instanceof String;
3
7
  }
4
8
 
9
+ /**
10
+ * Checks if the value is an object
11
+ * @param value - The value to check
12
+ */
5
13
  export function isObject(value: any): boolean {
6
14
  return value && typeof value === 'object' && value instanceof Object;
7
15
  }
8
16
 
17
+ /**
18
+ * Checks if a MessageAttribute is valid
19
+ * @param messageAttribute - The MessageAttribute to check
20
+ */
9
21
  export function isMessageAttributeValid(messageAttribute: any): boolean {
10
22
  if (!messageAttribute.DataType) {
11
23
  throw new Error('A MessageAttribute must have a DataType key');
package/typedoc.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "sort": ["kind", "instance-first", "required-first", "alphabetical"],
4
+ "treatWarningsAsErrors": false,
5
+ "searchInComments": true,
6
+ "entryPoints": ["./src/index.ts"],
7
+ "out": "public",
8
+ "name": "SQS Producer",
9
+ "hideGenerator": true,
10
+ "navigationLinks": {
11
+ "GitHub": "https://github.com/bbc/sqs-producer"
12
+ }
13
+ }