@leanstacks/lambda-utils 0.3.0 → 0.4.0-alpha.1

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.
@@ -0,0 +1,352 @@
1
+ # SQS Client Utilities
2
+
3
+ The SQS client utilities provide a reusable singleton instance of `SQSClient` for use in AWS Lambda functions. These utilities enable you to configure the client once and reuse it across invocations, following AWS best practices for Lambda performance optimization.
4
+
5
+ ## Overview
6
+
7
+ The utility exports the following functions:
8
+
9
+ - `initializeSQSClient()` - Initialize the SQS client with optional configuration
10
+ - `getSQSClient()` - Get the singleton SQS client instance
11
+ - `sendToQueue()` - Send a message to an SQS queue
12
+ - `resetSQSClient()` - Reset the client instance (useful for testing)
13
+
14
+ ## Usage
15
+
16
+ ### Basic Usage
17
+
18
+ ```typescript
19
+ import { sendToQueue } from '@leanstacks/lambda-utils';
20
+
21
+ export const handler = async (event: any) => {
22
+ // Send a message to an SQS queue
23
+ const messageId = await sendToQueue('https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue', {
24
+ orderId: '12345',
25
+ status: 'completed',
26
+ });
27
+
28
+ return {
29
+ statusCode: 200,
30
+ body: JSON.stringify({ messageId }),
31
+ };
32
+ };
33
+ ```
34
+
35
+ ### Sending with Message Attributes
36
+
37
+ Message attributes enable SQS subscribers to filter messages based on metadata:
38
+
39
+ ```typescript
40
+ import { sendToQueue, SQSMessageAttributes } from '@leanstacks/lambda-utils';
41
+
42
+ export const handler = async (event: any) => {
43
+ const attributes: SQSMessageAttributes = {
44
+ priority: {
45
+ DataType: 'String',
46
+ StringValue: 'high',
47
+ },
48
+ attempts: {
49
+ DataType: 'Number',
50
+ StringValue: '1',
51
+ },
52
+ };
53
+
54
+ const messageId = await sendToQueue(
55
+ 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue',
56
+ { orderId: '12345', status: 'completed' },
57
+ attributes,
58
+ );
59
+
60
+ return { statusCode: 200, body: JSON.stringify({ messageId }) };
61
+ };
62
+ ```
63
+
64
+ ### Using Binary Data in Message Attributes
65
+
66
+ SQS supports binary data in message attributes:
67
+
68
+ ```typescript
69
+ import { sendToQueue, SQSMessageAttributes } from '@leanstacks/lambda-utils';
70
+
71
+ export const handler = async (event: any) => {
72
+ const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
73
+ const attributes: SQSMessageAttributes = {
74
+ imageData: {
75
+ DataType: 'Binary',
76
+ BinaryValue: binaryData,
77
+ },
78
+ };
79
+
80
+ const messageId = await sendToQueue(
81
+ 'https://sqs.us-east-1.amazonaws.com/123456789012/MyQueue',
82
+ { imageId: '12345' },
83
+ attributes,
84
+ );
85
+
86
+ return { statusCode: 200, body: JSON.stringify({ messageId }) };
87
+ };
88
+ ```
89
+
90
+ ### Using the SQS Client Directly
91
+
92
+ For advanced use cases, you can access the underlying SQS client:
93
+
94
+ ```typescript
95
+ import { getSQSClient } from '@leanstacks/lambda-utils';
96
+ import { ListQueuesCommand } from '@aws-sdk/client-sqs';
97
+
98
+ export const handler = async (event: any) => {
99
+ const client = getSQSClient();
100
+
101
+ const response = await client.send(new ListQueuesCommand({}));
102
+
103
+ return {
104
+ statusCode: 200,
105
+ body: JSON.stringify(response.QueueUrls),
106
+ };
107
+ };
108
+ ```
109
+
110
+ ### Advanced Configuration
111
+
112
+ #### Custom SQS Client Configuration
113
+
114
+ ```typescript
115
+ import { initializeSQSClient } from '@leanstacks/lambda-utils';
116
+
117
+ // Initialize client with custom configuration (typically done once outside the handler)
118
+ initializeSQSClient({
119
+ region: 'us-west-2',
120
+ endpoint: 'http://localhost:9324', // For local development with LocalStack
121
+ });
122
+
123
+ export const handler = async (event: any) => {
124
+ // Client is now initialized and ready to use
125
+ // Use sendToQueue or getSQSClient as needed
126
+ };
127
+ ```
128
+
129
+ ### Lambda Handler Pattern
130
+
131
+ ```typescript
132
+ import { initializeSQSClient, sendToQueue } from '@leanstacks/lambda-utils';
133
+
134
+ // Initialize client outside the handler (runs once per cold start)
135
+ initializeSQSClient({ region: process.env.AWS_REGION });
136
+
137
+ export const handler = async (event: any) => {
138
+ const messageId = await sendToQueue(process.env.QUEUE_URL!, {
139
+ timestamp: new Date().toISOString(),
140
+ data: event,
141
+ });
142
+
143
+ return {
144
+ statusCode: 200,
145
+ body: JSON.stringify({ messageId }),
146
+ };
147
+ };
148
+ ```
149
+
150
+ ## API Reference
151
+
152
+ ### `initializeSQSClient(config?): SQSClient`
153
+
154
+ Initializes the SQS client with the provided configuration.
155
+
156
+ **Parameters:**
157
+
158
+ - `config` (optional) - SQS client configuration object
159
+
160
+ **Returns:**
161
+
162
+ - The `SQSClient` instance
163
+
164
+ **Notes:**
165
+
166
+ - If called multiple times, it will replace the existing client instance
167
+ - If no config is provided, uses default AWS SDK configuration
168
+
169
+ ### `getSQSClient(): SQSClient`
170
+
171
+ Returns the singleton SQS client instance.
172
+
173
+ **Returns:**
174
+
175
+ - The `SQSClient` instance
176
+
177
+ **Notes:**
178
+
179
+ - If the client has not been initialized, creates one with default configuration
180
+ - Automatically initializes the client on first use if not already initialized
181
+
182
+ ### `sendToQueue(queueUrl, message, attributes?): Promise<string>`
183
+
184
+ Sends a message to an SQS queue.
185
+
186
+ **Parameters:**
187
+
188
+ - `queueUrl` (string) - The URL of the SQS queue to send to
189
+ - `message` (Record<string, unknown>) - The message content (will be converted to JSON string)
190
+ - `attributes` (optional) - Message attributes for filtering
191
+
192
+ **Returns:**
193
+
194
+ - Promise that resolves to the message ID (string)
195
+
196
+ **Throws:**
197
+
198
+ - Error if the SQS send operation fails
199
+
200
+ **Notes:**
201
+
202
+ - Automatically initializes the SQS client if not already initialized
203
+ - Message is automatically serialized to JSON
204
+ - Returns empty string if MessageId is not provided in the response
205
+
206
+ ### `resetSQSClient(): void`
207
+
208
+ Resets the SQS client instance to null.
209
+
210
+ **Notes:**
211
+
212
+ - Primarily useful for testing scenarios where you need to reinitialize the client with different configurations
213
+ - After calling this, the client will be automatically re-initialized on next use
214
+
215
+ ### `SQSMessageAttributes`
216
+
217
+ Type definition for SQS message attributes.
218
+
219
+ **Interface:**
220
+
221
+ ```typescript
222
+ interface SQSMessageAttributes {
223
+ [key: string]: {
224
+ DataType: 'String' | 'Number' | 'Binary';
225
+ StringValue?: string;
226
+ BinaryValue?: Uint8Array;
227
+ };
228
+ }
229
+ ```
230
+
231
+ **Supported Data Types:**
232
+
233
+ - `String` - UTF-8 encoded string values
234
+ - `Number` - Numeric values (stored as strings)
235
+ - `Binary` - Binary data
236
+
237
+ **Note:** Unlike SNS, SQS does not support array data types (`String.Array`).
238
+
239
+ ## Best Practices
240
+
241
+ 1. **Initialize Outside the Handler**: Always initialize the client outside your Lambda handler function to reuse the instance across invocations.
242
+
243
+ 2. **Use Environment Variables**: Configure the client using environment variables for flexibility across environments.
244
+
245
+ 3. **Error Handling**: Always wrap send operations in try-catch blocks to handle errors gracefully.
246
+
247
+ 4. **Message Attributes**: Use message attributes for message filtering and routing rather than including filter criteria in the message body.
248
+
249
+ 5. **Testing**: Use `resetSQSClient()` in test setup/teardown to ensure clean test isolation.
250
+
251
+ ## Message Attribute Examples
252
+
253
+ ### String Attribute
254
+
255
+ ```typescript
256
+ const attributes: SQSMessageAttributes = {
257
+ priority: {
258
+ DataType: 'String',
259
+ StringValue: 'high',
260
+ },
261
+ };
262
+ ```
263
+
264
+ ### Number Attribute
265
+
266
+ ```typescript
267
+ const attributes: SQSMessageAttributes = {
268
+ temperature: {
269
+ DataType: 'Number',
270
+ StringValue: '72.5',
271
+ },
272
+ };
273
+ ```
274
+
275
+ ### Binary Attribute
276
+
277
+ ```typescript
278
+ const attributes: SQSMessageAttributes = {
279
+ thumbnail: {
280
+ DataType: 'Binary',
281
+ BinaryValue: new Uint8Array([1, 2, 3, 4]),
282
+ },
283
+ };
284
+ ```
285
+
286
+ ## Testing Example
287
+
288
+ ```typescript
289
+ import { initializeSQSClient, sendToQueue, resetSQSClient } from '@leanstacks/lambda-utils';
290
+
291
+ describe('MyLambdaHandler', () => {
292
+ beforeEach(() => {
293
+ resetSQSClient();
294
+ initializeSQSClient({
295
+ region: 'us-east-1',
296
+ endpoint: 'http://localhost:9324', // LocalStack
297
+ });
298
+ });
299
+
300
+ afterEach(() => {
301
+ resetSQSClient();
302
+ });
303
+
304
+ it('should send message to SQS queue', async () => {
305
+ const messageId = await sendToQueue('https://sqs.us-east-1.amazonaws.com/123456789012/TestQueue', {
306
+ test: 'data',
307
+ });
308
+
309
+ expect(messageId).toBeTruthy();
310
+ });
311
+ });
312
+ ```
313
+
314
+ ## Error Handling Example
315
+
316
+ ```typescript
317
+ import { sendToQueue } from '@leanstacks/lambda-utils';
318
+
319
+ export const handler = async (event: any) => {
320
+ try {
321
+ const messageId = await sendToQueue(
322
+ process.env.QUEUE_URL!,
323
+ { orderId: event.orderId, status: 'processing' },
324
+ {
325
+ priority: {
326
+ DataType: 'String',
327
+ StringValue: 'high',
328
+ },
329
+ },
330
+ );
331
+
332
+ return {
333
+ statusCode: 200,
334
+ body: JSON.stringify({ success: true, messageId }),
335
+ };
336
+ } catch (error) {
337
+ console.error('Failed to send message to SQS', error);
338
+
339
+ return {
340
+ statusCode: 500,
341
+ body: JSON.stringify({ success: false, error: 'Failed to send message' }),
342
+ };
343
+ }
344
+ };
345
+ ```
346
+
347
+ ## Related Resources
348
+
349
+ - **[AWS SDK for JavaScript v3 - SQS Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sqs/)**
350
+ - **[Amazon SQS Developer Guide](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/)**
351
+ - **[AWS Lambda Best Practices](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)**
352
+ - **[Back to the project documentation](README.md)**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanstacks/lambda-utils",
3
- "version": "0.3.0",
3
+ "version": "0.4.0-alpha.1",
4
4
  "description": "A collection of utilities and helper functions designed to streamline the development of AWS Lambda functions using TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -48,8 +48,9 @@
