npm package: @fnd-platform/dynamodb
Description: Type-safe DynamoDB client wrapper with single-table design utilities for fnd-platform
Latest version: 1.0.0-alpha.5

# @fnd-platform/dynamodb

Type-safe DynamoDB client wrapper with single-table design utilities, entity definitions, and key builders for fnd-platform applications.

## Installation

```bash
npm install @fnd-platform/dynamodb
# or
pnpm add @fnd-platform/dynamodb
```

## Quick Start

```typescript
import { FndDynamoDB, EntityRepository, UserEntity, keys } from '@fnd-platform/dynamodb';

// Create client
const db = new FndDynamoDB({ tableName: 'my-table' });

// Create repository for User entity
const userRepo = new EntityRepository(db, UserEntity);

// Create a user
const user = await userRepo.create({
  email: 'john@example.com',
  name: 'John Doe',
  role: 'admin',
});

// Query using key builders
const profile = await db.get({
  pk: keys.user.pk(user.id),
  sk: keys.user.sk.profile(),
});
```

## Features

- **Type-Safe Client** - Full TypeScript support with automatic type inference
- **Entity System** - Define entities with automatic key generation and timestamps
- **Key Builders** - Type-safe key generation for single-table design
- **Query Helpers** - Pre-built query patterns for common access patterns
- **Expression Builders** - Utilities for update and condition expressions

## Configuration

```typescript
import { FndDynamoDB } from '@fnd-platform/dynamodb';

const db = new FndDynamoDB({
  tableName: process.env.TABLE_NAME!,
  // Optional: custom DynamoDB client options
});
```

## Entity System

### Defining Entities

```typescript
import { defineEntity } from '@fnd-platform/dynamodb';

const ProductEntity = defineEntity({
  name: 'Product',
  keyConfig: {
    pk: (ctx) => `PRODUCT#${ctx.id}`,
    sk: () => 'METADATA',
  },
  gsiConfig: {
    GSI1: {
      pk: (ctx) => `CATEGORY#${ctx.category}`,
      sk: (ctx) => `PRODUCT#${ctx.id}`,
    },
  },
  attributes: {
    name: { type: 'string', required: true },
    price: { type: 'number', required: true },
    category: { type: 'string', required: true },
    description: { type: 'string' },
  },
});
```

### Using Entity Repository

```typescript
import { EntityRepository } from '@fnd-platform/dynamodb';

const productRepo = new EntityRepository(db, ProductEntity);

// Create
const product = await productRepo.create({
  name: 'Widget',
  price: 29.99,
  category: 'gadgets',
});

// Get by ID
const found = await productRepo.get(product.id);

// Update
const updated = await productRepo.update(product.id, {
  price: 24.99,
});

// Delete
await productRepo.delete(product.id);

// Query
const products = await productRepo.query({
  indexName: 'GSI1',
  pk: `CATEGORY#gadgets`,
});
```

## Pre-defined Entities

### UserEntity

```typescript
import { UserEntity, type User, type UserRole } from '@fnd-platform/dynamodb';

// UserRole: 'admin' | 'editor' | 'viewer'
const userRepo = new EntityRepository(db, UserEntity);
```

### ContentEntity

```typescript
import { ContentEntity, type Content, type ContentStatus } from '@fnd-platform/dynamodb';

// ContentStatus: 'draft' | 'published' | 'archived'
const contentRepo = new EntityRepository(db, ContentEntity);
```

### MediaEntity

```typescript
import { MediaEntity, type Media } from '@fnd-platform/dynamodb';

const mediaRepo = new EntityRepository(db, MediaEntity);
```

## Key Builders

```typescript
import { keys } from '@fnd-platform/dynamodb';

// User keys
keys.user.pk('user-123'); // 'USER#user-123'
keys.user.sk.profile(); // 'PROFILE'
keys.user.sk.post('post-456'); // 'POST#post-456'

