@aws-blocks/bb-data

中文文档
0.5.0发布于 2026/11/02Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 6.4万

完整的 PostgreSQL 数据库——默认情况下提供 Aurora Serverles v2,或连接到现有的 PostgreSQL 数据库(Supabase, Neon等) 通过 fromExisting()。 与外国密钥、交易、行级安全以及打字机建立完整的关系模型

中文使用文档
文档目录15 节
  1. 快速启动
  2. 移徙
  3. Kysely 查询构建器
  4. 行级安全( RLS)
  5. CRUD 处理器
  6. 连接到现有数据库
  7. TLS 证书验证
  8. 从Supabase迁移
  9. 处理错误
  10. 它的规定
  11. 地方发展
  12. 本地对 AWS: 列类型
  13. 配置
  14. 软件包导出条件
  15. 业绩

@aws- blocks/ bb- data (原始内容存档于2018-09-28) (英语)

完整的 PostgreSQL 数据库——默认情况下提供 Aurora Serverles v2,或连接到现有的 PostgreSQL 数据库(Supabase, Neon等) 通过 fromExisting()。与外国密钥、交易、行级安全以及一个类型安全的 Kysely 查询构建器建立完整的关系模型.

何时使用 : 复杂的多表JOIN,ACID交易,外接键约束,聚合,行级安全,或连接到现有的PostgreSQL数据库. 需要PostgreSQL全能时使用.

不使用时 : 用于简单的密钥值检查, 使用 KVStore。对于带有二级索引的 NoSQL,使用 DistributedTable对于没有FK/RLS/触发器的无服务器 SQL(多区域,即时提供),使用 DistributedDatabase。 。 。 .

设计与模拟等价细节 : 设计

快速启动

import { Database, sql } from '@aws-blocks/bb-data';

const db = new Database(scope, 'main', {
  migrationsPath: './aws-blocks/migrations',
});

// Parameterized queries via sql tagged template (injection-safe)
const users = await db.query<{ id: string; name: string }>(
  sql`SELECT * FROM users WHERE active = ${true}`
);

const user = await db.queryOne<{ id: string; name: string }>(
  sql`SELECT * FROM users WHERE id = ${userId}`
);

const { rowCount } = await db.execute(
  sql`INSERT INTO users (id, name, email) VALUES (${id}, ${name}, ${email})`
);

// Transactions
await db.transaction(async (tx) => {
  await tx.execute(sql`UPDATE accounts SET balance = balance - ${100} WHERE id = ${fromId}`);
  await tx.execute(sql`UPDATE accounts SET balance = balance + ${100} WHERE id = ${toId}`);
});

移徙

创建编号 .sql 迁移目录中的文件 :

aws-blocks/migrations/
  001_create_users.sql
  002_create_posts.sql
  003_seed_admin.sql
-- 001_create_users.sql
CREATE TABLE users (
  id TEXT PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

迁移自动运行 :

  • 本地 dev : 在第一次查询时( PGlite, 坚持在 .bb-data/(中文(简体) )
  • AWS部署: 期间使用自定义资源 Lambda cdk deploy

应用迁移情况在以下表格中跟踪: _migrations 页:1 每个文件运行一次.

设定 migrationsPath 与工程根相对的路径 (如"快起步"—— './aws-blocks/migrations'); 由您运行的目录合成解析 cdk 编号 : npm run deploy 进来 这是最简单的可靠模式.

你用不着 fileURLToPath(import.meta.url) 为了这个 您的后端模块在当地作为无害环境管理运行,但捆绑到 常见JS 在兰布达,在那里 import.meta 为空。 AWS 屏蔽闪烁 import.meta.url 编号 : import.meta.dirname {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}所以它不会在装货时坠毁 {\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}但是在运行时 捆绑输出 位置,而不是您的源树。 所以别用 import.meta.url 在请求的时间读取与您来源相关的文件; 输入数据或将其作为Lambda资产.

Kysely 查询构建器

对于没有原始 SQL 的类型安全查询:

import { createKyselyAdapter } from '@aws-blocks/bb-data';

interface Schema {
  users: { id: string; email: string; name: string };
  posts: { id: string; user_id: string; title: string };
}

const kysely = createKyselyAdapter<Schema>(db);

// Type-safe SELECT
const users = await kysely
  .selectFrom('users')
  .where('email', '=', '[email protected]')
  .selectAll()
  .execute();

// JOINs
const posts = await kysely
  .selectFrom('posts')
  .innerJoin('users', 'users.id', 'posts.user_id')
  .select(['posts.title', 'users.name'])
  .execute();

// Transactions
await kysely.transaction().execute(async (trx) => {
  await trx.insertInto('users').values({ id: '1', email: '[email protected]', name: 'A' }).execute();
  await trx.insertInto('posts').values({ id: '1', user_id: '1', title: 'Hello' }).execute();
});

见 Kysely 文档 用于完整查询构建器 API.

行级安全( RLS)

与 Supabase 兼容会话变量的用户背景范围查询 :

const scoped = db.withRLS({ userId: 'user-123', role: 'authenticated' });

// All queries on `scoped` run inside a transaction with SET LOCAL ROLE
// and request.jwt.claims set — PostgreSQL RLS policies are enforced.
const myPosts = await scoped.query<Post>(sql`SELECT * FROM posts`);

request.jwt.claims 总是带着 sub =: userId 财务报告和审定财务报表 role = 数字 role 你通过。 额外 claims 被合并,但他们不能 覆盖这两个:a sub 或者说 role 键入 claims 被忽略。 因此政策可以信任两者,例如: USING (owner_id = current_setting('request.jwt.claims', true)::jsonb ->> 'sub')。当您从身份提供者处转发请求时,将特定提供者的值置于他们自己的密钥下(例如 claims: { idp_sub: token.sub }) (中文(简体) ).

先决条件(当地和AWS): withRLS 问题 SET LOCAL ROLE <role> (默认) authenticated) (中文(简体) ). 该角色必须存在,数据库用户必须是其中的一员. 在 PostgreSQL 16 上,以及Aurora 运行后,创建角色的用户只获得 ADMIN 上面没有 SET,所以明确赋予角色。 在您的迁移中添加:

CREATE ROLE authenticated;
CREATE ROLE anon;
GRANT authenticated TO CURRENT_USER;
GRANT anon TO CURRENT_USER;
-- grant table privileges to these roles as needed, then define RLS policies

如果角色切换被拒绝, 每个 withRLS() 调用 500 失败 QueryFailed,而服务器日志为缺失的 GRANT。 。 。 .

CRUD 处理器

从计划定义中生成输入的 CRUD 方法 :

const crud = db.crud({
  tables: ['users', 'posts'],
  // `auth` takes no arguments — close over your request context to resolve the user.
  auth: async () => {
    const user = await auth.requireAuth(context);
    return { userId: user.userId };
  },
});

// Auto-generated flat method names per table:
//   crud.listUsers(), crud.getUser(id), crud.createUser(data),
//   crud.updateUser(id, data), crud.deleteUser(id)
//   crud.listPosts(), crud.getPost(id), ...

连接到现有数据库

import { Database, fromExisting } from '@aws-blocks/bb-data';

// Supabase, Neon, or any PostgreSQL-compatible database
const db = new Database(scope, 'external', {
  connection: fromExisting({ connectionString: process.env.DATABASE_URL! }),
});

TLS 证书验证

服务器的 TLS 证书是 默认验证管理下供应商 (Supabase, neon, RDS) 提交由特定供应商 CA 签名的证书 这不在Node的内置信托店里 所以验证需要打针 那个CA. ssl.ca 获取证书 目录 (一个PEM字符串),不是路径—— 用于Supabase, 下载 prod-ca-2021.crt 从您的项目 数据库设置 — SSL 配置数字 :

import { readFileSync } from 'node:fs';

const db = new Database(scope, 'external', {
  connection: fromExisting({
    connectionString: process.env.DATABASE_URL!,
    ssl: { ca: readFileSync('./supabase-ca.crt', 'utf8') },
  }),
});

bb-data pull 给您接线: 它会提示您的 CA 证书并输入 给 aws-blocks/database.ca.ts (捆绑成 ,所以连接是 默认验证 - 包括: 在部署的Lambda, 没有运行时间配置. DATABASE_CA_CERT (内在 PEM 或文件路径 ) 覆盖已执行的证书 。 如果两者都没有,则 生成的接线返回到 ssl: { rejectUnauthorized: false } (单位:千美元)加密但 未认证仅以本地数据表示 已部署的函数未关闭 (拒绝连接)而不是运行未经验证. 为生产提供CA.

从Supabase迁移

已经有Supabase软件了? bb-data pull 连接到您现有的 Supabase 数据库并生成一个完整、 类型安全的后端 —— 将您的表格、 数据和 RLS 政策保持原样 .

npx bb-data pull

它会做什么:

  • 透视您的公示表( 只读 —— 您的数据库没有被修改)
  • 生成打入的定义、 CRUD 操作和个性化迁移指南
  • 将您的连接字符串保存到本地 SUPABASE_DB_URL 内 .env.local (部署时在SSM中加密). 只有该条目被添加或更新——其他设置、注释和文件的权限被保存 SUPABASE_DB_URL 线条本身是重写整行的,所以其末尾的注释不保存。 若为 .env.local 无法安全更新(例如,更改将改变另一个条目的读取方式), db pull 在生成任何文件之前停止,请您手动设置条目。 选择“ 生产” 对 .env.production。 。 。 .

它不迁移的东西:Supabase Auth、存储、实时或边缘函数。 如果使用第三方的OIDC供应商(Auth0, Clerfer, Google, Cognitto),可以将其接入Blocks——查看生成的 MIGRATION_GUIDE.md#auth。 。 。 .

在拉后,运行 npm run dev 开始根据您真正的数据库本地开发.

调取后, 用版本控制的 SQL 移入管理 ./migrations/ 自动应用 npm run dev 财务报告和审定财务报表 npm run deploy。参见生成 MIGRATION_GUIDE.md#evolving-your-schema。 。 。 .

处理错误

import { DatabaseErrors } from '@aws-blocks/bb-data';
import { isBlocksError } from '@aws-blocks/core';

try {
  await db.execute(sql`INSERT INTO users (id, email) VALUES (${id}, ${email})`);
} catch (e: unknown) {
  if (isBlocksError(e, DatabaseErrors.UniqueConstraintViolation)) {
    // Duplicate key — email already exists. Serialized as HTTP 409 (Conflict),
    // not retriable (a blind retry of the same insert fails identically).
  }
  if (isBlocksError(e, DatabaseErrors.PermissionDenied)) {
    // Your statement was refused: a row-level-security policy rejected the row
    // (for example a withRLS() user writing someone else's row), or the role has
    // no grant on the table. Serialized as HTTP 403.
  }
  if (isBlocksError(e, DatabaseErrors.CheckViolation) || isBlocksError(e, DatabaseErrors.NotNullViolation)) {
    // A value fails a CHECK constraint, or a required column is missing.
    // Serialized as HTTP 400.
  }
  if (isBlocksError(e, DatabaseErrors.ForeignKeyViolation)) {
    // The referenced row doesn't exist, or other rows still reference the one
    // being deleted. Serialized as HTTP 409 (Conflict).
  }
  if (isBlocksError(e, DatabaseErrors.QueryFailed)) {
    // General query failure (syntax error, missing table, etc.)
  }
  if (isBlocksError(e, DatabaseErrors.TransactionFailed)) {
    // Transaction could not commit
  }
  if (isBlocksError(e, DatabaseErrors.SerializationFailure)) {
    // Serializable-isolation conflict with a concurrent transaction — serialized
    // as HTTP 409 (Conflict), retriable — safe to retry
  }
  if (isBlocksError(e, DatabaseErrors.ConnectionFailed)) {
    // Cannot reach the database — includes a `minCapacity: 0` cluster resuming
    // from auto-pause, which succeeds on retry a few seconds later
  }
}

每个错误的客户端可见消息是固定字符串; 驱动程序本身 文本,将表格、列和限制的名称保留在服务器上 错误 cause。仅限 SerializationFailure 财务报告和审定财务报表 ConnectionFailed 价值 重试: 请求出错( r)PermissionDenied, (中文(简体) ), CheckViolation, (中文(简体) ), NotNullViolation, (中文(简体) ), ForeignKeyViolation, (中文(简体) ), UniqueConstraintViolation失败 每次都一样.

每个错误都会中止所附的 Postgres 交易 。 内部a db.transaction() 调回,一个被捕获的错误使交易无法使用: 下个语句因 QueryFailed. 在外接他们 transaction(),或 在保存点中将语句包裹( )SAVEPOINT s . ROLLBACK TO SAVEPOINT s如果 交易应继续下去.

它的规定

  • Aurora 无服务器 v2 ——相容后SQL相容,分级为0.5-128ACU. 存储 休息时加密为 通过上下文旗选择进入 因此,新项目的安全通过 默认不替换已存在的集群。 新设 create-blocks-app 项目 设定 "@aws-blocks/bb-data:encryptStorageByDefault": true 内 cdk.json,哪个 打开账户AWS管理的加密 aws/rds 键。 通过一个 storageEncryptionKeyArn (客户管理的 KMS 密钥的 ARN) 也转动 无论旗帜如何加密并使用该密钥( 它也加密) 生成的证书秘密 。 当国旗或密钥都没有设定时 集群合成时没有 StorageEncrypted 财产(现有, 未加密集群未受影响)和合成警告解释如何选择 进去 关键是 进口 (锁不能改变它的政策),所以它的政策 必须已经授予部署本金 kms:CreateGrant + 键 kms:DescribeKey (RDS使用赠款加密存储量)和赠款 kms:Decrypt 页:1 在数据 API 上读取证书的校长。 钥匙必须在里面 页:1 同一账户和区域 作为集群.
  • 自动备份 ——默认保留 15天时间,这也是 点入时间恢复窗口。 由单人控制 pointInTimeRecovery 选项(模仿所有其他块块): true 启用15天窗口, { retentionDays: n } 针入1至35天窗口 false 夹住1天 最小值( Aurora 无法关闭自动备份) 。 省略时跟随 堆栈宽度 defaults.pointInTimeRecovery (关于 production关闭在下面 sandbox ——最少1天着陆.
  • 云表日志导出 — PostgreSQL 引擎日志被导出到 Cloud Watch 记录 日志组保留跟随整个堆栈 defaults.logRetention 何时 设置;否则它使用账户默认值.
  • 职业介绍所 私人子网(同化,无NAT)
  • 机密管理器 ——自动生成的证书. 尚未自动旋转 接通(在VPC组中旋转Lambda是计划的后续行动) 密钥用您的加密 storageEncryptionKeyArn 当一个被提供.
  • 移徙Lambda —运行 .sql 通过自定义资源部署的文件
  • 行政会议 —— 说 rds-data:* 财务报告和审定财务报表 secretsmanager:GetSecretValue 给Lambda的应用软件

访问模式 : 数据库完全通过 RDS 数据 API 连接 (HTTPS + 机密管理者证书),从不使用原始 Postgres socket. 数据库级别 IAM认证(iamAuthentication因此,它被故意置之不理—— 不适用于 Data API 访问路径.

对现有未加密集群进行加密需要 替换——替换具有破坏性. RDS 无法加密 已经设置了未加密的集群, 因此正在打开存储加密 上( 或更改 KMS 密钥) 使 CloudFormation 创建 新建, 空 加密集群并重点堆栈。 有一个 无位置路径。 。 。 . 旧的集群及其数据将取决于删除政策:

  • 生产(保留): 古老的群落被抛在后头,成为孤儿,没有 更长时间的引用 。 应用程序回来 指向新的 空 分组。 迁移自定义资源 没有 在集群交换中重新运行—— 其唯一的 Cloud Formation 属性是服务符和迁移 散列, 集群被替换时也不会改变, 因此 Cloud Formation 永远不会 引用来. 因此,替换组产生 无计划· ; 仅当移取文件更改时( 更改移取文件) 移取会运行 ) (中文(简体) ). 您的数据仍然存在于孤星群中, 但未被恢复 .
  • 沙盒(DESTROY): (中文(简体) ) 旧数据组及其所有数据为 删除。 。 。 .
  • 抓图( T)removalPolicy: 'snapshot': 旧组图示为 它被替换。 生产 deletionProtection: true后续行动 删除旧集群可能失败并留作原地; 此清理路径是 未经核实的真实部署.

取而代之为相. 将加密调回 关 - 删除 旗帜(或 storageEncryptionKeyArn)来自已经部署的项目 加密,是否通过删除 cdk.json 线条,或者通过一个将它放下的合并—— 并更改 StorageEncrypted 财产,所以 同样取代 分组 (恢复到未加密) 使用相同的新空集群 / no-schema 上述结果。 在删除旗帜前审查 diff 和快照 不仅在添加之前.

唯一安全的路线是将数据传遍你们自己: 简介 页:1 现有集群, 恢复 以加密方式快照到新集群 启用,然后切到它。 检查"云形" diff 并拍摄快照 在将此项更改部署到您需要的数据组之前。 正在添加或 更改 KMS 密钥还替换集群生成的证书密钥( a) 新的逻辑 id, 从而生成新的密码),所以记录现有的 证书——或者在旧集群上重置主密码——如果您仍然 需要进入孤儿群体.

地方发展

  • 引擎 : PGlite (WASM PostgreSQL) —— 完整的 Postgres 兼容性
  • 存储 : .bb-data/{fullId}/ ——坚持跨重启,以擦去 rm -rf .bb-data
  • 移徙: 在第一个查询中自动运行

本地对 AWS: 列类型

阵列和 json 编号 : jsonb 列返回相同的 JavaScript 值 两个引擎。 阵列( R)text[], (中文(简体) ), int[])作为JS阵列回来 json 编号 : jsonb 列作为解析对象返回, 不管你在本地运行 PGlite)或位于RDS数据API上的AWS上. 要素表述仍然遵循 缩写如下——例如:. numeric[] 元素作为字符串回来 数据API.

