@alxia/events

中文文档
0.2.0发布于 2026/11/06MITTypeScriptES Module零依赖近 30 天下载 1810

用于在 @softistx/mongo 和 @softistx/redis 上应用的事件总线: 将事件写入交易输出框, 并更改域名, 转发到队列, 至少发送一次, 通过收件箱应用一次

中文使用文档
文档目录6 节
  1. 30秒内
  2. 交付
  3. 保证
  4. API 密码
  5. 文档
  6. 许可证

@alxia/活动

用于应用程序的事件总线 @softistx/mongo 财务报告和审定财务报表 @softistx/redis,基于 交易发件箱。 模块在同一 MongoDB 交易中写入事件 作为导致它的变化, 所以两个站在一起或跌倒在一起。 一个接力手 每个事件通过队列订阅的模块; 每个订阅者 施用一次,无论交付多次.

bun add @alxia/events @alxia/modules @alxia/tenancy @softistx/mongo @softistx/redis mongodb zod
bun add -d typescript

@softistx/mongo 财务报告和审定财务报表 @softistx/redis 是私人的,在 GitHub 包。 绘制范围 项目的 bunfig.toml 和导出 GITHUB_TOKEN,与 read:packages数字 :

[install.scopes]
"@softistx" = { url = "https://npm.pkg.github.com/", token = "$GITHUB_TOKEN" }

蒙戈DB必须运行为 复制集 (交易需要一个). 见 排除出问题。 。 。 .

30秒内

import { collectionsOf, defineModule } from '@alxia/modules';
import {
    createEvents,
    eventsModule,
    type EventEnvelope,
    type SubscriberContext,
} from '@alxia/events';
import { single } from '@alxia/tenancy';
import { connectMongo, defineMongo, openMongo } from '@softistx/mongo';

// `Tenant` and `Core` are your tenant and core collection wirings
// (see the guide, "Write a subscriber").

// 1. Declare what a module emits and what it subscribes to.
export const shop = defineModule({
    name: 'shop',
    emits: ['shop.order.placed'],
});

export const billing = defineModule({
    name: 'billing',
    subscribers: {
        'shop.order.placed': async (
            event: EventEnvelope,
            context: SubscriberContext<'billing', Tenant, Core>,
        ) => {
            // `context.mongo` is in the transaction that records the inbox row,
            // and narrowed to billing's collections and those of its dependsOn.
            const { mongo } = context;
            await mongo.db.invoices.create({ orderId: event.aggregate.id });
        },
    },
});

// 2. Put the kernel module in the registry you give the tenant store,
//    then build the bus from that store.
const modules = [eventsModule, shop, billing];
const { client } = await connectMongo(process.env.MONGO_URI!);
const mongo = await openMongo(
    defineMongo({ client, database: 'app', collections: collectionsOf(modules) }),
);
const tenancy = single({
    mongo,
    modules,
    tenant: { id: 'main', slug: 'main', name: 'Main' },
}); // or perOrganization(...), see @alxia/tenancy
const events = createEvents({ store: tenancy });
// `request` and `viewer` are the HTTP request and its signed-in account
const scope = await tenancy.scope(request, viewer);

// 3. Emit inside the transaction of the change.
await scope.mongo.transaction(async (tx) => {
    const order = await tx.db.orders.create({ label: 'Ada' });
    await events.emit(
        { tenant: scope.tenant, mongo: tx },
        {
            type: 'shop.order.placed',
            aggregate: { type: 'order', id: order.id },
            payload: { label: 'Ada' },
        },
    );
});

交付

在生产中,一个继电器和工人运行在应用程序旁边. 每个模块 订阅者得到一个队列, events.<module>数字 :

import { bindQueue, connectRedis } from '@softistx/redis';
import { createEvents, eventsQueue } from '@alxia/events';

const redis = await connectRedis(process.env.REDIS_URL!);
const queues = { billing: bindQueue(redis.client, eventsQueue('billing')) };
const events = createEvents({ store: tenancy, queues }); // `tenancy` from above

const relay = events.relay({ redis: redis.client }); // one leader per deployment
relay.start();
const workers = events.work();

// on shutdown
await relay.stop();
await workers.stop();

没有Redis(dev,测试),您会按以下顺序运行您的进程订阅者:

await events.drain(scope.tenant.id); // omit the tenant to drain every tenant