// Content keys
keys.content.pk('content-123'); // 'CONTENT#content-123'
keys.content.sk.draft(); // 'v#draft'
keys.content.sk.published(); // 'v#published'
keys.content.gsi1.bySlug('my-post'); // { GSI1PK: 'CONTENT#SLUG#my-post', GSI1SK: 'CONTENT' }

// Media keys
keys.media.pk('media-123'); // 'MEDIA#media-123'
```

## Query Helpers

```typescript
import { ContentQueries, UserQueries, MediaQueries } from '@fnd-platform/dynamodb';

// Content queries
const contentQueries = new ContentQueries(db);
const post = await contentQueries.getBySlug('my-post');
const published = await contentQueries.listPublished({ limit: 10 });
const byType = await contentQueries.listByType('blog-post', { status: 'published' });

// User queries
const userQueries = new UserQueries(db);
const admins = await userQueries.listByRole('admin');

// Media queries
const mediaQueries = new MediaQueries(db);
const images = await mediaQueries.listByContentType('image/*');
```

## Query Builder

```typescript
import { createQueryBuilder } from '@fnd-platform/dynamodb';

const results = await createQueryBuilder(db)
  .index('GSI1')
  .pk('CATEGORY#gadgets')
  .skBeginsWith('PRODUCT#')
  .filter('price', '<', 50)
  .limit(20)
  .execute();
```

## API Reference

See the [full API documentation](../../docs/api/modules/dynamodb_src.html) for detailed type definitions and examples.

### Client

- `FndDynamoDB` - Main DynamoDB client class
- `FndDynamoDBConfig` - Client configuration type

### Entity System

```typescript
import {
  defineEntity, // Define a new entity
  EntityRepository, // CRUD operations for entities
  // Validation utilities
  validateBaseEntity,
  validateKeys,
  isValidTimestamp,
  isEntity,
} from '@fnd-platform/dynamodb';
```

### Pre-defined Entities

```typescript
import { UserEntity, ContentEntity, MediaEntity } from '@fnd-platform/dynamodb';
```

### Key Builders

```typescript
import { keys } from '@fnd-platform/dynamodb';
```

### Query Helpers

```typescript
import { ContentQueries, UserQueries, MediaQueries } from '@fnd-platform/dynamodb';
```

### Expression Utilities

```typescript
import {
  buildUpdateExpression,
  buildKeyConditionExpression,
  mergeExpressionValues,
} from '@fnd-platform/dynamodb';
```

### Types

```typescript
import type {
  // Entity types
  BaseEntity,
  EntityDefinition,
  EntityType,
  EntityInput,
  DefinedEntity,
  KeyFunctionContext,
  KeyConfig,
  GSIKeyConfig,
  GSIConfig,
  // Operation types
  GetParams,
  PutParams,
  UpdateParams,
  DeleteParams,
  QueryParams,
  QueryResult,
  BatchKey,
  BatchGetParams,
  BatchPutRequest,
  BatchDeleteRequest,
  BatchWriteParams,
  // Pre-defined entity types
  User,
  UserAttributes,
  UserRole,
  Content,
  ContentAttributes,
  ContentStatus,
  Media,
  MediaAttributes,
  // Key types
  Keys,
  UserKeys,
  ContentKeys,
  MediaKeys,
  TagKeys,
  GSI1KeyResult,
  GSI2KeyResult,
  // Query types
  ContentListOptions,
  UserListOptions,
  MediaListOptions,
  EntityQueryOptions,
  // Expression types
  UpdateExpressionResult,
  KeyConditionResult,
  KeyConditionParams,
  // Validation types
  ValidationResult,
  ValidationError,
} from '@fnd-platform/dynamodb';
```

## Requirements

- Node.js 20+
- AWS SDK v3 (peer dependency)

## Related

- [@fnd-platform/api](../api/README.md) - API handlers using DynamoDB
- [@fnd-platform/constructs](../constructs/README.md) - DynamoDB table CDK construct
- [Single-Table Design Patterns](../../docs/patterns/single-table-design.md)

## License

MIT