跳转到内容

TypeScript DynamoDB

此生成器创建一个新的 TypeScript DynamoDB 项目,由 Amazon DynamoDB 支持,使用 ElectroDB 进行类型安全的实体建模。它生成应用程序代码和基础设施,用于使用 AWS CDK 或 Terraform 配置和管理 DynamoDB 表,支持单表设计,并通过 DynamoDB Local 内置本地开发功能。

运行此生成器@aws/nx-plugin:ts#dynamodb

pnpm nx g @aws/nx-plugin:ts#dynamodb
构建你的命令8

必需

生成器选项8 个选项
name必需string

要生成的 DynamoDB 项目名称

directorystring默认值: packages

存储项目的目录。

frameworkenum默认值: electrodb

用于 DynamoDB 实体的框架。

electrodb
infraenum默认值: dynamodb

为 DynamoDB 表配置的基础设施。

dynamodbnone
iacenum默认值: inherit

首选的 IaC 提供商。默认情况下,这继承自您的初始选择。

inheritcdkterraform
subDirectorystring

项目放置的子目录。默认情况下为项目名称。

tableNamestring

DynamoDB 表名称。如果未指定则自动生成。

preferInstallDependenciesboolean默认值: true

是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。

生成器在 <directory>/<name> 目录中创建以下项目结构:

  • 文件夹src
    • index.ts Project entry point and exports
    • client.ts DynamoDB client singleton and table name resolution
    • 文件夹entities
      • 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)之间共享,并生成一次到:

  • 文件夹packages/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

由于此生成器根据您选择的 iac 提供基础设施即代码,它将在 packages/common 中创建一个项目,其中包含相关的 CDK 构造或 Terraform 模块。

通用基础设施即代码项目的结构如下:

  • 文件夹packages/common/constructs
    • 文件夹src
      • 文件夹app/ Constructs for infrastructure specific to a project/generator
      • 文件夹core/ Generic constructs which are reused by constructs in app
      • index.ts Entry point exporting constructs from app
    • project.json Project build targets and configuration
  • 文件夹packages/common/constructs/src
    • 文件夹app
      • 文件夹dynamodb
        • <name>.ts 特定于您的表的基础设施
    • 文件夹core
      • dynamodb.ts 通用 DynamoDB 表构造

部署的项目配置表本身,任何连接到它的项目都可以读取和写入:

Loading the diagram…

生成器配置了一个 dev 目标,用于启动 DynamoDB Local 实例并创建表。使用项目的 dev 目标:

Terminal window
pnpm nx dev <project-name>

这会自动:

  1. 拉取 DynamoDB Local 镜像(pull-image 目标)
  2. 启动容器
  3. 使用 config.json 中定义的索引创建本地表

生成的项目使用 ElectroDB 在单个 DynamoDB 表上进行类型安全的实体建模,遵循 DynamoDB 的单表设计。在 src/entities/ 下添加或更新实体文件,使用生成的示例实体作为起点。

示例实体定义:

packages/my-table/src/entities/example.ts
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 实体文档

生成的 src/client.ts 导出两个关键实用程序:

  • getDynamoDBClient() — 返回一个缓存的单例 DynamoDBClient。当 LOCAL_DEV=true 时,连接到本地 DynamoDB Local 实例;否则使用默认凭证链创建 AWS 客户端。
  • resolveTableName() — 返回 DynamoDB 表名称。当 LOCAL_DEV=true 时,返回本地表名称常量;否则使用 RUNTIME_CONFIG_APP_ID 环境变量从 AWS AppConfig 获取名称,并将其缓存以供后续调用。

停止 dev(例如使用 Ctrl+C)会自动删除 DynamoDB Local 容器,但会保留命名卷,因此您的数据在重启后仍然存在。

GSI 在项目根目录的 config.json 中的 tableConfig.globalSecondaryIndexes 键下定义。为每个 GSI 添加一个条目,遵循 单表设计 的 GSI 键命名约定:

