TypeScript 关系型数据库
此生成器创建一个由 Amazon Aurora(PostgreSQL 或 MySQL)和 Prisma ORM 支持的新关系型数据库项目。它生成使用 AWS CDK 或 Terraform 配置和管理数据库所需的应用程序代码和基础设施,具有声明式架构定义、自动迁移部署和类型安全的 ORM 客户端。
生成关系数据库
Section titled “生成关系数据库”您可以通过两种方式生成新的关系数据库项目:
- 安装 Nx Console VSCode Plugin 如果您尚未安装
- 在VSCode中打开Nx控制台
- 点击
Generate (UI)在"Common Nx Commands"部分 - 搜索
@aws/nx-plugin - ts#rdb - 填写必需参数
- 点击
Generate
pnpm nx g @aws/nx-plugin:ts#rdbyarn nx g @aws/nx-plugin:ts#rdbnpx nx g @aws/nx-plugin:ts#rdbbunx nx g @aws/nx-plugin:ts#rdb| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| name 必需 | string | - | 要生成的数据库项目名称 |
| directory | string | packages | 存储应用程序的目录。 |
| subDirectory | string | - | 项目所在的子目录。默认为项目名称。 |
| infra | aurora | none | aurora | 要配置的关系数据库服务。 |
| engine | postgres | mysql | postgres | 与所选服务一起使用的数据库引擎。 |
| databaseUser | string | dbadmin | 数据库管理员用户名。默认为 'dbadmin'。 |
| databaseName | string | - | 初始数据库名称。默认为项目名称。 |
| framework | prisma | prisma | 用于生成项目的 ORM 框架。 |
| iac | inherit | cdk | terraform | inherit | 首选的 IaC 提供商。默认情况下,这继承自您的初始选择。 |
| preferInstallDependencies | boolean | true | 是否在生成器运行后优先安装依赖项。设置为 false 可在批量运行多个生成器时延迟安装(如果后续生成器需要计算 Nx 项目图,仍会运行安装);在最后统一安装一次。 |
生成器将在 <directory>/<name> 目录中创建以下项目结构:
文件夹prisma
文件夹models
- example.prisma 示例模型定义
- schema.prisma 主 Prisma 架构(引用模型)
文件夹src
- index.ts 项目入口点
- prisma.ts Prisma 运行时客户端包装器
- utils.ts 运行时配置和密钥助手
- create-db-user-handler.ts 用于在部署期间创建应用程序数据库用户的 Lambda 处理程序
- migration-handler.ts 用于在部署期间运行数据库迁移的 Lambda 处理程序
- .gitignore Git 忽略条目,包括生成的 Prisma 客户端输出
- config.json 本地开发连接详细信息和运行时配置键
- Dockerfile 迁移处理程序的容器镜像定义
- project.json 项目配置和构建目标
- prisma.config.ts Prisma CLI 的配置
本地开发脚本在所有数据库项目之间共享,并生成到 packages/common/scripts/ 中:
文件夹packages/common/scripts/src/rdb
- pull-image.ts 拉取数据库容器镜像
- start-container.ts 启动本地数据库容器
- wait-for-postgres-db.ts 等待本地数据库准备就绪(PostgreSQL)
- wait-for-mysql-db.ts 等待本地数据库准备就绪(MySQL)
由于该生成器会根据您选择的 iacProvider 以基础设施即代码的形式输出,它将在 packages/common 目录下创建一个包含相关 CDK 构造体或 Terraform 模块的项目。
通用的基础设施即代码项目结构如下:
文件夹packages/common/constructs
文件夹src
文件夹app/ 针对特定项目/生成器的基础设施构造体
- …
文件夹core/ 被
app目录构造体重用的通用构造体- …
- index.ts 导出
app目录构造体的入口文件
- project.json 项目构建目标与配置
文件夹packages/common/terraform
文件夹src
文件夹app/ 针对特定项目/生成器的 Terraform 模块
- …
文件夹core/ 被
app目录模块重用的通用模块- …
- project.json 项目构建目标与配置
文件夹packages/common/constructs/src
文件夹app
文件夹dbs
- <name>.ts 特定于您的数据库的基础设施
文件夹core
文件夹rdb
- aurora.ts 通用 Aurora 数据库构造
文件夹packages/common/terraform/src
文件夹app
文件夹dbs
文件夹<name>
- <name>.tf 特定于您的数据库的模块
文件夹core
文件夹rdb
文件夹aurora
- aurora.tf 通用 Aurora 模块
已部署的数据库具有以下架构。默认情况下,Amazon RDS Proxy 位于 Aurora 集群前面,用于池化连接并启用 IAM 身份验证 — 有关替代方案,请参阅禁用 RDS Proxy。无论您选择 PostgreSQL 还是 MySQL 引擎,架构都是相同的;只有 Aurora 引擎类型不同。
生成的项目使用 Prisma ORM 来定义数据库架构并生成类型安全的客户端。工作流程是模型优先的:在数据库项目的 prisma/models/ 目录下添加或更新 Prisma 模型文件,然后从这些模型更改生成迁移。
User 模型示例:
model User { id Int @id @default(autoincrement()) firstName String lastName String}有关更多详细信息,请参阅官方 Prisma 数据建模指南。
生成数据库客户端
Section titled “生成数据库客户端”生成器会自动配置 generate 目标,以便在构建项目时创建类型安全的 TypeScript Prisma 客户端。客户端被写入 generated/prisma(已添加到 .gitignore)。
您也可以随时手动生成客户端:
pnpm nx generate <your-db-project-name>yarn nx generate <your-db-project-name>npx nx generate <your-db-project-name>bunx nx generate <your-db-project-name>使用 prisma 目标从工作区根目录运行 Prisma CLI 命令:
pnpm nx run <project>:prisma generateyarn nx run <project>:prisma generatenpx nx run <project>:prisma generatebunx nx run <project>:prisma generatesrc/prisma.ts 中的运行时包装器导出:
getPrisma()- 从 AWS AppConfig 加载数据库连接设置并使用 IAM 认证创建 Prisma 客户端
客户端自动:
- 使用
RUNTIME_CONFIG_APP_ID环境变量从 AWS AppConfig 检索数据库配置 - 通过 AWS RDS Signer 生成临时认证令牌以进行 IAM 认证
- 通过证书验证管理 SSL/TLS 连接
- 通过持久数据库连接池处理连接池
在 prisma/models/ 下添加或更新模型后,使用 migrate dev 生成迁移文件并同时将它们应用到本地数据库。
生成的 prisma 目标会在运行前自动启动本地数据库容器:
pnpm nx run <project>:prisma migrate devyarn nx run <project>:prisma migrate devnpx nx run <project>:prisma migrate devbunx nx run <project>:prisma migrate dev如果您只想生成迁移文件而不将它们应用到本地数据库,请添加 --create-only:
pnpm nx run <project>:prisma migrate dev --create-onlyyarn nx run <project>:prisma migrate dev --create-onlynpx nx run <project>:prisma migrate dev --create-onlybunx nx run <project>:prisma migrate dev --create-only这会在每次架构更改时在 prisma/migrations 中生成一个新的迁移文件夹:
文件夹prisma
文件夹migrations
文件夹20260405013911_initial_migrations
- migration.sql
- migration_lock.toml
- schema.prisma
当您部署 AWS 堆栈时,生成的基础设施会自动将生成的迁移应用到已部署的数据库。
应用现有迁移
Section titled “应用现有迁移”当您拉取其他开发人员创建的迁移文件时,使用 migrate deploy 将这些现有迁移应用到本地数据库。
pnpm nx run <project>:prisma migrate deployyarn nx run <project>:prisma migrate deploynpx nx run <project>:prisma migrate deploybunx nx run <project>:prisma migrate deploy在此本地开发流程中,migrate deploy 将迁移文件应用到本地数据库;它不会将数据库部署到 AWS。
运行 Prisma 命令
Section titled “运行 Prisma 命令”生成的 prisma 目标公开了 Prisma CLI,因此您可以使用它对本地数据库运行 Prisma 支持的任何命令。有关可用命令,请参阅 Prisma CLI 参考。
pnpm nx run <project>:prisma <prisma-command>yarn nx run <project>:prisma <prisma-command>npx nx run <project>:prisma <prisma-command>bunx nx run <project>:prisma <prisma-command>使用 Prisma Studio
Section titled “使用 Prisma Studio”Prisma Studio 是本地数据库的可视化编辑器。使用它浏览表、检查和编辑记录、过滤数据、跟踪关系,并通过内置 SQL 控制台运行原始 SQL。它对于在开发期间验证迁移和填充测试数据很有用。使用以下命令启动它:
pnpm nx run <project>:prisma studioyarn nx run <project>:prisma studionpx nx run <project>:prisma studiobunx nx run <project>:prisma studio停止本地数据库
Section titled “停止本地数据库”停止 dev(例如使用 Ctrl+C)会自动删除本地数据库容器,但保留命名卷,因此您的数据在重启后仍然保留。
连接到数据库
Section titled “连接到数据库”在任何 TypeScript 项目中,从数据库包导入 getPrisma 并调用它以获取类型安全的 Prisma 客户端:
import { getPrisma } from ':my-scope/db';
const prisma = await getPrisma();const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });getPrisma() 返回一个延迟初始化的缓存客户端。在同一 Lambda 执行上下文中的后续调用会重用现有连接池,而不是打开新连接。
Prisma 客户端公开从您的 prisma/models/ 架构派生的完全类型化模型,为您提供从数据库一直到 API 响应的端到端类型安全。
部署您的数据库
Section titled “部署您的数据库”关系型数据库生成器会根据您选择的 iacProvider 创建 CDK 或 Terraform 基础设施。
CDK 构造在 common/constructs 中创建。示例用法:
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, } }); }}这将配置一个 Aurora 集群,包含 RDS Proxy、管理员凭证、应用程序数据库用户、运行时配置注册和迁移处理程序。
生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 自定义资源创建,启用 IAM 身份验证,并对应用程序数据库具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
Terraform 模块在 common/terraform 中创建。示例用法:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
vpc_id = module.vpc.vpc_id database_subnet_ids = module.vpc.private_isolated_subnet_ids lambda_subnet_ids = module.vpc.private_subnet_ids
tags = local.common_tags}这将配置一个 Aurora 集群,包含 RDS Proxy、管理员凭证、create-db-user Lambda、运行时配置注册、迁移 Lambda 和容器注册表资源。
生成的基础设施会创建两个数据库用户:
- 管理员用户 - 在集群配置期间创建,凭证存储在 AWS Secrets Manager 中
- 应用程序用户 - 通过 Lambda 函数创建,启用 IAM 身份验证,并对应用程序数据库具有 DML 权限(SELECT、INSERT、UPDATE、DELETE)
应用程序用户会自动创建,使用随机名称和 IAM 身份验证。生成的数据库客户端已配置为使用短期 RDS 令牌以该用户身份进行身份验证,因此您的应用程序代码永远不会处理数据库密码。
您的 VPC 应包括公有子网、具有出口的私有子网和私有隔离子网。数据库可以在私有隔离子网中运行,而应用程序 Lambda 函数应在具有出口的私有子网中运行,以便它们可以访问 AWS 服务(如 AppConfig)。
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, }, ],});module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 6.0"
name = "app" ... public_subnet_names = ["public"] private_subnet_names = ["private_with_egress"] intra_subnet_names = ["private_isolated"]
enable_nat_gateway = true single_nat_gateway = true}使用 connection 生成器将项目连接到此数据库 — 请参阅相关计算类型(例如 FastAPI、MCP 服务器、代理)的连接指南,了解访问数据库所需的基础设施配置。
RDS Proxy 配置
Section titled “RDS Proxy 配置”生成的基础设施默认包含一个 RDS Proxy,它位于您的应用程序和 Aurora 集群之间。RDS Proxy 提供以下几个优势:
- 连接池 - 维护一个可在应用程序实例之间共享的数据库连接池,减少建立新连接的开销
- 连接弹性 - 在 Aurora 实例替换或维护期间自动处理故障转移和重新连接
- IAM 身份验证 - 支持基于 IAM 的数据库身份验证,无需在应用程序代码中管理数据库凭证
- 增强的安全性 - 对所有连接强制执行 TLS 加密
禁用 RDS Proxy
Section titled “禁用 RDS Proxy”您可以按如下方式禁用 RDS 代理:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});当 RDS Proxy 被禁用时,您的应用程序将直接连接到 Aurora 集群端点。
默认情况下,RDS Proxy 是启用的。如果需要,您可以禁用它:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}当 RDS Proxy 被禁用时,您的应用程序将直接连接到 Aurora 集群端点。
在不使用 RDS Proxy 的情况下连接时的 SSL 要求
Section titled “在不使用 RDS Proxy 的情况下连接时的 SSL 要求”当直接连接到 Aurora 集群(不使用 RDS Proxy)时,调用 getPrisma() 的运行时必须信任 Amazon RDS CA 捆绑包。生成的 Prisma 客户端启用证书验证;如何使 CA 捆绑包可用取决于连接到数据库的运行时。
对于 Amazon RDS,请使用以下全局 CA 捆绑包:
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem运行时容器镜像
Section titled “运行时容器镜像”如果您为运行时准备自己的容器镜像,请在 Dockerfile 中下载 RDS CA 捆绑包并将其添加到操作系统信任存储中。
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-trustRUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \ rm -rf /var/lib/apt/lists/* && \ curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \ -o /usr/local/share/ca-certificates/rds-bundle.crt && \ update-ca-certificates压缩的 Lambda 函数
Section titled “压缩的 Lambda 函数”对于使用 Node.js 20 或更高版本运行时的压缩 Lambda 函数,通过设置 NODE_EXTRA_CA_CERTS 加载 Amazon RDS CA 捆绑包:
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this) .withDefaultOptions({ environment: { NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem', }, }) .build(),});module "api" { source = "..." ...
environment_variables = { NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem" }}有关更多详细信息,请参阅 AWS Lambda Amazon RDS 连接的 SSL/TLS 要求。使用 RDS Proxy 时,您无需在连接到数据库的运行时中配置 RDS CA 捆绑包。
为您的 Aurora 集群配置写入器和读取器实例。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... writer: ClusterInstance.serverlessV2('writer'), readers: [ClusterInstance.serverlessV2('reader')],});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... instance_count = 2 # 1 writer + 1 reader}无服务器容量
Section titled “无服务器容量”控制 Aurora Serverless v2 扩展限制以匹配您的工作负载。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... serverlessV2MinCapacity: 0.5, serverlessV2MaxCapacity: 8,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... serverless_min_capacity = 0.5 serverless_max_capacity = 8}固定特定的 Aurora 引擎版本。
默认情况下,生成的本地数据库容器镜像与默认的 Aurora 引擎版本匹配。如果您更改 Aurora 引擎版本,建议同时使用匹配的本地容器镜像版本以获得最大兼容性。请参阅 AWS 发布说明中的 Aurora PostgreSQL 版本 和 Aurora MySQL 版本 以确定相应的社区数据库版本。
本地数据库镜像在数据库项目根目录下生成的 config.json 文件的 localDev.image 字段中配置。当您更改引擎版本时,请更新该值。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraPostgresEngineVersion.VER_17_7,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "17.7"}import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "8.0.mysql_aurora.3.12.0"}默认情况下启用删除保护(CDK 中为 deletionProtection: true,Terraform 中为 deletion_protection = true),以保护 Aurora 集群免遭意外删除。
禁用删除保护
Section titled “禁用删除保护”您可以为预期会删除数据库的环境禁用删除保护,例如短期开发或预览堆栈。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false}CDK 构造默认保留 Aurora 集群(removalPolicy: RemovalPolicy.RETAIN)。当您希望 CDK 堆栈删除时对集群进行快照或销毁时,请更改此设置。
使用 RemovalPolicy.DESTROY 时,还必须在删除集群之前禁用删除保护。
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});对于应随堆栈一起删除数据库的临时环境:
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});Terraform 不使用 CDK 删除策略。默认情况下,模块在删除时创建最终快照(skip_final_snapshot = false)。要跳过临时环境的最终快照:
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}日志记录和监控
Section titled “日志记录和监控”默认情况下,Performance Insights 在 Aurora 写入实例上启用(使用集群的 KMS 密钥加密)。您还可以将 Aurora 引擎日志导出到 CloudWatch Logs(Aurora PostgreSQL 使用 postgresql;Aurora MySQL 使用 audit、error、general 和 slowquery)。为每个数据库启用日志导出:
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableCloudwatchLogs: true, enablePerformanceInsights: false, // disable if not required});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_cloudwatch_logs = true enable_performance_insights = false # disable if not required}加密密钥轮换
Section titled “加密密钥轮换”用于加密 Aurora 集群及其凭证密钥的 KMS 密钥默认启用自动密钥轮换。如果您的安全策略在外部管理轮换,请禁用它。
import { MyDatabase } from ':my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableKeyRotation: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_key_rotation = false}MySQL:API Gateway 流式模式
Section titled “MySQL:API Gateway 流式模式”当将 Aurora MySQL 与 API Gateway 流式响应(例如使用 tRPC 的 httpBatchStreamLink)一起使用时,Prisma MySQL 客户端在查询完成后会保持 Node.js 事件循环,从而阻止 Lambda 刷新流并结束请求。
要解决此问题,在每次查询后在 finally 块中显式断开客户端连接,以便事件循环可以自由退出并完成流式响应。
选项 1:每个过程
export const listExampleTable = publicProcedure .output(z.array(ExampleTableSchema)) .query(async () => { const prisma = await getPrisma(); try { return await prisma.exampleTable.findMany(); } finally { await prisma.$disconnect(); } });选项 2:tRPC 中间件
如果您使用中间件模式,请将 $disconnect() 调用添加到中间件,以便基于它构建的所有过程都会自动覆盖:
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(); } });};MySQL:IAM 令牌过期
Section titled “MySQL:IAM 令牌过期”RDS IAM 认证令牌在 15 分钟后过期。MySQL Prisma 客户端在调用 getPrisma() 时将 IAM 令牌捕获为静态值。现有的打开连接不受影响,但如果在令牌过期后需要建立新连接,认证将失败。PostgreSQL 适配器通过在池每次打开新连接时动态刷新令牌来避免这种情况,但 MySQL 适配器没有等效机制。
对于长时间运行的任务(如批处理作业或数据迁移),在每个工作单元开始时调用 getPrisma(),而不是为整个操作调用一次。因为 getPrisma() 总是为 MySQL 创建一个新客户端并获取新的 IAM 令牌,这确保每个连接都使用有效的令牌进行认证。
使用 connection 生成器将此项目与工作区中的其他项目集成。以下连接涉及此项目: