Socket
Socket
Sign inDemoInstall

sqs-producer

Package Overview
Dependencies
Maintainers
2
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sqs-producer - npm Package Compare versions

Comparing version 2.2.0 to 3.0.0-alpha.1

.eslintignore

4

.github/ISSUE_TEMPLATE/bug-report.md

@@ -7,3 +7,2 @@ ---

assignees: ''
---

@@ -16,2 +15,3 @@

Steps to reproduce the behaviour:
1. Go to '...'

@@ -29,2 +29,2 @@ 2. Select '....'

**Additional context**
Add any other context about the problem here, such as specific device information.
Add any other context about the problem here, such as specific device information.

@@ -7,3 +7,2 @@ ---

assignees: ''
---

@@ -10,0 +9,0 @@

@@ -7,3 +7,2 @@ ---

assignees: ''
---

@@ -10,0 +9,0 @@

@@ -1,3 +0,2 @@

import { SQS } from 'aws-sdk';
import { SendMessageBatchResultEntryList } from 'aws-sdk/clients/sqs';
import { SQSClient, SendMessageBatchResultEntry } from '@aws-sdk/client-sqs';
import { Message } from './types';

@@ -7,3 +6,3 @@ interface ProducerOptions {

batchSize?: number;
sqs?: SQS;
sqs?: SQSClient;
region?: string;

@@ -15,7 +14,7 @@ }

batchSize: number;
sqs: SQS;
sqs: SQSClient;
region?: string;
constructor(options: ProducerOptions);
queueSize(): Promise<number>;
send(messages: string | Message | (string | Message)[]): Promise<SendMessageBatchResultEntryList>;
send(messages: string | Message | (string | Message)[]): Promise<SendMessageBatchResultEntry[]>;
private validate;

