TypeScript DynamoDB
Este gerador cria um novo projeto TypeScript DynamoDB apoiado pelo Amazon DynamoDB, usando ElectroDB para modelagem de entidades com segurança de tipos. Ele gera o código da aplicação e a infraestrutura necessária para provisionar e gerenciar uma tabela DynamoDB usando AWS CDK ou Terraform, com suporte a design de tabela única e desenvolvimento local integrado via DynamoDB Local.
Gerar um Projeto TypeScript DynamoDB
Seção intitulada “Gerar um Projeto TypeScript DynamoDB”- Instale o Nx Console VSCode Plugin se ainda não o fez
- Abra o console Nx no VSCode
- Clique em
Generate (UI)na seção "Common Nx Commands" - Procure por
@aws/nx-plugin - ts#dynamodb - Preencha os parâmetros obrigatórios
- Clique em
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#dynamodbVocê também pode realizar uma execução simulada para ver quais arquivos seriam alterados
pnpm nx g @aws/nx-plugin:ts#dynamodb --dry-runyarn nx g @aws/nx-plugin:ts#dynamodb --dry-runnpx nx g @aws/nx-plugin:ts#dynamodb --dry-runbunx nx g @aws/nx-plugin:ts#dynamodb --dry-run| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| name Obrigatório | string | - | Nome do projeto DynamoDB a ser gerado |
| directory | string | packages | O diretório onde armazenar o projeto. |
| subDirectory | string | - | O subdiretório onde o projeto é colocado. Por padrão, este é o nome do projeto. |
| framework | electrodb | electrodb | O framework a ser usado para entidades DynamoDB. |
| tableName | string | - | O nome da tabela DynamoDB. Gerado automaticamente se não especificado. |
| infra | dynamodb | none | dynamodb | Infraestrutura a provisionar para a tabela DynamoDB. |
| iac | inherit | cdk | terraform | inherit | O provedor IaC preferido. Por padrão, isso é herdado da sua seleção inicial. |
| preferInstallDependencies | boolean | true | Se deve preferir instalar dependências após a execução do gerador. Defina como false para adiar a instalação ao executar múltiplos geradores em lote (uma instalação ainda é executada se necessário para que geradores subsequentes possam calcular o grafo de projetos Nx); instale uma vez no final. |
Saída do Gerador
Seção intitulada “Saída do Gerador”O gerador cria a seguinte estrutura de projeto no diretório <directory>/<name>:
Directorysrc
- index.ts Ponto de entrada do projeto e exportações
- client.ts Singleton do cliente DynamoDB e resolução do nome da tabela
Directoryentities
- example.ts Definição de entidade ElectroDB de exemplo
- index.ts Exportações de entidades
- config.json Configuração da tabela incluindo definições de GSI e configurações de desenvolvimento local
- project.json Configuração do projeto e alvos de build
Os scripts de desenvolvimento local são compartilhados entre todos os projetos DynamoDB (tanto TypeScript quanto Python) e gerados uma vez em:
Directorypackages/common/scripts/src/dynamodb
- create-local-table.ts Cria a tabela DynamoDB na instância local do DynamoDB Local
- pull-image.ts Baixa a imagem do DynamoDB Local
- start-container.ts Inicia o contêiner do DynamoDB Local
Infraestrutura
Seção intitulada “Infraestrutura”Como este gerador fornece infraestrutura como código com base no iacProvider escolhido, ele criará um projeto em packages/common que inclui os constructs CDK ou módulos Terraform relevantes.
O projeto comum de infraestrutura como código está estruturado da seguinte forma:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ Constructs para infraestrutura específica de um projeto/gerador
- …
Directorycore/ Constructs genéricos reutilizados pelos constructs em
app- …
- index.ts Ponto de entrada exportando os constructs de
app
- project.json Metas de build e configuração do projeto
Directorypackages/common/terraform
Directorysrc
Directoryapp/ Módulos Terraform para infraestrutura específica de um projeto/gerador
- …
Directorycore/ Módulos genéricos reutilizados pelos módulos em
app- …
- project.json Metas de build e configuração do projeto
Directorypackages/common/constructs/src
Directoryapp
Directorydynamodb
- <name>.ts Infraestrutura específica para sua tabela
Directorycore
- dynamodb.ts Construto genérico de tabela DynamoDB
Directorypackages/common/terraform/src
Directoryapp
Directorydynamodb
Directory<name>
- <name>.tf Módulo específico para sua tabela
Directorycore
Directorydynamodb
- dynamodb.tf Módulo genérico DynamoDB
Desenvolvimento Local
Seção intitulada “Desenvolvimento Local”Iniciando o DynamoDB Local
Seção intitulada “Iniciando o DynamoDB Local”O gerador configura um target dev que inicia uma instância do DynamoDB Local e cria a tabela. Use o target dev do projeto:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>Isso automaticamente:
- Baixa a imagem do DynamoDB Local (target
pull-image) - Inicia um contêiner
- Cria uma tabela local com os índices definidos em
config.json
Modelagem de Dados
Seção intitulada “Modelagem de Dados”O projeto gerado usa ElectroDB para modelagem de entidades com segurança de tipos em uma única tabela DynamoDB, seguindo o design de tabela única do DynamoDB. Adicione ou atualize arquivos de entidade em src/entities/, usando a entidade de exemplo gerada como ponto de partida.
Exemplo de definição de entidade:
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() }, );Para mais detalhes, consulte a documentação de entidades do ElectroDB.
Usando o Cliente DynamoDB
Seção intitulada “Usando o Cliente DynamoDB”O arquivo src/client.ts gerado exporta dois utilitários principais:
getDynamoDBClient()— retorna um singletonDynamoDBClientem cache. QuandoLOCAL_DEV=true, conecta-se à instância local do DynamoDB Local; caso contrário, cria um cliente AWS usando a cadeia de credenciais padrão.resolveTableName()— retorna o nome da tabela DynamoDB. QuandoLOCAL_DEV=true, retorna a constante do nome da tabela local; caso contrário, busca o nome do AWS AppConfig usando a variável de ambienteRUNTIME_CONFIG_APP_IDe o armazena em cache para chamadas subsequentes.
Parando o DynamoDB Local
Seção intitulada “Parando o DynamoDB Local”Parar o dev (por exemplo, com Ctrl+C) remove automaticamente o contêiner DynamoDB Local, mas preserva o volume nomeado para que seus dados persistam entre reinicializações.
Adicionar/Remover Índices Secundários Globais
Seção intitulada “Adicionar/Remover Índices Secundários Globais”GSIs são definidos em config.json na raiz do projeto sob a chave tableConfig.globalSecondaryIndexes. Adicione uma entrada para cada GSI, seguindo a convenção de nomenclatura de design de tabela única para chaves GSI:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}O campo sortKey é opcional para GSIs somente com chave de hash.
Este arquivo de configuração é a única fonte de verdade lida por todos os consumidores:
- Desenvolvimento local —
devlêconfig.jsone cria ou atualiza a tabela local para corresponder à lista de GSI - CDK — o construct lê
config.jsonno momento da síntese, então as mudanças de GSI são refletidas no próximocdk deploy - Terraform — o módulo lê
config.jsonno momento do plan/apply
Um GSI por Implantação
Seção intitulada “Um GSI por Implantação”Conectando à Tabela
Seção intitulada “Conectando à Tabela”Em qualquer projeto TypeScript, importe as fábricas de entidades do seu pacote DynamoDB e use-as diretamente:
import { createExampleEntity } from ':my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();Implantando sua Tabela
Seção intitulada “Implantando sua Tabela”O gerador DynamoDB cria infraestrutura CDK ou Terraform com base no seu iac selecionado.
O construtor CDK é criado em common/constructs. Exemplo de uso:
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'); }}Isso provisiona uma tabela DynamoDB com:
pk(chave de partição) esk(chave de ordenação), ambas do tipoString- Índices Secundários Globais conforme definido em
config.json - Cobrança sob demanda (
PAY_PER_REQUEST) - Criptografia KMS gerenciada pelo cliente com rotação automática de chaves
- Recuperação point-in-time habilitada
- Proteção contra exclusão habilitada
- Nome da tabela registrado no Runtime Config sob o namespace
dynamodbno AWS AppConfig
O módulo Terraform é criado em common/terraform. Exemplo de uso:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}Isso provisiona uma tabela DynamoDB com:
pk(chave de partição) esk(chave de ordenação), ambas do tipoString- Índices Secundários Globais conforme definido em
config.json - Cobrança sob demanda (
PAY_PER_REQUEST) - Criptografia KMS gerenciada pelo cliente com rotação automática de chaves
- Recuperação point-in-time habilitada
- Proteção contra exclusão habilitada
- Nome da tabela registrado no Runtime Config
Concedendo Acesso
Seção intitulada “Concedendo Acesso”Para permitir que funções Lambda acessem a tabela DynamoDB, conceda as permissões necessárias em sua infraestrutura.
Chame grantReadWriteData no construto da tabela. Isso concede as permissões do DynamoDB e KMS necessárias para a função de execução do Lambda:
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);});Conceda à função de execução do Lambda permissão para acessar a tabela DynamoDB e sua chave de criptografia 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] }, ] })}Proteção contra Exclusão
Seção intitulada “Proteção contra Exclusão”A proteção contra exclusão está habilitada por padrão para prevenir a exclusão acidental da tabela.
Desabilitar Proteção contra Exclusão
Seção intitulada “Desabilitar Proteção contra Exclusão”Desabilite-a para ambientes onde a exclusão da tabela é esperada, como stacks de desenvolvimento ou preview de curta duração.
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}Modo de Cobrança
Seção intitulada “Modo de Cobrança”A tabela usa por padrão cobrança sob demanda (PAY_PER_REQUEST). Mude para capacidade provisionada para cargas de trabalho previsíveis e de alto throughput.
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"}Recuperação Point-in-time
Seção intitulada “Recuperação Point-in-time”A recuperação point-in-time está habilitada por padrão, permitindo que você restaure a tabela para qualquer ponto nos últimos 35 dias.
Desabilitar Recuperação Point-in-time
Seção intitulada “Desabilitar Recuperação Point-in-time”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}Rotação de Chave de Criptografia
Seção intitulada “Rotação de Chave de Criptografia”A chave KMS usada para criptografar a tabela tem rotação automática de chaves habilitada por padrão. Desabilite-a se sua política de segurança gerencia a rotação externamente.
Desabilitar Rotação de Chave de Criptografia
Seção intitulada “Desabilitar Rotação de Chave de Criptografia”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}Conexões
Seção intitulada “Conexões”Use o gerador connection para integrar este projeto com outros em seu workspace. As seguintes conexões envolvem este projeto: