TypeScript DynamoDB
Questo generatore crea un nuovo progetto TypeScript DynamoDB supportato da Amazon DynamoDB, utilizzando ElectroDB per la modellazione di entità type-safe. Genera il codice dell’applicazione e l’infrastruttura necessaria per il provisioning e la gestione di una tabella DynamoDB utilizzando AWS CDK o Terraform, con supporto per il design single-table e sviluppo locale integrato tramite DynamoDB Local.
Utilizzo
Sezione intitolata “Utilizzo”Genera un progetto TypeScript DynamoDB
Sezione intitolata “Genera un progetto TypeScript DynamoDB”Esegui questo generatore@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- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - ts#dynamodb - Compila i parametri richiesti
- Clicca su
Generate
Componi il tuo comando8
Obbligatorio
Opzioni
Sezione intitolata “Opzioni”nameObbligatoriostringNome del progetto DynamoDB da generare
directorystringPredefinito:packagesLa directory in cui memorizzare il progetto.
frameworkenumPredefinito:electrodbIl framework da utilizzare per le entità DynamoDB.
electrodbinfraenumPredefinito:dynamodbInfrastruttura da fornire per la tabella DynamoDB.
dynamodbnoneiacenumPredefinito:inheritIl provider IaC preferito. Per impostazione predefinita viene ereditato dalla selezione iniziale.
inheritcdkterraformsubDirectorystringLa sotto-directory in cui viene posizionato il progetto. Per impostazione predefinita corrisponde al nome del progetto.
tableNamestringIl nome della tabella DynamoDB. Generato automaticamente se non specificato.
preferInstallDependenciesbooleanPredefinito:trueSe preferire l'installazione delle dipendenze dopo l'esecuzione del generatore. Impostare su false per rimandare l'installazione quando si eseguono più generatori in batch (l'installazione viene comunque eseguita se necessaria affinché i generatori successivi possano calcolare il grafo dei progetti Nx); installare una volta alla fine.
Output del generatore
Sezione intitolata “Output del generatore”Il generatore crea la seguente struttura di progetto nella directory <directory>/<name>:
Directorysrc
- index.ts Project entry point and exports
- client.ts DynamoDB client singleton and table name resolution
Directoryentities
- 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
Gli script di sviluppo locale sono condivisi tra tutti i progetti DynamoDB (sia TypeScript che Python) e generati una volta in:
Directorypackages/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
Infrastruttura
Sezione intitolata “Infrastruttura”Poiché questo generatore fornisce infrastruttura come codice basata sul tuo iac scelto, creerà un progetto in packages/common che include i costrutti CDK o i moduli Terraform pertinenti.
Il progetto comune di infrastruttura come codice è strutturato come segue:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ Constructs for infrastructure specific to a project/generator
- …
Directorycore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Directorypackages/common/terraform
Directorysrc
Directoryapp/ Terraform modules for infrastructure specific to a project/generator
- …
Directorycore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Directorypackages/common/constructs/src
Directoryapp
Directorydynamodb
- <name>.ts Infrastruttura specifica per la tua tabella
Directorycore
- dynamodb.ts Costrutto generico per tabelle DynamoDB
Directorypackages/common/terraform/src
Directoryapp
Directorydynamodb
Directory<name>
- <name>.tf Modulo specifico per la tua tabella
Directorycore
Directorydynamodb
- dynamodb.tf Modulo generico DynamoDB
Architettura
Sezione intitolata “Architettura”Il progetto distribuito effettua il provisioning della tabella stessa, che qualsiasi progetto ad essa connesso legge e scrive:
Sviluppo locale
Sezione intitolata “Sviluppo locale”Avvio di DynamoDB locale
Sezione intitolata “Avvio di DynamoDB locale”Il generatore configura un target dev che avvia un’istanza di DynamoDB Local e crea la tabella. Usa il target dev del progetto:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>Questo automaticamente:
- Scarica l’immagine DynamoDB Local (target
pull-image) - Avvia un container
- Crea una tabella locale con gli indici definiti in
config.json
Modellazione dei dati
Sezione intitolata “Modellazione dei dati”Il progetto generato utilizza ElectroDB per la modellazione di entità type-safe su una singola tabella DynamoDB, seguendo il design single-table di DynamoDB. Aggiungi o aggiorna i file di entità in src/entities/, utilizzando l’entità di esempio generata come punto di partenza.
Esempio di definizione di entità:
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() }, );Per maggiori dettagli, consulta la documentazione delle entità ElectroDB.
Utilizzo del client DynamoDB
Sezione intitolata “Utilizzo del client DynamoDB”Il file generato src/client.ts esporta due utility chiave:
getDynamoDBClient()— restituisce un singletonDynamoDBClientin cache. QuandoLOCAL_DEV=true, si connette all’istanza locale di DynamoDB Local; altrimenti crea un client AWS utilizzando la catena di credenziali predefinita.resolveTableName()— restituisce il nome della tabella DynamoDB. QuandoLOCAL_DEV=true, restituisce la costante del nome della tabella locale; altrimenti recupera il nome da AWS AppConfig utilizzando la variabile d’ambienteRUNTIME_CONFIG_APP_IDe lo memorizza in cache per le chiamate successive.
Arresto di DynamoDB locale
Sezione intitolata “Arresto di DynamoDB locale”L’arresto di dev (ad esempio con Ctrl+C) rimuove automaticamente il container DynamoDB Local, ma preserva il volume nominato in modo che i tuoi dati persistano tra i riavvii.
Aggiunta/Rimozione di Global Secondary Index
Sezione intitolata “Aggiunta/Rimozione di Global Secondary Index”I GSI sono definiti in config.json nella radice del progetto sotto la chiave tableConfig.globalSecondaryIndexes. Aggiungi una voce per ogni GSI, seguendo la convenzione di denominazione delle chiavi GSI del design single-table:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}Il campo sortKey è facoltativo per i GSI con solo hash-key.
Questo file di configurazione è l’unica fonte di verità letta da tutti i consumatori:
- Sviluppo locale —
devleggeconfig.jsone crea o aggiorna la tabella locale per corrispondere all’elenco dei GSI - CDK — il costrutto legge
config.jsonal momento della sintesi, quindi le modifiche ai GSI si riflettono al prossimocdk deploy - Terraform — il modulo legge
config.jsonal momento del plan/apply
Un GSI per Deployment
Sezione intitolata “Un GSI per Deployment”Connessione alla tabella
Sezione intitolata “Connessione alla tabella”In qualsiasi progetto TypeScript, importa le factory di entità dal tuo pacchetto DynamoDB e utilizzale direttamente:
import { createExampleEntity } from '@my-scope/my-table';
const entity = await createExampleEntity();const result = await entity.query.primary({ id: '123' }).go();Dietro le quinte, createExampleEntity() chiama resolveTableName() per recuperare il nome della tabella da AWS AppConfig a runtime.
Distribuzione della tabella
Sezione intitolata “Distribuzione della tabella”Il generatore DynamoDB crea l’infrastruttura CDK o Terraform in base all’iac selezionato.
Il costrutto CDK viene creato in common/constructs. Esempio di utilizzo:
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'); }}Questo esegue il provisioning di una tabella DynamoDB con:
pk(partition key) esk(sort key), entrambe di tipoString- Global Secondary Indexes come definiti in
config.json - Fatturazione on-demand (
PAY_PER_REQUEST) - Crittografia KMS gestita dal cliente con rotazione automatica delle chiavi
- Point-in-time recovery abilitato
- Protezione dall’eliminazione abilitata
- Nome della tabella registrato in Runtime Config nello spazio dei nomi
dynamodbin AWS AppConfig
Il modulo Terraform viene creato in common/terraform. Esempio di utilizzo:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}Questo esegue il provisioning di una tabella DynamoDB con:
pk(partition key) esk(sort key), entrambe di tipoString- Global Secondary Indexes come definiti in
config.json - Fatturazione on-demand (
PAY_PER_REQUEST) - Crittografia KMS gestita dal cliente con rotazione automatica delle chiavi
- Point-in-time recovery abilitato
- Protezione dall’eliminazione abilitata, più una protezione del ciclo di vita
prevent_destroy - Nome della tabella registrato in Runtime Config nello spazio dei nomi
dynamodbin AWS AppConfig
Il modulo core/runtime-config/appconfig espone lo spazio dei nomi dynamodb per impostazione predefinita, quindi il nome della tabella viene distribuito senza ulteriori configurazioni. Se passi namespaces a quel modulo esplicitamente, mantieni dynamodb nell’elenco — altrimenti non viene creato alcun profilo di configurazione per esso e il client della tabella generato non può risolvere il nome della tabella.
Protezione dall’eliminazione
Sezione intitolata “Protezione dall’eliminazione”La tabella è protetta da due protezioni indipendenti, in modo che disattivarne una sola non possa eliminare i tuoi dati:
deletionProtection, applicata da DynamoDB.RemovalPolicy.RETAIN, applicata da CloudFormation, che lascia la tabella al suo posto quando viene rimossa dallo stack.
deletion_protection_enabled, applicata da DynamoDB.lifecycle { prevent_destroy = true }sulla tabella incommon/terraform/src/core/dynamodb/dynamodb.tf, applicata da Terraform, che fa fallire qualsiasi piano che distruggerebbe la tabella.
Eliminazione della tabella
Sezione intitolata “Eliminazione della tabella”Disabilita la protezione per ambienti in cui è prevista l’eliminazione della tabella, come stack di sviluppo o di anteprima di breve durata.
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 deve essere un letterale — Terraform non consente di fare riferimento a una variabile — quindi non può essere disattivato da main.tf. Rimuovi anche il blocco lifecycle dalla tabella in common/terraform/src/core/dynamodb/dynamodb.tf:
resource "aws_dynamodb_table" "table" { # ...
lifecycle { prevent_destroy = true }}Modalità di fatturazione
Sezione intitolata “Modalità di fatturazione”La tabella utilizza per impostazione predefinita la fatturazione on-demand (PAY_PER_REQUEST). Passa alla capacità con provisioning per carichi di lavoro prevedibili ad 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"}Point-in-time Recovery
Sezione intitolata “Point-in-time Recovery”Il Point-in-time recovery è abilitato per impostazione predefinita, consentendoti di ripristinare la tabella a qualsiasi momento negli ultimi 35 giorni.
Disabilitare il Point-in-time Recovery
Sezione intitolata “Disabilitare il Point-in-time Recovery”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}Crittografia
Sezione intitolata “Crittografia”La tabella è crittografata con una chiave KMS gestita dal cliente per impostazione predefinita, creata automaticamente per te. Passa a una chiave gestita da AWS, alla chiave di proprietà di AWS, o porta la tua chiave KMS, se gestisci la crittografia in modo diverso.
Utilizzare una chiave gestita da AWS
Sezione intitolata “Utilizzare una chiave gestita da AWS”Utilizza la chiave KMS condivisa aws/dynamodb che AWS gestisce per tuo conto. È visibile nella console KMS del tuo account e fatturata per richiesta, ma non c’è alcuna chiave da creare, ruotare o eliminare.
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"}Utilizzare la chiave di proprietà di AWS
Sezione intitolata “Utilizzare la chiave di proprietà di AWS”Utilizza una chiave completamente posseduta e gestita da AWS — gratuita, senza alcuna chiave visibile nel tuo account. L’opzione più semplice quando non hai bisogno di una chiave visibile al cliente o all’account per motivi di conformità.
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"}Passaggio da CUSTOMER_MANAGED
Sezione intitolata “Passaggio da CUSTOMER_MANAGED”Su una tabella già distribuita, modificare encryption da CUSTOMER_MANAGED (a AWS_MANAGED o DEFAULT) in un singolo terraform apply fallisce: Terraform distrugge la chiave gestita dal cliente prima di aggiornare la tabella, e DynamoDB quindi rifiuta l’aggiornamento perché la chiave è già in attesa di eliminazione.
Aggiralo aggiornando prima la crittografia della tabella direttamente tramite AWS CLI, quindi lasciando che Terraform si allinei e pulisca la chiave orfana:
# 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.StatusQuindi aggiorna encryption nella tua configurazione Terraform ed esegui terraform apply normalmente — Terraform ora deve solo distruggere la chiave già inutilizzata, senza nulla che dipenda da essa.
Utilizzare la propria chiave KMS
Sezione intitolata “Utilizzare la propria chiave KMS”Fornisci una chiave gestita dal cliente esistente invece di farne creare una per te. La chiave deve già concedere al servizio DynamoDB le autorizzazioni necessarie nella propria policy della chiave.
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"}Rotazione della chiave di crittografia
Sezione intitolata “Rotazione della chiave di crittografia”Quando la tabella crea la propria chiave KMS gestita dal cliente (l’impostazione predefinita, e solo quando non hai fornito la tua chiave), quella chiave ha la rotazione automatica delle chiavi abilitata per impostazione predefinita. Disabilitala se la tua policy di sicurezza gestisce la rotazione esternamente.
Disabilitare la rotazione della chiave di crittografia
Sezione intitolata “Disabilitare la rotazione della chiave di crittografia”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}Connessioni
Sezione intitolata “Connessioni”Utilizza il generatore connection per integrare questo progetto con altri nel tuo workspace. Le seguenti connessioni coinvolgono questo progetto: