Ir al contenido

Base de Datos Relacional TypeScript

Filter this guidePick generator option values to hide sections that don't apply.

Este generador crea un nuevo proyecto de base de datos relacional respaldado por Amazon Aurora (PostgreSQL o MySQL) y Prisma ORM. Genera el código de aplicación y la infraestructura necesaria para aprovisionar y gestionar una base de datos usando AWS CDK o Terraform, con definición de esquema declarativa, despliegue automático de migraciones y un cliente ORM con tipos seguros.

Puedes generar un nuevo proyecto de base de datos relacional de dos maneras:

  1. Instale el Nx Console VSCode Plugin si aún no lo ha hecho
  2. Abra la consola Nx en VSCode
  3. Haga clic en Generate (UI) en la sección "Common Nx Commands"
  4. Busque @aws/nx-plugin - ts#rdb
  5. Complete los parámetros requeridos
    • Haga clic en Generate
    ParámetroTipoPredeterminadoDescripción
    name Requeridostring-Nombre del proyecto de base de datos a generar
    directory stringpackagesEl directorio donde almacenar la aplicación.
    subDirectory string-El subdirectorio donde se coloca el proyecto. Por defecto es el nombre del proyecto.
    infra aurora | noneauroraServicio de base de datos relacional a provisionar.
    engine postgres | mysqlpostgresMotor de base de datos a utilizar con el servicio seleccionado.
    databaseUser stringdbadminNombre de usuario del administrador de la base de datos. Por defecto es 'dbadmin'.
    databaseName string-Nombre inicial de la base de datos. Por defecto es el nombre del proyecto.
    framework prismaprismaFramework ORM a utilizar para el proyecto generado.
    iac inherit | cdk | terraforminheritEl proveedor IaC preferido. Por defecto, se hereda de tu selección inicial.
    preferInstallDependencies booleantrueSi 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 subsecuentes puedan calcular el grafo de proyectos de Nx); instalar una vez al final.

    El generador creará la siguiente estructura de proyecto en el directorio <directory>/<name>:

    • Directorioprisma
      • Directoriomodels
        • example.prisma Definición de modelo de ejemplo
      • schema.prisma Esquema principal de Prisma (referencia modelos)
    • Directoriosrc
      • index.ts Punto de entrada del proyecto
      • prisma.ts Envoltorio del cliente Prisma en tiempo de ejecución
      • utils.ts Ayudantes de configuración en tiempo de ejecución y secretos
      • create-db-user-handler.ts Manejador Lambda usado para crear el usuario de base de datos de aplicación durante el despliegue
      • migration-handler.ts Manejador Lambda usado para ejecutar migraciones de base de datos durante el despliegue
    • .gitignore Entradas de Git ignore incluyendo la salida del cliente Prisma generado
    • config.json Detalles de conexión de desarrollo local y clave de configuración en tiempo de ejecución
    • Dockerfile Definición de imagen de contenedor para el manejador de migración
    • project.json Configuración del proyecto y objetivos de construcción
    • prisma.config.ts Configuración para Prisma CLI

    Los scripts de desarrollo local se comparten entre todos los proyectos de base de datos y se generan en packages/common/scripts/:

    • Directoriopackages/common/scripts/src/rdb
      • pull-image.ts Descarga la imagen de contenedor de la base de datos
      • start-container.ts Inicia un contenedor de base de datos local
      • wait-for-postgres-db.ts Espera a que la base de datos local esté lista (PostgreSQL)
      • wait-for-mysql-db.ts Espera a que la base de datos local esté lista (MySQL)

    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/constructs/src
      • Directorioapp
        • Directoriodbs
          • <name>.ts Infraestructura específica para tu base de datos
      • Directoriocore
        • Directoriordb
          • aurora.ts Construcción genérica de base de datos Aurora

    La base de datos desplegada tiene la siguiente arquitectura. Por defecto, un Amazon RDS Proxy se sitúa frente al clúster Aurora para agrupar conexiones y habilitar la autenticación IAM — consulte Deshabilitar RDS Proxy para la alternativa. La arquitectura es la misma ya sea que seleccione el motor PostgreSQL o MySQL; solo difiere el tipo de motor Aurora.

    Application(Lambda, Agent, ...)RDS ProxyMigrations LambdaAurora(PostgreSQL or MySQL)Secrets Manager(DB credentials) SQL (IAM auth) Schema migrations Admin credentials

    El proyecto generado usa Prisma ORM para definir tu esquema de base de datos y generar un cliente con tipos seguros. El flujo de trabajo es model-first: agrega o actualiza archivos de modelo Prisma bajo el directorio prisma/models/ de tu proyecto de base de datos, luego genera una migración a partir de esos cambios de modelo.

    Ejemplo de modelo User:

    packages/postgres/prisma/models/user.prisma
    model User {
    id Int @id @default(autoincrement())
    firstName String
    lastName String
    }

    Para más detalles, consulta la guía oficial de modelado de datos con Prisma.

    El generador configura automáticamente el objetivo generate para crear un cliente TypeScript de Prisma con tipos seguros cada vez que construyes el proyecto. El cliente se escribe en generated/prisma (agregado a .gitignore).

    También puedes generar manualmente el cliente en cualquier momento:

    Terminal window
    pnpm nx generate <your-db-project-name>

    Usa el objetivo prisma para ejecutar comandos de Prisma CLI desde la raíz del workspace:

    Terminal window
    pnpm nx run <project>:prisma generate

    El envoltorio en tiempo de ejecución en src/prisma.ts exporta:

    • getPrisma() - carga la configuración de conexión de base de datos desde AWS AppConfig y crea un cliente Prisma usando autenticación IAM

    El cliente automáticamente:

    • Recupera la configuración de base de datos desde AWS AppConfig usando la variable de entorno RUNTIME_CONFIG_APP_ID
    • Genera tokens de autenticación temporales a través de AWS RDS Signer para autenticación IAM
    • Gestiona conexiones SSL/TLS con validación de certificados
    • Maneja el pooling de conexiones a través de pools de conexión de base de datos persistentes

    Después de agregar o actualizar modelos bajo prisma/models/, usa migrate dev para generar archivos de migración y aplicarlos a tu base de datos local al mismo tiempo.

    El objetivo prisma generado automáticamente inicia un contenedor de base de datos local antes de ejecutar:

    Terminal window
    pnpm nx run <project>:prisma migrate dev

    Si solo deseas generar los archivos de migración sin aplicarlos a la base de datos local, agrega --create-only:

    Terminal window
    pnpm nx run <project>:prisma migrate dev --create-only

    Esto genera una nueva carpeta de migración en prisma/migrations cada vez que tu esquema cambia:

    • Directorioprisma
      • Directoriomigrations
        • Directorio20260405013911_initial_migrations
          • migration.sql
        • migration_lock.toml
      • schema.prisma

    Cuando despliegas el stack de AWS, la infraestructura generada aplica automáticamente las migraciones generadas a la base de datos desplegada.

    Cuando obtienes archivos de migración creados por otros desarrolladores, usa migrate deploy para aplicar esas migraciones existentes a tu base de datos local.

    Terminal window
    pnpm nx run <project>:prisma migrate deploy

    En este flujo de desarrollo local, migrate deploy aplica los archivos de migración a tu base de datos local; no despliega la base de datos en AWS.

    El objetivo prisma generado expone la CLI de Prisma, por lo que puedes usarlo para ejecutar cualquier comando soportado por Prisma contra la base de datos local. Consulta la referencia de CLI de Prisma para los comandos disponibles.

    Terminal window
    pnpm nx run <project>:prisma <prisma-command>

    Prisma Studio es un editor visual para tu base de datos local. Úsalo para explorar tablas, inspeccionar y editar registros, filtrar datos, seguir relaciones y ejecutar SQL sin procesar a través de la consola SQL integrada. Es útil para verificar migraciones y sembrar datos de prueba durante el desarrollo. Inícialo con:

    Terminal window
    pnpm nx run <project>:prisma studio

    Detener dev (p. ej. con Ctrl+C) elimina automáticamente el contenedor de base de datos local, pero preserva el volumen nombrado para que tus datos persistan entre reinicios.

    En cualquier proyecto TypeScript, importa getPrisma desde tu paquete de base de datos y llámalo para obtener un cliente Prisma con tipos seguros:

    import { getPrisma } from ':my-scope/db';
    const prisma = await getPrisma();
    const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });

    getPrisma() devuelve un cliente inicializado de forma perezosa y en caché. Las llamadas subsiguientes dentro del mismo contexto de ejecución Lambda reutilizan el pool de conexiones existente en lugar de abrir uno nuevo.

    El cliente Prisma expone modelos completamente tipados derivados de tu esquema prisma/models/, brindándote seguridad de tipos de extremo a extremo desde la base de datos hasta la respuesta de tu API.

    El generador de base de datos relacional crea infraestructura CDK o Terraform basada en tu iacProvider seleccionado.

    El constructo CDK se crea en common/constructs. Ejemplo de uso:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    export class ApplicationStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
    ...
    const db = new MyDatabase(this, 'Db', {
    vpc,
    vpcSubnets: {
    subnetType: SubnetType.PRIVATE_ISOLATED,
    }
    });
    }
    }

    Esto aprovisiona un clúster Aurora con RDS Proxy, credenciales de administrador, usuario de base de datos de aplicación, registro de configuración en tiempo de ejecución y manejador de migraciones.

    La infraestructura generada crea dos usuarios de base de datos:

    • Usuario administrador - Creado durante el aprovisionamiento del clúster con credenciales almacenadas en AWS Secrets Manager
    • Usuario de aplicación - Creado a través de un recurso personalizado Lambda con autenticación IAM habilitada y privilegios DML (SELECT, INSERT, UPDATE, DELETE) en la base de datos de aplicación

    El usuario de aplicación se crea automáticamente con un nombre aleatorio y autenticación IAM. El cliente de base de datos generado ya está configurado para autenticarse como este usuario usando tokens RDS de corta duración, por lo que tu código de aplicación nunca maneja contraseñas de base de datos.

    Tu VPC debe incluir subredes públicas, subredes privadas con salida y subredes privadas aisladas. La base de datos puede ejecutarse en subredes privadas aisladas, mientras que las funciones Lambda de aplicación deben ejecutarse en subredes privadas con salida para que puedan alcanzar servicios de AWS como AppConfig.

    packages/infra/src/stacks/application-stack.ts
    const vpc = new Vpc(this, 'Vpc', {
    subnetConfiguration: [
    {
    name: 'public',
    subnetType: SubnetType.PUBLIC,
    },
    {
    name: 'private_with_egress',
    subnetType: SubnetType.PRIVATE_WITH_EGRESS,
    },
    {
    name: 'private_isolated',
    subnetType: SubnetType.PRIVATE_ISOLATED,
    },
    ],
    });

    Usa el generador connection para conectar un proyecto a esta base de datos — consulta la guía de conexión para el tipo de cómputo relevante (por ejemplo, FastAPI, servidor MCP, agente) para el cableado de infraestructura requerido para alcanzarla.

    La imagen Docker construida para este proyecto se escanea en busca de vulnerabilidades como parte de la construcción usando Trivy, ejecutándose desde la imagen Trivy alojada en ECR.

    Se agrega un target trivy a tu proyecto que escanea la imagen construida y falla la construcción si se encuentra alguna vulnerabilidad de severidad HIGH o CRITICAL. El Dockerfile generado utiliza una imagen base sin vulnerabilidades corregibles conocidas de estas severidades al momento de la generación, y actualiza las herramientas incluidas (como npm) para mantenerlo así.

    El escaneo utiliza el mismo motor de contenedores que tu construcción de imagen (docker o finch), por lo que no se requieren herramientas adicionales. Dado que el escaneo solo se vuelve a ejecutar cuando la imagen cambia, una imagen sin cambios no se vuelve a escanear.

    Puede haber casos en los que desees suprimir una vulnerabilidad específica, por ejemplo, cuando aún no hay una corrección disponible y has evaluado el riesgo como aceptable.

    Agrega el ID de vulnerabilidad (uno por línea) al archivo .trivyignore en la raíz de tu proyecto (es decir, junto a tu project.json):

    .trivyignore
    # node-tar arbitrary file write - not exploitable in our usage
    CVE-2024-XXXXX

    Para más detalles sobre el filtrado de hallazgos, consulta la documentación de filtrado de Trivy.

    La infraestructura generada incluye un RDS Proxy de forma predeterminada, que se sitúa entre tu aplicación y el clúster Aurora. RDS Proxy proporciona varios beneficios:

    • Agrupación de conexiones - Mantiene un pool de conexiones de base de datos que pueden compartirse entre instancias de aplicación, reduciendo la sobrecarga de establecer nuevas conexiones
    • Resiliencia de conexión - Maneja automáticamente las conmutaciones por error y reconexiones durante reemplazos de instancias Aurora o mantenimiento
    • Autenticación IAM - Admite autenticación de base de datos basada en IAM, eliminando la necesidad de gestionar credenciales de base de datos en el código de tu aplicación
    • Seguridad mejorada - Aplica cifrado TLS para todas las conexiones

    Puedes deshabilitar el proxy RDS de la siguiente manera:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableRdsProxy: false,
    });

    Cuando RDS Proxy está deshabilitado, tu aplicación se conecta directamente al endpoint del clúster Aurora.

    Cuando te conectas directamente al clúster Aurora (sin RDS Proxy), el runtime que llama a getPrisma() debe confiar en el paquete CA de Amazon RDS. El cliente Prisma generado habilita la verificación de certificados; cómo hacer que el paquete CA esté disponible depende del runtime que se conecta a la base de datos.

    Para Amazon RDS, usa el paquete CA global desde:

    https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

    Si preparas tu propia imagen de contenedor para el runtime, descarga el paquete CA de RDS en tu Dockerfile y agrégalo al almacén de confianza del sistema operativo.

    RUN curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \
    -o /etc/pki/ca-trust/source/anchors/rds-bundle.pem && \
    update-ca-trust

    Para funciones Lambda comprimidas usando runtimes de Node.js 20 o posterior, carga el paquete CA de Amazon RDS configurando NODE_EXTRA_CA_CERTS:

    packages/infra/src/stacks/application-stack.ts
    const api = new Api(this, 'Api', {
    integrations: Api.defaultIntegrations(this)
    .withDefaultOptions({
    environment: {
    NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
    },
    })
    .build(),
    });

    Para más detalles, consulta los requisitos SSL/TLS para conexiones de Amazon RDS de AWS Lambda. Cuando uses RDS Proxy, no necesitas configurar el paquete CA de RDS en el runtime que se conecta a la base de datos.

    Configure las instancias de escritura y lectura para su clúster Aurora.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    writer: ClusterInstance.serverlessV2('writer'),
    readers: [ClusterInstance.serverlessV2('reader')],
    });

    Controla los límites de escalado de Aurora Serverless v2 para adaptarse a tu carga de trabajo.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    serverlessV2MinCapacity: 0.5,
    serverlessV2MaxCapacity: 8,
    });

    Fija una versión específica del motor Aurora.

    Por defecto, la imagen del contenedor de base de datos local generada coincide con la versión predeterminada del motor Aurora. Si cambias la versión del motor Aurora, se recomienda también usar una versión de imagen de contenedor local que coincida para máxima compatibilidad. Consulta las notas de lanzamiento de AWS para versiones de Aurora PostgreSQL y versiones de Aurora MySQL para identificar la versión correspondiente de la base de datos comunitaria.

    La imagen de la base de datos local se configura en el campo localDev.image del archivo config.json generado en la raíz de tu proyecto de base de datos. Actualiza ese valor cuando cambies las versiones del motor.

    engine = postgres
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraPostgresEngineVersion.VER_17_7,
    });
    engine = mysql
    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,
    });

    La protección contra eliminación está habilitada por defecto (deletionProtection: true en CDK, deletion_protection = true en Terraform) para proteger el clúster de Aurora de eliminaciones accidentales.

    Deshabilitar la Protección contra Eliminación

    Sección titulada «Deshabilitar la Protección contra Eliminación»

    Puede deshabilitar la protección contra eliminación para entornos donde se espera la eliminación de la base de datos, como stacks de desarrollo o preview de corta duración.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    deletionProtection: false,
    });

    El constructo CDK retiene el clúster Aurora por defecto (removalPolicy: RemovalPolicy.RETAIN). Cambia esto cuando quieras que la eliminación del stack CDK haga una instantánea o destruya el clúster en su lugar.

    Cuando uses RemovalPolicy.DESTROY, la protección contra eliminación también debe estar deshabilitada antes de que el clúster pueda ser eliminado.

    packages/infra/src/stacks/application-stack.ts
    import { RemovalPolicy } from 'aws-cdk-lib';
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    removalPolicy: RemovalPolicy.SNAPSHOT,
    });

    Para un entorno efímero donde la base de datos debe ser eliminada con el stack:

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

    Performance Insights está habilitado en la instancia de escritura de Aurora de forma predeterminada (cifrado con la clave KMS del clúster). También puede exportar los registros del motor de Aurora a CloudWatch Logs (postgresql para Aurora PostgreSQL; audit, error, general y slowquery para Aurora MySQL). Habilite la exportación de registros por base de datos:

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableCloudwatchLogs: true,
    enablePerformanceInsights: false, // disable if not required
    });

    La clave KMS utilizada para cifrar el clúster Aurora y su secreto de credenciales tiene la rotación automática de claves habilitada por defecto. Deshabilítela si su política de seguridad gestiona la rotación externamente.

    packages/infra/src/stacks/application-stack.ts
    import { MyDatabase } from ':my-scope/common-constructs';
    const db = new MyDatabase(this, 'Db', {
    ...
    enableKeyRotation: false,
    });
    engine = mysql

    Al usar Aurora MySQL con respuestas de streaming de API Gateway (por ejemplo, con httpBatchStreamLink de tRPC), el cliente MySQL de Prisma retiene el bucle de eventos de Node.js después de que se completa una consulta, evitando que Lambda vacíe el stream y finalice la solicitud.

    Para solucionar esto, desconecta explícitamente el cliente en un bloque finally después de cada consulta para que el bucle de eventos esté libre para salir y la respuesta de streaming pueda completarse.

    Opción 1: por procedimiento

    export const listExampleTable = publicProcedure
    .output(z.array(ExampleTableSchema))
    .query(async () => {
    const prisma = await getPrisma();
    try {
    return await prisma.exampleTable.findMany();
    } finally {
    await prisma.$disconnect();
    }
    });

    Opción 2: middleware de tRPC

    Si estás usando el patrón de middleware, agrega la llamada $disconnect() al middleware para que todos los procedimientos construidos sobre él estén cubiertos automáticamente:

    packages/api/src/middleware/db.ts
    import { getPrisma } from ':my-scope/db';
    import { initTRPC } from '@trpc/server';
    export interface IDbContext {
    db: Awaited<ReturnType<typeof getPrisma>>;
    }
    export const createDbPlugin = () => {
    const t = initTRPC.context<IDbContext>().create();
    return t.procedure.use(async (opts) => {
    const db = await getPrisma();
    try {
    return await opts.next({
    ctx: {
    ...opts.ctx,
    db,
    },
    });
    } finally {
    await db.$disconnect();
    }
    });
    };

    Los tokens de autenticación IAM de RDS expiran después de 15 minutos. El cliente Prisma de MySQL captura el token IAM como un valor estático en el momento en que se llama a getPrisma(). Una conexión abierta existente no se ve afectada, pero si se necesita establecer una nueva conexión después de que el token haya expirado, la autenticación fallará. El adaptador de PostgreSQL evita esto refrescando el token dinámicamente cada vez que el pool abre una nueva conexión, pero el adaptador de MySQL no tiene un mecanismo equivalente.

    Para tareas de larga duración como trabajos por lotes o migraciones de datos, llama a getPrisma() al inicio de cada unidad de trabajo en lugar de una vez para toda la operación. Debido a que getPrisma() siempre crea un cliente nuevo y obtiene un nuevo token IAM para MySQL, esto asegura que cada conexión se autentique con un token válido.

    Usa el generador connection para integrar este proyecto con otros en tu workspace. Las siguientes conexiones involucran este proyecto:

    tRPCAmazon Aurora
    API tRPC a Base de Datos RelacionalConecta una API tRPC a una base de datos relacional Aurora
    SmithyAmazon Aurora
    API Smithy a Base de Datos RelacionalConecta una API Smithy a una base de datos relacional Aurora
    Strands AgentsTypeScriptAmazon Aurora
    TypeScript Agent a Base de Datos RelacionalConecta un TypeScript Agent a una base de datos relacional Aurora
    Model Context ProtocolAmazon Aurora
    Servidor MCP a Base de Datos RelacionalConecta un Servidor MCP en TypeScript a una base de datos relacional Aurora