@leanstacks/lambda-utils 0.3.0-alpha.4 → 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.
- package/README.md +135 -4
- package/dist/clients/lambda-client.d.ts +78 -0
- package/dist/clients/sns-client.d.ts +75 -0
- package/dist/clients/sqs-client.d.ts +74 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/docs/CONFIGURATION.md +348 -0
- package/docs/LAMBDA_CLIENT.md +292 -0
- package/docs/README.md +5 -3
- package/docs/SNS_CLIENT.md +363 -0
- package/docs/SQS_CLIENT.md +352 -0
- package/package.json +10 -6
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# SNS Client Utilities
|
|
2
|
+
|
|
3
|
+
The SNS client utilities provide a reusable singleton instance of `SNSClient` 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
|
+
- `initializeSNSClient()` - Initialize the SNS client with optional configuration
|
|
10
|
+
- `getSNSClient()` - Get the singleton SNS client instance
|
|
11
|
+
- `publishToTopic()` - Publish a message to an SNS topic
|
|
12
|
+
- `resetSNSClient()` - Reset the client instance (useful for testing)
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
### Basic Usage
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { publishToTopic } from '@leanstacks/lambda-utils';
|
|
20
|
+
|
|
21
|
+
export const handler = async (event: any) => {
|
|
22
|
+
// Publish a message to an SNS topic
|
|
23
|
+
const messageId = await publishToTopic('arn:aws:sns:us-east-1:123456789012:MyTopic', {
|
|
24
|
+
orderId: '12345',
|
|
25
|
+
status: 'completed',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
statusCode: 200,
|
|
30
|
+
body: JSON.stringify({ messageId }),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Publishing with Message Attributes
|
|
36
|
+
|
|
37
|
+
Message attributes enable SNS topic subscribers to filter messages based on metadata:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { publishToTopic, SNSMessageAttributes } from '@leanstacks/lambda-utils';
|
|
41
|
+
|
|
42
|
+
export const handler = async (event: any) => {
|
|
43
|
+
const attributes: SNSMessageAttributes = {
|
|
44
|
+
priority: {
|
|
45
|
+
DataType: 'String',
|
|
46
|
+
StringValue: 'high',
|
|
47
|
+
},
|
|
48
|
+
category: {
|
|
49
|
+
DataType: 'String',
|
|
50
|
+
StringValue: 'order',
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const messageId = await publishToTopic(
|
|
55
|
+
'arn:aws:sns:us-east-1:123456789012:MyTopic',
|
|
56
|
+
{ orderId: '12345', status: 'completed' },
|
|
57
|
+
attributes,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
return { statusCode: 200, body: JSON.stringify({ messageId }) };
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Using String Arrays in Message Attributes
|
|
65
|
+
|
|
66
|
+
AWS SNS supports `String.Array` as the only array data type:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { publishToTopic, SNSMessageAttributes } from '@leanstacks/lambda-utils';
|
|
70
|
+
|
|
71
|
+
export const handler = async (event: any) => {
|
|
72
|
+
const attributes: SNSMessageAttributes = {
|
|
73
|
+
tags: {
|
|
74
|
+
DataType: 'String.Array',
|
|
75
|
+
StringValue: JSON.stringify(['urgent', 'vip', 'customer-request']),
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const messageId = await publishToTopic(
|
|
80
|
+
'arn:aws:sns:us-east-1:123456789012:MyTopic',
|
|
81
|
+
{ orderId: '12345' },
|
|
82
|
+
attributes,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return { statusCode: 200, body: JSON.stringify({ messageId }) };
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Using the SNS Client Directly
|
|
90
|
+
|
|
91
|
+
For advanced use cases, you can access the underlying SNS client:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { getSNSClient } from '@leanstacks/lambda-utils';
|
|
95
|
+
import { ListTopicsCommand } from '@aws-sdk/client-sns';
|
|
96
|
+
|
|
97
|
+
export const handler = async (event: any) => {
|
|
98
|
+
const client = getSNSClient();
|
|
99
|
+
|
|
100
|
+
const response = await client.send(new ListTopicsCommand({}));
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
statusCode: 200,
|
|
104
|
+
body: JSON.stringify(response.Topics),
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Advanced Configuration
|
|
110
|
+
|
|
111
|
+
#### Custom SNS Client Configuration
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { initializeSNSClient } from '@leanstacks/lambda-utils';
|
|
115
|
+
|
|
116
|
+
// Initialize client with custom configuration (typically done once outside the handler)
|
|
117
|
+
initializeSNSClient({
|
|
118
|
+
region: 'us-west-2',
|
|
119
|
+
endpoint: 'http://localhost:4566', // For local development with LocalStack
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
export const handler = async (event: any) => {
|
|
123
|
+
// Client is now initialized and ready to use
|
|
124
|
+
// Use publishToTopic or getSNSClient as needed
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Lambda Handler Pattern
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
import { initializeSNSClient, publishToTopic } from '@leanstacks/lambda-utils';
|
|
132
|
+
|
|
133
|
+
// Initialize client outside the handler (runs once per cold start)
|
|
134
|
+
initializeSNSClient({ region: process.env.AWS_REGION });
|
|
135
|
+
|
|
136
|
+
export const handler = async (event: any) => {
|
|
137
|
+
const messageId = await publishToTopic(process.env.TOPIC_ARN!, {
|
|
138
|
+
timestamp: new Date().toISOString(),
|
|
139
|
+
data: event,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
statusCode: 200,
|
|
144
|
+
body: JSON.stringify({ messageId }),
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## API Reference
|
|
150
|
+
|
|
151
|
+
### `initializeSNSClient(config?): SNSClient`
|
|
152
|
+
|
|
153
|
+
Initializes the SNS client with the provided configuration.
|
|
154
|
+
|
|
155
|
+
**Parameters:**
|
|
156
|
+
|
|
157
|
+
- `config` (optional) - SNS client configuration object
|
|
158
|
+
|
|
159
|
+
**Returns:**
|
|
160
|
+
|
|
161
|
+
- The `SNSClient` instance
|
|
162
|
+
|
|
163
|
+
**Notes:**
|
|
164
|
+
|
|
165
|
+
- If called multiple times, it will replace the existing client instance
|
|
166
|
+
- If no config is provided, uses default AWS SDK configuration
|
|
167
|
+
|
|
168
|
+
### `getSNSClient(): SNSClient`
|
|
169
|
+
|
|
170
|
+
Returns the singleton SNS client instance.
|
|
171
|
+
|
|
172
|
+
**Returns:**
|
|
173
|
+
|
|
174
|
+
- The `SNSClient` instance
|
|
175
|
+
|
|
176
|
+
**Notes:**
|
|
177
|
+
|
|
178
|
+
- If the client has not been initialized, creates one with default configuration
|
|
179
|
+
- Automatically initializes the client on first use if not already initialized
|
|
180
|
+
|
|
181
|
+
### `publishToTopic(topicArn, message, attributes?): Promise<string>`
|
|
182
|
+
|
|
183
|
+
Publishes a message to an SNS topic.
|
|
184
|
+
|
|
185
|
+
**Parameters:**
|
|
186
|
+
|
|
187
|
+
- `topicArn` (string) - The ARN of the SNS topic to publish to
|
|
188
|
+
- `message` (Record<string, unknown>) - The message content (will be converted to JSON string)
|
|
189
|
+
- `attributes` (optional) - Message attributes for filtering
|
|
190
|
+
|
|
191
|
+
**Returns:**
|
|
192
|
+
|
|
193
|
+
- Promise that resolves to the message ID (string)
|
|
194
|
+
|
|
195
|
+
**Throws:**
|
|
196
|
+
|
|
197
|
+
- Error if the SNS publish operation fails
|
|
198
|
+
|
|
199
|
+
**Notes:**
|
|
200
|
+
|
|
201
|
+
- Automatically initializes the SNS client if not already initialized
|
|
202
|
+
- Message is automatically serialized to JSON
|
|
203
|
+
- Returns empty string if MessageId is not provided in the response
|
|
204
|
+
|
|
205
|
+
### `resetSNSClient(): void`
|
|
206
|
+
|
|
207
|
+
Resets the SNS client instance to null.
|
|
208
|
+
|
|
209
|
+
**Notes:**
|
|
210
|
+
|
|
211
|
+
- Primarily useful for testing scenarios where you need to reinitialize the client with different configurations
|
|
212
|
+
- After calling this, the client will be automatically re-initialized on next use
|
|
213
|
+
|
|
214
|
+
### `SNSMessageAttributes`
|
|
215
|
+
|
|
216
|
+
Type definition for SNS message attributes.
|
|
217
|
+
|
|
218
|
+
**Interface:**
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
interface SNSMessageAttributes {
|
|
222
|
+
[key: string]: {
|
|
223
|
+
DataType: 'String' | 'String.Array' | 'Number' | 'Binary';
|
|
224
|
+
StringValue?: string;
|
|
225
|
+
BinaryValue?: Uint8Array;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Supported Data Types:**
|
|
231
|
+
|
|
232
|
+
- `String` - UTF-8 encoded string values
|
|
233
|
+
- `String.Array` - Array of strings (must be JSON-stringified)
|
|
234
|
+
- `Number` - Numeric values (stored as strings)
|
|
235
|
+
- `Binary` - Binary data
|
|
236
|
+
|
|
237
|
+
**Note:** `String.Array` is the only array type supported by AWS SNS. There are no `Number.Array` or `Binary.Array` types.
|
|
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 publish operations in try-catch blocks to handle errors gracefully.
|
|
246
|
+
|
|
247
|
+
4. **Message Attributes**: Use message attributes for subscriber filtering rather than including filter criteria in the message body.
|
|
248
|
+
|
|
249
|
+
5. **Testing**: Use `resetSNSClient()` in test setup/teardown to ensure clean test isolation.
|
|
250
|
+
|
|
251
|
+
## Message Attribute Examples
|
|
252
|
+
|
|
253
|
+
### String Attribute
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
const attributes: SNSMessageAttributes = {
|
|
257
|
+
priority: {
|
|
258
|
+
DataType: 'String',
|
|
259
|
+
StringValue: 'high',
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Number Attribute
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
const attributes: SNSMessageAttributes = {
|
|
268
|
+
temperature: {
|
|
269
|
+
DataType: 'Number',
|
|
270
|
+
StringValue: '72.5',
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### String Array Attribute
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
const attributes: SNSMessageAttributes = {
|
|
279
|
+
tags: {
|
|
280
|
+
DataType: 'String.Array',
|
|
281
|
+
StringValue: JSON.stringify(['urgent', 'vip', 'customer-request']),
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Binary Attribute
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
const attributes: SNSMessageAttributes = {
|
|
290
|
+
thumbnail: {
|
|
291
|
+
DataType: 'Binary',
|
|
292
|
+
BinaryValue: new Uint8Array([1, 2, 3, 4]),
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Testing Example
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { initializeSNSClient, publishToTopic, resetSNSClient } from '@leanstacks/lambda-utils';
|
|
301
|
+
|
|
302
|
+
describe('MyLambdaHandler', () => {
|
|
303
|
+
beforeEach(() => {
|
|
304
|
+
resetSNSClient();
|
|
305
|
+
initializeSNSClient({
|
|
306
|
+
region: 'us-east-1',
|
|
307
|
+
endpoint: 'http://localhost:4566', // LocalStack
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
afterEach(() => {
|
|
312
|
+
resetSNSClient();
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it('should publish message to SNS topic', async () => {
|
|
316
|
+
const messageId = await publishToTopic('arn:aws:sns:us-east-1:123456789012:TestTopic', {
|
|
317
|
+
test: 'data',
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
expect(messageId).toBeTruthy();
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Error Handling Example
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { publishToTopic } from '@leanstacks/lambda-utils';
|
|
329
|
+
|
|
330
|
+
export const handler = async (event: any) => {
|
|
331
|
+
try {
|
|
332
|
+
const messageId = await publishToTopic(
|
|
333
|
+
process.env.TOPIC_ARN!,
|
|
334
|
+
{ orderId: event.orderId, status: 'completed' },
|
|
335
|
+
{
|
|
336
|
+
priority: {
|
|
337
|
+
DataType: 'String',
|
|
338
|
+
StringValue: 'high',
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
statusCode: 200,
|
|
345
|
+
body: JSON.stringify({ success: true, messageId }),
|
|
346
|
+
};
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error('Failed to publish message to SNS', error);
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
statusCode: 500,
|
|
352
|
+
body: JSON.stringify({ success: false, error: 'Failed to publish message' }),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Related Resources
|
|
359
|
+
|
|
360
|
+
- **[AWS SDK for JavaScript v3 - SNS Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sns/)**
|
|
361
|
+
- **[Amazon SNS Message Attributes](https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html)**
|
|
362
|
+
- **[AWS Lambda Best Practices](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)**
|
|
363
|
+
- **[Back to the project documentation](README.md)**
|
|
@@ -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)**
|