dynamo_table 0.2.0

A high-level DynamoDB table abstraction with get_item, query, update, filter, batch operations, pagination, and type-safe queries
Documentation
# Contributing to dynamo_table

Thank you for your interest in contributing to `dynamo_table`! This document provides guidelines and instructions for contributing.

## Getting Started

1. **Fork the repository** (once it's published on GitHub)
2. **Clone your fork**
3. **Create a feature branch**: `git checkout -b feature/my-feature`
4. **Make your changes**
5. **Run tests**: `cargo test`
6. **Run linter**: `cargo clippy`
7. **Format code**: `cargo fmt`
8. **Commit your changes**
9. **Push to your fork**
10. **Create a Pull Request**

## Development Setup

### Prerequisites

- Rust 1.75+ (uses `impl Trait` in trait methods)
- AWS SDK dependencies
- Tokio runtime

### Building

```bash
cargo build
```

### Testing

```bash
# Run all tests
cargo test

# Run with output
cargo test -- --nocapture

# Run specific test
cargo test test_name
```

### Linting

```bash
# Check for common mistakes
cargo clippy

# Apply automatic fixes
cargo clippy --fix
```

### Documentation

```bash
# Build and open documentation
cargo doc --open

# Check documentation
cargo doc --no-deps
```

## Priority Contributions

The project would especially benefit from:

### 1. API Refactoring (HIGH PRIORITY)

The most impactful contribution would be implementing the client parameter pattern. See `REFACTORING_GUIDE.md` for detailed instructions.

**Skills needed**: Rust, AWS SDK, async programming

**Estimated effort**: 15-20 hours

**Impact**: Makes the crate publishable

### 2. Testing

Add comprehensive tests:

- Unit tests with mocked DynamoDB client
- Integration tests (optional, requires localstack)
- Property-based tests for serialization/deserialization
- Edge case testing

**Skills needed**: Rust testing, mockall or similar mocking framework

### 3. Documentation

Improve documentation:

- Add more usage examples
- Document error handling patterns
- Add troubleshooting guide
- Create migration guide from other DynamoDB libraries

**Skills needed**: Technical writing, Rust

### 4. Features

Potential new features:

- TransactGetItems/TransactWriteItems support
- PartiQL query support
- Time To Live (TTL) support
- DynamoDB Streams integration
- Caching layer
- Metrics/observability integration

**Skills needed**: Varies by feature

## Code Style

### Formatting

- Use `rustfmt` with default settings
- Maximum line length: 100 characters
- Use 4 spaces for indentation

### Naming

- Use descriptive variable names
- Follow Rust naming conventions (snake_case for functions/variables, PascalCase for types)
- Prefix internal functions with `_` if not part of public API

### Documentation

- All public items must have doc comments
- Use `///` for outer doc comments
- Use `//!` for module-level documentation
- Include examples in doc comments where helpful
- Link to related items with `[OtherType]`

Example:
```rust
/// Retrieves an item from the DynamoDB table.
///
/// This method queries the table using the partition key and optional sort key,
/// returning `None` if the item doesn't exist.
///
/// # Arguments
///
/// * `client` - AWS DynamoDB client instance
/// * `partition_key` - The partition key value
/// * `sort_key` - Optional sort key value
///
/// # Errors
///
/// Returns [`Error::DynamoGetError`] if the DynamoDB operation fails.
///
/// # Example
///
/// ```no_run
/// # use dynamo_table::{DynamoTable, Error};
/// # use aws_sdk_dynamodb::Client;
/// # async fn example(client: &Client) -> Result<(), Error> {
/// # struct User { id: String }
/// # impl DynamoTable for User {
/// #     type PK = String;
/// #     type SK = ();
/// #     const TABLE: &'static str = "users";
/// #     const PARTITION_KEY: &'static str = "id";
/// #     fn primary_key(&self) -> Self::PK { self.id.clone() }
/// #     fn sort_key(&self) -> Self::SK { () }
/// # }
/// let user = User::get_item(&client, &"user123".to_string(), None).await?;
/// # Ok(())
/// # }
/// ```
pub async fn get_item(/* ... */) -> Result<Option<Self>, Error> {
    // Implementation
}
```

### Error Handling

- Use `Result<T, Error>` for all fallible operations
- Provide context in error messages
- Use `?` operator for error propagation
- Add error helper methods when appropriate (e.g., `is_not_found()`)

### Testing

- Write tests for all public functions
- Use descriptive test names: `test_get_item_returns_none_when_not_found`
- Group related tests in modules
- Use `#[tokio::test]` for async tests

Example:
```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_add_item_succeeds() {
        let client = mock_client();
        let item = TestItem::new();

        let result = item.add_item(&client).await;

        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_get_item_returns_none_when_missing() {
        let client = mock_client_empty();

        let result = TestItem::get_item(&client, &"missing", None).await;

        assert!(result.unwrap().is_none());
    }
}
```

## Pull Request Process

1. **Update documentation**: Ensure README, CHANGELOG, and code docs are updated
2. **Add tests**: New features should include tests
3. **Update CHANGELOG.md**: Add entry under "Unreleased"
4. **Ensure CI passes**: All checks must pass (once CI is set up)
5. **Request review**: Tag maintainers for review
6. **Address feedback**: Respond to review comments
7. **Squash commits** (optional): Clean up commit history before merge

### PR Title Format

Use conventional commit format:

- `feat: add TransactWriteItems support`
- `fix: correct pagination cursor encoding`
- `docs: improve error handling examples`
- `refactor: extract retry logic to module`
- `test: add integration tests for batch operations`
- `chore: update dependencies`

### PR Description Template

```markdown
## Description
Brief description of changes

## Motivation
Why is this change needed?

## Changes
- Change 1
- Change 2

## Testing
How was this tested?

## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] CHANGELOG.md updated
- [ ] Code formatted with rustfmt
- [ ] Clippy passes
- [ ] Builds successfully
```

## Release Process

(For maintainers)

1. Update version in `Cargo.toml`
2. Update `CHANGELOG.md` (move Unreleased to version number)
3. Commit: `git commit -m "chore: release v0.x.0"`
4. Tag: `git tag -a v0.x.0 -m "Release v0.x.0"`
5. Push: `git push && git push --tags`
6. Publish: `cargo publish`
7. Create GitHub release with changelog

## Code of Conduct

### Our Pledge

We are committed to providing a friendly, safe, and welcoming environment for all contributors.

### Our Standards

- Be respectful and inclusive
- Welcome newcomers and help them learn
- Focus on what is best for the community
- Show empathy towards other community members
- Accept constructive criticism gracefully

### Unacceptable Behavior

- Harassment, trolling, or discriminatory behavior
- Personal attacks
- Publishing others' private information
- Other conduct which could reasonably be considered inappropriate

## Questions?

Feel free to:

- Open an issue for bugs or feature requests
- Start a discussion for questions
- Reach out to maintainers directly

## License

By contributing, you agree that your contributions will be licensed under both MIT and Apache-2.0 licenses.