TypeScript DynamoDB
Este generador crea un nuevo proyecto de TypeScript DynamoDB respaldado por Amazon DynamoDB, utilizando ElectroDB para el modelado de entidades con seguridad de tipos. Genera el código de aplicación y la infraestructura necesaria para aprovisionar y gestionar una tabla DynamoDB usando AWS CDK o Terraform, con soporte para diseño de tabla única y desarrollo local integrado mediante DynamoDB Local.
Generar un Proyecto de TypeScript DynamoDB
Sección titulada «Generar un Proyecto de TypeScript DynamoDB»- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - ts#dynamodb - Complete los parámetros requeridos
- Haga clic en
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#dynamodbTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
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-runOpciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| name Requerido | string | - | Nombre del proyecto DynamoDB a generar |
| directory | string | packages | El directorio donde almacenar el proyecto. |
| subDirectory | string | - | El subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto. |
| framework | electrodb | electrodb | El framework a utilizar para las entidades de DynamoDB. |
| tableName | string | - | El nombre de la tabla de DynamoDB. Se genera automáticamente si no se especifica. |
| infra | dynamodb | none | dynamodb | Infraestructura a aprovisionar para la tabla DynamoDB. |
| iac | inherit | cdk | terraform | inherit | El proveedor de IaC preferido. Por defecto, se hereda de tu selección inicial. |
| preferInstallDependencies | boolean | true | Si se prefiere instalar las dependencias después de que se ejecute el generador. Establecer en false para diferir la instalación al ejecutar múltiples generadores en lote (la instalación aún se ejecuta si es necesario para que los generadores subsiguientes puedan calcular el grafo de proyectos de Nx); instalar una vez al final. |
Salida del Generador
Sección titulada «Salida del Generador»El generador crea la siguiente estructura de proyecto en el directorio <directory>/<name>:
Directoriosrc
- index.ts Punto de entrada del proyecto y exportaciones
- client.ts Singleton del cliente DynamoDB y resolución del nombre de tabla
Directorioentities
- example.ts Definición de entidad ElectroDB de ejemplo
- index.ts Exportaciones de entidades
- config.json Configuración de tabla incluyendo definiciones de GSI y configuración de desarrollo local
- project.json Configuración del proyecto y objetivos de compilación
Los scripts de desarrollo local se comparten entre todos los proyectos de DynamoDB (tanto TypeScript como Python) y se generan una vez en:
Directoriopackages/common/scripts/src/dynamodb
- create-local-table.ts Crea la tabla DynamoDB en la instancia local de DynamoDB Local
- pull-image.ts Descarga la imagen de DynamoDB Local
- start-container.ts Inicia el contenedor de DynamoDB Local
Infraestructura
Sección titulada «Infraestructura»Dado que este generador proporciona infraestructura como código basada en tu proveedor de iacProvider seleccionado, creará un proyecto en packages/common que incluye los constructos CDK o módulos de Terraform correspondientes.
El proyecto común de infraestructura como código tiene la siguiente estructura:
Directoriopackages/common/constructs
Directoriosrc
Directorioapp/ Constructos para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Constructos genéricos reutilizados por los constructos en
app- …
- index.ts Punto de entrada que exporta los constructos de
app
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/terraform
Directoriosrc
Directorioapp/ Módulos de Terraform para infraestructura específica de un proyecto/generador
- …
Directoriocore/ Módulos genéricos reutilizados por los módulos en
app- …
- project.json Objetivos de compilación y configuración del proyecto
Directoriopackages/common/constructs/src
Directorioapp
Directoriodynamodb
- <name>.ts Infraestructura específica para tu tabla
Directoriocore
- dynamodb.ts Construcción genérica de tabla DynamoDB
Directoriopackages/common/terraform/src
Directorioapp
Directoriodynamodb
Directorio<name>
- <name>.tf Módulo específico para tu tabla
Directoriocore
Directoriodynamodb
- dynamodb.tf Módulo genérico de DynamoDB
Desarrollo Local
Sección titulada «Desarrollo Local»Iniciar DynamoDB Local
Sección titulada «Iniciar DynamoDB Local»El generador configura un target dev que inicia una instancia de DynamoDB Local y crea la tabla. Usa el target dev del proyecto:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>Esto automáticamente:
- Descarga la imagen de DynamoDB Local (target
pull-image) - Inicia un contenedor
- Crea una tabla local con los índices definidos en
config.json
Modelado de Datos
Sección titulada «Modelado de Datos»El proyecto generado utiliza ElectroDB para el modelado de entidades con seguridad de tipos en una única tabla DynamoDB, siguiendo el diseño de tabla única de DynamoDB. Agrega o actualiza archivos de entidad en src/entities/, utilizando la entidad de ejemplo generada como punto de partida.
Ejemplo de definición de entidad:
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 más detalles, consulta la documentación de entidades de ElectroDB.
Usar el Cliente DynamoDB
Sección titulada «Usar el Cliente DynamoDB»El archivo generado src/client.ts exporta dos utilidades clave:
getDynamoDBClient()— devuelve un singleton en caché deDynamoDBClient. CuandoLOCAL_DEV=true, se conecta a la instancia local de DynamoDB Local; de lo contrario, crea un cliente AWS usando la cadena de credenciales predeterminada.resolveTableName()— devuelve el nombre de la tabla DynamoDB. CuandoLOCAL_DEV=true, devuelve la constante del nombre de tabla local; de lo contrario, obtiene el nombre de AWS AppConfig usando la variable de entornoRUNTIME_CONFIG_APP_IDy lo almacena en caché para llamadas posteriores.
Detener DynamoDB Local
Sección titulada «Detener DynamoDB Local»Detener dev (por ejemplo, con Ctrl+C) elimina automáticamente el contenedor de DynamoDB Local, pero conserva el volumen nombrado para que tus datos persistan entre reinicios.
Agregar/Eliminar Índices Secundarios Globales
Sección titulada «Agregar/Eliminar Índices Secundarios Globales»Los GSI se definen en config.json en la raíz del proyecto bajo la clave tableConfig.globalSecondaryIndexes. Agrega una entrada para cada GSI, siguiendo la convención de nomenclatura de diseño de tabla única para las claves GSI:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}El campo sortKey es opcional para GSIs de solo clave hash.
Este archivo de configuración es la única fuente de verdad leída por todos los consumidores:
- Desarrollo local —
devleeconfig.jsony crea o actualiza la tabla local para que coincida con la lista de GSI - CDK — el constructo lee
config.jsonen el momento de síntesis, por lo que los cambios de GSI se reflejan en el próximocdk deploy - Terraform — el módulo lee
config.jsonen el momento de plan/apply
Un GSI por Despliegue
Sección titulada «Un GSI por Despliegue»Conectarse a la Tabla
Sección titulada «Conectarse a la Tabla»En cualquier proyecto TypeScript, importa las fábricas de entidades de tu paquete DynamoDB y úsalas directamente:
import { createExampleEntity } from ':my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();Desplegar tu Tabla
Sección titulada «Desplegar tu Tabla»El generador de DynamoDB crea infraestructura CDK o Terraform basada en tu iac seleccionado.
El constructo CDK se crea en common/constructs. Ejemplo 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'); }}Esto aprovisiona una tabla DynamoDB con:
pk(clave de partición) ysk(clave de ordenación), ambas de tipoString- Índices Secundarios Globales según se definen en
config.json - Facturación bajo demanda (
PAY_PER_REQUEST) - Cifrado KMS gestionado por el cliente con rotación automática de claves
- Recuperación point-in-time habilitada
- Protección contra eliminación habilitada
- Nombre de tabla registrado en Runtime Config bajo el namespace
dynamodben AWS AppConfig
El módulo Terraform se crea en common/terraform. Ejemplo de uso:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}Esto aprovisiona una tabla DynamoDB con:
pk(clave de partición) ysk(clave de ordenación), ambas de tipoString- Índices Secundarios Globales según se definen en
config.json - Facturación bajo demanda (
PAY_PER_REQUEST) - Cifrado KMS gestionado por el cliente con rotación automática de claves
- Recuperación point-in-time habilitada
- Protección contra eliminación habilitada
- Nombre de tabla registrado en Runtime Config
Concediendo Acceso
Sección titulada «Concediendo Acceso»Para permitir que las funciones Lambda accedan a la tabla de DynamoDB, otorga los permisos necesarios en tu infraestructura.
Llama a grantReadWriteData en el constructo de la tabla. Esto otorga tanto los permisos de DynamoDB como de KMS requeridos por el rol de ejecución de 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);});Otorga al rol de ejecución de Lambda permiso para acceder a la tabla de DynamoDB y su clave de cifrado 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] }, ] })}Protección contra Eliminación
Sección titulada «Protección contra Eliminación»La protección contra eliminación está habilitada por defecto para prevenir la eliminación accidental de la tabla.
Deshabilitar la Protección contra Eliminación
Sección titulada «Deshabilitar la Protección contra Eliminación»Deshabilítala para entornos donde se espera la eliminación de la tabla, como stacks de desarrollo o preview de corta duración.
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 Facturación
Sección titulada «Modo de Facturación»La tabla utiliza por defecto facturación bajo demanda (PAY_PER_REQUEST). Cambia a capacidad aprovisionada para cargas de trabajo predecibles de alto rendimiento.
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"}Recuperación Point-in-time
Sección titulada «Recuperación Point-in-time»La recuperación point-in-time está habilitada por defecto, permitiéndote restaurar la tabla a cualquier punto en los últimos 35 días.
Deshabilitar la Recuperación Point-in-time
Sección titulada «Deshabilitar la Recuperación 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}Rotación de Clave de Cifrado
Sección titulada «Rotación de Clave de Cifrado»La clave KMS utilizada para cifrar la tabla tiene la rotación automática de claves habilitada por defecto. Deshabilítala si tu política de seguridad gestiona la rotación externamente.
Deshabilitar la Rotación de Clave de Cifrado
Sección titulada «Deshabilitar la Rotación de Clave de Cifrado»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}Conexiones
Sección titulada «Conexiones»Usa el generador connection para integrar este proyecto con otros en tu workspace. Las siguientes conexiones involucran este proyecto: