# @castore/event-storage-adapter-dynamodb 中文文档

规范地址：https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/

版本：2\.4\.2
npm 元数据更新时间：2025-04-18T15:44:48.657Z
中文译文更新时间：2026-11-09T06:12:05.362Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40castore/event-storage-adapter-dynamodb
原文对照：https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/?lang=original
项目主页：https://github.com/castore-dev/castore#readme
源码仓库：https://github.com/castore-dev/castore

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：380 kB，61 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：@aws-sdk/client-dynamodb ^3\.0\.0，@castore/core ^2\.0\.0
- 首次发布：2023-10-27T17:24:56.307Z
- 最新版本发布：2025-04-18T15:44:48.427Z
- 近 30 天下载量：4975（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：8（近 12 个月 0 个）

## 中文简介

DRY Castore EventStorageAdapter 使用 DynamoDB 执行程序

## 安装

```sh
npm install @castore/event-storage-adapter-dynamodb
```

也可以使用：`pnpm add @castore/event-storage-adapter-dynamodb`、`yarn add @castore/event-storage-adapter-dynamodb`、`bun add @castore/event-storage-adapter-dynamodb`

## README

# DynamoDB 事件存储适应器

德里·卡斯托尔 [`EventStorageAdapter`](https://castore-dev.github.io/castore/docs/event-sourcing/fetching-events/) 使用 [AWS 迪纳摩DB](https://aws.amazon.com/dynamodb/)。 。 。 .

## \* 安装

```bash
# npm
npm install @castore/event-storage-adapter-dynamodb

# yarn
yarn add @castore/event-storage-adapter-dynamodb
```

这个软件包 `@castore/core` 财务报告和审定财务报表 `@aws-sdk/client-dynamodb` (以上 v3) 作为对等依赖, 您也必须安装它们 :

```bash
# npm
npm install @castore/core @aws-sdk/client-dynamodb

# yarn
yarn add @castore/core @aws-sdk/client-dynamodb
```

## 目录

这个图书馆暴露出两个适配器:

-   `DynamoDBSingleTableEventStorageAdapter` 它可以将多个事件存储器插到单个的DynamoDB表格上.
-   (单位:千美元)_已贬值_(中文(简体) ) `DynamoDBEventStorageAdapter` 它需要一个DynamoDB表 每个事件商店.

遗产 `DynamoDBEventStorageAdapter` 仍然暴露在后向兼容性中。 它会被腐烂并重新命名 `LegacyDynamoDBEventStorageAdapter` 在v2中,最终去掉在v3中.

联合国

-   [`DynamoDBSingleTableEventStorageAdapter`](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme-dynamodbsingletableeventstorageadapter)
    -   [使用量](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--usage)
    -   [如何运作](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--how-it-works)
    -   [实例](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--examples)
        -   [云阵](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme-cloudformation)
        -   [光盘](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme-cdk)
        -   [地形](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme-terraform)
    -   [活动组](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--eventgroups)
    -   [——————————————](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--iam)
    -   [📸 `ImageParser`](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme--imageparser)
-   [`DynamoDBEventStorageAdapter`](https://npmcn.com/package/%40castore/event-storage-adapter-dynamodb/#readme-legacy-dynamodbeventstorageadapter)

## `DynamoDBSingleTableEventStorageAdapter`

### 使用量

```ts
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

import { DynamoDBSingleTableEventStorageAdapter } from '@castore/event-storage-adapter-dynamodb';

const dynamoDBClient = new DynamoDBClient({});

const pokemonsEventStorageAdapter = new DynamoDBSingleTableEventStorageAdapter(
  {
    tableName: 'my-table-name',
    dynamoDBClient,
  },
);

// 👇 Alternatively, provide a getter
const pokemonsEventStorageAdapter =
  new DynamoDBSingleTableEventStorageAdapter({
    tableName: () => process.env.MY_TABLE_NAME,
    dynamoDBClient,
  });

const pokemonsEventStore = new EventStore({
  ...
  eventStorageAdapter: pokemonsEventStorageAdapter,
});
```

这将直接将您的事件Store 插入 DynamoDB QQ

### 如何运作

此适配器在 **单独的分区**: 当某一事件持续存在时 `aggregateId`,前缀为 `eventStoreId`,用作分区键(_字符串_ 属性)及其属性 `version` 用作排序键( e)_编号_ 属性).

A 类 [全球二级指数](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html) 也要求有效取回事件存储集合id(`listAggregateIds` 操作)。 仅是初始事件(`version = 1`预测数。 A 类 `KEYS_ONLY` 投影类型已经足够.

```ts
// 👇 Initial event
{
  "aggregateId": "POKEMONS#123", // <= Partition key
  "version": 1, // <= Sort key
  "eventStoreId": "POKEMONS", // <= initialEvents index partition key
  "timestamp": "2022-01-01T00:00:00.000Z", // <= initialEvents index sort key
  "type": "POKEMON_APPEARED",
  "payload": { "name": "Pikachu", "level": 42 },
  "metadata": { "trigger": "random" }
}

// 👇 Non-initial event
{
  "aggregateId": "POKEMONS#123",
  "version": 2,
  // Event is not projected on initialEvents index (to limit costs)
  "timestamp": "2023-01-01T00:00:00.000Z",
  "type": "POKEMON_LEVELED_UP"
}
```

这个 `getEvents` 方法(用于 `getAggregate` 财务报告和审定财务报表 `getExistingAggregate` 工作方法 `EventStore` 使用一致的读取,同样 **始终一致**。 。 。 .

这个 `pushEvent` 方法是一种写操作,所以 **始终一致**以避免种族条件为条件,如: [卡斯托尔规格](https://github.com/castore-dev/castore/blob/main/docs/building-your-own-event-storage-adapter.md)。 。 。 .

根据设计 `listAggregateIds` 操作只能是 **最终一致** (通用读取不能一致).

### 实例

请注意,如果您在 TypeScript 中将您的基础设施定义为代码,您可以直接使用此软件包,而不是硬编码以下数值:

```ts
import {
  EVENT_TABLE_PK, // => aggregateId
  EVENT_TABLE_SK, // => version
  EVENT_TABLE_INITIAL_EVENT_INDEX_NAME, // => initialEvents
  EVENT_TABLE_EVENT_STORE_ID_KEY, // => eventStoreId
  EVENT_TABLE_TIMESTAMP_KEY, // => timestamp
} from '@castore/event-storage-adapter-dynamodb';
```

#### 云阵

```json
{
  "Type": "AWS::DynamoDB::Table",
  "Properties": {
    "AttributeDefinitions": [
      { "AttributeName": "aggregateId", "AttributeType": "S" },
      { "AttributeName": "version", "AttributeType": "N" }
      { "AttributeName": "eventStoreId", "AttributeType": "S" },
      { "AttributeName": "timestamp", "AttributeType": "S" }
    ],
    "KeySchema": [
      { "AttributeName": "aggregateId", "KeyType": "HASH" },
      { "AttributeName": "version", "KeyType": "RANGE" }
    ],
    "GlobalSecondaryIndexes": [
      {
        "IndexName": "initialEvents",
        "KeySchema": [
          { "AttributeName": "eventStoreId", "KeyType": "HASH" },
          { "AttributeName": "timestamp", "KeyType": "RANGE" }
        ],
        "Projection": "KEYS_ONLY"
      }
    ]
  }
}
```

#### 光盘

```ts
import { Table, AttributeType, ProjectionType } from 'aws-cdk-lib/aws-dynamodb';

const { STRING, NUMBER } = AttributeType;
const { KEYS_ONLY } = ProjectionType;

const pokemonsEventsTable = new Table(scope, 'PokemonEvents', {
  partitionKey: {
    name: 'aggregateId',
    type: STRING,
  },
  sortKey: {
    name: 'version',
    type: NUMBER,
  },
});

pokemonsEventsTable.addGlobalSecondaryIndex({
  indexName: 'initialEvents',
  partitionKey: {
    name: 'eventStoreId',
    type: STRING,
  },
  sortKey: {
    name: 'timestamp',
    type: STRING,
  },
  projectionType: KEYS_ONLY,
});
```

#### 地形

```h
resource "aws_dynamodb_table" "pokemons-events-table" {
  hash_key       = "aggregateId"
  range_key      = "version"

  attribute {
    name = "aggregateId"
    type = "S"
  }

  attribute {
    name = "version"
    type = "N"
  }

  attribute {
    name = "eventStoreId"
    type = "S"
  }

  attribute {
    name = "timestamp"
    type = "S"
  }

  global_secondary_index {
    name               = "initialEvents"
    hash_key           = "eventStoreId"
    range_key          = "timestamp"
    projection_type    = "KEYS_ONLY"
  }
}
```

### 活动组

此适配器执行 [事件组](https://castore-dev.github.io/castore/docs/event-sourcing/joining-data/) 使用 [DynamoDB 交易 API](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html)数字 :

```ts
import { EventStore } from '@castore/core';

// 👇 TransactWriteItems N events simultaneously
await EventStore.pushEventGroup(
  // events are correctly typed 🙌
  eventStoreA.groupEvent(eventA1),
  eventStoreA.groupEvent(eventA2),
  eventStoreB.groupEvent(eventB),
  ...
);
```

注意:

-   交易所涉的所有事件商店都需要使用 `DynamoDBSingleTableEventStorageAdapter`
-   此工具继承 [`TransactWriteItem` API 密码](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems) 限制 : 它可以在同一AWS账户和同一区域的一个或多个DynamoDB表格中针对多达100个不同事件.

### ——————————————

每次操作所需的 IAM 权限 :

-   `getEvents` (+ 数) `getAggregate`, (中文(简体) ), `getExistingAggregate`: `dynamodb:Query`
-   `pushEvent`数字 : `dynamodb:PutItem`
-   `listAggregateIds`数字 : `dynamodb:Query` 编辑 `initialEvents` 指数

### 📸 `ImageParser`

这个图书馆也暴露了一个有用的 `ImageParser` 要解析的类 [迪纳摩DB流](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html) 图像来自 a `DynamoDBSingleTableEventStorageAdapter`。它将构建一个正确的键入 `NotificationMessage` 流出图像的 uf, 解析它, 删除前缀 `aggregateId` 并验证 `eventStoreId`数字 :

```ts
import { ImageParser } from '@castore/event-storage-adapter-dynamodb';

const imageParser = new ImageParser({
  sourceEventStores: [pokemonsEventStore, trainersEventStore],
});

// 🙌 Typed as EventStoreNotificationMessage<
//  typeof pokemonsEventStore
//  | typeof trainersEventStore...
// >
const notificationMessage = imageParser.parseImage(
  streamImage,
  // 👇 Optional options
  unmarshallOptions,
);
```

## 遗产 `DynamoDBEventStorageAdapter`

**页:1**

### 使用量

```ts
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

import { DynamoDBEventStorageAdapter } from '@castore/event-storage-adapter-dynamodb';

const dynamoDBClient = new DynamoDBClient({});

const pokemonsEventStorageAdapter = new DynamoDBEventStorageAdapter({
  tableName: 'my-table-name',
  dynamoDBClient,
});

// 👇 Alternatively, provide a getter
const pokemonsEventStorageAdapter = new DynamoDBEventStorageAdapter({
  tableName: () => process.env.MY_TABLE_NAME,
  dynamoDBClient,
});

const pokemonsEventStore = new EventStore({
  ...
  eventStorageAdapter: pokemonsEventStorageAdapter
})
```

这将直接将您的事件Store 插入 DynamoDB QQ

### 如何运作

此适配器在 **单独的分区**: 当某一事件持续存在时 `aggregateId` 用作分区键( e)_字符串_ 属性)及其属性 `version` 用作排序键( e)_编号_ 属性).

A 类 [全球二级指数](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html) 也要求有效取回事件存储集合id(`listAggregateIds` 操作)。 仅是初始事件(`version = 1`预测数。 A 类 `KEYS_ONLY` 投影类型已经足够.

```ts
// 👇 Initial event
{
  "aggregateId": "123", // <= Partition key
  "version": 1, // <= Sort key
  "isInitialEvent": 1, // <= initialEvents index partition key
  "timestamp": "2022-01-01T00:00:00.000Z", // <= initialEvents index sort key
  "type": "POKEMON_APPEARED",
  "payload": { "name": "Pikachu", "level": 42 },
  "metadata": { "trigger": "random" }
}

// 👇 Non-initial event
{
  "aggregateId": "123",
  "version": 2,
  // Event is not projected on initialEvents index (to limit costs)
  "timestamp": "2023-01-01T00:00:00.000Z",
  "type": "POKEMON_LEVELED_UP"
}
```

这个 `getEvents` 方法(用于 `getAggregate` 财务报告和审定财务报表 `getExistingAggregate` 工作方法 `EventStore` 使用一致的读取,同样 **始终一致**。 。 。 .

这个 `pushEvent` 方法是一种写操作,所以 **始终一致**以避免种族条件为条件,如: [卡斯托尔规格](https://github.com/castore-dev/castore/blob/main/docs/building-your-own-event-storage-adapter.md)。 。 。 .

根据设计 `listAggregateIds` 操作只能是 **最终一致** (通用读取不能一致).

### 实例

请注意,如果您在 TypeScript 中将您的基础设施定义为代码,您可以直接使用此软件包,而不是硬编码以下数值:

```ts
import {
  EVENT_TABLE_PK, // => aggregateId
  EVENT_TABLE_SK, // => version
  EVENT_TABLE_INITIAL_EVENT_INDEX_NAME, // => initialEvents
  EVENT_TABLE_IS_INITIAL_EVENT_KEY, // => isInitialEvent
  EVENT_TABLE_TIMESTAMP_KEY, // => timestamp
} from '@castore/event-storage-adapter-dynamodb';
```

#### 云阵

```json
{
  "Type": "AWS::DynamoDB::Table",
  "Properties": {
    "AttributeDefinitions": [
      { "AttributeName": "aggregateId", "AttributeType": "S" },
      { "AttributeName": "version", "AttributeType": "N" }
      { "AttributeName": "isInitialEvent", "AttributeType": "N" },
      { "AttributeName": "timestamp", "AttributeType": "S" }
    ],
    "KeySchema": [
      { "AttributeName": "aggregateId", "KeyType": "HASH" },
      { "AttributeName": "version", "KeyType": "RANGE" }
    ],
    "GlobalSecondaryIndexes": [
      {
        "IndexName": "initialEvents",
        "KeySchema": [
          { "AttributeName": "isInitialEvent", "KeyType": "HASH" },
          { "AttributeName": "timestamp", "KeyType": "RANGE" }
        ],
        "Projection": "KEYS_ONLY"
      }
    ]
  }
}
```

#### 光盘

```ts
import { Table, AttributeType, ProjectionType } from 'aws-cdk-lib/aws-dynamodb';

const { STRING, NUMBER } = AttributeType;
const { KEYS_ONLY } = ProjectionType;

const pokemonsEventsTable = new Table(scope, 'PokemonEvents', {
  partitionKey: {
    name: 'aggregateId',
    type: STRING,
  },
  sortKey: {
    name: 'version',
    type: NUMBER,
  },
});

pokemonsEventsTable.addGlobalSecondaryIndex({
  indexName: 'initialEvents',
  partitionKey: {
    name: 'isInitialEvent',
    type: NUMBER,
  },
  sortKey: {
    name: 'timestamp',
    type: STRING,
  },
  projectionType: KEYS_ONLY,
});
```

#### 地形

```h
resource "aws_dynamodb_table" "pokemons-events-table" {
  hash_key       = "aggregateId"
  range_key      = "version"

  attribute {
    name = "aggregateId"
    type = "S"
  }

  attribute {
    name = "version"
    type = "N"
  }

  attribute {
    name = "isInitialEvent"
    type = "N"
  }

  attribute {
    name = "timestamp"
    type = "S"
  }

  global_secondary_index {
    name               = "initialEvents"
    hash_key           = "isInitialEvent"
    range_key          = "timestamp"
    projection_type    = "KEYS_ONLY"
  }
}
```

### 活动组

此适配器执行 [事件组](https://castore-dev.github.io/castore/docs/event-sourcing/joining-data/) 使用 [DynamoDB 交易 API](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html)数字 :

```ts
import { EventStore } from '@castore/core';

// 👇 TransactWriteItems N events simultaneously
await EventStore.pushEventGroup(
  // events are correctly typed 🙌
  eventStoreA.groupEvent(eventA1),
  eventStoreA.groupEvent(eventA2),
  eventStoreB.groupEvent(eventB),
  ...
);
```

注意:

-   交易所涉的所有事件商店都需要使用 `DynamoDBEventStorageAdapter`
-   此工具继承 [`TransactWriteItem` API 密码](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems) 限制 : 它可以在同一AWS账户和同一区域的一个或多个DynamoDB表格中针对多达100个不同事件.

### ——————————————

每次操作所需的 IAM 权限 :

-   `getEvents` (+ 数) `getAggregate`, (中文(简体) ), `getExistingAggregate`: `dynamodb:Query`
-   `pushEvent`数字 : `dynamodb:PutItem`
-   `listAggregateIds`数字 : `dynamodb:Query` 编辑 `initialEvents` 指数

## 常见问题

### @castore/event-storage-adapter-dynamodb 是什么？

DRY Castore EventStorageAdapter 使用 DynamoDB 执行程序

### 如何安装 @castore/event-storage-adapter-dynamodb？

在项目目录运行 npm install @castore/event-storage-adapter-dynamodb，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@aws-sdk/client-dynamodb（^3\.0\.0）、@castore/core（^2\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @castore/event-storage-adapter-dynamodb 支持 TypeScript 吗？

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

### @castore/event-storage-adapter-dynamodb 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @castore/event-storage-adapter-dynamodb 可以商用吗？

@castore/event-storage-adapter-dynamodb 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @castore/event-storage-adapter-dynamodb 的下载量有多少？

根据 npm 官方下载统计，@castore/event-storage-adapter-dynamodb 在 2026/10/09 – 2026/11/07 这 30 天内被下载 4,975 次，日均约 166 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @castore/event-storage-adapter-dynamodb 还在维护吗？

最新版本 2\.4\.2 发布于 2025/04/18（1\.6 年前）；至今共发布 8 个版本，其中过去 12 个月发布了 0 个；首次发布于 2023/10/28。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