保证

  • 原子发射. 该活动是在 _outbox 如果且只有在交易中 释放了它.
  • 起码一次. 中继器为每个任务( 事件, 订阅者) 排入 jobId = <eventId>:<module>:<type>,然后标记已发送的事件。 撞车 在再次排入同一编号之间,队列忽略了这些编号.
  • 申请一次. 用户的效果及其 _inbox 单行执行 交易; 第二次发送找到行并什么都不做.
  • 肃静. 每个租户,中继发送事件 _id 秩序。 秩序。 没有 全球秩序,一个用户必须容忍重订顺序.
  • 每家店都一样. 释放、中继和 drain 运行不变 perOrganization 财务报告和审定财务报表 single (一个数据库,一个固定租户).

API 密码

导出它会做什么
eventsModule拥有内核模块 _outbox (发送后7天TTL)和 _inbox (30天);加入登记册
createEvents({ store, queues?, batchSize? })总线; 立即检查登记簿
events.emit(source, event, options?)将事件写入 source.mongo,交易的手柄
events.drain(tenant?)在这个过程中通过用户管理待办活动
events.relay(options)tick(), (中文(简体) ), start(), (中文(简体) ), stop(): 以领袖为主的民意调查
events.work(options?)一个 @softistx/redis 每个签名模块的工人队列
events.deadLetters({ limit? })使用他们所有尝试的工作
eventsQueue(module, options?), (中文(简体) ), queueName(module), (中文(简体) ), EventsQueueOptions, (中文(简体) ), EventQueue, (中文(简体) ), EventJob定义 events.<module>,它的选项,绑定队列的类型和任务的有效载荷
deliver(store, mongo, tenant, event, subscription), (中文(简体) ), Delivery一个用户,一次: 收件箱行加交易处理器, 交出其模块的收缩范围
emittedTypes(modules), (中文(简体) ), subscriptionsOf(modules), (中文(简体) ), Subscription检查靴子后面的注册读取器和一个模块的处理器
outbox, (中文(简体) ), inbox, (中文(简体) ), OUTBOX_TTL, (中文(简体) ), INBOX_TTL收集定义和TTL
EventsError, (中文(简体) ), EventsErrorCode拒绝,有稳定的 code 名称空格 events. (单位:千美元)events.undeclared-type, (中文(简体) ), events.missing-queue, (...) (中文(简体) )
EventEnvelope, (中文(简体) ), EventInput, (中文(简体) ), EmitOptions, (中文(简体) ), EventWorkers, (中文(简体) ), EmitSource, (中文(简体) ), EventsMongo, (中文(简体) ), Subscriber, (中文(简体) ), SubscriberContext, (中文(简体) ), DeadLetter, (中文(简体) ), Relay, (中文(简体) ), RelayOptions, (中文(简体) ), Events, (中文(简体) ), EventsOptions类型

端点 : @alxia/modules, (中文(简体) ), @alxia/tenancy, (中文(简体) ), @softistx/mongo, (中文(简体) ), @softistx/redis, (中文(简体) ), mongodb, (中文(简体) ), zod, (中文(简体) ), typescript。 。 。 .

文档

  • 指南信封、发包箱、订户、继电器和工人, drain死信 房客 测试.
  • 解决问题:一个错误消息,以及该如何应对.
  • 路线图:即将到来的,以及没有计划的.

许可证

麻省理工学院

版本与发布记录

@alxia/events 共发布 11 个版本,首次发布于 2026/11/01;过去 12 个月发布了 11 个版本。

版本发布日期距今
0.2.0latest2026/11/062 天前
0.1.82026/11/017 天前
0.1.72026/11/017 天前
0.1.62026/11/017 天前
0.1.52026/11/017 天前
0.1.42026/11/017 天前

关于 @alxia/events 的常见问题

@alxia/events 是什么?

用于在 @softistx/mongo 和 @softistx/redis 上应用的事件总线: 将事件写入交易输出框, 并更改域名, 转发到队列, 至少发送一次, 通过收件箱应用一次

如何安装 @alxia/events?

在项目目录运行 npm install @alxia/events,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:zod(^4.6.5)、mongodb(^7.7.0)、typescript(^6.0.3 || ^7.0.0)、@alxia/modules(^0.4.0)、@alxia/tenancy(^0.6.0)、@softistx/mongo(^0.27.0)、@softistx/redis(^0.14.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@alxia/events 支持 TypeScript 吗?

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

@alxia/events 支持 ESM 还是 CommonJS?

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

@alxia/events 可以商用吗?

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

@alxia/events 的下载量有多少?

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

@alxia/events 还在维护吗?

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