TypeScript DynamoDB
Generator này tạo một dự án TypeScript DynamoDB mới được hỗ trợ bởi Amazon DynamoDB, sử dụng ElectroDB để mô hình hóa thực thể an toàn kiểu. Nó tạo ra mã ứng dụng và cơ sở hạ tầng cần thiết để cung cấp và quản lý bảng DynamoDB bằng AWS CDK hoặc Terraform, với hỗ trợ thiết kế bảng đơn và phát triển cục bộ tích hợp sẵn thông qua DynamoDB Local.
Cách sử dụng
Phần tiêu đề “Cách sử dụng”Tạo một Dự án TypeScript DynamoDB
Phần tiêu đề “Tạo một Dự án TypeScript DynamoDB”Chạy generator này@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- Cài đặt Nx Console VSCode Plugin nếu bạn chưa cài đặt
- Mở Nx Console trong VSCode
- Nhấp
Generate (UI)trong phần "Common Nx Commands" - Tìm kiếm
@aws/nx-plugin - ts#dynamodb - Điền các tham số bắt buộc
- Nhấp
Generate
Xây dựng lệnh của bạn8
Bắt buộc
Tùy chọn
Phần tiêu đề “Tùy chọn”nameBắt buộcstringTên của dự án DynamoDB cần tạo
directorystringMặc định:packagesThư mục để lưu trữ dự án.
frameworkenumMặc định:electrodbFramework sử dụng cho các entity DynamoDB.
electrodbinfraenumMặc định:dynamodbCơ sở hạ tầng để cung cấp cho bảng DynamoDB.
dynamodbnoneiacenumMặc định:inheritNhà cung cấp IaC ưa thích. Mặc định giá trị này được kế thừa từ lựa chọn ban đầu của bạn.
inheritcdkterraformsubDirectorystringThư mục con mà dự án được đặt trong đó. Mặc định là tên dự án.
tableNamestringTên bảng DynamoDB. Tự động tạo nếu không chỉ định.
preferInstallDependenciesbooleanMặc định:trueCó nên cài đặt các dependencies sau khi generator chạy hay không. Đặt thành false để hoãn việc cài đặt khi chạy nhiều generator liên tiếp (việc cài đặt vẫn sẽ chạy nếu cần thiết để các generator tiếp theo có thể tính toán Nx project graph); cài đặt một lần vào cuối.
Đầu ra của Generator
Phần tiêu đề “Đầu ra của Generator”Generator tạo cấu trúc dự án sau trong thư mục <directory>/<name>:
Thư mụcsrc
- index.ts Project entry point and exports
- client.ts DynamoDB client singleton and table name resolution
Thư mụcentities
- 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
Các script phát triển cục bộ được chia sẻ trên tất cả các dự án DynamoDB (cả TypeScript và Python) và được tạo một lần vào:
Thư mụcpackages/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
Cơ sở hạ tầng
Phần tiêu đề “Cơ sở hạ tầng”Vì generator này cung cấp infrastructure as code dựa trên iac bạn đã chọn, nó sẽ tạo một dự án trong packages/common bao gồm các CDK constructs hoặc Terraform modules liên quan.
Dự án infrastructure as code chung được cấu trúc như sau:
Thư mụcpackages/common/constructs
Thư mụcsrc
Thư mụcapp/ Constructs for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Thư mụcpackages/common/terraform
Thư mụcsrc
Thư mụcapp/ Terraform modules for infrastructure specific to a project/generator
- …
Thư mụccore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Thư mụcpackages/common/constructs/src
Thư mụcapp
Thư mụcdynamodb
- <name>.ts Cơ sở hạ tầng cụ thể cho bảng của bạn
Thư mụccore
- dynamodb.ts Construct bảng DynamoDB chung
Thư mụcpackages/common/terraform/src
Thư mụcapp
Thư mụcdynamodb
Thư mục<name>
- <name>.tf Module cụ thể cho bảng của bạn
Thư mụccore
Thư mụcdynamodb
- dynamodb.tf Module DynamoDB chung
Kiến trúc
Phần tiêu đề “Kiến trúc”Dự án được triển khai cung cấp chính bảng đó, mà bất kỳ dự án nào được kết nối với nó đều đọc và ghi:
Phát triển Cục bộ
Phần tiêu đề “Phát triển Cục bộ”Khởi động DynamoDB Cục bộ
Phần tiêu đề “Khởi động DynamoDB Cục bộ”Generator cấu hình một target dev để khởi động một instance DynamoDB Local và tạo bảng. Sử dụng target dev của dự án:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>Điều này tự động:
- Kéo image DynamoDB Local (target
pull-image) - Khởi động một container
- Tạo một bảng local với các index được định nghĩa trong
config.json
Mô hình hóa Dữ liệu
Phần tiêu đề “Mô hình hóa Dữ liệu”Dự án được tạo sử dụng ElectroDB để mô hình hóa thực thể an toàn kiểu trên một bảng DynamoDB đơn, tuân theo thiết kế bảng đơn của DynamoDB. Thêm hoặc cập nhật các tệp thực thể trong src/entities/, sử dụng thực thể ví dụ được tạo làm điểm khởi đầu.
Định nghĩa thực thể ví dụ:
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() }, );Để biết thêm chi tiết, xem tài liệu thực thể ElectroDB.
Sử dụng DynamoDB Client
Phần tiêu đề “Sử dụng DynamoDB Client”src/client.ts được tạo xuất hai tiện ích chính:
getDynamoDBClient()— trả về mộtDynamoDBClientsingleton được lưu trong bộ nhớ cache. KhiLOCAL_DEV=true, kết nối đến phiên bản DynamoDB Local cục bộ; nếu không tạo một AWS client sử dụng chuỗi thông tin xác thực mặc định.resolveTableName()— trả về tên bảng DynamoDB. KhiLOCAL_DEV=true, trả về hằng số tên bảng cục bộ; nếu không lấy tên từ AWS AppConfig sử dụng biến môi trườngRUNTIME_CONFIG_APP_IDvà lưu vào bộ nhớ cache cho các lần gọi tiếp theo.
Dừng DynamoDB Cục bộ
Phần tiêu đề “Dừng DynamoDB Cục bộ”Việc dừng dev (ví dụ: bằng Ctrl+C) sẽ tự động xóa container DynamoDB Local, nhưng vẫn giữ lại named volume để dữ liệu của bạn được bảo toàn qua các lần khởi động lại.
Thêm/Xóa Global Secondary Indexes
Phần tiêu đề “Thêm/Xóa Global Secondary Indexes”GSI được định nghĩa trong config.json ở thư mục gốc dự án dưới khóa tableConfig.globalSecondaryIndexes. Thêm một mục cho mỗi GSI, tuân theo quy ước đặt tên khóa GSI thiết kế bảng đơn:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}Trường sortKey là tùy chọn cho các GSI chỉ có hash-key.
File cấu hình này là nguồn sự thật duy nhất được đọc bởi tất cả các consumer:
- Phát triển cục bộ —
devđọcconfig.jsonvà tạo hoặc cập nhật bảng cục bộ để khớp với danh sách GSI - CDK — construct đọc
config.jsontại thời điểm synth, do đó các thay đổi GSI được phản ánh trong lầncdk deploytiếp theo - Terraform — module đọc
config.jsontại thời điểm plan/apply
Một GSI mỗi Triển khai
Phần tiêu đề “Một GSI mỗi Triển khai”Kết nối đến Bảng
Phần tiêu đề “Kết nối đến Bảng”Trong bất kỳ dự án TypeScript nào, import các factory thực thể từ gói DynamoDB của bạn và sử dụng chúng trực tiếp:
import { createExampleEntity } from '@my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();Ở hậu trường, createExampleEntity() gọi resolveTableName() để lấy tên bảng từ AWS AppConfig tại thời điểm chạy.
Triển khai Bảng của bạn
Phần tiêu đề “Triển khai Bảng của bạn”Generator DynamoDB tạo cơ sở hạ tầng CDK hoặc Terraform dựa trên iac bạn đã chọn.
Construct CDK được tạo trong common/constructs. Ví dụ sử dụng:
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'); }}Điều này cung cấp một bảng DynamoDB với:
pk(partition key) vàsk(sort key), cả hai đều là kiểuString- Global Secondary Indexes như được định nghĩa trong
config.json - Thanh toán theo yêu cầu (
PAY_PER_REQUEST) - Mã hóa KMS do khách hàng quản lý với tự động xoay vòng khóa
- Khôi phục theo thời điểm được bật
- Bảo vệ xóa được bật
- Tên bảng được đăng ký trong Runtime Config dưới namespace
dynamodbtrong AWS AppConfig
Module Terraform được tạo trong common/terraform. Ví dụ sử dụng:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}Điều này cung cấp một bảng DynamoDB với:
pk(partition key) vàsk(sort key), cả hai đều là kiểuString- Global Secondary Indexes như được định nghĩa trong
config.json - Thanh toán theo yêu cầu (
PAY_PER_REQUEST) - Mã hóa KMS do khách hàng quản lý với tự động xoay vòng khóa
- Khôi phục theo thời điểm được bật
- Bảo vệ xóa được bật, cùng với bảo vệ vòng đời
prevent_destroy - Tên bảng được đăng ký trong Runtime Config dưới namespace
dynamodbtrong AWS AppConfig
Module core/runtime-config/appconfig hiển thị namespace dynamodb theo mặc định, vì vậy tên bảng được triển khai mà không cần cấu hình thêm. Nếu bạn truyền namespaces vào module đó một cách rõ ràng, hãy giữ dynamodb trong danh sách — nếu không, không có configuration profile nào được tạo cho nó và table client được tạo ra không thể phân giải tên bảng.
Bảo vệ Xóa
Phần tiêu đề “Bảo vệ Xóa”Bảng được bảo vệ bởi hai biện pháp bảo vệ độc lập, do đó việc tắt một trong hai không thể xóa dữ liệu của bạn:
deletionProtection, được thực thi bởi DynamoDB.RemovalPolicy.RETAIN, được thực thi bởi CloudFormation, giữ bảng tại chỗ khi nó bị xóa khỏi stack.
deletion_protection_enabled, được thực thi bởi DynamoDB.lifecycle { prevent_destroy = true }trên bảng trongcommon/terraform/src/core/dynamodb/dynamodb.tf, được thực thi bởi Terraform, làm thất bại bất kỳ kế hoạch nào sẽ phá hủy bảng.
Xóa Bảng
Phần tiêu đề “Xóa Bảng”Vô hiệu hóa bảo vệ cho các môi trường mà việc xóa bảng được mong đợi, chẳng hạn như các stack phát triển hoặc xem trước có thời gian tồn tại ngắn.
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 phải là một giá trị cố định — Terraform không cho phép nó tham chiếu đến một biến — vì vậy nó không thể được tắt từ main.tf. Cũng xóa khối lifecycle khỏi bảng trong common/terraform/src/core/dynamodb/dynamodb.tf:
resource "aws_dynamodb_table" "table" { # ...
lifecycle { prevent_destroy = true }}Chế độ Thanh toán
Phần tiêu đề “Chế độ Thanh toán”Bảng mặc định sử dụng thanh toán theo yêu cầu (PAY_PER_REQUEST). Chuyển sang dung lượng được cung cấp cho các khối lượng công việc có thông lượng cao và có thể dự đoán.
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"}Khôi phục Theo Thời điểm
Phần tiêu đề “Khôi phục Theo Thời điểm”Khôi phục theo thời điểm được bật mặc định, cho phép bạn khôi phục bảng về bất kỳ thời điểm nào trong 35 ngày qua.
Vô hiệu hóa Khôi phục Theo Thời điểm
Phần tiêu đề “Vô hiệu hóa Khôi phục Theo Thời điểm”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}Mã hóa
Phần tiêu đề “Mã hóa”Bảng được mã hóa với khóa KMS do khách hàng quản lý theo mặc định, được tạo tự động cho bạn. Chuyển sang khóa do AWS quản lý, khóa thuộc sở hữu của AWS, hoặc mang khóa KMS của riêng bạn, nếu bạn quản lý mã hóa theo cách khác.
Sử dụng Khóa do AWS Quản lý
Phần tiêu đề “Sử dụng Khóa do AWS Quản lý”Sử dụng khóa KMS aws/dynamodb được chia sẻ mà AWS quản lý thay mặt bạn. Nó hiển thị trong bảng điều khiển KMS của tài khoản bạn và được tính phí theo yêu cầu, nhưng không có khóa nào để bạn tạo, xoay vòng hoặc xóa.
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"}Sử dụng Khóa Thuộc sở hữu của AWS
Phần tiêu đề “Sử dụng Khóa Thuộc sở hữu của AWS”Sử dụng một khóa hoàn toàn thuộc sở hữu và được quản lý bởi AWS — miễn phí, không có khóa nào hiển thị trong tài khoản của bạn. Tùy chọn đơn giản nhất khi bạn không cần khóa hiển thị cho khách hàng hoặc tài khoản vì lý do tuân thủ.
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"}Chuyển đổi khỏi CUSTOMER_MANAGED
Phần tiêu đề “Chuyển đổi khỏi CUSTOMER_MANAGED”Trên bảng đã triển khai, việc thay đổi encryption khỏi CUSTOMER_MANAGED (sang AWS_MANAGED hoặc DEFAULT) trong một lệnh terraform apply duy nhất sẽ thất bại: Terraform phá hủy khóa do khách hàng quản lý trước khi cập nhật bảng, và DynamoDB sau đó từ chối cập nhật vì khóa đã đang chờ xóa.
Giải quyết bằng cách cập nhật mã hóa của bảng trực tiếp qua AWS CLI trước, sau đó để Terraform bắt kịp và dọn dẹp khóa bị bỏ rơi:
# 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.StatusSau đó cập nhật encryption trong cấu hình Terraform của bạn và chạy terraform apply như bình thường — Terraform bây giờ chỉ cần phá hủy khóa đã không sử dụng, không còn gì phụ thuộc vào nó.
Sử dụng Khóa KMS của Riêng Bạn
Phần tiêu đề “Sử dụng Khóa KMS của Riêng Bạn”Cung cấp một khóa do khách hàng quản lý hiện có thay vì để một khóa được tạo cho bạn. Khóa phải đã cấp cho dịch vụ DynamoDB các quyền cần thiết trong chính sách khóa của nó.
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"}Xoay vòng Khóa Mã hóa
Phần tiêu đề “Xoay vòng Khóa Mã hóa”Khi bảng tạo khóa KMS do khách hàng quản lý của riêng nó (mặc định, và chỉ khi bạn chưa cung cấp khóa của riêng mình), khóa đó có tính năng xoay vòng khóa tự động được bật theo mặc định. Vô hiệu hóa nó nếu chính sách bảo mật của bạn quản lý xoay vòng từ bên ngoài.
Vô hiệu hóa Xoay vòng Khóa Mã hóa
Phần tiêu đề “Vô hiệu hóa Xoay vòng Khóa Mã hóa”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}Kết nối
Phần tiêu đề “Kết nối”Sử dụng generator connection để tích hợp dự án này với các dự án khác trong workspace của bạn. Các kết nối sau liên quan đến dự án này: