@zucker-framework/event 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,813 @@
1
+ import { ClassConstructor } from 'class-transformer';
2
+ import { OnModuleInit, OnModuleDestroy, DynamicModule } from '@nestjs/common';
3
+
4
+ declare enum EntityEventType {
5
+ CREATE = "create",
6
+ /** modify */
7
+ MODIFY = "modify",
8
+ DELETE = "delete",
9
+ /** save */
10
+ SAVE = "save",
11
+ QUERY = "query",
12
+ /**
13
+ * @deprecated 请使用 MODIFY
14
+ */
15
+ UPDATE = "modify"
16
+ }
17
+ declare enum EntityEventPhase {
18
+ /**
19
+ * PREPARE 阶段 — 实体数据预处理
20
+ *
21
+ * 契约:监听器可以修改 event.entity 上的字段值,
22
+ * 修改后的数据会流入后续的数据库操作。
23
+ * 典型用途:自动填充 creatorId/createdAt、数据清洗、默认值设置。
24
+ */
25
+ PREPARE = "prepare",
26
+ /**
27
+ * BEFORE 阶段 — 操作前校验与拦截
28
+ *
29
+ * 契约:监听器可以调用 event.cancel() 取消操作,
30
+ * BaseService 将在此阶段后检查 cancelled 标志并抛出 OperationCancelledException。
31
+ * 典型用途:业务规则校验、权限检查、并发控制。
32
+ */
33
+ BEFORE = "before",
34
+ /**
35
+ * AFTER 阶段 — 操作完成后的后续处理
36
+ *
37
+ * 契约:数据已持久化,此阶段用于触发副作用。
38
+ * 在事务内时,建议使用 TransactionUtils.afterCommit() 确保 commit 后才执行。
39
+ */
40
+ AFTER = "after"
41
+ }
42
+ /**
43
+ * 所有事件阶段
44
+ *
45
+ * 便捷常量,包含 PREPARE、BEFORE 和 AFTER 三个阶段。
46
+ */
47
+ declare const ALL_EVENT_PHASES: readonly EntityEventPhase[];
48
+ interface EntityEvent<T = unknown> {
49
+ type: EntityEventType;
50
+ phase: EntityEventPhase;
51
+ entityType: string;
52
+ entity: T | T[];
53
+ timestamp: number;
54
+ /**
55
+ * 修改前的实体数据
56
+ *
57
+ * 仅在 MODIFY 类型事件中有值。
58
+ * before 保存旧数据,entity 保存新数据;二者均支持单条实体或实体列表。
59
+ */
60
+ readonly before?: T | T[];
61
+ /** 事件是否已被取消(仅 BEFORE 阶段有效) */
62
+ readonly cancelled: boolean;
63
+ /**
64
+ * 取消操作(仅 BEFORE 阶段有意义)
65
+ * 调用后 BaseService 将抛出 OperationCancelledException
66
+ * @param reason 取消原因,会包含在异常消息中
67
+ */
68
+ cancel(reason?: string): void;
69
+ /** 取消原因 */
70
+ readonly cancelReason?: string;
71
+ }
72
+ /**
73
+ * Create a new EntityEvent instance with cancel support.
74
+ * @param type - The event type (CREATE, MODIFY, DELETE, etc.)
75
+ * @param phase - The event phase (PREPARE, BEFORE, AFTER)
76
+ * @param entityType - The entity/model name
77
+ * @param entity - The entity data (single or batch). For MODIFY events this is the "after" data.
78
+ * @param before - Optional "before" data for MODIFY events
79
+ * @returns A new EntityEvent with cancel() capability
80
+ */
81
+ declare function createEntityEvent<T>(type: EntityEventType, phase: EntityEventPhase, entityType: string, entity: T | T[], before?: T | T[]): EntityEvent<T>;
82
+ /**
83
+ * 生成事件名: entity/{entityType}/{type}/{phase}
84
+ * 例如: entity/user/create/before
85
+ *
86
+ * 使用 `/` 分隔符以匹配 DefaultTopicEventBus 的 delimiter 配置,
87
+ * 使通配符订阅(如 `entity/* /create/*`)能正确匹配事件名。
88
+ */
89
+ declare function getEntityEventName(entityType: string, type: EntityEventType, phase: EntityEventPhase): string;
90
+
91
+ interface EntityEventListener<T = unknown> {
92
+ onEvent(event: EntityEvent<T>): void | Promise<void>;
93
+ /**
94
+ * 监听器优先级,数值越小优先级越高
95
+ * 默认 0
96
+ */
97
+ readonly order?: number;
98
+ }
99
+ /**
100
+ * 当前用户信息
101
+ */
102
+ interface CurrentUser {
103
+ id: string;
104
+ name?: string;
105
+ }
106
+ /**
107
+ * 创建者监听器 - Prepare 阶段自动填充创建人/修改人信息
108
+ *
109
+ * - CREATE/SAVE: 填充 creatorId, creatorName, createdAt, modifierId, modifierName, updatedAt
110
+ * - MODIFY/UPDATE: 仅填充 modifierId, modifierName, updatedAt
111
+ *
112
+ * 填充规则:
113
+ * - 使用 ??= 确保不覆盖已有的 creatorId(用户可提前设置)
114
+ * - modifierId/modifierName 始终覆盖
115
+ * - order 为最高优先级(HIGHEST_PRECEDENCE)
116
+ */
117
+ declare class CreatorEventListener implements EntityEventListener {
118
+ private readonly getCurrentUser;
119
+ readonly order: number;
120
+ constructor(getCurrentUser: () => CurrentUser | undefined);
121
+ onEvent(event: EntityEvent): Promise<void>;
122
+ }
123
+ /**
124
+ * 组合事件监听器
125
+ *
126
+ * 聚合多个 EntityEventListener 并按 order 排序执行。
127
+ * 数值越小优先级越高。
128
+ */
129
+ declare class CompositeEventListener<T = unknown> implements EntityEventListener<T> {
130
+ private listeners;
131
+ addListener(listener: EntityEventListener<T>): void;
132
+ removeListener(listener: EntityEventListener<T>): void;
133
+ onEvent(event: EntityEvent<T>): Promise<void>;
134
+ getListeners(): readonly EntityEventListener<T>[];
135
+ }
136
+
137
+ declare const SUBSCRIBE_KEY = "zucker:event:subscribe";
138
+ declare const SUBSCRIBE_METHODS_KEY = "zucker:event:subscribeMethods";
139
+ /**
140
+ * Subscription feature — controls message scope.
141
+ * Mirrors jetlinks Subscription.Feature enum.
142
+ */
143
+ declare enum SubscribeFeature {
144
+ /** Only subscribe to local process messages */
145
+ LOCAL = "local",
146
+ /** Subscribe to messages from the entire cluster */
147
+ CLUSTER = "cluster",
148
+ /** Subscribe to shared messages (load-balanced across instances) */
149
+ SHARED = "shared",
150
+ /**
151
+ * Broker mode — 参考 jetlinks Subscription.Feature.broker
152
+ * Subscribe to messages forwarded by the event broker (cross-node communication).
153
+ * In jetlinks, broker mode enables EventConnection-based inter-cluster event forwarding.
154
+ */
155
+ BROKER = "broker"
156
+ }
157
+ interface SubscribeOptions {
158
+ /** Topic patterns to subscribe to (supports * and ** wildcards) */
159
+ topics: string[];
160
+ /** Subscriber ID — defaults to method name */
161
+ id?: string;
162
+ /** Subscription features — defaults to [LOCAL] */
163
+ features?: SubscribeFeature[];
164
+ /** Priority — lower value = higher priority. Defaults to Infinity */
165
+ priority?: number;
166
+ }
167
+ /**
168
+ * @Subscribe decorator — 参考 jetlinks @Subscribe 注解
169
+ *
170
+ * 用于方法上,声明式订阅 TopicEventBus 的消息。
171
+ * 框架通过扫描带有此装饰器的方法,自动注册订阅。
172
+ *
173
+ * 用法:
174
+ * ```typescript
175
+ * @Subscribe({ topics: ['/device/ * / * /message'] })
176
+ * async handleDeviceMessage(payload: DeviceMessage): Promise<void> { ... }
177
+ *
178
+ * // 简写:单个 topic
179
+ * @Subscribe('/device/** ')
180
+ * async handleAllDevice(payload: unknown): Promise<void> { ... }
181
+ * ```
182
+ */
183
+ declare function Subscribe(topicsOrOptions: string | string[] | SubscribeOptions): MethodDecorator;
184
+ /**
185
+ * Get all @Subscribe method entries from a class.
186
+ */
187
+ declare function getSubscriptions(target: Function): Array<{
188
+ propertyKey: string;
189
+ options: SubscribeOptions;
190
+ }>;
191
+
192
+ /**
193
+ * Event handler function that receives a TopicPayload.
194
+ * @param payload - The topic payload containing topic, data, and headers
195
+ */
196
+ type EventHandler = (payload: TopicPayload) => void | Promise<void>;
197
+ /**
198
+ * Legacy handler signature for backward compatibility.
199
+ * Accepts raw payload and topic string.
200
+ */
201
+ type LegacyEventHandler = (payload: unknown, topic: string) => void | Promise<void>;
202
+ /**
203
+ * TopicPayload — 参考 jetlinks TopicPayload
204
+ *
205
+ * 封装事件的 topic、payload 和 headers。
206
+ * jetlinks 的 TopicPayload 包含 topic + Payload(ByteBuf) + headers,
207
+ * 在 TypeScript 中简化为泛型 payload + Map headers。
208
+ */
209
+ interface TopicPayload<T = unknown> {
210
+ /** The topic this event was published to */
211
+ readonly topic: string;
212
+ /** The event payload */
213
+ readonly payload: T;
214
+ /**
215
+ * Optional headers — 参考 jetlinks TopicPayload headers
216
+ * Used for metadata propagation (tracing, source info, etc.)
217
+ */
218
+ readonly headers: ReadonlyMap<string, unknown>;
219
+ }
220
+ /**
221
+ * Create a TopicPayload instance.
222
+ */
223
+ declare function createTopicPayload<T = unknown>(topic: string, payload: T, headers?: Record<string, unknown> | Map<string, unknown>): TopicPayload<T>;
224
+ /**
225
+ * Handle returned by subscribe() — call unsubscribe() to stop receiving events.
226
+ */
227
+ interface Subscription {
228
+ /** Remove this subscription and stop receiving events */
229
+ unsubscribe: () => void;
230
+ }
231
+ /**
232
+ * SubscriptionInfo — 参考 jetlinks Subscription (org.jetlinks.core.event.Subscription)
233
+ *
234
+ * 结构化订阅信息,包含:
235
+ * - subscriberId: 订阅者标识
236
+ * - topics: 订阅的 topic 模式列表
237
+ * - features: 订阅特性(local/shared/broker/cluster)
238
+ * - priority: 优先级(值越小优先级越高,与 jetlinks 一致)
239
+ */
240
+ interface SubscriptionInfo {
241
+ /** Unique subscriber ID — 参考 jetlinks Subscription.subscriberId */
242
+ subscriberId: string;
243
+ /** Topic patterns to subscribe to (supports *, **, and comma-separated segments) */
244
+ topics: string[];
245
+ /** Subscription features — defaults to [LOCAL] */
246
+ features?: SubscribeFeature[];
247
+ /** Priority — lower value = higher priority (jetlinks convention) */
248
+ priority?: number;
249
+ }
250
+ /**
251
+ * Subscription builder chain — 参考 jetlinks Subscription.builder()
252
+ */
253
+ interface SubscriptionInfoBuilder {
254
+ subscriberId(id: string): SubscriptionInfoBuilder;
255
+ topics(...topics: string[]): SubscriptionInfoBuilder;
256
+ features(...features: SubscribeFeature[]): SubscriptionInfoBuilder;
257
+ priority(p: number): SubscriptionInfoBuilder;
258
+ build(): SubscriptionInfo;
259
+ }
260
+ /**
261
+ * SubscriptionInfo factory — 参考 jetlinks Subscription.builder() / Subscription.of()
262
+ */
263
+ declare const SubscriptionBuilder: {
264
+ /**
265
+ * Quick factory — 参考 jetlinks Subscription.of(subscriberId, topic, ...features)
266
+ */
267
+ of(subscriberId: string, topics: string | string[], ...features: SubscribeFeature[]): SubscriptionInfo;
268
+ /**
269
+ * Builder pattern — 参考 jetlinks Subscription.builder()
270
+ */
271
+ builder(): SubscriptionInfoBuilder;
272
+ };
273
+ interface TopicEventBus {
274
+ /**
275
+ * Publish an event to a topic.
276
+ * @param topic The topic path
277
+ * @param payload The event data
278
+ * @param headers Optional headers for metadata propagation
279
+ */
280
+ publish(topic: string, payload: unknown, headers?: Record<string, unknown>): Promise<void>;
281
+ /**
282
+ * Subscribe using a structured SubscriptionInfo — 参考 jetlinks EventBus.subscribe(Subscription)
283
+ */
284
+ subscribe(subscription: SubscriptionInfo, handler: EventHandler): Subscription;
285
+ /**
286
+ * Subscribe with simple arguments (backward compatible).
287
+ * @param topicPattern Topic pattern with wildcards
288
+ * @param handler Event handler
289
+ * @param priority Priority (lower = higher priority, default Infinity)
290
+ */
291
+ subscribe(topicPattern: string, handler: EventHandler | LegacyEventHandler, priority?: number): Subscription;
292
+ }
293
+ /**
294
+ * 基于自定义 Topic 匹配的 EventBus 实现
295
+ *
296
+ * 支持:
297
+ * - * (单级) 和 ** (多级) 通配符
298
+ * - 逗号分隔的多值匹配: /device/p1/d1,d2/online
299
+ * - MQTT 通配符自动转换: # -> **, + -> *
300
+ * - TopicPayload 结构化消息
301
+ * - 监听器优先级排序(值越小优先级越高,与 jetlinks 一致)
302
+ *
303
+ * 参考 jetlinks DefaultEventBus
304
+ */
305
+ declare class DefaultTopicEventBus implements TopicEventBus {
306
+ private readonly logger;
307
+ private handlersByPattern;
308
+ publish(topic: string, payload: unknown, headers?: Record<string, unknown>): Promise<void>;
309
+ subscribe(subscriptionOrPattern: SubscriptionInfo | string, handler: EventHandler | LegacyEventHandler, priority?: number): Subscription;
310
+ private _subscribeSingle;
311
+ /**
312
+ * Remove all handlers — used during module shutdown to prevent leaks.
313
+ */
314
+ removeAllListeners(): void;
315
+ }
316
+ /**
317
+ * 通配符匹配:支持 * (单级)、** (多级) 和逗号分隔的多值段
318
+ *
319
+ * 逗号分隔支持参考 jetlinks TopicUtils:
320
+ * /device/p1/d1,d2/online 匹配 /device/p1/d1/online 和 /device/p1/d2/online
321
+ */
322
+ declare function matchesTopic(pattern: string, topic: string): boolean;
323
+
324
+ /**
325
+ * 异步事件接口
326
+ *
327
+ * 支持两级异步任务链:
328
+ * - first: 优先异步任务(在 commit 前先执行)
329
+ * - async: 普通异步任务
330
+ *
331
+ * 执行顺序:first 任务全部完成后,再执行 async 任务。
332
+ * 错误会沿链传播。
333
+ */
334
+ interface AsyncEvent<T = unknown> {
335
+ payload: T;
336
+ timestamp: number;
337
+ handled: boolean;
338
+ markHandled(): void;
339
+ /** 注册优先异步任务(在普通异步任务之前执行) */
340
+ first(fn: () => Promise<void>): void;
341
+ /** 注册普通异步任务 */
342
+ async(fn: () => Promise<void>): void;
343
+ /**
344
+ * 对 first 链进行变换
345
+ *
346
+ * 回调接收当前的 first 链 Promise,返回新的 Promise。
347
+ * 可用于包装事务边界、添加日志等横切逻辑。
348
+ */
349
+ transformFirst(mapper: (current: Promise<void>) => Promise<void>): void;
350
+ /**
351
+ * 对 async 链进行变换
352
+ *
353
+ * 回调接收当前的 async 链 Promise,返回新的 Promise。
354
+ */
355
+ transform(mapper: (current: Promise<void>) => Promise<void>): void;
356
+ /** 执行所有已注册任务:first 先于 async */
357
+ getAsync(): Promise<void>;
358
+ /** 是否有监听器注册了异步任务 */
359
+ readonly hasListener: boolean;
360
+ }
361
+ /**
362
+ * Create a new AsyncEvent with two-level async task chain support.
363
+ * First tasks execute before async tasks; errors propagate along the chain.
364
+ * @param payload - The event payload data
365
+ * @returns A new AsyncEvent instance
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * const event = createAsyncEvent({ userId: '123' });
370
+ * event.first(async () => { /* pre-commit work *\/ });
371
+ * event.async(async () => { /* post-commit work *\/ });
372
+ * await event.getAsync(); // executes first, then async tasks
373
+ * ```
374
+ */
375
+ declare function createAsyncEvent<T>(payload: T): AsyncEvent<T>;
376
+
377
+ /**
378
+ * 验证分组
379
+ *
380
+ * 使用 class-validator 的 groups 功能区分创建和更新时的不同校验规则。
381
+ *
382
+ * @example
383
+ * ```ts
384
+ * class User {
385
+ * @IsNotEmpty({ groups: [CREATE_GROUP] })
386
+ * name: string;
387
+ *
388
+ * @IsEmail({}, { groups: [CREATE_GROUP, UPDATE_GROUP] })
389
+ * email: string;
390
+ * }
391
+ * ```
392
+ */
393
+ declare const CREATE_GROUP = "create";
394
+ declare const UPDATE_GROUP = "update";
395
+ declare const SAVE_GROUP = "save";
396
+ /**
397
+ * PREPARE 阶段的自动校验监听器
398
+ *
399
+ * 在 PREPARE 阶段使用 class-validator 校验实体数据。
400
+ * 校验失败时,取消操作(event.cancel)。
401
+ *
402
+ * 验证规则:
403
+ * - CREATE/SAVE 操作使用 CreateGroup
404
+ * - UPDATE/MODIFY 操作使用 UpdateGroup
405
+ * - 用户可通过 options.groups 覆盖默认分组
406
+ *
407
+ * 用法:
408
+ * new ValidateEventListener(UserEntity)
409
+ * 注册到 entity.user.create.prepare 和 entity.user.update.prepare
410
+ */
411
+ declare class ValidateEventListener<T extends object> implements EntityEventListener<T> {
412
+ private readonly entityClass;
413
+ private readonly options?;
414
+ constructor(entityClass: ClassConstructor<T>, options?: {
415
+ /** 跳过校验的事件类型 */
416
+ skipTypes?: EntityEventType[];
417
+ /** class-validator 的 groups(覆盖默认分组策略) */
418
+ groups?: string[];
419
+ /** 是否跳过缺失属性(适用于 partial update) */
420
+ skipMissingProperties?: boolean;
421
+ } | undefined);
422
+ onEvent(event: EntityEvent<T>): Promise<void>;
423
+ /**
424
+ * 根据事件类型解析默认的校验分组
425
+ */
426
+ private resolveGroups;
427
+ }
428
+
429
+ /**
430
+ * 实体事件配置元数据 key
431
+ */
432
+ declare const ENTITY_EVENT_CONFIG_KEY = "zucker:event:entityEventConfig";
433
+ /**
434
+ * 实体事件配置
435
+ */
436
+ interface EntityEventConfig {
437
+ [EntityEventType.CREATE]?: boolean;
438
+ [EntityEventType.MODIFY]?: boolean;
439
+ [EntityEventType.DELETE]?: boolean;
440
+ [EntityEventType.SAVE]?: boolean;
441
+ [EntityEventType.QUERY]?: boolean;
442
+ }
443
+ /**
444
+ * @EnableEntityEvent() 装饰器
445
+ *
446
+ * 用于 Service 类,控制哪些实体事件需要发出。
447
+ * 默认启用 create/modify/delete/save,禁用 query。
448
+ *
449
+ * @example
450
+ * ```ts
451
+ * @EnableEntityEvent({ query: true })
452
+ * class UserService extends BaseService<User> { ... }
453
+ *
454
+ * @EnableEntityEvent({ delete: false })
455
+ * class LogService extends BaseService<Log> { ... }
456
+ * ```
457
+ */
458
+ declare function EnableEntityEvent(config?: Partial<EntityEventConfig>): ClassDecorator;
459
+ /**
460
+ * 获取实体事件配置
461
+ * 如果没有装饰器,返回默认配置(全部启用除 query)
462
+ */
463
+ declare function getEntityEventConfig(target: Function): EntityEventConfig;
464
+ /**
465
+ * 检查指定事件类型是否启用
466
+ */
467
+ declare function isEntityEventEnabled(target: Function, type: EntityEventType): boolean;
468
+
469
+ /**
470
+ * 运行时实体事件开关配置
471
+ *
472
+ * 支持三个粒度级别的控制(从粗到细):
473
+ * 1. 实体级别:enable('user') / disable('user')
474
+ * 2. 事件类型级别:enable('user', EntityEventType.CREATE)
475
+ * 3. 事件阶段级别:enable('user', EntityEventType.CREATE, EntityEventPhase.BEFORE)
476
+ *
477
+ * 优先级(从高到低):
478
+ * 1. 运行时 disable 配置(精确匹配优先)
479
+ * 2. 运行时 enable 配置(精确匹配优先)
480
+ * 3. @EnableEntityEvent 装饰器
481
+ * 4. 默认全部启用
482
+ *
483
+ * enable 和 disable 互斥,enable 某个阶段会自动从 disabled 集合中移除,反之亦然。
484
+ *
485
+ * 并发安全改进:
486
+ * 在初次 CRUD 操作并发执行时,多个请求可能同时尝试初始化同一实体类型的事件配置。
487
+ * 初始化过程同步执行,不跨异步边界。
488
+ * 使用已初始化标志确保初始化逻辑只执行一次。
489
+ */
490
+ declare class EntityEventListenerConfigure {
491
+ private readonly enabled;
492
+ private readonly disabled;
493
+ /**
494
+ * 启用整个实体的事件
495
+ */
496
+ enable(entityType: string): void;
497
+ /**
498
+ * 启用指定实体的指定事件类型
499
+ */
500
+ enable(entityType: string, eventType: EntityEventType): void;
501
+ /**
502
+ * 启用指定实体的指定事件类型的指定阶段
503
+ */
504
+ enable(entityType: string, eventType: EntityEventType, ...phases: EntityEventPhase[]): void;
505
+ /**
506
+ * 禁用整个实体的事件
507
+ */
508
+ disable(entityType: string): void;
509
+ /**
510
+ * 禁用指定实体的指定事件类型
511
+ */
512
+ disable(entityType: string, eventType: EntityEventType): void;
513
+ /**
514
+ * 禁用指定实体的指定事件类型的指定阶段
515
+ */
516
+ disable(entityType: string, eventType: EntityEventType, ...phases: EntityEventPhase[]): void;
517
+ /**
518
+ * 检查某个实体是否启用了事件(实体级别)
519
+ */
520
+ isEnabled(entityType: string): boolean;
521
+ /**
522
+ * 检查某个实体的某种事件在某个阶段是否启用
523
+ */
524
+ isEnabled(entityType: string, eventType: EntityEventType, phase?: EntityEventPhase): boolean;
525
+ /**
526
+ * 清除指定实体的运行时覆盖配置
527
+ */
528
+ reset(entityType: string, eventType?: EntityEventType, phase?: EntityEventPhase): void;
529
+ /**
530
+ * 清除所有运行时覆盖配置
531
+ */
532
+ resetAll(): void;
533
+ }
534
+
535
+ /**
536
+ * 实体事件监听器自定义接口
537
+ *
538
+ * 实现此接口可在应用启动时对 EntityEventListenerConfigure 进行编程式配置。
539
+ *
540
+ * @example
541
+ * ```ts
542
+ * @Injectable()
543
+ * class MyCustomizer implements EntityEventListenerCustomizer {
544
+ * customize(configure: EntityEventListenerConfigure): void {
545
+ * // 禁用 audit_log 实体的 QUERY 事件
546
+ * configure.disable('audit_log', EntityEventType.QUERY);
547
+ * // 仅禁用 user 实体的 DELETE.BEFORE 阶段
548
+ * configure.disable('user', EntityEventType.DELETE, EntityEventPhase.BEFORE);
549
+ * }
550
+ * }
551
+ * ```
552
+ */
553
+ interface EntityEventListenerCustomizer {
554
+ customize(configure: EntityEventListenerConfigure): void;
555
+ }
556
+ declare const ENTITY_EVENT_LISTENER_CUSTOMIZER = "ENTITY_EVENT_LISTENER_CUSTOMIZER";
557
+
558
+ /**
559
+ * 检查当前上下文是否应该触发事件
560
+ * @param defaultIfEmpty 未设置时的默认值(默认 true)
561
+ */
562
+ declare function isDoFireEvent(defaultIfEmpty?: boolean): boolean;
563
+ /**
564
+ * 在回调范围内禁用事件触发
565
+ *
566
+ * @example
567
+ * ```ts
568
+ * await withoutFireEvent(async () => {
569
+ * await service.save(entity); // 不会触发实体事件
570
+ * });
571
+ * ```
572
+ */
573
+ declare function withoutFireEvent<T>(fn: () => Promise<T>): Promise<T>;
574
+ /**
575
+ * 在回调范围内启用事件触发(用于嵌套恢复)
576
+ */
577
+ declare function withFireEvent<T>(fn: () => Promise<T>): Promise<T>;
578
+ /**
579
+ * 尝试触发事件 — 如果当前上下文禁用了事件则跳过
580
+ */
581
+ declare function tryFireEvent(task: () => Promise<void>): Promise<void>;
582
+ /**
583
+ * 创建并返回一个 EntityEvent,便捷方法
584
+ */
585
+ declare function createSingleEntityEvent<T>(type: EntityEventType, phase: EntityEventPhase, entityType: string, entity: T): EntityEvent<T>;
586
+ /**
587
+ * 创建并返回一个批量 EntityEvent
588
+ */
589
+ declare function createBatchEntityEvent<T>(type: EntityEventType, phase: EntityEventPhase, entityType: string, entities: T[]): EntityEvent<T>;
590
+ /**
591
+ * 创建批量修改事件(带 before/after)
592
+ *
593
+ * 修改事件同时包含修改前(before)和修改后(after)的数据列表,
594
+ * 供监听器对比差异或进行审计日志记录。
595
+ *
596
+ * @param phase - 事件阶段
597
+ * @param entityType - 实体类型名称
598
+ * @param before - 修改前的实体列表
599
+ * @param after - 修改后的实体列表
600
+ */
601
+ declare function createModifyEntityEvent<T>(phase: EntityEventPhase, entityType: string, before: T[], after: T[]): EntityEvent<T> | null;
602
+ /**
603
+ * 创建批量创建事件
604
+ */
605
+ declare function createCreatedEntityEvent<T>(phase: EntityEventPhase, entityType: string, entities: T[]): EntityEvent<T>;
606
+ /**
607
+ * 创建批量删除事件
608
+ */
609
+ declare function createDeletedEntityEvent<T>(phase: EntityEventPhase, entityType: string, entities: T[]): EntityEvent<T>;
610
+ /**
611
+ * 创建批量保存事件
612
+ */
613
+ declare function createSavedEntityEvent<T>(phase: EntityEventPhase, entityType: string, entities: T[]): EntityEvent<T>;
614
+
615
+ declare const TOPIC_EVENT_BUS = "TOPIC_EVENT_BUS";
616
+ declare class ZuckerEventModule implements OnModuleInit, OnModuleDestroy {
617
+ private readonly listenerConfigure;
618
+ private readonly eventBus;
619
+ private readonly customizers?;
620
+ constructor(listenerConfigure: EntityEventListenerConfigure, eventBus: TopicEventBus, customizers?: EntityEventListenerCustomizer[] | undefined);
621
+ /**
622
+ * 模块初始化时执行所有 EntityEventListenerCustomizer
623
+ * 通过 EntityEventListenerCustomizer 进行运行时配置
624
+ */
625
+ onModuleInit(): void;
626
+ onModuleDestroy(): void;
627
+ static forRoot(): DynamicModule;
628
+ }
629
+
630
+ /**
631
+ * 事件持久化存储接口。
632
+ * 支持事件溯源和重放。
633
+ *
634
+ * 默认无实现(事件只在内存中传播)。
635
+ * 生产环境可注入数据库实现以支持事件审计和重放。
636
+ */
637
+ interface EventStore {
638
+ /** 持久化一个事件 */
639
+ save(event: StoredEvent): Promise<void>;
640
+ /** 按主题查询事件 */
641
+ findByTopic(topic: string, options?: EventQueryOptions): Promise<StoredEvent[]>;
642
+ /** 按聚合根查询事件 */
643
+ findByAggregateId(aggregateId: string, options?: EventQueryOptions): Promise<StoredEvent[]>;
644
+ /** 重放事件(按时间顺序) */
645
+ replay(topic: string, fromTimestamp?: number): AsyncIterable<StoredEvent>;
646
+ /** 统计事件数 */
647
+ count(topic?: string): Promise<number>;
648
+ }
649
+ interface StoredEvent {
650
+ id?: string;
651
+ topic: string;
652
+ aggregateId?: string;
653
+ aggregateType?: string;
654
+ payload: unknown;
655
+ metadata?: Record<string, unknown>;
656
+ timestamp: number;
657
+ version?: number;
658
+ }
659
+ interface EventQueryOptions {
660
+ fromTimestamp?: number;
661
+ toTimestamp?: number;
662
+ limit?: number;
663
+ offset?: number;
664
+ }
665
+ declare const EVENT_STORE = "EVENT_STORE";
666
+
667
+ /**
668
+ * 集群事件传输接口
669
+ *
670
+ * 用于跨进程/跨节点的事件分发。
671
+ * 本地事件走 TopicEventBus,远程事件走此接口。
672
+ */
673
+ interface ClusterTransport {
674
+ /** 将事件广播到集群其他节点 */
675
+ broadcast(topic: string, payload: unknown): Promise<void>;
676
+ /** 订阅来自集群其他节点的事件 */
677
+ onRemoteEvent(handler: (topic: string, payload: unknown) => void): void;
678
+ }
679
+ declare const CLUSTER_TRANSPORT: unique symbol;
680
+ /**
681
+ * 统一事件总线
682
+ *
683
+ * 对标 Claude Code 的 Hook Registry 模式:
684
+ * 所有事件走同一个管道,通过 topic 模式匹配做路由。
685
+ *
686
+ * 整合了:
687
+ * - TopicEventBus(本地发布/订阅,带 wildcard 匹配)
688
+ * - EventEmitter2(NestJS 内置,访问日志等)
689
+ * - ClusterTransport(可选,跨节点广播)
690
+ *
691
+ * 用法:
692
+ * ```ts
693
+ * // 发布事件(本地 + 集群)
694
+ * await eventBus.publish('entity/user/create/after', { user });
695
+ *
696
+ * // 只发布到本地
697
+ * await eventBus.publishLocal('access.log', { path, method });
698
+ *
699
+ * // 订阅
700
+ * const sub = eventBus.subscribe('entity/user/**', handler);
701
+ * sub.unsubscribe();
702
+ * ```
703
+ */
704
+ declare class UnifiedEventBus {
705
+ private readonly cluster?;
706
+ private readonly logger;
707
+ private readonly localBus;
708
+ constructor(localBus: TopicEventBus, cluster?: ClusterTransport | undefined);
709
+ /**
710
+ * 发布事件(本地 + 集群)
711
+ * @param topic 事件主题
712
+ * @param payload 事件负载
713
+ */
714
+ publish(topic: string, payload: unknown): Promise<void>;
715
+ /**
716
+ * 仅发布到本地(不广播到集群)
717
+ * 适用于访问日志等高频、无需跨节点的事件
718
+ */
719
+ publishLocal(topic: string, payload: unknown): Promise<void>;
720
+ /**
721
+ * 订阅事件(支持 wildcard 模式)
722
+ * @param pattern 主题匹配模式(支持 * 和 **)
723
+ * @param handler 事件处理函数
724
+ */
725
+ subscribe(pattern: string, handler: EventHandler): Subscription;
726
+ /**
727
+ * 发布并等待所有处理完成
728
+ * 用于需要确保所有 listener 执行完毕的场景(如事务内事件)
729
+ */
730
+ publishAndWait(topic: string, payload: unknown): Promise<void>;
731
+ }
732
+
733
+ /**
734
+ * 通用操作 Hook 系统
735
+ *
736
+ * 对标 Claude Code 的 PreToolUse / PostToolUse hook:
737
+ * 允许在任意操作前后注入逻辑(审批、记录、拦截),而不限于 CRUD 事件。
738
+ *
739
+ * 用法:
740
+ * ```ts
741
+ * const hooks = new OperationHookRegistry();
742
+ *
743
+ * // 注册 hook: 在 storage.upload 之前执行
744
+ * hooks.register('storage.upload', 'before', async (ctx) => {
745
+ * if (ctx.data.size > MAX_SIZE) ctx.cancel('文件超过大小限制');
746
+ * });
747
+ *
748
+ * // 执行 hook
749
+ * const ctx = hooks.createContext('storage.upload', { file });
750
+ * await hooks.executeBefore(ctx);
751
+ * if (ctx.cancelled) throw new Error(ctx.cancelReason);
752
+ * // ... 执行实际操作 ...
753
+ * await hooks.executeAfter(ctx);
754
+ * ```
755
+ */
756
+ type HookPhase = 'before' | 'after';
757
+ interface OperationContext {
758
+ /** 操作名称(如 'storage.upload', 'config.update') */
759
+ readonly operation: string;
760
+ /** 操作数据 */
761
+ data: unknown;
762
+ /** 操作是否被取消 */
763
+ cancelled: boolean;
764
+ /** 取消原因 */
765
+ cancelReason?: string;
766
+ /** 操作结果(仅在 after 阶段可用) */
767
+ result?: unknown;
768
+ /** 自定义属性 */
769
+ readonly attributes: Map<string, unknown>;
770
+ /** 取消操作 */
771
+ cancel(reason: string): void;
772
+ }
773
+ type HookHandler = (ctx: OperationContext) => void | Promise<void>;
774
+ declare class OperationHookRegistry {
775
+ private readonly logger;
776
+ private readonly hooks;
777
+ /**
778
+ * 注册操作 hook
779
+ * @param operation 操作名称模式(支持 * 和 ** 通配符)
780
+ * @param phase 执行阶段
781
+ * @param handler hook 处理函数
782
+ * @param options 可选配置
783
+ * @returns 取消注册的函数
784
+ */
785
+ register(operation: string, phase: HookPhase, handler: HookHandler, options?: {
786
+ priority?: number;
787
+ name?: string;
788
+ }): () => void;
789
+ /**
790
+ * 创建操作上下文
791
+ */
792
+ createContext(operation: string, data: unknown): OperationContext;
793
+ /**
794
+ * 执行 before 阶段的所有 hook
795
+ * 如果任意 hook 取消了操作,后续 hook 不再执行
796
+ */
797
+ executeBefore(ctx: OperationContext): Promise<void>;
798
+ /**
799
+ * 执行 after 阶段的所有 hook
800
+ */
801
+ executeAfter(ctx: OperationContext): Promise<void>;
802
+ private executePhase;
803
+ /**
804
+ * 获取已注册的 hook 数量
805
+ */
806
+ get size(): number;
807
+ /**
808
+ * 清除所有 hook
809
+ */
810
+ clear(): void;
811
+ }
812
+
813
+ export { ALL_EVENT_PHASES, type AsyncEvent, CLUSTER_TRANSPORT, CREATE_GROUP, type ClusterTransport, CompositeEventListener, CreatorEventListener, type CurrentUser, DefaultTopicEventBus, ENTITY_EVENT_CONFIG_KEY, ENTITY_EVENT_LISTENER_CUSTOMIZER, EVENT_STORE, EnableEntityEvent, type EntityEvent, type EntityEventConfig, type EntityEventListener, EntityEventListenerConfigure, type EntityEventListenerCustomizer, EntityEventPhase, EntityEventType, type EventHandler, type EventQueryOptions, type EventStore, type HookHandler, type HookPhase, type LegacyEventHandler, type OperationContext, OperationHookRegistry, SAVE_GROUP, SUBSCRIBE_KEY, SUBSCRIBE_METHODS_KEY, type StoredEvent, Subscribe, SubscribeFeature, type SubscribeOptions, type Subscription, SubscriptionBuilder, type SubscriptionInfo, type SubscriptionInfoBuilder, TOPIC_EVENT_BUS, type TopicEventBus, type TopicPayload, UPDATE_GROUP, UnifiedEventBus, ValidateEventListener, ZuckerEventModule, createAsyncEvent, createBatchEntityEvent, createCreatedEntityEvent, createDeletedEntityEvent, createEntityEvent, createModifyEntityEvent, createSavedEntityEvent, createSingleEntityEvent, createTopicPayload, getEntityEventConfig, getEntityEventName, getSubscriptions, isDoFireEvent, isEntityEventEnabled, matchesTopic, tryFireEvent, withFireEvent, withoutFireEvent };