一些平面数字类型在两者的表示上仍然可能有所不同 引擎 : numeric 编号 : decimal 以字符串的形式在数据 API 上返回,并且 bigint 编号 : int8 回来当JS number 在数据 API 上 pg 编号 : PGlite 驱动程序默认情况下作为字符串返回. 刻出或清晰解析 如果你需要两个引擎的相同值.

一个 Postgres 键入 RDS 数据 API 无法返回 tsvector: 选择一个 tsvector 直接列(例如 select * 在一张产生量的桌子上 search tsvector 在 AWS 上失败。 从选定的列表中排除它——a tsvector 通常只用于 WHERE 编号 : ORDER BY 全文上游, 不读取为值 .

配置

interface DatabaseOptions {
  /** Path to directory containing numbered .sql migration files. */
  migrationsPath?: string;
  /** Connect to an existing database instead of provisioning one. */
  connection?: ExternalDatabaseRef;
  /** Schema metadata for crud() support. */
  schema?: TableSchema;
  /** Aurora PostgreSQL engine version, e.g. '16.13'. Override the Aurora engine version. @default '16.13' */
  postgresVersion?: string;
  /**
   * ARN of a customer-managed KMS key for the cluster's storage-at-rest encryption
   * (also encrypts the auto-generated credentials secret). Supplying it turns
   * storage encryption on regardless of the `@aws-blocks/bb-data:encryptStorageByDefault`
   * context flag. When omitted, encryption follows that flag — on with the
   * account's AWS-managed `aws/rds` key when set, otherwise left unset. The key is
   * imported, so its policy must already grant the deploying principal
   * `kms:CreateGrant` + `kms:DescribeKey` and grant `kms:Decrypt` to the principal
   * reading the credentials secret; it must be in the same account + region.
   */
  storageEncryptionKeyArn?: string;
  /**
   * Automated-backup retention, which is also the point-in-time-recovery (PITR)
   * window. `true` enables the 15-day window; `{ retentionDays: n }` pins a
   * 1–35-day window; `false` clamps to the 1-day minimum (Aurora cannot disable
   * automated backups). When omitted, follows `defaults.pointInTimeRecovery`.
   */
  pointInTimeRecovery?: boolean | { retentionDays: number };
}

软件包导出条件

{
  "exports": {
    ".": {
      "cdk": "./dist/index.cdk.js",
      "aws-runtime": "./dist/index.aws.js",
      "default": "./dist/index.mock.js"
    }
  }
}

业绩

  • 查询间隔 : 10-50ms(温),~500ms从0 ACU起冷
  • 通过量 : 请求通过 RDS 数据 API (HTTPS) 而不是集合数据库连接,所以没有连接池上限或 RDS 代理服务器; 货币以 Data API 请求限制和集群的 ACU 缩放相接.
  • 存储 : 最多128个TiB,10个GiB增量的自动分级
  • 费用: ~ 0.12/ACU-小时+~ 0.10/GB-月存储
  • 重复性 : 3个AZ区6份,可用率99.99%

版本与发布记录

@aws-blocks/bb-data 共发布 15 个版本,首次发布于 2026/06/16;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.5.0latest2026/11/025 天前
0.4.02026/10/1622 天前
0.0.0-canary.esql-canary.c93c81b.1791235863canary-esql-canary2026/10/061 个月前
0.3.12026/10/051 个月前
0.0.0-canary.esql-canary.f7f39ac.17909891272026/10/031 个月前
0.0.0-canary.ci-publish-canary-npm.f53dfdc.1790988617canary-ci-publish-canary-npm2026/10/031 个月前

关于 @aws-blocks/bb-data 的常见问题

@aws-blocks/bb-data 是什么?

完整的 PostgreSQL 数据库——默认情况下提供 Aurora Serverles v2,或连接到现有的 PostgreSQL 数据库(Supabase, Neon等) 通过 fromExisting()。 与外国密钥、交易、行级安全以及打字机建立完整的关系模型

如何安装 @aws-blocks/bb-data?

在项目目录运行 npm install @aws-blocks/bb-data,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:kysely(>=0.28.12 <0.30.0)、constructs(^10.6.0)、aws-cdk-lib(^2.257.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 bb-data,可以用 npx bb-data 直接运行。

@aws-blocks/bb-data 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aws-blocks/bb-data 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aws-blocks/bb-data 可以商用吗?

@aws-blocks/bb-data 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@aws-blocks/bb-data 的下载量有多少?

根据 npm 官方下载统计,@aws-blocks/bb-data 在 2026/10/07 – 2026/11/05 这 30 天内被下载 64,487 次,日均约 2,150 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aws-blocks/bb-data 还在维护吗?

最新版本 0.5.0 发布于 2026/11/02(5 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/06/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。