@leanstacks/lambda-utils 0.3.0 → 0.4.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/docs/README.md CHANGED
@@ -12,13 +12,16 @@ Lambda Utilities is a collection of pre-configured tools and helpers designed to
12
12
  - **[Logging Guide](./LOGGING.md)** – Implement structured logging in your Lambda functions with Pino and automatic AWS context enrichment
13
13
  - **[API Gateway Responses](./API_GATEWAY_RESPONSES.md)** – Format Lambda responses for API Gateway with standard HTTP status codes and headers
14
14
  - **[DynamoDB Client](./DYNAMODB_CLIENT.md)** – Reusable singleton DynamoDB client instances with custom configuration
15
+ - **[Lambda Client](./LAMBDA_CLIENT.md)** – Reusable singleton Lambda client for invoking other Lambda functions
16
+ - **[SNS Client](./SNS_CLIENT.md)** – Reusable singleton SNS client for publishing messages to topics with message attributes
17
+ - **[SQS Client](./SQS_CLIENT.md)** – Reusable singleton SQS client for sending messages to queues with message attributes
15
18
 
16
19
  ## Features
17
20
 
18
21
  - 📝 **Structured Logging** – Pino logger pre-configured for Lambda with automatic request context
19
22
  - 📤 **API Response Helpers** – Standard response formatting for API Gateway integration
20
23
  - ⚙️ **Configuration Validation** – Environment variable validation with Zod schema support
21
- - 🔌 **AWS Clients** – Pre-configured AWS SDK v3 clients for common services
24
+ - 🔌 **AWS Clients** – Pre-configured AWS SDK v3 clients for DynamoDB, SNS, SQS, and Lambda
22
25
  - 🔒 **Type Safe** – Full TypeScript support with comprehensive type definitions
23
26
 
24
27
  ## Support
@@ -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)**