Ir al contenido

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.

Ejecute este generador@aws/nx-plugin:ts#dynamodb

pnpm nx g @aws/nx-plugin:ts#dynamodb
Construya su comando8

Requerido

Opciones del generador8 opciones
nameRequeridostring

Nombre del proyecto DynamoDB a generar

directorystringPredeterminado: packages

El directorio donde almacenar el proyecto.

frameworkenumPredeterminado: electrodb

El framework a utilizar para las entidades de DynamoDB.

electrodb
infraenumPredeterminado: dynamodb

Infraestructura a aprovisionar para la tabla DynamoDB.

dynamodbnone
iacenumPredeterminado: inherit

El proveedor de IaC preferido. Por defecto, se hereda de tu selección inicial.

inheritcdkterraform
subDirectorystring

El subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto.

tableNamestring

El nombre de la tabla de DynamoDB. Se genera automáticamente si no se especifica.

preferInstallDependenciesbooleanPredeterminado: 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.

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

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/constructs/src
    • Directorioapp
      • Directoriodynamodb
        • <name>.ts Infraestructura específica para tu tabla
    • Directoriocore
      • dynamodb.ts Construcción genérica de tabla DynamoDB

El proyecto desplegado aprovisiona la tabla en sí, la cual cualquier proyecto al que esté conectado lee y escribe:

Loading the diagram…

El generador configura un target dev que inicia una instancia de DynamoDB Local y crea la tabla. Usa el target dev del proyecto:

Terminal window
pnpm nx dev <project-name>

Esto automáticamente:

  1. Descarga la imagen de DynamoDB Local (target pull-image)
  2. Inicia un contenedor
  3. Crea una tabla local con los índices definidos en config.json

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:

packages/my-table/src/entities/example.ts
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.

El archivo generado src/client.ts exporta dos utilidades clave:

  • getDynamoDBClient() — devuelve un singleton en caché DynamoDBClient. Cuando LOCAL_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. Cuando LOCAL_DEV=true, devuelve la constante del nombre de la tabla local; de lo contrario, obtiene el nombre de AWS AppConfig utilizando la variable de entorno RUNTIME_CONFIG_APP_ID y lo almacena en caché para llamadas posteriores.

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:

config.json
{
...
"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 localdev lee config.json y crea o actualiza la tabla local para que coincida con la lista de GSI
  • CDK — el constructo lee config.json en el momento de síntesis, por lo que los cambios de GSI se reflejan en el próximo cdk deploy
  • Terraform — el módulo lee config.json en el momento de plan/apply

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.

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:

packages/infra/src/stacks/application-stack.ts
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) y sk (clave de ordenación), ambas de tipo String
  • Í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 dynamodb en AWS AppConfig

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.

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.

packages/infra/src/stacks/application-stack.ts
import { RemovalPolicy } from 'aws-cdk-lib';
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
deletionProtection: false,
removalPolicy: RemovalPolicy.DESTROY,
});

La tabla utiliza por defecto facturación bajo demanda (PAY_PER_REQUEST). Cambia a capacidad aprovisionada para cargas de trabajo predecibles de alto rendimiento.

packages/infra/src/stacks/application-stack.ts
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,
});

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»
packages/infra/src/stacks/application-stack.ts
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: false },
});

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.

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.

packages/infra/src/stacks/application-stack.ts
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,
});

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.

packages/infra/src/stacks/application-stack.ts
import { TableEncryption } from 'aws-cdk-lib/aws-dynamodb';
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
encryption: TableEncryption.DEFAULT,
});
iac = terraform

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:

Ventana de terminal
# 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.Status

Luego 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.

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.

packages/infra/src/stacks/application-stack.ts
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,
});

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»
packages/infra/src/stacks/application-stack.ts
import { MyTable } from '@my-scope/common-constructs';
const table = new MyTable(this, 'Table', {
enableKeyRotation: false,
});

Utiliza el generador connection para integrar este proyecto con otros en tu espacio de trabajo. Las siguientes conexiones involucran este proyecto:

tRPCAmazon DynamoDB
tRPC API to TypeScript DynamoDBConnect a tRPC API to a DynamoDB table
SmithyAmazon DynamoDB
Smithy API to TypeScript DynamoDBConnect a Smithy API to a DynamoDB table
Strands AgentsTypeScriptAmazon DynamoDB
TypeScript Agent to TypeScript DynamoDBConnect a TypeScript Agent to a DynamoDB table
Model Context ProtocolAmazon DynamoDB
MCP Server to TypeScript DynamoDBConnect a TypeScript MCP Server to a DynamoDB table