@application-kit/transaction-outbox

中文文档
0.4.1发布于 2026/11/05MITTypeScriptESM + CJS近 30 天下载 2198

Transactional outbox на TypeORM: запись событий в одной транзакции с изменением, роутинг через Debezium, версия контракта события

原始使用文档
文档目录6 节
  1. Установка
  2. Подключение
  3. Запись событий
  4. Версия контракта
  5. Миграция
  6. Тесты потребителя

@application-kit/transaction-outbox

Transactional outbox на TypeORM и NestJS: события пишутся в таблицу transaction_outboxes в одной транзакции с изменением и тут же удаляются — Debezium читает вставку из WAL и по полю queue_name раскладывает событие по топикам Kafka (EventRouter, route.by.field: queue_name).

Установка

yarn add @application-kit/transaction-outbox

Peer-зависимости: @application-kit/kafka (вход /event-contract), @application-kit/typeorm, @libs-for-dev/nestjs-ddd-library, @nestjs/common, @nestjs/core, @nestjs/typeorm, nestjs-pino, oxide.ts, typeorm. kafkajs и @nestjs/microservices не нужны: пакет берёт из kafka только правила версии контракта.

Подключение

Приложение приносит два токена — глобально (например, из корневого модуля): TransactionOutboxModule импортируется статически в каждый модуль-потребитель и опций не принимает.

import {
  TRANSACTION_OUTBOX_LOGGER,
  TRANSACTION_OUTBOX_REQUEST_FACTS,
  TransactionOutboxLogger,
} from '@application-kit/transaction-outbox'

@Global()
@Module({
  exports: [TRANSACTION_OUTBOX_LOGGER, TRANSACTION_OUTBOX_REQUEST_FACTS],
  providers: [
    { provide: TRANSACTION_OUTBOX_LOGGER, useClass: TransactionOutboxLogger },
    { provide: TRANSACTION_OUTBOX_REQUEST_FACTS, useValue: () => ({ ip: currentIp() }) },
  ],
})
class CommonModule {}
  • TRANSACTION_OUTBOX_LOGGER — любой класс с error(context, message); TransactionOutboxLogger — реализация на nestjs-pino (нужен глобальный LoggerModule).
  • TRANSACTION_OUTBOX_REQUEST_FACTS — хук обогащения: функция без аргументов, результат которой ложится в payload.facts событий с carriesRequestFacts: true. Пакет не знает, что такое факты. Адрес и user-agent разбирает resolveRequestFacts из @application-kit/observability/http; текущий запрос функции без аргументов приложение держит само, например в AsyncLocalStorage. Хук необязателен: без него события с carriesRequestFacts пишутся без facts.

Запись событий

const result = await outbox.save([new UserWasCreatedEvent({ id })], async () => {
  return repository.save(user)
})

Колбэк может ничего не возвращать: это штатный успех, save отвечает Ok(true). Result нужен, когда у работы есть ожидаемый отказ.

События пишутся до колбэка в той же транзакции. Err из колбэка откатывает её наравне со сбоем — иначе Debezium разослал бы потребителям факт о невыполненной работе; сам отказ возвращается значением. save внутри колбэка другого save присоединяется к открытой транзакции. Репозитории, которые участвуют в транзакции, регистрируются через TransactionAwareTypeOrmModule.forFeature([...]) вместо TypeOrmModule.forFeature.

Версия контракта

Имя очереди собирается versionedQueueName(queueName, eventVersion) из @application-kit/kafka/event-contract: у первой версии имя прежнее, у остальных — <queue>.v<N>. Базовый класс AbstractSingleIdOutboxEvent фиксирует версию 1.

Миграция

Пакет экспортирует orm — сущность TransactionOutboxEntity и миграцию TransactionOutbox1734780489810 классами: передайте его в packages фабрики CLI DataSource. Имя класса миграции записано в таблице migrations уже мигрированных баз — переименование заставит TypeORM прогнать миграцию повторно.

import { orm as outboxOrm } from '@application-kit/transaction-outbox'

createCliDataSource({ ..., packages: [outboxOrm] }) // @application-kit/typeorm/nest

Тесты потребителя

import { TransactionOutboxFake } from '@application-kit/transaction-outbox/testing'

const outbox = new TransactionOutboxFake(logger)
await service.run()
expect(outbox.events.size).toBe(1)

Фейк копит события в events и откатывает их на Err и исключении колбэка, как настоящая транзакция.

版本与发布记录

@application-kit/transaction-outbox 共发布 10 个版本,首次发布于 2026/10/06;过去 12 个月发布了 10 个版本。

版本发布日期距今
0.4.1latest2026/11/052 天前
0.4.02026/11/052 天前
0.3.32026/11/052 天前
0.3.22026/10/2612 天前
0.3.12026/10/2118 天前
0.3.02026/10/1721 天前

关于 @application-kit/transaction-outbox 的常见问题

@application-kit/transaction-outbox 是什么?

Transactional outbox на TypeORM: запись событий в одной транзакции с изменением, роутинг через Debezium, версия контракта события

如何安装 @application-kit/transaction-outbox?

在项目目录运行 npm install @application-kit/transaction-outbox,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:typeorm(^1.0.0)、oxide.ts(^1.1.0)、nestjs-pino(^4.6.1)、@nestjs/core(^11.0.0)、@nestjs/common(^11.0.0)、@nestjs/typeorm(^11.0.3 || ^12.0.0)、@libs-for-dev/nestjs-ddd-library(^1.4.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@application-kit/transaction-outbox 支持 TypeScript 吗?

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

@application-kit/transaction-outbox 支持 ESM 还是 CommonJS?

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

@application-kit/transaction-outbox 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@application-kit/transaction-outbox 可以商用吗?

@application-kit/transaction-outbox 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@application-kit/transaction-outbox 的下载量有多少?

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

@application-kit/transaction-outbox 还在维护吗?

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