48
48
  "@types/aws-lambda": "8.10.159",
49
49
  "@types/jest": "30.0.0",
50
50
  "@types/node": "25.0.3",
51
- "@typescript-eslint/eslint-plugin": "8.50.0",
52
- "@typescript-eslint/parser": "8.50.0",
51
+ "@typescript-eslint/eslint-plugin": "8.50.1",
52
+ "@typescript-eslint/parser": "8.50.1",
53
+ "aws-sdk-client-mock": "4.1.0",
53
54
  "eslint": "9.39.2",
54
55
  "husky": "9.1.7",
55
56
  "jest": "30.2.0",
@@ -63,8 +64,11 @@
63
64
  "typescript": "5.9.3"
64
65
  },
65
66
  "dependencies": {
66
- "@aws-sdk/client-dynamodb": "3.956.0",
67
- "@aws-sdk/lib-dynamodb": "3.956.0",
67
+ "@aws-sdk/client-dynamodb": "3.957.0",
68
+ "@aws-sdk/client-lambda": "3.957.0",
69
+ "@aws-sdk/client-sns": "3.957.0",
70
+ "@aws-sdk/client-sqs": "3.957.0",
71
+ "@aws-sdk/lib-dynamodb": "3.957.0",
68
72
  "pino": "10.1.0",
69
73
  "pino-lambda": "4.4.1",
70
74
  "zod": "4.2.1"