TypeScript DynamoDB
此生成器创建一个由 Amazon DynamoDB 支持的新 TypeScript DynamoDB 项目,使用 ElectroDB 进行类型安全的实体建模。它生成应用程序代码和基础设施,用于使用 AWS CDK 或 Terraform 配置和管理 DynamoDB 表,支持单表设计,并通过 DynamoDB Local 内置本地开发功能。
生成 TypeScript DynamoDB 项目
Section titled “生成 TypeScript DynamoDB 项目”- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#dynamodb - 填写必需参数
- 点击
Generate
pnpm nx g @aws/nx-plugin:ts#dynamodbyarn nx g @aws/nx-plugin:ts#dynamodbnpx nx g @aws/nx-plugin:ts#dynamodbbunx nx g @aws/nx-plugin:ts#dynamodb| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| name 必需 | string | - | 要生成的 DynamoDB 项目名称 |
| directory | string | packages | 存储项目的目录。 |
| subDirectory | string | - | 项目放置的子目录。默认情况下为项目名称。 |
| framework | electrodb | electrodb | 用于 DynamoDB 实体的框架。 |
| tableName | string | - | DynamoDB 表名称。如果未指定则自动生成。 |
| infra | dynamodb | none | dynamodb | 为 DynamoDB 表配置的基础设施。 |
| iac | inherit | cdk | terraform | inherit | 首选的 IaC 提供商。默认情况下,这继承自您的初始选择。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。 |
生成器在 <directory>/<name> 目录中创建以下项目结构:
文件夹src
- index.ts 项目入口点和导出
- client.ts DynamoDB 客户端单例和表名解析
文件夹entities
- example.ts 示例 ElectroDB 实体定义
- index.ts 实体导出
- config.json 表配置,包括 GSI 定义和本地开发设置
- project.json 项目配置和构建目标
本地开发脚本在所有 DynamoDB 项目(TypeScript 和 Python)之间共享,并生成一次到:
文件夹packages/common/scripts/src/dynamodb
- create-local-table.ts 在本地 DynamoDB Local 实例中创建 DynamoDB 表
- pull-image.ts 拉取 DynamoDB Local 镜像
- start-container.ts 启动 DynamoDB Local 容器
由于该生成器会根据您选择的 iacProvider 以基础设施即代码的形式输出,它将在 packages/common 目录下创建一个包含相关 CDK 构造体或 Terraform 模块的项目。
通用的基础设施即代码项目结构如下:
文件夹packages/common/constructs
文件夹src
文件夹app/ 针对特定项目/生成器的基础设施构造体
- …
文件夹core/ 被
app目录构造体重用的通用构造体- …
- index.ts 导出
app目录构造体的入口文件
- project.json 项目构建目标与配置
文件夹packages/common/terraform
文件夹src
文件夹app/ 针对特定项目/生成器的 Terraform 模块
- …
文件夹core/ 被
app目录模块重用的通用模块- …
- project.json 项目构建目标与配置
文件夹packages/common/constructs/src
文件夹app
文件夹dynamodb
- <name>.ts 特定于您的表的基础设施
文件夹core
- dynamodb.ts 通用 DynamoDB 表构造
文件夹packages/common/terraform/src
文件夹app
文件夹dynamodb
文件夹<name>
- <name>.tf 特定于您的表的模块
文件夹core
文件夹dynamodb
- dynamodb.tf 通用 DynamoDB 模块
启动本地 DynamoDB
Section titled “启动本地 DynamoDB”生成器配置了一个 dev 目标,用于启动 DynamoDB Local 实例并创建表。使用项目的 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中定义的索引创建本地表
生成的项目使用 ElectroDB 在单个 DynamoDB 表上进行类型安全的实体建模,遵循 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 导出两个关键实用程序:
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" } ] }}对于仅使用哈希键的 GSI,sortKey 字段是可选的。
此配置文件是所有使用者读取的单一数据源:
- 本地开发 —
dev读取config.json并创建或更新本地表以匹配 GSI 列表 - CDK — 构造在合成时读取
config.json,因此 GSI 更改会在下次cdk deploy时反映出来 - Terraform — 模块在计划/应用时读取
config.json
每次部署一个 GSI
Section titled “每次部署一个 GSI”在任何 TypeScript 项目中,从您的 DynamoDB 包导入实体工厂并直接使用它们:
import { createExampleEntity } from ':my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();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命名空间下注册到运行时配置中
Terraform 模块在 common/terraform 中创建。使用示例:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}这将配置一个具有以下特性的 DynamoDB 表:
pk(分区键)和sk(排序键),均为String类型- 在
config.json中定义的全局二级索引 - 按需(
PAY_PER_REQUEST)计费 - 客户管理的 KMS 加密,并自动轮换密钥
- 启用时间点恢复
- 启用删除保护
- 表名注册到运行时配置中
授予访问权限
Section titled “授予访问权限”要允许 Lambda 函数访问 DynamoDB 表,请在您的基础设施中授予必要的权限。
在表构造上调用 grantReadWriteData。这将授予 Lambda 执行角色所需的 DynamoDB 和 KMS 权限:
import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table');
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this).build(),});
Object.entries(api.integrations).forEach(([, integration]) => { table.grantReadWriteData(integration.handler);});授予 Lambda 执行角色访问 DynamoDB 表及其 KMS 加密密钥的权限:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}
resource "aws_iam_role_policy" "dynamodb_access" { role = module.my_api.lambda_role_name
policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", ] Resource = [ module.my_table.table_arn, "${module.my_table.table_arn}/index/*", ] }, { Effect = "Allow" Action = [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ] Resource = [module.my_table.kms_key_arn] }, ] })}默认启用删除保护以防止意外删除表。
禁用删除保护
Section titled “禁用删除保护”对于预期会删除表的环境(例如短期开发或预览堆栈),可以禁用删除保护。
import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table', { deletionProtection: false,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" deletion_protection_enabled = false}表默认使用按需(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"}默认启用时间点恢复,允许您将表恢复到过去 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}加密密钥轮换
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 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目: