TypeScript DynamoDB
Este generador crea un nuevo proyecto 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 administrar una tabla DynamoDB utilizando AWS CDK o Terraform, con soporte para diseño de tabla única y desarrollo local integrado a través de DynamoDB Local.
Generar un Proyecto TypeScript DynamoDB
Sección titulada «Generar un Proyecto TypeScript DynamoDB»Ejecute este generador@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- 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
Construya su comando8
Requerido
Opciones
Sección titulada «Opciones»nameRequeridostringNombre del proyecto DynamoDB a generar
directorystringPredeterminado:packagesEl directorio donde almacenar el proyecto.
frameworkenumPredeterminado:electrodbEl framework a utilizar para las entidades de DynamoDB.
electrodbinfraenumPredeterminado:dynamodbInfraestructura a aprovisionar para la tabla DynamoDB.
dynamodbnoneiacenumPredeterminado:inheritEl proveedor de IaC preferido. Por defecto, se hereda de tu selección inicial.
inheritcdkterraformsubDirectorystringEl subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto.
tableNamestringEl nombre de la tabla de DynamoDB. Se genera automáticamente si no se especifica.
preferInstallDependenciesbooleanPredeterminado:trueSi 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 Project entry point and exports
- client.ts DynamoDB client singleton and table name resolution
Directorioentities
- 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
Los scripts de desarrollo local se comparten entre todos los proyectos DynamoDB (tanto TypeScript como Python) y se generan una vez en:
Directoriopackages/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
Infraestructura
Sección titulada «Infraestructura»Dado que este generador proporciona infraestructura como código basada en tu iac elegido, creará un proyecto en packages/common que incluye las construcciones CDK o módulos Terraform relevantes.
El proyecto común de infraestructura como código está estructurado de la siguiente manera:
Directoriopackages/common/constructs
Directoriosrc
Directorioapp/ Constructs for infrastructure specific to a project/generator
- …
Directoriocore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Directoriopackages/common/terraform
Directoriosrc
Directorioapp/ Terraform modules for infrastructure specific to a project/generator
- …
Directoriocore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
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
Arquitectura
Sección titulada «Arquitectura»El proyecto desplegado aprovisiona la tabla en sí, la cual cualquier proyecto al que esté conectado lee y escribe:
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 sola 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éDynamoDBClient. CuandoLOCAL_DEV=true, se conecta a la instancia local de DynamoDB Local; de lo contrario, crea un cliente AWS utilizando la cadena de credenciales predeterminada.resolveTableName()— devuelve el nombre de la tabla DynamoDB. CuandoLOCAL_DEV=true, devuelve la constante del nombre de la tabla local; de lo contrario, obtiene el nombre de AWS AppConfig utilizando 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();Detrás de escena, createExampleEntity() llama a resolveTableName() para obtener el nombre de la tabla de AWS AppConfig en tiempo de ejecución.
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 de 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 a un punto en el tiempo habilitada
- Protección contra eliminación habilitada
- Nombre de tabla registrado en Runtime Config bajo el espacio de nombres
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 de 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 a un punto en el tiempo habilitada
- Protección contra eliminación habilitada, más una protección de ciclo de vida
prevent_destroy - Nombre de tabla registrado en Runtime Config bajo el espacio de nombres
dynamodben AWS AppConfig
El módulo core/runtime-config/appconfig expone el espacio de nombres dynamodb por defecto, por lo que el nombre de la tabla se despliega sin configuración adicional. Si pasas namespaces a ese módulo explícitamente, mantén dynamodb en la lista; de lo contrario, no se crea ningún perfil de configuración para él y el cliente de tabla generado no puede resolver el nombre de la tabla.
Protección contra eliminación
Sección titulada «Protección contra eliminación»La tabla está protegida por dos protecciones independientes, de modo que desactivar cualquiera de ellas por sí sola no puede eliminar tus datos:
deletionProtection, aplicada por DynamoDB.RemovalPolicy.RETAIN, aplicada por CloudFormation, que deja la tabla en su lugar cuando se elimina del stack.
deletion_protection_enabled, aplicada por DynamoDB.lifecycle { prevent_destroy = true }en la tabla encommon/terraform/src/core/dynamodb/dynamodb.tf, aplicada por Terraform, que falla cualquier plan que destruiría la tabla.
Eliminando la tabla
Sección titulada «Eliminando la tabla»Deshabilita la protección para entornos donde se espera la eliminación de tablas, como stacks de desarrollo o vista previa de corta duració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 debe ser un literal — Terraform no permite que haga referencia a una variable — por lo que no se puede desactivar desde main.tf. También elimina el bloque lifecycle de la tabla en common/terraform/src/core/dynamodb/dynamodb.tf:
resource "aws_dynamodb_table" "table" { # ...
lifecycle { prevent_destroy = true }}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 a un punto en el tiempo
Sección titulada «Recuperación a un punto en el tiempo»La recuperación a un punto en el tiempo está habilitada por defecto, permitiéndote restaurar la tabla a cualquier punto en los últimos 35 días.
Deshabilitar la recuperación a un punto en el tiempo
Sección titulada «Deshabilitar la recuperación a un punto en el tiempo»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}Cifrado
Sección titulada «Cifrado»La tabla está cifrada con una clave KMS gestionada por el cliente por defecto, creada automáticamente para ti. Cambia a una clave gestionada por AWS, la clave propiedad de AWS, o trae tu propia clave KMS, si gestionas el cifrado de manera diferente.
Usar una clave gestionada por AWS
Sección titulada «Usar una clave gestionada por AWS»Usa la clave KMS compartida aws/dynamodb que AWS gestiona en tu nombre. Es visible en la consola KMS de tu cuenta y se factura por solicitud, pero no hay ninguna clave que debas crear, rotar o eliminar.
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"}Usar la clave propiedad de AWS
Sección titulada «Usar la clave propiedad de AWS»Usa una clave totalmente propiedad y gestionada por AWS — gratuita, sin ninguna clave visible en tu cuenta. La opción más simple cuando no necesitas una clave visible para el cliente o la cuenta por razones de cumplimiento.
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"}Cambiar desde CUSTOMER_MANAGED
Sección titulada «Cambiar desde CUSTOMER_MANAGED»En una tabla ya desplegada, cambiar encryption desde CUSTOMER_MANAGED (a AWS_MANAGED o DEFAULT) en un solo terraform apply falla: Terraform destruye la clave gestionada por el cliente antes de actualizar la tabla, y DynamoDB rechaza la actualización porque la clave ya está pendiente de eliminación.
Soluciona esto actualizando el cifrado de la tabla directamente a través de AWS CLI primero, y luego dejando que Terraform se ponga al día y limpie la clave huérfana:
# 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.StatusLuego actualiza encryption en tu configuración de Terraform y ejecuta terraform apply normalmente — Terraform ahora solo necesita destruir la clave ya no utilizada, sin nada que dependa de ella.
Usar tu propia clave KMS
Sección titulada «Usar tu propia clave KMS»Proporciona una clave gestionada por el cliente existente en lugar de que se cree una para ti. La clave ya debe otorgar al servicio DynamoDB los permisos que necesita en su propia política de claves.
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"}Rotación de clave de cifrado
Sección titulada «Rotación de clave de cifrado»Cuando la tabla crea su propia clave KMS gestionada por el cliente (el valor por defecto, y solo cuando no has proporcionado tu propia clave), esa clave 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»Utiliza el generador connection para integrar este proyecto con otros en tu espacio de trabajo. Las siguientes conexiones involucran este proyecto: