sqs-producer 3.0.0 → 3.1.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.
- package/.github/CONTRIBUTING.md +10 -0
- package/.github/ISSUE_TEMPLATE/bug-report.yml +115 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/workflows/cla.yml +24 -0
- package/.github/workflows/codeql.yml +76 -0
- package/dist/format.d.ts +3 -0
- package/dist/format.js +68 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/producer.d.ts +4 -12
- package/dist/producer.js +12 -11
- package/dist/types.d.ts +10 -4
- package/dist/types.js +0 -66
- package/package.json +2 -2
- package/src/format.ts +90 -0
- package/src/index.ts +1 -0
- package/src/producer.ts +3 -8
- package/src/types.ts +8 -92
- package/.github/ISSUE_TEMPLATE/bug-report.md +0 -27
- package/.github/ISSUE_TEMPLATE/feature-request.md +0 -19
- package/.github/ISSUE_TEMPLATE/technical-question.md +0 -16
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -34,6 +34,16 @@ Follow the setup instructions in the [README](../README.md).
|
|
|
34
34
|
|
|
35
35
|
Ensure all your code is thoroughly tested and that this testing is detailed in the pull request.
|
|
36
36
|
|
|
37
|
+
## Contributors Licence Agreement
|
|
38
|
+
|
|
39
|
+
In order to accept contributions, we need all contributors grant Us a licence to the intellectual
|
|
40
|
+
property rights in their Contributions. This Agreement (“Agreement”) is intended to protect your
|
|
41
|
+
rights as a contributor, and to help ensure that the intellectual property contained
|
|
42
|
+
within is available to the whole community, to use and build on.
|
|
43
|
+
|
|
44
|
+
When you raise a pull request and you haven't previously signed a CLA, the bot will automatically
|
|
45
|
+
ask you to do this. You must complete this step in order for your PR to be merged.
|
|
46
|
+
|
|
37
47
|
## Pull Request Process
|
|
38
48
|
|
|
39
49
|
1. Make sure you have opened an issue and it was approved by a project maintainer before working on a PR
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: 'Bug report'
|
|
2
|
+
title: "[Bug]: "
|
|
3
|
+
labels: ["bug", "triage"]
|
|
4
|
+
description: Report a reproducible bug or regression
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thank you for reporting an issue!
|
|
10
|
+
|
|
11
|
+
This issue tracker is for reporting reproducible bugs or regression's found in this package, if you have a question or feature request, please report it within the [Discussions tab](https://github.com/bbc/sqs-producer/discussions) instead.
|
|
12
|
+
|
|
13
|
+
Before submitting a new bug/issue, please check the links below to see if there is a solution or question posted there already:
|
|
14
|
+
|
|
15
|
+
- [Discussions](https://github.com/bbc/sqs-producer/discussions)
|
|
16
|
+
- [Open Issues](https://github.com/bbc/sqs-producer/issues?q=is%3Aopen+is%3Aissue)
|
|
17
|
+
- [Closed Issues](https://github.com/bbc/sqs-producer/issues?q=is%3Aissue+is%3Aclosed)
|
|
18
|
+
|
|
19
|
+
The more information you fill in, the better the community can help you.
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: description
|
|
22
|
+
attributes:
|
|
23
|
+
label: Describe the bug
|
|
24
|
+
description: Provide a clear and concise description of what the bug is.
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: input
|
|
28
|
+
id: link
|
|
29
|
+
attributes:
|
|
30
|
+
label: Your minimal, reproducible example
|
|
31
|
+
description: |
|
|
32
|
+
Please add a link to a minimal reproduction.
|
|
33
|
+
Note:
|
|
34
|
+
- Please keep your example as simple and reproduceable as possible, try leaving out dependencies that are not required for reproduction.
|
|
35
|
+
- To create a shareable code example for web, you can use CodeSandbox (https://codesandbox.io/s/new) or Stackblitz (https://stackblitz.com/).
|
|
36
|
+
- Please make sure the example is complete and runnable - e.g. avoid localhost URLs.
|
|
37
|
+
placeholder: |
|
|
38
|
+
e.g. Code Sandbox, Stackblitz, Expo Snack or TypeScript playground
|
|
39
|
+
validations:
|
|
40
|
+
required: true
|
|
41
|
+
- type: textarea
|
|
42
|
+
id: steps
|
|
43
|
+
attributes:
|
|
44
|
+
label: Steps to reproduce
|
|
45
|
+
description: Describe the steps we have to take to reproduce the behavior.
|
|
46
|
+
placeholder: |
|
|
47
|
+
1. Go to '...'
|
|
48
|
+
2. Click on '....'
|
|
49
|
+
3. Scroll down to '....'
|
|
50
|
+
4. See error
|
|
51
|
+
validations:
|
|
52
|
+
required: true
|
|
53
|
+
- type: textarea
|
|
54
|
+
id: expected
|
|
55
|
+
attributes:
|
|
56
|
+
label: Expected behavior
|
|
57
|
+
description: Provide a clear and concise description of what you expected to happen.
|
|
58
|
+
placeholder: |
|
|
59
|
+
As a user, I expected ___ behavior but i am seeing ___
|
|
60
|
+
validations:
|
|
61
|
+
required: true
|
|
62
|
+
- type: dropdown
|
|
63
|
+
attributes:
|
|
64
|
+
label: How often does this bug happen?
|
|
65
|
+
description: |
|
|
66
|
+
Following the repro steps above, how easily are you able to reproduce this bug?
|
|
67
|
+
options:
|
|
68
|
+
- Every time
|
|
69
|
+
- Often
|
|
70
|
+
- Sometimes
|
|
71
|
+
- Only once
|
|
72
|
+
- type: textarea
|
|
73
|
+
id: screenshots_or_videos
|
|
74
|
+
attributes:
|
|
75
|
+
label: Screenshots or Videos
|
|
76
|
+
description: |
|
|
77
|
+
If applicable, add screenshots or a video to help explain your problem.
|
|
78
|
+
For more information on the supported file image/file types and the file size limits, please refer
|
|
79
|
+
to the following link: https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/attaching-files
|
|
80
|
+
placeholder: |
|
|
81
|
+
You can drag your video or image files inside of this editor ↓
|
|
82
|
+
- type: textarea
|
|
83
|
+
id: platform
|
|
84
|
+
attributes:
|
|
85
|
+
label: Platform
|
|
86
|
+
description: |
|
|
87
|
+
Please let us know which Operating System and Node version you were using when the issue occurred.
|
|
88
|
+
placeholder: |
|
|
89
|
+
- OS: [e.g. macOS, Windows, Linux, iOS, Android]
|
|
90
|
+
- Node Version: [e.g. 16.6.0]
|
|
91
|
+
validations:
|
|
92
|
+
required: true
|
|
93
|
+
- type: input
|
|
94
|
+
id: package-version
|
|
95
|
+
attributes:
|
|
96
|
+
label: Package version
|
|
97
|
+
description: |
|
|
98
|
+
Please let us know the exact version of the package you were using when the issue occurred. Please don't just put in "latest", as this is subject to change.
|
|
99
|
+
placeholder: |
|
|
100
|
+
e.g. v6.0.0
|
|
101
|
+
validations:
|
|
102
|
+
required: true
|
|
103
|
+
- type: input
|
|
104
|
+
id: ts-version
|
|
105
|
+
attributes:
|
|
106
|
+
label: AWS SDK version
|
|
107
|
+
description: |
|
|
108
|
+
Please include what version of the AWS SDK you are using
|
|
109
|
+
placeholder: |
|
|
110
|
+
e.g. v3.226.0
|
|
111
|
+
- type: textarea
|
|
112
|
+
id: additional
|
|
113
|
+
attributes:
|
|
114
|
+
label: Additional context
|
|
115
|
+
description: Add any other context about the problem here.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: "CLA Check"
|
|
2
|
+
on:
|
|
3
|
+
issue_comment:
|
|
4
|
+
types: [created]
|
|
5
|
+
pull_request_target:
|
|
6
|
+
types: [opened,closed,synchronize]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
CLAAssistant:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: "CLA Check"
|
|
13
|
+
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
|
|
15
|
+
env:
|
|
16
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
17
|
+
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
|
|
18
|
+
with:
|
|
19
|
+
path-to-signatures: 'sqs-producer/v1/cla.json'
|
|
20
|
+
remote-organization-name: 'bbc'
|
|
21
|
+
remote-repository-name: 'cla-signatures'
|
|
22
|
+
path-to-document: 'https://bbc.github.io/cla-signatures/cla/v1/cla.html'
|
|
23
|
+
branch: 'main'
|
|
24
|
+
allowlist: bot*
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
|
2
|
+
# to commit it to your repository.
|
|
3
|
+
#
|
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
|
5
|
+
# or to provide custom queries or build logic.
|
|
6
|
+
#
|
|
7
|
+
# ******** NOTE ********
|
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
|
10
|
+
# supported CodeQL languages.
|
|
11
|
+
#
|
|
12
|
+
name: "CodeQL"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [ "main" ]
|
|
17
|
+
pull_request:
|
|
18
|
+
# The branches below must be a subset of the branches above
|
|
19
|
+
branches: [ "main" ]
|
|
20
|
+
schedule:
|
|
21
|
+
- cron: '41 21 * * 3'
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
analyze:
|
|
25
|
+
name: Analyze
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
actions: read
|
|
29
|
+
contents: read
|
|
30
|
+
security-events: write
|
|
31
|
+
|
|
32
|
+
strategy:
|
|
33
|
+
fail-fast: false
|
|
34
|
+
matrix:
|
|
35
|
+
language: [ 'javascript' ]
|
|
36
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
|
37
|
+
# Use only 'java' to analyze code written in Java, Kotlin or both
|
|
38
|
+
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
|
39
|
+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
- name: Checkout repository
|
|
43
|
+
uses: actions/checkout@v3
|
|
44
|
+
|
|
45
|
+
# Initializes the CodeQL tools for scanning.
|
|
46
|
+
- name: Initialize CodeQL
|
|
47
|
+
uses: github/codeql-action/init@v2
|
|
48
|
+
with:
|
|
49
|
+
languages: ${{ matrix.language }}
|
|
50
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
51
|
+
# By default, queries listed here will override any specified in a config file.
|
|
52
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
53
|
+
|
|
54
|
+
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
55
|
+
# queries: security-extended,security-and-quality
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
|
59
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
|
60
|
+
- name: Autobuild
|
|
61
|
+
uses: github/codeql-action/autobuild@v2
|
|
62
|
+
|
|
63
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
64
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
65
|
+
|
|
66
|
+
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
|
67
|
+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
|
68
|
+
|
|
69
|
+
# - run: |
|
|
70
|
+
# echo "Run, Build Application using script"
|
|
71
|
+
# ./location_of_script_within_repo/buildscript.sh
|
|
72
|
+
|
|
73
|
+
- name: Perform CodeQL Analysis
|
|
74
|
+
uses: github/codeql-action/analyze@v2
|
|
75
|
+
with:
|
|
76
|
+
category: "/language:${{matrix.language}}"
|
package/dist/format.d.ts
ADDED
package/dist/format.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toEntry = void 0;
|
|
4
|
+
const validation_1 = require("./validation");
|
|
5
|
+
function entryFromObject(message) {
|
|
6
|
+
if (!message.body) {
|
|
7
|
+
throw new Error(`Object messages must have 'body' prop`);
|
|
8
|
+
}
|
|
9
|
+
if (!message.groupId && !message.deduplicationId && !message.id) {
|
|
10
|
+
throw new Error(`Object messages must have 'id' prop`);
|
|
11
|
+
}
|
|
12
|
+
if (message.deduplicationId && !message.groupId) {
|
|
13
|
+
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
|
|
14
|
+
}
|
|
15
|
+
if (message.id) {
|
|
16
|
+
if (!(0, validation_1.isString)(message.id)) {
|
|
17
|
+
throw new Error('Message.id value must be a string');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const entry = {
|
|
21
|
+
Id: message.id,
|
|
22
|
+
MessageBody: message.body
|
|
23
|
+
};
|
|
24
|
+
if (message.delaySeconds) {
|
|
25
|
+
if (typeof message.delaySeconds !== 'number' ||
|
|
26
|
+
message.delaySeconds < 0 ||
|
|
27
|
+
message.delaySeconds > 900) {
|
|
28
|
+
throw new Error('Message.delaySeconds value must be a number contained within [0 - 900]');
|
|
29
|
+
}
|
|
30
|
+
entry.DelaySeconds = message.delaySeconds;
|
|
31
|
+
}
|
|
32
|
+
if (message.messageAttributes) {
|
|
33
|
+
if (!(0, validation_1.isObject)(message.messageAttributes)) {
|
|
34
|
+
throw new Error('Message.messageAttributes must be an object');
|
|
35
|
+
}
|
|
36
|
+
Object.values(message.messageAttributes).every(validation_1.isMessageAttributeValid);
|
|
37
|
+
entry.MessageAttributes = message.messageAttributes;
|
|
38
|
+
}
|
|
39
|
+
if (message.groupId) {
|
|
40
|
+
if (!(0, validation_1.isString)(message.groupId)) {
|
|
41
|
+
throw new Error('Message.groupId value must be a string');
|
|
42
|
+
}
|
|
43
|
+
entry.MessageGroupId = message.groupId;
|
|
44
|
+
}
|
|
45
|
+
if (message.deduplicationId) {
|
|
46
|
+
if (!(0, validation_1.isString)(message.deduplicationId)) {
|
|
47
|
+
throw new Error('Message.deduplicationId value must be a string');
|
|
48
|
+
}
|
|
49
|
+
entry.MessageDeduplicationId = message.deduplicationId;
|
|
50
|
+
}
|
|
51
|
+
return entry;
|
|
52
|
+
}
|
|
53
|
+
function entryFromString(message) {
|
|
54
|
+
return {
|
|
55
|
+
Id: message,
|
|
56
|
+
MessageBody: message
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function toEntry(message) {
|
|
60
|
+
if ((0, validation_1.isString)(message)) {
|
|
61
|
+
return entryFromString(message);
|
|
62
|
+
}
|
|
63
|
+
if ((0, validation_1.isObject)(message)) {
|
|
64
|
+
return entryFromObject(message);
|
|
65
|
+
}
|
|
66
|
+
throw new Error('A message can either be an object or a string');
|
|
67
|
+
}
|
|
68
|
+
exports.toEntry = toEntry;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
17
|
exports.Producer = void 0;
|
|
4
18
|
var producer_1 = require("./producer");
|
|
5
19
|
Object.defineProperty(exports, "Producer", { enumerable: true, get: function () { return producer_1.Producer; } });
|
|
20
|
+
__exportStar(require("./types"), exports);
|
package/dist/producer.d.ts
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Message } from './types';
|
|
4
|
-
interface ProducerOptions {
|
|
5
|
-
queueUrl?: string;
|
|
6
|
-
batchSize?: number;
|
|
7
|
-
sqs?: SQS;
|
|
8
|
-
region?: string;
|
|
9
|
-
}
|
|
1
|
+
import { SQSClient, SendMessageBatchResultEntry } from '@aws-sdk/client-sqs';
|
|
2
|
+
import { Message, ProducerOptions } from './types';
|
|
10
3
|
export declare class Producer {
|
|
11
4
|
static create: (options: ProducerOptions) => Producer;
|
|
12
5
|
queueUrl: string;
|
|
13
6
|
batchSize: number;
|
|
14
|
-
sqs:
|
|
7
|
+
sqs: SQSClient;
|
|
15
8
|
region?: string;
|
|
16
9
|
constructor(options: ProducerOptions);
|
|
17
10
|
queueSize(): Promise<number>;
|
|
18
|
-
send(messages: string | Message | (string | Message)[]): Promise<
|
|
11
|
+
send(messages: string | Message | (string | Message)[]): Promise<SendMessageBatchResultEntry[]>;
|
|
19
12
|
private validate;
|
|
20
13
|
private sendBatch;
|
|
21
14
|
}
|
|
22
|
-
export {};
|
package/dist/producer.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Producer = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const client_sqs_1 = require("@aws-sdk/client-sqs");
|
|
5
|
+
const format_1 = require("./format");
|
|
6
6
|
const requiredOptions = ['queueUrl'];
|
|
7
7
|
class Producer {
|
|
8
8
|
constructor(options) {
|
|
@@ -11,15 +11,14 @@ class Producer {
|
|
|
11
11
|
this.batchSize = options.batchSize || 10;
|
|
12
12
|
this.sqs =
|
|
13
13
|
options.sqs ||
|
|
14
|
-
new
|
|
14
|
+
new client_sqs_1.SQSClient(Object.assign(Object.assign({}, options), { region: options.region || 'eu-west-1' }));
|
|
15
15
|
}
|
|
16
16
|
async queueSize() {
|
|
17
|
-
const
|
|
18
|
-
.getQueueAttributes({
|
|
17
|
+
const command = new client_sqs_1.GetQueueAttributesCommand({
|
|
19
18
|
QueueUrl: this.queueUrl,
|
|
20
19
|
AttributeNames: ['ApproximateNumberOfMessages']
|
|
21
|
-
})
|
|
22
|
-
|
|
20
|
+
});
|
|
21
|
+
const result = await this.sqs.send(command);
|
|
23
22
|
return Number(result &&
|
|
24
23
|
result.Attributes &&
|
|
25
24
|
result.Attributes.ApproximateNumberOfMessages);
|
|
@@ -42,15 +41,17 @@ class Producer {
|
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
async sendBatch(failedMessages, successfulMessages, messages, startIndex) {
|
|
44
|
+
var _a;
|
|
45
45
|
const endIndex = startIndex + this.batchSize;
|
|
46
46
|
const batch = messages.slice(startIndex, endIndex);
|
|
47
47
|
const params = {
|
|
48
48
|
QueueUrl: this.queueUrl,
|
|
49
|
-
Entries: batch.map(
|
|
49
|
+
Entries: batch.map(format_1.toEntry)
|
|
50
50
|
};
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
51
|
+
const command = new client_sqs_1.SendMessageBatchCommand(params);
|
|
52
|
+
const result = await this.sqs.send(command);
|
|
53
|
+
const failedMessagesBatch = failedMessages.concat(((_a = result === null || result === void 0 ? void 0 : result.Failed) === null || _a === void 0 ? void 0 : _a.map((entry) => entry.Id)) || []);
|
|
54
|
+
const successfulMessagesBatch = successfulMessages.concat((result === null || result === void 0 ? void 0 : result.Successful) || []);
|
|
54
55
|
if (endIndex < messages.length) {
|
|
55
56
|
return this.sendBatch(failedMessagesBatch, successfulMessagesBatch, messages, endIndex);
|
|
56
57
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { MessageAttributeValue, SQSClient } from '@aws-sdk/client-sqs';
|
|
2
|
+
export interface ProducerOptions {
|
|
3
|
+
queueUrl: string;
|
|
4
|
+
batchSize?: number;
|
|
5
|
+
sqs?: SQSClient;
|
|
6
|
+
region?: string;
|
|
7
|
+
}
|
|
3
8
|
export interface Message {
|
|
4
9
|
id: string;
|
|
5
10
|
body: string;
|
|
6
11
|
groupId?: string;
|
|
7
12
|
deduplicationId?: string;
|
|
8
13
|
delaySeconds?: number;
|
|
9
|
-
messageAttributes?:
|
|
14
|
+
messageAttributes?: {
|
|
15
|
+
[key: string]: MessageAttributeValue;
|
|
16
|
+
};
|
|
10
17
|
}
|
|
11
|
-
export declare function toEntry(message: string | Message): SendMessageBatchRequestEntry;
|
package/dist/types.js
CHANGED
|
@@ -1,68 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toEntry = void 0;
|
|
4
|
-
const { isObject, isString, isMessageAttributeValid } = require('./validation');
|
|
5
|
-
function entryFromObject(message) {
|
|
6
|
-
if (!message.body) {
|
|
7
|
-
throw new Error(`Object messages must have 'body' prop`);
|
|
8
|
-
}
|
|
9
|
-
if (!message.groupId && !message.deduplicationId && !message.id) {
|
|
10
|
-
throw new Error(`Object messages must have 'id' prop`);
|
|
11
|
-
}
|
|
12
|
-
if (message.deduplicationId && !message.groupId) {
|
|
13
|
-
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
|
|
14
|
-
}
|
|
15
|
-
if (message.id) {
|
|
16
|
-
if (!isString(message.id)) {
|
|
17
|
-
throw new Error('Message.id value must be a string');
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
const entry = {
|
|
21
|
-
Id: message.id,
|
|
22
|
-
MessageBody: message.body
|
|
23
|
-
};
|
|
24
|
-
if (message.delaySeconds) {
|
|
25
|
-
if (typeof message.delaySeconds !== 'number' ||
|
|
26
|
-
message.delaySeconds < 0 ||
|
|
27
|
-
message.delaySeconds > 900) {
|
|
28
|
-
throw new Error('Message.delaySeconds value must be a number contained within [0 - 900]');
|
|
29
|
-
}
|
|
30
|
-
entry.DelaySeconds = message.delaySeconds;
|
|
31
|
-
}
|
|
32
|
-
if (message.messageAttributes) {
|
|
33
|
-
if (!isObject(message.messageAttributes)) {
|
|
34
|
-
throw new Error('Message.messageAttributes must be an object');
|
|
35
|
-
}
|
|
36
|
-
Object.values(message.messageAttributes).every(isMessageAttributeValid);
|
|
37
|
-
entry.MessageAttributes = message.messageAttributes;
|
|
38
|
-
}
|
|
39
|
-
if (message.groupId) {
|
|
40
|
-
if (!isString(message.groupId)) {
|
|
41
|
-
throw new Error('Message.groupId value must be a string');
|
|
42
|
-
}
|
|
43
|
-
entry.MessageGroupId = message.groupId;
|
|
44
|
-
}
|
|
45
|
-
if (message.deduplicationId) {
|
|
46
|
-
if (!isString(message.deduplicationId)) {
|
|
47
|
-
throw new Error('Message.deduplicationId value must be a string');
|
|
48
|
-
}
|
|
49
|
-
entry.MessageDeduplicationId = message.deduplicationId;
|
|
50
|
-
}
|
|
51
|
-
return entry;
|
|
52
|
-
}
|
|
53
|
-
function entryFromString(message) {
|
|
54
|
-
return {
|
|
55
|
-
Id: message,
|
|
56
|
-
MessageBody: message
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function toEntry(message) {
|
|
60
|
-
if (isString(message)) {
|
|
61
|
-
return entryFromString(message);
|
|
62
|
-
}
|
|
63
|
-
if (isObject(message)) {
|
|
64
|
-
return entryFromObject(message);
|
|
65
|
-
}
|
|
66
|
-
throw new Error('A message can either be an object or a string');
|
|
67
|
-
}
|
|
68
|
-
exports.toEntry = toEntry;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sqs-producer",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Enqueues messages onto a given SQS queue",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"format": "prettier --loglevel 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
20
|
"clean": "rm -fr dist/*"
|
package/src/format.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SendMessageBatchRequestEntry } from '@aws-sdk/client-sqs';
|
|
2
|
+
import { Message } from './types';
|
|
3
|
+
import { isObject, isString, isMessageAttributeValid } from './validation';
|
|
4
|
+
|
|
5
|
+
function entryFromObject(message: Message): SendMessageBatchRequestEntry {
|
|
6
|
+
if (!message.body) {
|
|
7
|
+
throw new Error(`Object messages must have 'body' prop`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (!message.groupId && !message.deduplicationId && !message.id) {
|
|
11
|
+
throw new Error(`Object messages must have 'id' prop`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (message.deduplicationId && !message.groupId) {
|
|
15
|
+
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (message.id) {
|
|
19
|
+
if (!isString(message.id)) {
|
|
20
|
+
throw new Error('Message.id value must be a string');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const entry: SendMessageBatchRequestEntry = {
|
|
25
|
+
Id: message.id,
|
|
26
|
+
MessageBody: message.body
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (message.delaySeconds) {
|
|
30
|
+
if (
|
|
31
|
+
typeof message.delaySeconds !== 'number' ||
|
|
32
|
+
message.delaySeconds < 0 ||
|
|
33
|
+
message.delaySeconds > 900
|
|
34
|
+
) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
'Message.delaySeconds value must be a number contained within [0 - 900]'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
entry.DelaySeconds = message.delaySeconds;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (message.messageAttributes) {
|
|
44
|
+
if (!isObject(message.messageAttributes)) {
|
|
45
|
+
throw new Error('Message.messageAttributes must be an object');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Object.values(message.messageAttributes).every(isMessageAttributeValid);
|
|
49
|
+
|
|
50
|
+
entry.MessageAttributes = message.messageAttributes;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (message.groupId) {
|
|
54
|
+
if (!isString(message.groupId)) {
|
|
55
|
+
throw new Error('Message.groupId value must be a string');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
entry.MessageGroupId = message.groupId;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (message.deduplicationId) {
|
|
62
|
+
if (!isString(message.deduplicationId)) {
|
|
63
|
+
throw new Error('Message.deduplicationId value must be a string');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
entry.MessageDeduplicationId = message.deduplicationId;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return entry;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function entryFromString(message: string): SendMessageBatchRequestEntry {
|
|
73
|
+
return {
|
|
74
|
+
Id: message,
|
|
75
|
+
MessageBody: message
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function toEntry(
|
|
80
|
+
message: string | Message
|
|
81
|
+
): SendMessageBatchRequestEntry {
|
|
82
|
+
if (isString(message)) {
|
|
83
|
+
return entryFromString(message as string);
|
|
84
|
+
}
|
|
85
|
+
if (isObject(message)) {
|
|
86
|
+
return entryFromObject(message as Message);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
throw new Error('A message can either be an object or a string');
|
|
90
|
+
}
|
package/src/index.ts
CHANGED
package/src/producer.ts
CHANGED
|
@@ -4,15 +4,10 @@ import {
|
|
|
4
4
|
SendMessageBatchCommand,
|
|
5
5
|
GetQueueAttributesCommand
|
|
6
6
|
} from '@aws-sdk/client-sqs';
|
|
7
|
-
import { Message,
|
|
8
|
-
|
|
7
|
+
import { Message, ProducerOptions } from './types';
|
|
8
|
+
import { toEntry } from './format';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
queueUrl?: string;
|
|
12
|
-
batchSize?: number;
|
|
13
|
-
sqs?: SQSClient;
|
|
14
|
-
region?: string;
|
|
15
|
-
}
|
|
10
|
+
const requiredOptions = ['queueUrl'];
|
|
16
11
|
|
|
17
12
|
export class Producer {
|
|
18
13
|
static create: (options: ProducerOptions) => Producer;
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { MessageAttributeValue, SQSClient } from '@aws-sdk/client-sqs';
|
|
2
|
+
|
|
3
|
+
export interface ProducerOptions {
|
|
4
|
+
queueUrl: string;
|
|
5
|
+
batchSize?: number;
|
|
6
|
+
sqs?: SQSClient;
|
|
7
|
+
region?: string;
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
export interface Message {
|
|
8
11
|
id: string;
|
|
@@ -12,90 +15,3 @@ export interface Message {
|
|
|
12
15
|
delaySeconds?: number;
|
|
13
16
|
messageAttributes?: { [key: string]: MessageAttributeValue };
|
|
14
17
|
}
|
|
15
|
-
|
|
16
|
-
function entryFromObject(message: Message): SendMessageBatchRequestEntry {
|
|
17
|
-
if (!message.body) {
|
|
18
|
-
throw new Error(`Object messages must have 'body' prop`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!message.groupId && !message.deduplicationId && !message.id) {
|
|
22
|
-
throw new Error(`Object messages must have 'id' prop`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (message.deduplicationId && !message.groupId) {
|
|
26
|
-
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (message.id) {
|
|
30
|
-
if (!isString(message.id)) {
|
|
31
|
-
throw new Error('Message.id value must be a string');
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const entry: SendMessageBatchRequestEntry = {
|
|
36
|
-
Id: message.id,
|
|
37
|
-
MessageBody: message.body
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (message.delaySeconds) {
|
|
41
|
-
if (
|
|
42
|
-
typeof message.delaySeconds !== 'number' ||
|
|
43
|
-
message.delaySeconds < 0 ||
|
|
44
|
-
message.delaySeconds > 900
|
|
45
|
-
) {
|
|
46
|
-
throw new Error(
|
|
47
|
-
'Message.delaySeconds value must be a number contained within [0 - 900]'
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
entry.DelaySeconds = message.delaySeconds;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (message.messageAttributes) {
|
|
55
|
-
if (!isObject(message.messageAttributes)) {
|
|
56
|
-
throw new Error('Message.messageAttributes must be an object');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
Object.values(message.messageAttributes).every(isMessageAttributeValid);
|
|
60
|
-
|
|
61
|
-
entry.MessageAttributes = message.messageAttributes;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (message.groupId) {
|
|
65
|
-
if (!isString(message.groupId)) {
|
|
66
|
-
throw new Error('Message.groupId value must be a string');
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
entry.MessageGroupId = message.groupId;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (message.deduplicationId) {
|
|
73
|
-
if (!isString(message.deduplicationId)) {
|
|
74
|
-
throw new Error('Message.deduplicationId value must be a string');
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
entry.MessageDeduplicationId = message.deduplicationId;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return entry;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function entryFromString(message: string): SendMessageBatchRequestEntry {
|
|
84
|
-
return {
|
|
85
|
-
Id: message,
|
|
86
|
-
MessageBody: message
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function toEntry(
|
|
91
|
-
message: string | Message
|
|
92
|
-
): SendMessageBatchRequestEntry {
|
|
93
|
-
if (isString(message)) {
|
|
94
|
-
return entryFromString(message as string);
|
|
95
|
-
}
|
|
96
|
-
if (isObject(message)) {
|
|
97
|
-
return entryFromObject(message as Message);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
throw new Error('A message can either be an object or a string');
|
|
101
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Bug report
|
|
3
|
-
about: Create a report to help us improve
|
|
4
|
-
title: ''
|
|
5
|
-
labels: bug
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
**Describe the bug**
|
|
10
|
-
A clear and concise description of what the bug is.
|
|
11
|
-
|
|
12
|
-
**To Reproduce**
|
|
13
|
-
Steps to reproduce the behaviour:
|
|
14
|
-
|
|
15
|
-
1. Go to '...'
|
|
16
|
-
2. Select '....'
|
|
17
|
-
3. Scroll down to '....'
|
|
18
|
-
4. See error
|
|
19
|
-
|
|
20
|
-
**Expected behaviour**
|
|
21
|
-
A clear and concise description of what you expected to happen.
|
|
22
|
-
|
|
23
|
-
**screenshots**
|
|
24
|
-
If applicable, add screenshots to help explain your problem.
|
|
25
|
-
|
|
26
|
-
**Additional context**
|
|
27
|
-
Add any other context about the problem here, such as specific device information.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Feature request
|
|
3
|
-
about: Suggest an idea for this project
|
|
4
|
-
title: ''
|
|
5
|
-
labels: feature-request
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
**The problem**
|
|
10
|
-
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
11
|
-
|
|
12
|
-
**Suggested solution**
|
|
13
|
-
A clear and concise description of what you want to happen.
|
|
14
|
-
|
|
15
|
-
**Alternatives considered**
|
|
16
|
-
A clear and concise description of any alternative solutions or features you've considered.
|
|
17
|
-
|
|
18
|
-
**Additional context**
|
|
19
|
-
Add any other context or screenshots about the feature request here.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Technical question
|
|
3
|
-
about: Want to ask a technical question about the project
|
|
4
|
-
title: ''
|
|
5
|
-
labels: 'question'
|
|
6
|
-
assignees: ''
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
**Question**
|
|
10
|
-
A clear technical question could be asked here.
|
|
11
|
-
|
|
12
|
-
**screenshots**
|
|
13
|
-
If applicable, add screenshots to help explain your question.
|
|
14
|
-
|
|
15
|
-
**Additional context**
|
|
16
|
-
Add any other context about the question here, such as specific device information, technology choice etc.
|