config.json
{
...
"tableConfig": {
"globalSecondaryIndexes": [
{
"indexName": "gsi1pk-gsi1sk-index",
"partitionKey": "gsi1pk",
"sortKey": "gsi1sk"
},
{
"indexName": "gsi2pk-gsi2sk-index",
"partitionKey": "gsi2pk",
"sortKey": "gsi2sk"
}
]
}
}

对于仅使用哈希键的 GSI,sortKey 字段是可选的。

此配置文件是所有使用者读取的单一事实来源:

  • 本地开发dev 读取 config.json 并创建或更新本地表以匹配 GSI 列表
  • CDK — 构造在合成时读取 config.json,因此 GSI 更改会在下次 cdk deploy 时反映出来
  • Terraform — 模块在计划/应用时读取 config.json

在任何 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 获取表名称。

DynamoDB 生成器根据您选择的 iac 创建 CDK 或 Terraform 基础设施。

CDK 构造在 common/constructs 中创建。使用示例:

packages/infra/src/stacks/application-stack.ts
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

表由两个独立的保护机制保护,因此单独关闭其中任何一个都无法删除您的数据:

  • deletionProtection,由 DynamoDB 强制执行。
  • RemovalPolicy.RETAIN,由 CloudFormation 强制执行,当表从堆栈中移除时会将其保留在原处。

对于预期会删除表的环境(例如短期开发或预览堆栈),可以禁用保护。

packages/infra/src/stacks/application-stack.ts
import { RemovalPolicy } from 'aws-cdk-lib';
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
deletionProtection: false,
removalPolicy: RemovalPolicy.DESTROY,
});

表默认使用按需(PAY_PER_REQUEST)计费。对于可预测的高吞吐量工作负载,可以切换到预配置容量。

packages/infra/src/stacks/application-stack.ts
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,
});

默认启用时间点恢复,允许您将表恢复到过去 35 天内的任何时间点。

packages/infra/src/stacks/application-stack.ts
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: false },
});

默认情况下,表使用客户托管的 KMS 密钥进行加密,该密钥会自动为您创建。如果您以不同方式管理加密,可以切换到 AWS 托管密钥、AWS 拥有的密钥或使用您自己的 KMS 密钥。

使用 AWS 代表您管理的共享 aws/dynamodb KMS 密钥。它在您账户的 KMS 控制台中可见并按请求计费,但您无需创建、轮换或删除密钥。

packages/infra/src/stacks/application-stack.ts
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,
});

使用完全由 AWS 拥有和管理的密钥——免费,且您的账户中完全看不到密钥。当您出于合规原因不需要客户或账户可见的密钥时,这是最简单的选项。

packages/infra/src/stacks/application-stack.ts
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
encryption: TableEncryption.DEFAULT,
});
iac = terraform

已部署的表上,在单次 terraform apply 中将 encryptionCUSTOMER_MANAGED 更改为 AWS_MANAGEDDEFAULT 会失败: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 现在只需要销毁已经未使用的密钥,没有任何东西依赖它。

提供现有的客户托管密钥,而不是为您创建一个。该密钥必须在其自己的密钥策略中已经授予 DynamoDB 服务所需的权限。

packages/infra/src/stacks/application-stack.ts
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,
});

当表创建自己的客户托管 KMS 密钥时(默认情况,且仅当您未提供自己的密钥时),该密钥默认启用自动密钥轮换。如果您的安全策略在外部管理轮换,可以禁用它。

packages/infra/src/stacks/application-stack.ts
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
enableKeyRotation: false,
});

使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目:

tRPCAmazon DynamoDB
tRPC API to TypeScript DynamoDB将 tRPC API 连接到 DynamoDB 表
SmithyAmazon DynamoDB
Smithy API to TypeScript DynamoDB将 Smithy API 连接到 DynamoDB 表
Strands AgentsTypeScriptAmazon DynamoDB
TypeScript Agent to TypeScript DynamoDB将 TypeScript Agent 连接到 DynamoDB 表
Model Context ProtocolAmazon DynamoDB
MCP Server to TypeScript DynamoDB将 TypeScript MCP Server 连接到 DynamoDB 表