Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 22 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const handler = async (event: APIGatewayProxyEvent) => {
- **📝 Structured Logging** – Pino logger pre-configured for Lambda with automatic AWS request context enrichment
- **📤 API Response Helpers** – Standard response formatting for API Gateway with proper HTTP status codes
- **⚙️ Configuration Validation** – Environment variable validation with Zod schema support
- **🔌 AWS SDK Clients** – Pre-configured AWS SDK v3 clients for DynamoDB, Lambda, and more
- **🔌 AWS SDK Clients** – Pre-configured AWS SDK v3 clients including DynamoDB with document client support
- **🔒 Full TypeScript Support** – Complete type definitions and IDE autocomplete
- **⚡ Lambda Optimized** – Designed for performance in serverless environments

Expand All @@ -79,9 +79,7 @@ Comprehensive guides and examples are available in the `docs` directory:
| ------------------------------------------------------------ | ---------------------------------------------------------------------- |
| **[Logging Guide](./docs/LOGGING.md)** | Configure and use structured logging with automatic AWS Lambda context |
| **[API Gateway Responses](./docs/API_GATEWAY_RESPONSES.md)** | Format responses for API Gateway with standard HTTP patterns |
| **[Configuration](./docs/CONFIGURATION.md)** | Validate and manage environment variables with type safety |
| **[AWS Clients](./docs/CLIENTS.md)** | Use pre-configured AWS SDK v3 clients in your handlers |
| **[Getting Started](./docs/GETTING_STARTED.md)** | Setup and first steps guide |
| **[AWS Clients](./docs/README.md)** | Use pre-configured AWS SDK v3 clients in your handlers |

## Usage

Expand Down Expand Up @@ -119,39 +117,35 @@ export const handler = async (event: APIGatewayProxyEvent) => {

**→ See [API Gateway Responses](./docs/API_GATEWAY_RESPONSES.md) for all response types**

### Configuration Validation

Validate your Lambda environment configuration:

```typescript
import { validateConfig } from '@leanstacks/lambda-utils';
import { z } from 'zod';

const configSchema = z.object({
DATABASE_URL: z.string().url(),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']),
API_KEY: z.string(),
});

const config = validateConfig(configSchema);
```
### AWS Clients

**→ See [Configuration](./docs/CONFIGURATION.md) for validation patterns**
Use pre-configured AWS SDK v3 clients. Currently available:

### AWS Clients
#### DynamoDB Client

Use pre-configured AWS SDK v3 clients:
Initialize the DynamoDB clients (base client and document client) once during handler initialization:

```typescript
import { getDynamoDBClient, getLambdaClient } from '@leanstacks/lambda-utils';
import { initializeDynamoDBClients, getDynamoDBDocumentClient } from '@leanstacks/lambda-utils';

const dynamoDB = getDynamoDBClient();
const lambda = getLambdaClient();
export const handler = async (event: any, context: any) => {
// Initialize clients once
initializeDynamoDBClients({ region: 'us-east-1' });

// Use the document client for operations
const docClient = getDynamoDBDocumentClient();
const result = await docClient.get({
TableName: 'MyTable',
Key: { id: 'item-123' },
});

// Use clients for API calls
return { statusCode: 200, body: JSON.stringify(result) };
};
```

**→ See [AWS Clients](./docs/CLIENTS.md) for available clients and examples**
**→ See [DynamoDB Client Guide](./docs/DYNAMODB_CLIENT.md) for detailed configuration and examples**

Additional AWS Clients are coming soon.

## Examples

Expand Down
214 changes: 214 additions & 0 deletions docs/DYNAMODB_CLIENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# DynamoDB Client Utilities

The DynamoDB client utilities provide reusable singleton instances of `DynamoDBClient` and `DynamoDBDocumentClient` for use in AWS Lambda functions. These utilities enable you to configure clients once and reuse them across invocations, following AWS best practices for Lambda performance optimization.

## Overview

The utility exports the following functions:

- `initializeDynamoDBClients()` - Initialize both DynamoDB clients with optional configuration
- `getDynamoDBClient()` - Get the singleton DynamoDB client instance
- `getDynamoDBDocumentClient()` - Get the singleton DynamoDB Document client instance
- `resetDynamoDBClients()` - Reset both client instances (useful for testing)

## Usage

### Basic Usage

```typescript
import { initializeDynamoDBClients, getDynamoDBDocumentClient } from '@leanstacks/lambda-utils';
import { PutCommand } from '@aws-sdk/lib-dynamodb';

// Initialize both clients (typically done once outside the handler)
initializeDynamoDBClients({ region: 'us-east-1' });

export const handler = async (event: any) => {
// Get the document client (most common use case)
const docClient = getDynamoDBDocumentClient();

// Use the document client
await docClient.send(
new PutCommand({
TableName: 'MyTable',
Item: { id: '123', name: 'Example' },
}),
);
};
```

### Using the Base DynamoDB Client

````typescript
import { initializeDynamoDBClients, getDynamoDBClient } from '@leanstacks/lambda-utils';
import { PutItemCommand } from '@aws-sdk/client-dynamodb';

// Initialize both clients
initializeDynamoDBClients({ region: 'us-east-1' });

export const handler = async (event: any) => {
// Get the base client for advanced use cases
const client = getDynamoDBClient();

// Use the base client
await client.send(new PutItemCommand({
TableName: 'MyTable',
Item: { id: { S: '123' }, name: { S: 'Example' } }
}));

### Advanced Configuration

#### Custom DynamoDB Client Configuration

```typescript
import { initializeDynamoDBClients } from '@leanstacks/lambda-utils';

initializeDynamoDBClients({
region: 'us-west-2',
endpoint: 'http://localhost:8000', // For local development
credentials: {
accessKeyId: 'local',
secretAccessKey: 'local',
},
});
````

#### Custom Marshall/Unmarshall Options

```typescript
import { initializeDynamoDBClients } from '@leanstacks/lambda-utils';

initializeDynamoDBClients(
{ region: 'us-east-1' },
{
// Marshall options
removeUndefinedValues: true,
convertEmptyValues: false,
convertClassInstanceToMap: true,
},
{
// Unmarshall options
wrapNumbers: false,
},
);
```

### Lambda Handler Pattern

```typescript
import { initializeDynamoDBClients, getDynamoDBDocumentClient } from '@leanstacks/lambda-utils';
import { GetCommand } from '@aws-sdk/lib-dynamodb';

// Initialize clients outside the handler (runs once per cold start)
initializeDynamoDBClients({ region: process.env.AWS_REGION }, { removeUndefinedValues: true });

// Handler function
export const handler = async (event: any) => {
const docClient = getDynamoDBDocumentClient();

const result = await docClient.send(
new GetCommand({
TableName: process.env.TABLE_NAME,
Key: { id: event.id },
}),
);

return result.Item;
};
```

## API Reference

### `initializeDynamoDBClients(config?, marshallOptions?, unmarshallOptions?): { client: DynamoDBClient; documentClient: DynamoDBDocumentClient }`

Initializes both the DynamoDB client and DynamoDB Document client with the provided configuration.

**Parameters:**

- `config` (optional) - DynamoDB client configuration object
- `marshallOptions` (optional) - Options for marshalling JavaScript objects to DynamoDB AttributeValues
- `unmarshallOptions` (optional) - Options for unmarshalling DynamoDB AttributeValues to JavaScript objects

**Returns:**

- An object containing both `client` (DynamoDBClient) and `documentClient` (DynamoDBDocumentClient)

**Notes:**

- Creates both clients in a single call
- If called multiple times, it will replace the existing client instances
- If no config is provided, uses default AWS SDK configuration
- Most users will only need the `documentClient` from the return value or via `getDynamoDBDocumentClient()`

### `getDynamoDBClient(): DynamoDBClient`

Returns the singleton DynamoDB client instance.

**Returns:**

- The `DynamoDBClient` instance

**Throws:**

- Error if the client has not been initialized

### `getDynamoDBDocumentClient(): DynamoDBDocumentClient`

Returns the singleton DynamoDB Document client instance.

**Returns:**

- The `DynamoDBDocumentClient` instance

**Throws:**

- Error if the document client has not been initialized

### `resetDynamoDBClients(): void`

Resets both DynamoDB client instances to null.

**Notes:**

- Primarily useful for testing scenarios where you need to reinitialize clients with different configurations
- After calling this, you must reinitialize the clients before using the getter functions

## Best Practices

1. **Initialize Outside the Handler**: Always initialize clients outside your Lambda handler function to reuse the instance across invocations.

2. **Use Environment Variables**: Configure clients using environment variables for flexibility across environments.

3. **Error Handling**: Always wrap client operations in try-catch blocks to handle errors gracefully.

4. **Testing**: Use `resetDynamoDBClients()` in test setup/teardown to ensure clean test isolation.

## Testing Example

```typescript
import { initializeDynamoDBClients, getDynamoDBDocumentClient, resetDynamoDBClients } from '@leanstacks/lambda-utils';

describe('MyLambdaHandler', () => {
beforeEach(() => {
resetDynamoDBClients();
initializeDynamoDBClients(
{ region: 'us-east-1', endpoint: 'http://localhost:8000' },
{ removeUndefinedValues: true },
);
});

afterEach(() => {
resetDynamoDBClients();
});

it('should retrieve item from DynamoDB', async () => {
// Your test code here
});
});
```

## Related Resources

- **[AWS SDK for JavaScript v3 - DynamoDB Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/)**
- **[AWS SDK for JavaScript v3 - DynamoDB Document Client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-lib-dynamodb/Class/DynamoDBDocumentClient/)**
- **[AWS Lambda Best Practices](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)**
- **[Back to the project documentation](README.md)**
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Lambda Utilities is a collection of pre-configured tools and helpers designed to

- **[Logging Guide](./LOGGING.md)** – Implement structured logging in your Lambda functions with Pino and automatic AWS context enrichment
- **[API Gateway Responses](./API_GATEWAY_RESPONSES.md)** – Format Lambda responses for API Gateway with standard HTTP status codes and headers
- **[DynamoDB Client](./DYNAMODB_CLIENT.md)** – Reusable singleton DynamoDB client instances with custom configuration
- **[Configuration](./CONFIGURATION.md)** – Validate environment variables and configuration with Zod type safety
- **[AWS Clients](./CLIENTS.md)** – Pre-configured AWS SDK v3 clients optimized for Lambda
- **[Getting Started](./GETTING_STARTED.md)** – Quick setup and installation instructions

## Features
Expand Down
Loading