@@ -22,0 +21,0 @@ private sendBatch;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Producer = void 0;
const aws_sdk_1 = require("aws-sdk");
const client_sqs_1 = require("@aws-sdk/client-sqs");
const types_1 = require("./types");
const requiredOptions = [
'queueUrl'
];
const requiredOptions = ['queueUrl'];
class Producer {

@@ -14,10 +12,15 @@ constructor(options) {

this.batchSize = options.batchSize || 10;
this.sqs = options.sqs || new aws_sdk_1.SQS(Object.assign(Object.assign({}, options), { region: options.region || 'eu-west-1' }));
this.sqs =
options.sqs ||
new client_sqs_1.SQSClient(Object.assign(Object.assign({}, options), { region: options.region || 'eu-west-1' }));
}
async queueSize() {
const result = await this.sqs.getQueueAttributes({
const command = new client_sqs_1.GetQueueAttributesCommand({
QueueUrl: this.queueUrl,
AttributeNames: ['ApproximateNumberOfMessages']
}).promise();
return Number(result && result.Attributes && result.Attributes.ApproximateNumberOfMessages);
});
const result = await this.sqs.send(command);
return Number(result &&
result.Attributes &&
result.Attributes.ApproximateNumberOfMessages);
}

@@ -48,3 +51,4 @@ async send(messages) {

};
const result = await this.sqs.sendMessageBatch(params).promise();
const command = new client_sqs_1.SendMessageBatchCommand(params);
const result = await this.sqs.send(command);
const failedMessagesBatch = failedMessages.concat(result.Failed.map((entry) => entry.Id));

@@ -51,0 +55,0 @@ const successfulMessagesBatch = successfulMessages.concat(result.Successful);

@@ -1,3 +0,2 @@

import { SQS } from 'aws-sdk';
import { SendMessageBatchRequestEntry } from 'aws-sdk/clients/sqs';
import { SendMessageBatchRequestEntry, MessageAttributeValue } from '@aws-sdk/client-sqs';
export interface Message {

@@ -9,4 +8,6 @@ id: string;

delaySeconds?: number;
messageAttributes?: SQS.MessageBodyAttributeMap;
messageAttributes?: {
[key: string]: MessageAttributeValue;
};
}
export declare function toEntry(message: string | Message): SendMessageBatchRequestEntry;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toEntry = void 0;
const { isObject, isString, isMessageAttributeValid } = require('./validation');
const validation_1 = require("./validation");
function entryFromObject(message) {

@@ -16,3 +16,3 @@ if (!message.body) {

if (message.id) {
if (!isString(message.id)) {
if (!(0, validation_1.isString)(message.id)) {
throw new Error('Message.id value must be a string');

@@ -26,4 +26,5 @@ }

if (message.delaySeconds) {
if ((typeof message.delaySeconds !== 'number') ||
(message.delaySeconds < 0 || message.delaySeconds > 900)) {
if (typeof message.delaySeconds !== 'number' ||
message.delaySeconds < 0 ||
message.delaySeconds > 900) {
throw new Error('Message.delaySeconds value must be a number contained within [0 - 900]');

@@ -34,10 +35,10 @@ }

if (message.messageAttributes) {
if (!isObject(message.messageAttributes)) {
if (!(0, validation_1.isObject)(message.messageAttributes)) {
throw new Error('Message.messageAttributes must be an object');
}
Object.values(message.messageAttributes).every(isMessageAttributeValid);
Object.values(message.messageAttributes).every(validation_1.isMessageAttributeValid);
entry.MessageAttributes = message.messageAttributes;
}
if (message.groupId) {
if (!isString(message.groupId)) {
if (!(0, validation_1.isString)(message.groupId)) {
throw new Error('Message.groupId value must be a string');

@@ -48,3 +49,3 @@ }

if (message.deduplicationId) {
if (!isString(message.deduplicationId)) {
if (!(0, validation_1.isString)(message.deduplicationId)) {
throw new Error('Message.deduplicationId value must be a string');

@@ -63,6 +64,6 @@ }

function toEntry(message) {
if (isString(message)) {
if ((0, validation_1.isString)(message)) {
return entryFromString(message);
}
if (isObject(message)) {
if ((0, validation_1.isObject)(message)) {
return entryFromObject(message);

@@ -69,0 +70,0 @@ }

{
"name": "sqs-producer",
"version": "2.2.0",
"version": "3.0.0-alpha.1",
"description": "Enqueues messages onto a given SQS queue",

@@ -9,6 +9,9 @@ "main": "dist/index.js",

"test": "mocha --recursive --full-trace --exit",
"posttest": "npm run lint",
"posttest": "npm run lint && npm run format:check",
"coverage": "nyc mocha && nyc report --reporter=html && nyc report --reporter=json-summary",
"lcov": "nyc mocha && nyc report --reporter=lcov",
"lint": "tsc --noEmit",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --fix",
"format": "prettier --loglevel warn --write \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
"format:check": "prettier --check \"**/*.{js,json,jsx,md,ts,tsx,html}\"",
"build": "npm run clean && tsc",

@@ -45,4 +48,8 @@ "prepublish": "npm run build",

"chai": "^4.3.7",
"eslint": "^8.29.0",
"eslint-config-iplayer-ts": "^4.1.0",
"eslint-config-prettier": "^4.3.0",
"mocha": "^10.1.0",
"nyc": "^15.1.0",
"prettier": "^2.8.1",
"sinon": "^15.0.0",

@@ -53,6 +60,6 @@ "ts-node": "^10.9.1",

"dependencies": {
"aws-sdk": "^2.1271.0"
"@aws-sdk/client-sqs": "^3.226.0"
},
"peerDependencies": {
"aws-sdk": "^2.1271.0"
"@aws-sdk/client-sqs": "^3.226.0"
},

@@ -75,3 +82,28 @@ "mocha": {

"instrument": true
},
"eslintConfig": {
"extends": [
"iplayer-ts",
"prettier",
"prettier/react",
"prettier/@typescript-eslint"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "variable",
"format": [
"camelCase",
"UPPER_CASE",
"PascalCase"
],
"leadingUnderscore": "allow"
}
]
}
}
}

@@ -1,7 +0,6 @@

sqs-producer
====================
# sqs-producer
[![NPM downloads](https://img.shields.io/npm/dm/sqs-producer.svg?style=flat)](https://npmjs.org/package/sqs-producer)
[![Build Status](https://github.com/bbc/sqs-producer/actions/workflows/test.yml/badge.svg)](https://github.com/bbc/sqs-producer/actions/workflows/test.yml)
[![Code Climate](https://codeclimate.com/github/BBC/sqs-producer/badges/gpa.svg)](https://codeclimate.com/github/BBC/sqs-producer)
[![Code Climate](https://codeclimate.com/github/BBC/sqs-producer/badges/gpa.svg)](https://codeclimate.com/github/BBC/sqs-producer)
[![Test Coverage](https://codeclimate.com/github/BBC/sqs-producer/badges/coverage.svg)](https://codeclimate.com/github/BBC/sqs-producer)

@@ -16,7 +15,15 @@

```
> **Note**
> This library assumes you are using [AWS SDK v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sqs/index.html). If you are using v2, please install v2.2.0:
>
> ```bash
> npm install sqs-producer@5.8.0 --save-dev
> ```
## Usage
```js
const { Producer } = require('sqs-producer');
import AWS from 'aws-sdk'
import { Producer } from 'sqs-producer';
import { SQSClient } from '@aws-sdk/client-sqs';

@@ -29,15 +36,2 @@ // create simple producer

// create custom producer (supporting all opts as per the API docs: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SQS.html#constructor-property)
AWS.config.update({
accessKeyId: 'yourAccessKey',
secretAccessKey: 'yourSecret',
region: 'eu-west-1',
});
const producer = Producer.create({
queueUrl: 'https://sqs.eu-west-1.amazonaws.com/account-id/queue-name',
region: 'eu-west-1',
sqs: new AWS.SQS(),
});
// send messages to the queue

@@ -51,6 +45,8 @@ await producer.send(['msg1', 'msg2']);

// send a message to the queue with a specific ID (by default the body is used as the ID)
await producer.send([{
id: 'id1',
body: 'Hello world'
}]);
await producer.send([
{
id: 'id1',
body: 'Hello world'
}
]);

@@ -86,3 +82,3 @@ // send a message to the queue with

await producer.send({
id: "testId",
id: 'testId',
body: 'Hello world from our FIFO queue!',

@@ -94,2 +90,34 @@ groupId: 'group1234',

### Credentials
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:
```bash
export AWS_SECRET_ACCESS_KEY=...
export AWS_ACCESS_KEY_ID=...
```
If you need to specify your credentials manually, you can use a pre-configured instance of the [SQS Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sqs/classes/sqsclient.html) client.
```js
import { Producer } from 'sqs-producer';
import { SQSClient } from '@aws-sdk/client-sqs';
// create simple producer
const producer = Producer.create({
queueUrl: 'https://sqs.eu-west-1.amazonaws.com/account-id/queue-name',
region: 'eu-west-1',
sqs: new SQSClient({
region: 'my-region',
credentials: {
accessKeyId: 'yourAccessKey',
secretAccessKey: 'yourSecret'
}
})
});
// send messages to the queue
await producer.send(['msg1', 'msg2']);
```
## Development

@@ -104,2 +132,3 @@

### Coverage
For coverage report, run the command:

@@ -112,2 +141,3 @@

### Lint
To check for problems using ESLint

@@ -120,2 +150,3 @@

## Contributing
See [contributing guildlines](./.github/CONTRIBUTING.md)

@@ -1,7 +0,9 @@

import { SQS } from 'aws-sdk';
import { SendMessageBatchResultEntryList } from 'aws-sdk/clients/sqs';
import {
SQSClient,
SendMessageBatchResultEntry,
SendMessageBatchCommand,
GetQueueAttributesCommand
} from '@aws-sdk/client-sqs';
import { Message, toEntry } from './types';
const requiredOptions = [
'queueUrl'
];
const requiredOptions = ['queueUrl'];

@@ -11,3 +13,3 @@ interface ProducerOptions {

batchSize?: number;
sqs?: SQS;
sqs?: SQSClient;
region?: string;

@@ -20,3 +22,3 @@ }

batchSize: number;
sqs: SQS;
sqs: SQSClient;
region?: string;

@@ -28,18 +30,28 @@

this.batchSize = options.batchSize || 10;
this.sqs = options.sqs || new SQS({
...options,
region: options.region || 'eu-west-1'
});
this.sqs =
options.sqs ||
new SQSClient({
...options,
region: options.region || 'eu-west-1'
});
}
async queueSize(): Promise<number> {
const result = await this.sqs.getQueueAttributes({
const command = new GetQueueAttributesCommand({
QueueUrl: this.queueUrl,
AttributeNames: ['ApproximateNumberOfMessages']
}).promise();
});
return Number(result && result.Attributes && result.Attributes.ApproximateNumberOfMessages);
const result = await this.sqs.send(command);
return Number(
result &&
result.Attributes &&
result.Attributes.ApproximateNumberOfMessages
);
}
async send(messages: string | Message | (string | Message)[]): Promise<SendMessageBatchResultEntryList> {
async send(
messages: string | Message | (string | Message)[]
): Promise<SendMessageBatchResultEntry[]> {
const failedMessages = [];

@@ -50,3 +62,8 @@ const successfulMessages = [];

return this.sendBatch(failedMessages, successfulMessages, messagesArr, startIndex);
return this.sendBatch(
failedMessages,
successfulMessages,
messagesArr,
startIndex
);
}

@@ -65,3 +82,8 @@

private async sendBatch(failedMessages?: string[], successfulMessages?: SendMessageBatchResultEntryList, messages?: (string | Message)[], startIndex?: number): Promise<SendMessageBatchResultEntryList> {
private async sendBatch(
failedMessages?: string[],
successfulMessages?: SendMessageBatchResultEntry[],
messages?: (string | Message)[],
startIndex?: number
): Promise<SendMessageBatchResultEntry[]> {
const endIndex = startIndex + this.batchSize;

@@ -74,8 +96,18 @@ const batch = messages.slice(startIndex, endIndex);

const result = await this.sqs.sendMessageBatch(params).promise();
const failedMessagesBatch = failedMessages.concat(result.Failed.map((entry) => entry.Id));
const successfulMessagesBatch = successfulMessages.concat(result.Successful);
const command = new SendMessageBatchCommand(params);
const result = await this.sqs.send(command);
const failedMessagesBatch = failedMessages.concat(
result.Failed.map((entry) => entry.Id)
);
const successfulMessagesBatch = successfulMessages.concat(
result.Successful
);
if (endIndex < messages.length) {
return this.sendBatch(failedMessagesBatch, successfulMessagesBatch, messages, endIndex);
return this.sendBatch(
failedMessagesBatch,
successfulMessagesBatch,
messages,
endIndex
);
}

@@ -86,5 +118,6 @@

}
throw new Error(`Failed to send messages: ${failedMessagesBatch.join(', ')}`);
throw new Error(
`Failed to send messages: ${failedMessagesBatch.join(', ')}`
);
}
}

@@ -91,0 +124,0 @@

@@ -1,88 +0,101 @@

import { SQS } from 'aws-sdk';
import { SendMessageBatchRequestEntry } from 'aws-sdk/clients/sqs';
const { isObject, isString, isMessageAttributeValid } = require('./validation');
import {
SendMessageBatchRequestEntry,
MessageAttributeValue
} from '@aws-sdk/client-sqs';
import { isObject, isString, isMessageAttributeValid } from './validation';
export interface Message {
id: string;
body: string;
groupId?: string;
deduplicationId?: string;
delaySeconds?: number;
messageAttributes?: SQS.MessageBodyAttributeMap;
id: string;
body: string;
groupId?: string;
deduplicationId?: string;
delaySeconds?: number;
messageAttributes?: { [key: string]: MessageAttributeValue };
}
function entryFromObject(message: Message): SendMessageBatchRequestEntry {
if (!message.body) {
throw new Error(`Object messages must have 'body' prop`);
}
if (!message.body) {
throw new Error(`Object messages must have 'body' prop`);
}
if (!message.groupId && !message.deduplicationId && !message.id) {
throw new Error(`Object messages must have 'id' prop`);
}
if (!message.groupId && !message.deduplicationId && !message.id) {
throw new Error(`Object messages must have 'id' prop`);
}
if (message.deduplicationId && !message.groupId) {
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
if (message.deduplicationId && !message.groupId) {
throw new Error(`FIFO Queue messages must have 'groupId' prop`);
}
if (message.id) {
if (!isString(message.id)) {
throw new Error('Message.id value must be a string');
}
}
if (message.id) {
if (!isString(message.id)) {
throw new Error('Message.id value must be a string');
}
const entry: SendMessageBatchRequestEntry = {
Id: message.id,
MessageBody: message.body
};
if (message.delaySeconds) {
if (
typeof message.delaySeconds !== 'number' ||
message.delaySeconds < 0 ||
message.delaySeconds > 900
) {
throw new Error(
'Message.delaySeconds value must be a number contained within [0 - 900]'
);
}
const entry: SendMessageBatchRequestEntry = {
Id: message.id,
MessageBody: message.body
};
entry.DelaySeconds = message.delaySeconds;
}
if (message.delaySeconds) {
if ((typeof message.delaySeconds !== 'number') ||
(message.delaySeconds < 0 || message.delaySeconds > 900)) {
throw new Error('Message.delaySeconds value must be a number contained within [0 - 900]');
}
entry.DelaySeconds = message.delaySeconds;
if (message.messageAttributes) {
if (!isObject(message.messageAttributes)) {
throw new Error('Message.messageAttributes must be an object');
}
if (message.messageAttributes) {
if (!isObject(message.messageAttributes)) {
throw new Error('Message.messageAttributes must be an object');
}
Object.values(message.messageAttributes).every(isMessageAttributeValid);
Object.values(message.messageAttributes).every(isMessageAttributeValid);
entry.MessageAttributes = message.messageAttributes;
}
entry.MessageAttributes = message.messageAttributes;
if (message.groupId) {
if (!isString(message.groupId)) {
throw new Error('Message.groupId value must be a string');
}
if (message.groupId) {
if (!isString(message.groupId)) {
throw new Error('Message.groupId value must be a string');
}
entry.MessageGroupId = message.groupId;
}
entry.MessageGroupId = message.groupId;
if (message.deduplicationId) {
if (!isString(message.deduplicationId)) {
throw new Error('Message.deduplicationId value must be a string');
}
if (message.deduplicationId) {
if (!isString(message.deduplicationId)) {
throw new Error('Message.deduplicationId value must be a string');
}
entry.MessageDeduplicationId = message.deduplicationId;
}
entry.MessageDeduplicationId = message.deduplicationId;
}
return entry;
return entry;
}
function entryFromString(message: string): SendMessageBatchRequestEntry {
return {
Id: message,
MessageBody: message
};
return {
Id: message,
MessageBody: message
};
}
export function toEntry(message: string | Message): SendMessageBatchRequestEntry {
if (isString(message)) { return entryFromString(<string>message); }
if (isObject(message)) { return entryFromObject(<Message>message); }
export function toEntry(
message: string | Message
): SendMessageBatchRequestEntry {
if (isString(message)) {
return entryFromString(message as string);
}
if (isObject(message)) {
return entryFromObject(message as Message);
}
throw new Error('A message can either be an object or a string');
throw new Error('A message can either be an object or a string');
}

@@ -1,18 +0,17 @@

export function isString(value: any): boolean {
return typeof value === 'string' || value instanceof String;
return typeof value === 'string' || value instanceof String;
}
export function isObject(value: any): boolean {
return value && typeof value === 'object' && value instanceof Object;
return value && typeof value === 'object' && value instanceof Object;
}
export function isMessageAttributeValid(messageAttribute: any): boolean {
if (!messageAttribute.DataType) {
throw new Error('A MessageAttribute must have a DataType key');
}
if (!isString(messageAttribute.DataType)) {
throw new Error('The DataType key of a MessageAttribute must be a String');
}
return true;
if (!messageAttribute.DataType) {
throw new Error('A MessageAttribute must have a DataType key');
}
if (!isString(messageAttribute.DataType)) {
throw new Error('The DataType key of a MessageAttribute must be a String');
}
return true;
}

@@ -12,9 +12,4 @@ {

},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist"
]
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc