TypeScript DynamoDB
このジェネレーターは、Amazon DynamoDB をバックエンドとする新しい TypeScript DynamoDB プロジェクトを作成します。型安全なエンティティモデリングには ElectroDB を使用します。AWS CDK または Terraform を使用して DynamoDB テーブルをプロビジョニングおよび管理するために必要なアプリケーションコードとインフラストラクチャを生成し、シングルテーブル設計のサポートと DynamoDB Local によるローカル開発機能を備えています。
TypeScript DynamoDB プロジェクトを生成する
Section titled “TypeScript DynamoDB プロジェクトを生成する”このジェネレーターを実行@aws/nx-plugin:ts#dynamodb
pnpm nx g @aws/nx-plugin:ts#dynamodb yarn nx g @aws/nx-plugin:ts#dynamodb npx nx g @aws/nx-plugin:ts#dynamodb bunx nx g @aws/nx-plugin:ts#dynamodb- インストール Nx Console VSCode Plugin まだインストールしていない場合
- VSCodeでNxコンソールを開く
- クリック
Generate (UI)"Common Nx Commands"セクションで - 検索
@aws/nx-plugin - ts#dynamodb - 必須パラメータを入力
- クリック
Generate
コマンドを組み立てる8
必須
name必須string生成するDynamoDBプロジェクトの名前
directorystringデフォルト:packagesプロジェクトを保存するディレクトリ
frameworkenumデフォルト:electrodbDynamoDB エンティティに使用するフレームワーク。
electrodbinfraenumデフォルト:dynamodbDynamoDBテーブルのためにプロビジョニングするインフラストラクチャ。
dynamodbnoneiacenumデフォルト:inherit優先するIaCプロバイダー。デフォルトでは、初期選択から継承されます。
inheritcdkterraformsubDirectorystringプロジェクトが配置されるサブディレクトリ。デフォルトではプロジェクト名になります。
tableNamestringDynamoDB テーブル名。指定しない場合は自動生成されます。
preferInstallDependenciesbooleanデフォルト:trueジェネレーター実行後に依存関係のインストールを優先するかどうか。複数のジェネレーターをバッチ処理する際にインストールを延期する場合は false に設定します(後続のジェネレーターが Nx プロジェクトグラフを計算できるよう、必要に応じてインストールは実行されます)。最後に一度だけインストールします。
ジェネレーターの出力
Section titled “ジェネレーターの出力”ジェネレーターは <directory>/<name> ディレクトリに以下のプロジェクト構造を作成します:
Directorysrc
- index.ts Project entry point and exports
- client.ts DynamoDB client singleton and table name resolution
Directoryentities
- example.ts Example ElectroDB entity definition
- index.ts Entity exports
- config.json Table configuration including GSI definitions and local development settings
- package.json Project manifest defining the project’s package name and dependencies
- project.json Project configuration and build targets
ローカル開発スクリプトは、すべての DynamoDB プロジェクト(TypeScript と Python の両方)で共有され、以下に一度生成されます:
Directorypackages/common/scripts/src/dynamodb
- create-local-table.ts Creates the DynamoDB table in the local DynamoDB Local instance
- pull-image.ts Pulls the DynamoDB Local image
- start-container.ts Starts the DynamoDB Local container
インフラストラクチャ
Section titled “インフラストラクチャ”このジェネレーターは、選択した iac に基づいてインフラストラクチャをコードとして提供するため、関連する CDK コンストラクトまたは Terraform モジュールを含む packages/common にプロジェクトを作成します。
共通のインフラストラクチャコードプロジェクトは、次のように構成されています:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ プロジェクト/ジェネレーター固有のインフラストラクチャ用のコンストラクト
- …
Directorycore/
app内のコンストラクトによって再利用される汎用コンストラクト- …
- index.ts
appからコンストラクトをエクスポートするエントリーポイント
- project.json プロジェクトのビルドターゲットと設定
Directorypackages/common/terraform
Directorysrc
Directoryapp/ プロジェクト/ジェネレーター固有のインフラストラクチャ用の Terraform モジュール
- …
Directorycore/
app内のモジュールによって再利用される汎用モジュール- …
- project.json プロジェクトのビルドターゲットと設定
Directorypackages/common/constructs/src
Directoryapp
Directorydynamodb
- <name>.ts テーブル固有のインフラストラクチャ
Directorycore
- dynamodb.ts 汎用 DynamoDB テーブルコンストラクト
Directorypackages/common/terraform/src
Directoryapp
Directorydynamodb
Directory<name>
- <name>.tf テーブル固有のモジュール
Directorycore
Directorydynamodb
- dynamodb.tf 汎用 DynamoDB モジュール
アーキテクチャ
Section titled “アーキテクチャ”デプロイされたプロジェクトはテーブル自体をプロビジョニングし、接続されたすべてのプロジェクトがそれを読み書きします:
ローカル開発
Section titled “ローカル開発”ローカル DynamoDB の起動
Section titled “ローカル DynamoDB の起動”ジェネレーターは、DynamoDB Local インスタンスを起動してテーブルを作成する dev ターゲットを設定します。プロジェクトの dev ターゲットを使用してください:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>これにより自動的に以下が実行されます:
- DynamoDB Local イメージをプル(
pull-imageターゲット) - コンテナを起動
config.jsonで定義されたインデックスを持つローカルテーブルを作成
データモデリング
Section titled “データモデリング”生成されたプロジェクトは、単一の DynamoDB テーブル上で型安全なエンティティモデリングを行うために ElectroDB を使用し、DynamoDB のシングルテーブル設計に従います。生成されたサンプルエンティティを出発点として、src/entities/ 配下にエンティティファイルを追加または更新してください。
エンティティ定義の例:
import { Entity } from 'electrodb';import { getDynamoDBClient, resolveTableName } from '../client.js';
export const createExampleEntity = async () => new Entity( { model: { entity: 'example', version: '1', service: 'MyTable', }, attributes: { id: { type: 'string', required: true, }, createdAt: { type: 'string', required: true, default: () => new Date().toISOString(), readOnly: true, }, updatedAt: { type: 'string', required: true, default: () => new Date().toISOString(), watch: '*', set: () => new Date().toISOString(), }, }, indexes: { primary: { pk: { field: 'pk', composite: ['id'], }, sk: { field: 'sk', composite: [], }, }, }, }, { client: getDynamoDBClient(), table: await resolveTableName() }, );詳細については、ElectroDB エンティティドキュメントを参照してください。
DynamoDB クライアントの使用
Section titled “DynamoDB クライアントの使用”生成された src/client.ts は、2つの主要なユーティリティをエクスポートします:
getDynamoDBClient()— キャッシュされたシングルトンのDynamoDBClientを返します。LOCAL_DEV=trueの場合、ローカルの DynamoDB Local インスタンスに接続します。それ以外の場合は、デフォルトの認証情報チェーンを使用して AWS クライアントを作成します。resolveTableName()— DynamoDB テーブル名を返します。LOCAL_DEV=trueの場合、ローカルテーブル名定数を返します。それ以外の場合は、RUNTIME_CONFIG_APP_ID環境変数を使用して AWS AppConfig から名前を取得し、後続の呼び出しのためにキャッシュします。
ローカル DynamoDB の停止
Section titled “ローカル DynamoDB の停止”dev を停止する(例:Ctrl+C で)と、DynamoDB Local コンテナは自動的に削除されますが、名前付きボリュームは保持されるため、データは再起動後も保持されます。
グローバルセカンダリインデックスの追加/削除
Section titled “グローバルセカンダリインデックスの追加/削除”GSI は、プロジェクトルートの config.json の tableConfig.globalSecondaryIndexes キーで定義されます。GSI キーのシングルテーブル設計命名規則に従って、各 GSI のエントリを追加してください:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}sortKeyフィールドは、ハッシュキーのみのGSIの場合はオプションです。
この設定ファイルは、すべての利用者が読み取る唯一の信頼できる情報源です:
- ローカル開発 —
devはconfig.jsonを読み取り、GSIリストに一致するようにローカルテーブルを作成または更新します - CDK — コンストラクトは合成時に
config.jsonを読み取るため、GSIの変更は次回のcdk deployに反映されます - Terraform — モジュールはplan/apply時に
config.jsonを読み取ります
デプロイごとに1つのGSI
Section titled “デプロイごとに1つのGSI”テーブルへの接続
Section titled “テーブルへの接続”任意の TypeScript プロジェクトで、DynamoDB パッケージからエンティティファクトリをインポートして直接使用します:
import { createExampleEntity } from '@my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();内部的には、createExampleEntity() は resolveTableName() を呼び出して、実行時に AWS AppConfig からテーブル名を取得します。
テーブルのデプロイ
Section titled “テーブルのデプロイ”DynamoDB ジェネレーターは、選択した iac に基づいて CDK または Terraform インフラストラクチャを作成します。
CDK コンストラクトは common/constructs に作成されます。使用例:
import { MyTable } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
const table = new MyTable(this, 'Table'); }}これにより、以下の設定で DynamoDB テーブルがプロビジョニングされます:
pk(パーティションキー)とsk(ソートキー)、両方ともString型config.jsonで定義されたグローバルセカンダリインデックス- オンデマンド(
PAY_PER_REQUEST)課金 - 自動キーローテーション付きのカスタマー管理 KMS 暗号化
- ポイントインタイムリカバリが有効
- 削除保護が有効
- AWS AppConfig の
dynamodb名前空間下の Runtime Config にテーブル名が登録される
Terraform モジュールは common/terraform に作成されます。使用例:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}これにより、以下の設定で DynamoDB テーブルがプロビジョニングされます:
pk(パーティションキー)とsk(ソートキー)、両方ともString型config.jsonで定義されたグローバルセカンダリインデックス- オンデマンド(
PAY_PER_REQUEST)課金 - 自動キーローテーション付きのカスタマー管理 KMS 暗号化
- ポイントインタイムリカバリが有効
- 削除保護が有効、さらに
prevent_destroyライフサイクルガード - AWS AppConfig の
dynamodb名前空間下の Runtime Config にテーブル名が登録される
core/runtime-config/appconfig モジュールはデフォルトで dynamodb 名前空間を公開するため、テーブル名は追加の設定なしでデプロイされます。そのモジュールに明示的に namespaces を渡す場合は、リストに dynamodb を含めてください。そうしないと、設定プロファイルが作成されず、生成されたテーブルクライアントがテーブル名を解決できなくなります。
テーブルは 2 つの独立したガードによって保護されているため、どちらか一方だけをオフにしてもデータを削除することはできません:
deletionProtection、DynamoDB によって強制されます。RemovalPolicy.RETAIN、CloudFormation によって強制され、スタックから削除されてもテーブルをそのまま残します。
deletion_protection_enabled、DynamoDB によって強制されます。common/terraform/src/core/dynamodb/dynamodb.tfのテーブルに対するlifecycle { prevent_destroy = true }、Terraform によって強制され、テーブルを破棄するプランは失敗します。
テーブルの削除
Section titled “テーブルの削除”短期間の開発環境やプレビュースタックなど、テーブルの削除が想定される環境では保護を無効にします。
import { RemovalPolicy } from 'aws-cdk-lib';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" deletion_protection_enabled = false}prevent_destroy はリテラルでなければなりません — Terraform は変数を参照することを許可していません — そのため、main.tf からオフにすることはできません。また、common/terraform/src/core/dynamodb/dynamodb.tf のテーブルから lifecycle ブロックを削除してください:
resource "aws_dynamodb_table" "table" { # ...
lifecycle { prevent_destroy = true }}テーブルはデフォルトでオンデマンド(PAY_PER_REQUEST)課金です。予測可能で高スループットのワークロードの場合は、プロビジョニングされたキャパシティに切り替えます。
import { BillingMode } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { billingMode: BillingMode.PROVISIONED, readCapacity: 5, writeCapacity: 5,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" billing_mode = "PROVISIONED"}ポイントインタイムリカバリ
Section titled “ポイントインタイムリカバリ”ポイントインタイムリカバリはデフォルトで有効になっており、過去 35 日間の任意の時点にテーブルを復元できます。
ポイントインタイムリカバリを無効にする
Section titled “ポイントインタイムリカバリを無効にする”import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: false },});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" point_in_time_recovery_enabled = false}テーブルはデフォルトでカスタマー管理 KMS キーで暗号化され、自動的に作成されます。暗号化を異なる方法で管理する場合は、AWS 管理キー、AWS 所有キー、または独自の KMS キーに切り替えます。
AWS 管理キーを使用する
Section titled “AWS 管理キーを使用する”AWS があなたに代わって管理する共有 aws/dynamodb KMS キーを使用します。アカウントの KMS コンソールに表示され、リクエストごとに課金されますが、作成、ローテーション、削除するキーはありません。
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { encryption: TableEncryption.AWS_MANAGED,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" encryption = "AWS_MANAGED"}AWS 所有キーを使用する
Section titled “AWS 所有キーを使用する”AWS が完全に所有および管理するキーを使用します — 無料で、アカウントにキーが表示されることはありません。コンプライアンス上の理由でカスタマーまたはアカウントに表示されるキーが不要な場合の最もシンプルなオプションです。
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { encryption: TableEncryption.DEFAULT,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" encryption = "DEFAULT"}CUSTOMER_MANAGED からの切り替え
Section titled “CUSTOMER_MANAGED からの切り替え”すでにデプロイされているテーブルで、encryption を CUSTOMER_MANAGED から(AWS_MANAGED または DEFAULT のいずれかに)単一の terraform apply で変更すると失敗します:Terraform はテーブルを更新する前にカスタマー管理キーを破棄し、DynamoDB はキーがすでに削除保留中であるため更新を拒否します。
回避策として、まず AWS CLI を介してテーブルの暗号化を直接更新し、その後 Terraform に追いつかせて孤立したキーをクリーンアップします:
# For AWS_MANAGED:aws dynamodb update-table --table-name <table-name> \ --sse-specification Enabled=true,SSEType=KMS,KMSMasterKeyId=alias/aws/dynamodb
# For DEFAULT:aws dynamodb update-table --table-name <table-name> --sse-specification Enabled=false
# Then wait for this to report ENABLED (or for SSEDescription to disappear, for DEFAULT):aws dynamodb describe-table --table-name <table-name> --query Table.SSEDescription.Status次に、Terraform 設定で encryption を更新し、通常通り terraform apply を実行します — Terraform は、何も依存していない、すでに使用されていないキーを破棄するだけで済みます。
独自の KMS キーを使用する
Section titled “独自の KMS キーを使用する”自動作成されるキーの代わりに、既存のカスタマー管理キーを提供します。キーは、独自のキーポリシーで DynamoDB サービスに必要な権限をすでに付与している必要があります。
import { Key } from 'aws-cdk-lib/aws-kms';import { MyTable } from '@my-scope/common-constructs';
const key = Key.fromKeyArn(this, 'Key', 'arn:aws:kms:us-east-1:111111111111:key/my-key-id');
const table = new MyTable(this, 'Table', { encryptionKey: key,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" kms_key_arn = "arn:aws:kms:us-east-1:111111111111:key/my-key-id"}暗号化キーのローテーション
Section titled “暗号化キーのローテーション”テーブルが独自のカスタマー管理 KMS キーを作成する場合(デフォルトで、独自のキーを提供していない場合のみ)、そのキーは自動キーローテーションがデフォルトで有効になっています。セキュリティポリシーで外部的にローテーションを管理する場合は無効にします。
暗号化キーのローテーションを無効にする
Section titled “暗号化キーのローテーションを無効にする”import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', { enableKeyRotation: false,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" enable_key_rotation = false}connection ジェネレーターを使用して、このプロジェクトをワークスペース内の他のプロジェクトと統合します。このプロジェクトに関連する接続は以下の通りです: