ローカル環境でDynamoDBを操作する

AWS環境で色々試そうとするとお値段が気になる。
SDK使ってDBアクセスする場合LambdaやIAMRoleのセットアップも必要。（Lambdaは使わなくてもローカルからできますが）
**DynamoDB Local** というものあったので触ってみました！

:::note
以下の前提で話しています。
* 言語：Typescript
* Docker Desktopインストール済
:::

# DynamoDB Local のセットアップ
[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html)に DynamoDB Local のセットアップ手順があります。
いくつか手段がありますが、私は Docker を用いた手順を選択しました。

以下ymlが提供されています。
```docker-compose.yml
version: '3.8'
services:
 dynamodb-local:
   command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
   image: "amazon/dynamodb-local:latest"
   container_name: dynamodb-local
   ports:
     - "8000:8000"
   volumes:
     - "./docker/dynamodb:/home/dynamodblocal/data"
   working_dir: /home/dynamodblocal
```
これをテスト用のプロジェクトに置いて`docker-compose up -d`するだけ。
これだけで構築完了。（めちゃ簡単）

# SDK v3 を使用してローカルDBを操作する
### DynamoDB-client の設定

Dockerにて`port:8000`で立ち上げているので`endpoint: 'http://localhost:8000'`という指定が必要です。
（ローカルなら region や credentials は指定しなくても大丈夫です）
```dynamodb.ts
import { DynamoDBClient, DynamoDBClientConfig, CreateTableCommand, DeleteTableCommand, ListTablesCommand, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
import { DeleteCommand, DynamoDBDocumentClient, GetCommand, PutCommand, UpdateCommand, ScanCommand } from '@aws-sdk/lib-dynamodb';
import ItemList from './item.json';

// ローカルDBへの接続定義
const config: DynamoDBClientConfig = {
  endpoint: 'http://localhost:8000',
  region: 'ap-northeast-1',
  credentials: { accessKeyId: 'dummy', secretAccessKey: 'dummy' },
};

const ddbClient = new DynamoDBClient(config);
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient); // DynamoDBClientをより抽象化した記述が可能
```

### テーブルを作成する

```dynamodb.ts
const TABLE_NAME = 'OrderHistory';

/***************************************
  create table >> use ddbClient
***************************************/
const createTable = async () => {
  try {
    const command = new CreateTableCommand({
      TableName: TABLE_NAME,
      KeySchema: [
        { AttributeName: 'CustomerId', KeyType: 'HASH' }, // partition key
        { AttributeName: 'OrderNumber', KeyType: 'RANGE' }, // sort key
      ],
      AttributeDefinitions: [
        { AttributeName: 'CustomerId', AttributeType: 'S' }, // 属性：String
        { AttributeName: 'OrderNumber', AttributeType: 'N' }, // 属性：Number
      ],
      // capacity unit settings
      ProvisionedThroughput: {
        ReadCapacityUnits: 1,
        WriteCapacityUnits: 1,
      },
    });
    const output = await ddbClient.send(command);
    console.log('===================== createTable success =====================\n', JSON.stringify(output, null, 2));
  } catch (err) {
    console.error('===================== createTable error =====================\n', err);
  }
};

createTable();
```

### 実行結果
```shell
~/workspace/dynamodb-test (main) % npm run test                                                                                                                                              13:22:12

> dynamodb-test@1.0.0 test
> ./node_modules/.bin/ts-node ./src/dynamodb.ts

===================== createTable success =====================
 {
  "$metadata": {
    "httpStatusCode": 200,
    "requestId": "c1f648c0-f96c-46e9-87d5-ef1cb2d5939a",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "TableDescription": {
    "AttributeDefinitions": [
      {
        "AttributeName": "CustomerId",
        "AttributeType": "S"
      },
      {
        "AttributeName": "OrderNumber",
        "AttributeType": "N"
      }
    ],
    "CreationDateTime": "2023-11-02T04:22:16.331Z",
    "ItemCount": 0,
    "KeySchema": [
      {
        "AttributeName": "CustomerId",
        "KeyType": "HASH"
      },
      {
        "AttributeName": "OrderNumber",
        "KeyType": "RANGE"
      }
    ],
    "ProvisionedThroughput": {
      "LastDecreaseDateTime": "1970-01-01T00:00:00.000Z",
      "LastIncreaseDateTime": "1970-01-01T00:00:00.000Z",
      "NumberOfDecreasesToday": 0,
      "ReadCapacityUnits": 1,
      "WriteCapacityUnits": 1
    },
    "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/OrderHistory",
    "TableName": "OrderHistory",
    "TableSizeBytes": 0,
    "TableStatus": "ACTIVE"
  }
}
```

できてますね。
これで色々試せそうです。

# おまけ
https://github.com/y-h-github/dynamodb-local.git
検証環境の構築や CreateTableCommand 以外に試したものはこちらにて公開していますのでご参考になれば。

# 参考
* https://maku.blog/p/5mv5dkt/#dynamodb-%E7%94%A8%E3%81%AE-nodejs-sdk-ver3-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B
* https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html
* https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/