@chainsaws/sqs
v0.1.2
Published
Typed SQS wrapper for Node.js with Python-style validation, FIFO defaults, batch helpers, and async iteration.
Downloads
220
Maintainers
Readme
@chainsaws/sqs
Typed SQS wrapper for Node.js with Python-style validation, FIFO defaults, batch helpers, and async iteration.
Requirements
- Node.js
>= 22 - AWS credentials available through the normal AWS SDK resolution chain, or a custom SQS-compatible endpoint such as LocalStack
Installation
npm install @chainsaws/sqs
yarn add @chainsaws/sqs
pnpm add @chainsaws/sqsThis package is ESM-only.
Quick Start
import { SQSAPI } from "@chainsaws/sqs";
const sqs = new SQSAPI(
"https://sqs.ap-northeast-2.amazonaws.com/123456789012/my-queue",
{
region: "ap-northeast-2",
}
);
const sendResp = await sqs.send_message({
type: "created",
id: 1,
});
console.log(sendResp.MessageId);
const recvResp = await sqs.receive_messages(
undefined,
undefined,
10,
undefined,
20
);
for (const msg of recvResp.Messages ?? []) {
console.log(msg.Body);
if (msg.ReceiptHandle) {
await sqs.delete_message(msg.ReceiptHandle);
}
}Package Surface
Most applications only need the high-level queue-bound client:
SQSAPISQSValidationErrorSQSBatchOperationError
Advanced callers can also use:
LowLevelSQScreate_sqs_api_config(...)- message attribute and response model types
SQSAPI is intentionally bound to one queue URL. That keeps FIFO detection,
validation, and convenience helpers local to the queue you are actually using.
Creating the Client
import { SQSAPI, create_sqs_api_config } from "@chainsaws/sqs";
const config = create_sqs_api_config({
endpoint: process.env.SQS_ENDPOINT,
max_pool_connections: 100,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
sessionToken: process.env.AWS_SESSION_TOKEN,
},
});
const sqs = new SQSAPI(
"https://sqs.ap-northeast-2.amazonaws.com/123456789012/my-queue",
config
);SQSAPIConfig supports:
regionendpointcredentialsmax_pool_connections
All fields are optional. When region or credentials are omitted, the AWS SDK
falls back to its normal default resolution chain. Use endpoint for LocalStack
or test environments.
Queue Semantics
The client intentionally mirrors a few Python-side ergonomics:
- JSON objects and arrays passed to
send_message()are serialized automatically. - FIFO queues default
message_group_idto"default"when omitted. - FIFO queues default
message_deduplication_idtomd5(serializedBody)when omitted. - Standard queues reject FIFO-only fields before AWS is called.
strict=trueon batch methods raisesSQSBatchOperationErrorwhen SQS reports failed entries.
Single Message APIs
send_message
await sqs.send_message("hello");
await sqs.send_message(
{ type: "user.created", id: "u_1" },
30,
{
tenant: {
DataType: "String",
StringValue: "acme",
},
}
);For TypeScript-heavy callers, the same method also accepts a trailing options object:
await sqs.send_message("hello", {
delay_seconds: 30,
message_attributes: {
tenant: {
DataType: "String",
StringValue: "acme",
},
},
});Behavior:
- accepts a string, JSON object, or JSON array
- serializes JSON payloads with
JSON.stringify - validates body size before calling AWS
- validates message attributes and system attributes locally
receive_messages
const response = await sqs.receive_messages(
["All"],
["All"],
10,
30,
20
);Object-style receive options are also supported:
const response = await sqs.receive_messages({
message_attributes_names: ["All"],
message_system_attributes_names: ["All"],
max_number_of_messages: 10,
visibility_timeout: 30,
wait_time_seconds: 20,
});Arguments are positional for Python parity:
message_attributes_namesmessage_system_attributes_namesmax_number_of_messagesvisibility_timeoutwait_time_secondsreceive_request_attempt_id
Behavior:
- validates receive limits before calling AWS
- rejects
receive_request_attempt_idon standard queues - preserves explicit zero values such as
visibility_timeout=0
delete_message
await sqs.delete_message(receiptHandle);Batch APIs
send_message_batch
await sqs.send_message_batch([
{
Id: "1",
MessageBody: "hello",
},
{
Id: "2",
MessageBody: "world",
},
]);When strict=true, failed batch entries raise SQSBatchOperationError.
await sqs.send_message_batch(entries, true);
await sqs.send_message_batch(entries, { strict: true });send_messages
send_messages is the convenience form of send_message_batch.
await sqs.send_messages([
{ type: "created", id: 1 },
{ type: "deleted", id: 2 },
]);Arguments:
messagesdelay_secondsfifomessage_group_idstrict
await sqs.send_messages(messages, {
fifo: true,
message_group_id: "jobs",
strict: true,
});delete_message_batch
await sqs.delete_message_batch([
{ Id: "1", ReceiptHandle: "rh-1" },
{ Id: "2", ReceiptHandle: "rh-2" },
]);delete_messages
delete_messages is the convenience form of delete_message_batch.
await sqs.delete_messages(["rh-1", "rh-2"], true);FIFO Queue Behavior
For queue URLs ending with .fifo:
send_message()defaultsmessage_group_idto"default"send_message()defaultsmessage_deduplication_idtomd5(serializedBody)send_message_batch()defaultsMessageGroupIdto"default"send_message_batch()defaultsMessageDeduplicationIdtomd5(MessageBody)- per-message
delay_seconds/DelaySecondsis rejected
For standard queues:
- FIFO-only parameters are rejected early
fifo=trueinsend_messages()is rejected
Iteration Helper
Use iter_messages() for worker-style receive loops.
for await (const msg of sqs.iter_messages(
10,
undefined,
20,
true,
true,
100
)) {
console.log(msg.Body);
}Arguments:
max_number_of_messagesvisibility_timeoutwait_time_secondsauto_deleteauto_delete_strictstop_after
Behavior:
- performs repeated
receive_messages()calls until SQS returns no messages - when
auto_delete=true, batches receipt handles and deletes after each page - when
stop_afteris reached, flushes pending deletes before returning - still flushes pending deletes if iteration exits early
Validation
The client validates common SQS constraints before calling AWS:
- batch size:
1..10 max_number_of_messages:1..10wait_time_seconds:0..20visibility_timeout:0..43200- message body size:
<= 262144 bytes - batch
Idformat:[A-Za-z0-9_-]{1,80} - FIFO identifier size:
<= 128 bytes - message attributes: max
10 - message attribute data type prefixes:
String,Number,Binary - system attributes:
AWSTraceHeaderonly receive_messages(message_attributes_names=...): supportsAll,.*, andprefix.*
Validation errors raise SQSValidationError.
Errors
The package exports:
SQSExceptionSQSValidationErrorSQSBatchOperationError
Typical cases:
- invalid queue URL
- invalid batch size or entry ids
- FIFO-only parameters used on a standard queue
- strict batch responses containing failed entries
Low-Level Adapter
LowLevelSQS is also exported for advanced callers who want the thin AWS SDK adapter directly.
import { LowLevelSQS } from "@chainsaws/sqs";
const low = new LowLevelSQS({ region: "ap-northeast-2" });
await low.send_message({
queue_url: "https://sqs.ap-northeast-2.amazonaws.com/123456789012/my-queue",
message_body: "hello",
delay_seconds: 0,
});The low-level adapter intentionally does not perform business-rule validation. It only:
- translates snake_case inputs into AWS SDK commands
- preserves explicit zero values
- keeps the internal
message_sytstem_attributes_namesalias for parity
Compatibility Notes
This package is intentionally transport-focused. It does not yet add a typed
message codec layer on top of SQS Body, so received messages still come back
with Body?: string.
Development
pnpm --filter @chainsaws/sqs check-types
pnpm --filter @chainsaws/sqs test
pnpm --filter @chainsaws/sqs lint
pnpm --filter @chainsaws/sqs buildLicense
MIT
