Skip to content

Commit

Permalink
feat: add support for v2 and v3 DocumentClient (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
sam authored Mar 4, 2022
1 parent 16cac1a commit 2ca185f
Show file tree
Hide file tree
Showing 32 changed files with 2,256 additions and 703 deletions.
4 changes: 4 additions & 0 deletions .projen/deps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .projenrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ const project = new typescript.TypeScriptProject({
deps: [
"aws-sdk",
"@aws-sdk/client-dynamodb",
"@aws-sdk/util-dynamodb",
"@aws-sdk/lib-dynamodb",
"@aws-sdk/smithy-client",
"@aws-sdk/types",
"@aws-sdk/util-dynamodb",
"@types/aws-lambda",
],
eslintOptions: {
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,58 @@ await client.send(
);
```

### Document Client

Both the AWS SDK v2 and v3 provide a javascript-friendly interface called the `DocumentClient`. Instead of using the AttributeValue format, such as `{ S: "hello" }` or `{ N: "123" }`, the `DocumentClient` enables you to use native javascript types, e.g. `"hello"` or `123`.

#### AWS SDK V2

For the SDK V2 client, cast it to `TypeSafeDynamoDBv2`.

See: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html

```ts
import { DynamoDB } from "aws-sdk";
import { TypeSafeDocumentClientV2 } from "typesafe-dynamodb/lib/document-client-v2";

const table = new DynamoDB.DocumentClient() as TypeSafeDocumentClientV2<
MyItem,
"pk",
"sk"
>;
```

#### AWS SDK V3

When defining your Command types, specify the `JsonFormat.Document` type parameter to adapt it to the `DocumentClient` interface.

See: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_lib_dynamodb.html

```ts
import { JsonFormat } from "typesafe-dynamodb";
import { TypeSafeGetItemCommand } from "typesafe-dynamodb/lib/get-item-command";

const GetItemCommand = TypeSafeGetItemCommand<
MyType,
"key",
"sort",
JsonFormat.Document // specify the format as Document.
>();
```

For the SDK V3 client, cast it to `TypeSafeDynamoDBv3`.

```ts
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";
import { TypeSafeDocumentClientV3 } from "typesafe-dynamodb/lib/document-client-v3";

const client = new DynamoDBClient({});

const docClient = DynamoDBDocumentClient.from(
client
) as TypeSafeDocumentClientV3<MyType, "key", "sort">;
```

## Features

### Type-aware Input and Output
Expand Down
9 changes: 5 additions & 4 deletions package.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/attribute-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ export type NativeBinaryAttribute =
| Uint8Array
| Uint8ClampedArray;

export type DocumentValue =
| undefined
| null
| boolean
| number
| string
| Document[]
| NativeBinaryAttribute
| {
[key: string]: DocumentValue;
};

export type ToAttributeMap<T extends object> = ToAttributeValue<T>["M"];

/**
Expand Down
137 changes: 117 additions & 20 deletions src/client-v2.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { AWSError, DynamoDB, Request } from "aws-sdk";
import { Callback } from "./callback";
import { DeleteItemInput, DeleteItemOutput } from "./delete-item";
import { JsonFormat } from "./json-format";
import { GetItemInput, GetItemOutput } from "./get-item";
import { KeyAttribute } from "./key";
import { TableKey } from "./key";
import { PutItemInput, PutItemOutput } from "./put-item";
import { QueryInput, QueryOutput } from "./query";
import { ScanInput, ScanOutput } from "./scan";
import { UpdateItemInput, UpdateItemOutput } from "./update-item";

export interface TypeSafeDynamoDBv2<
Expand All @@ -13,10 +15,15 @@ export interface TypeSafeDynamoDBv2<
RangeKey extends keyof Item | undefined = undefined
> extends Omit<
DynamoDB,
"getItem" | "deleteItem" | "putItem" | "query" | "updateItem"
"getItem" | "deleteItem" | "putItem" | "query" | "scan" | "updateItem"
> {
getItem<
Key extends KeyAttribute<Item, PartitionKey, RangeKey>,
Key extends TableKey<
Item,
PartitionKey,
RangeKey,
JsonFormat.AttributeValue
>,
AttributesToGet extends keyof Item | undefined = undefined,
ProjectionExpression extends string | undefined = undefined
>(
Expand All @@ -26,19 +33,41 @@ export interface TypeSafeDynamoDBv2<
RangeKey,
Key,
AttributesToGet,
ProjectionExpression
ProjectionExpression,
JsonFormat.AttributeValue
>,
callback?: Callback<
GetItemOutput<Item, Key, AttributesToGet, ProjectionExpression>,
GetItemOutput<
Item,
PartitionKey,
RangeKey,
Key,
AttributesToGet,
ProjectionExpression,
JsonFormat.AttributeValue
>,
AWSError
>
): Request<
GetItemOutput<Item, Key, AttributesToGet, ProjectionExpression>,
GetItemOutput<
Item,
PartitionKey,
RangeKey,
Key,
AttributesToGet,
ProjectionExpression,
JsonFormat.AttributeValue
>,
AWSError
>;

deleteItem<
Key extends KeyAttribute<Item, PartitionKey, RangeKey>,
Key extends TableKey<
Item,
PartitionKey,
RangeKey,
JsonFormat.AttributeValue
>,
ConditionExpression extends string | undefined,
ReturnValue extends DynamoDB.ReturnValue = "NONE"
>(
Expand All @@ -48,21 +77,44 @@ export interface TypeSafeDynamoDBv2<
RangeKey,
Key,
ConditionExpression,
ReturnValue
ReturnValue,
JsonFormat.AttributeValue
>,
callback?: Callback<DeleteItemOutput<Item, ReturnValue>, AWSError>
): Request<DeleteItemOutput<Item, ReturnValue>, AWSError>;
callback?: Callback<
DeleteItemOutput<Item, ReturnValue, JsonFormat.AttributeValue>,
AWSError
>
): Request<
DeleteItemOutput<Item, ReturnValue, JsonFormat.AttributeValue>,
AWSError
>;

putItem<
ConditionExpression extends string | undefined,
ReturnValue extends DynamoDB.ReturnValue = "NONE"
>(
params: PutItemInput<Item, ConditionExpression, ReturnValue>,
callback?: Callback<PutItemOutput<Item, ReturnValue>, AWSError>
): Request<PutItemOutput<Item, ReturnValue>, AWSError>;
params: PutItemInput<
Item,
ConditionExpression,
ReturnValue,
JsonFormat.AttributeValue
>,
callback?: Callback<
PutItemOutput<Item, ReturnValue, JsonFormat.AttributeValue>,
AWSError
>
): Request<
PutItemOutput<Item, ReturnValue, JsonFormat.AttributeValue>,
AWSError
>;

updateItem<
Key extends KeyAttribute<Item, PartitionKey, RangeKey>,
Key extends TableKey<
Item,
PartitionKey,
RangeKey,
JsonFormat.AttributeValue
>,
UpdateExpression extends string,
ConditionExpression extends string | undefined,
ReturnValue extends DynamoDB.ReturnValue = "NONE"
Expand All @@ -74,28 +126,73 @@ export interface TypeSafeDynamoDBv2<
Key,
UpdateExpression,
ConditionExpression,
ReturnValue
ReturnValue,
JsonFormat.AttributeValue
>,
callback?: Callback<
UpdateItemOutput<Item, PartitionKey, RangeKey, Key, ReturnValue>,
UpdateItemOutput<
Item,
PartitionKey,
RangeKey,
Key,
ReturnValue,
JsonFormat.AttributeValue
>,
AWSError
>
): Request<
UpdateItemOutput<Item, PartitionKey, RangeKey, Key, ReturnValue>,
UpdateItemOutput<
Item,
PartitionKey,
RangeKey,
Key,
ReturnValue,
JsonFormat.AttributeValue
>,
AWSError
>;

query<
KeyConditionExpression extends string | undefined = undefined,
FilterExpression extends string | undefined = undefined,
ProjectionExpression extends string | undefined = undefined,
AttributesToGet extends keyof Item | undefined = undefined
>(
params: QueryInput<
Item,
KeyConditionExpression,
FilterExpression,
AttributesToGet
ProjectionExpression,
AttributesToGet,
JsonFormat.AttributeValue
>,
callback?: Callback<QueryOutput<Item, AttributesToGet>, AWSError>
): Request<QueryOutput<Item, AttributesToGet>, AWSError>;
callback?: Callback<
QueryOutput<Item, AttributesToGet, JsonFormat.AttributeValue>,
AWSError
>
): Request<
QueryOutput<Item, AttributesToGet, JsonFormat.AttributeValue>,
AWSError
>;

scan<
FilterExpression extends string | undefined = undefined,
ProjectionExpression extends string | undefined = undefined,
AttributesToGet extends keyof Item | undefined = undefined
>(
params: ScanInput<
Item,
FilterExpression,
ProjectionExpression,
AttributesToGet,
JsonFormat.AttributeValue
>,
callback?: Callback<
ScanOutput<Item, AttributesToGet, JsonFormat.AttributeValue>,
AWSError
>
): Request<
ScanOutput<Item, AttributesToGet, JsonFormat.AttributeValue>,
AWSError
>;
}
Loading

0 comments on commit 2ca185f

Please sign in to comment.