Strongly typed library for querying and modeling DynamoDB documents.
npm install ddb-table
alt="Build Status">
alt="Dependency Status">
alt="Coverage Status" />
DDB-Table was built to provide strongly-typed data structures over DynamoDB tables. Using **AWS
DocumentClient & TypeScript** you can easily fetch and store any JSON document and validate itโs
structure statically. Query secondary indexes and run complicated update expressions without any
error on runtime.
``ts`
await table
.update('demo@example.com')
.set('FullName', 'John Doe')
// ๐จ TypeScript Error: 'fullName' is not assignable to 'Email' | 'FullName'
.condition((cond) => cond.eq('fullName', 'Johnny Doe'))
.exec();
- Strongly Typed - End-to-end TypeScript validation for your data.
- Easy Query Expressions - Automatically escape name attributes and values.
- Smart Projections - Make sure you only access the fields you project.
- Query & Scan Indexes - Complete support for global or local indexes.
- Pure JavaScript - Also works without TypeScript.
If you like this project, please consider sponsoring us to help us continue to maintain and improve
this project.
`bash`
npm i ddb-table
`ts
import Table from 'ddb-table';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
interface MessageSchema {
threadId: string;
timestamp: number;
senderId: string;
message: string;
status: 'sent' | 'received';
tags?: Set
attachments: {
name: string;
URL: string;
}[];
}
const client = new DynamoDBClient({
// settings...
});
// create the basic table definition
const messages = new Table
tableName: 'Messages',
primaryKey: 'threadId',
sortKey: 'timestamp',
documentClient: DynamoDBDocument.from(client);
});
const updateRes = await messages
.update('john@gmail.com', 1588191225322)
.set('message', 'Hello World!')
.add('tags', new Set(['unread', 'important']))
.set('attachments', (exp) =>
exp.listAppend([{ name: 'Test', URL: 'demo.com' }]),
)
.return('ALL_NEW')
.exec();
console.log(updateRes.Attributes);
`
#### Working with indexes as well:
`ts
// create a secondary index definition
type SenderTimestampIndex = Pick<
MessageSchema,
'threadId' | 'timestamp' | 'senderId'
>;
const outboxIndex = messages.index<
SenderTimestampIndex,
'senderId',
'timestamp'
>('senderId-timestamp-index', 'senderId', 'timestamp');
const it = outboxIndex
.query()
.keyCondition((cond) => cond.eq('senderId', 'john@gmail.com'))
.keyCondition((cond) =>
cond.between('timestamp', Date.now() - 3600e3, Date.now()),
)
.project({ threadId: 1, message: 1 })
.reverseIndex()
.entries();
for await (const item of it) {
console.log(item);
}
`
`ts
import { DynamoDBExceptionName } from 'ddb-table';
try {
await table.put(...).exec();
} catch (err) {
if ((err as DynamoDBServiceException)?.name === DynamoDBExceptionName.ConditionalCheckFailedException) {
// handle exception
}
}
``