@zucker-framework/rule-engine 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,839 @@
1
+ import { OnModuleDestroy, Logger } from '@nestjs/common';
2
+ import { TopicEventBus } from '@zucker-framework/event';
3
+
4
+ interface Term {
5
+ column: string;
6
+ termType: string;
7
+ value: unknown;
8
+ /** 嵌套条件组(对齐 jetlinks Term 嵌套) */
9
+ terms?: Term[];
10
+ /** 嵌套组的连接类型 */
11
+ termsType?: 'and' | 'or';
12
+ }
13
+ interface TermCondition {
14
+ terms: Term[];
15
+ type: 'and' | 'or';
16
+ }
17
+ declare class TermsEvaluator {
18
+ /**
19
+ * 注册自定义操作符 — 对齐 jetlinks 可扩展的 TermType
20
+ */
21
+ registerOperator(name: string, fn: (fieldValue: unknown, termValue: unknown) => boolean): void;
22
+ /**
23
+ * 获取已注册的所有操作符名称
24
+ */
25
+ getOperatorNames(): string[];
26
+ evaluate(data: Record<string, unknown>, condition: TermCondition): boolean;
27
+ private evaluateTerms;
28
+ }
29
+
30
+ interface ExpressionCondition {
31
+ expression: string;
32
+ }
33
+ /**
34
+ * ExpressionEvaluator — simple expression evaluation for rule-engine conditions.
35
+ *
36
+ * SECURITY NOTE: Node.js `vm` module is NOT a secure sandbox. It provides
37
+ * isolation from the host global scope but a determined attacker can escape.
38
+ * This evaluator is intended ONLY for trusted / admin-authored expressions,
39
+ * NOT for arbitrary user input from untrusted sources. Additional hardening
40
+ * (Object.freeze, timeout, arguments restriction) reduces the attack surface
41
+ * but does not eliminate all escape vectors.
42
+ */
43
+ declare class ExpressionEvaluator {
44
+ /** Default timeout in milliseconds for expression evaluation */
45
+ private static readonly EVAL_TIMEOUT_MS;
46
+ evaluate(data: Record<string, unknown>, condition: ExpressionCondition): boolean;
47
+ }
48
+
49
+ /**
50
+ * Shake-limit (debounce / throttle) support for rule branches.
51
+ * Mirrors jetlinks ShakeLimit — prevents rapid re-triggering.
52
+ */
53
+ interface ShakeLimitConfig {
54
+ /** Whether shake limiting is enabled. */
55
+ enabled: boolean;
56
+ /** Time window in milliseconds. */
57
+ time: number;
58
+ /** Maximum number of triggers allowed within the time window. */
59
+ threshold: number;
60
+ /** Alarm on drop — fire error event when messages are dropped. */
61
+ alarmFirst?: boolean;
62
+ }
63
+ interface ShakeLimitResult<T> {
64
+ /** The element that passed the shake limit. */
65
+ element: T;
66
+ /** Total number of triggers within the current window. */
67
+ times: number;
68
+ }
69
+ /**
70
+ * Creates a shake-limit filter that suppresses rapid invocations.
71
+ * Returns a function that decides whether to allow the current invocation.
72
+ *
73
+ * When alarmFirst is true, the first event that meets the threshold fires
74
+ * immediately. When false (default), only events within the threshold pass.
75
+ * This mirrors jetlinks ShakeLimit.transfer() semantics.
76
+ */
77
+ declare function createShakeLimit(config: ShakeLimitConfig): {
78
+ tryAcquire: () => boolean;
79
+ reset: () => void;
80
+ getCurrentCount: () => number;
81
+ };
82
+
83
+ /**
84
+ * Branch condition evaluator — mirrors jetlinks SceneConditionAction.
85
+ *
86
+ * Supports if/else-if/else branching with:
87
+ * - Term-based conditions (field comparisons)
88
+ * - Expression-based conditions (JS expressions)
89
+ * - executeAnyway flag (always-run branches, like 'also' in addition to if/else)
90
+ * - Shake-limit (debounce) per branch
91
+ * - Parallel or serial action groups within each branch
92
+ */
93
+ interface BranchActionGroup {
94
+ /** Whether actions in this group execute in parallel. */
95
+ parallel: boolean;
96
+ /** Action definitions to execute. */
97
+ actions: BranchAction[];
98
+ }
99
+ interface BranchAction {
100
+ /** Action type identifier. */
101
+ type: string;
102
+ /** Action-specific configuration. */
103
+ config: Record<string, unknown>;
104
+ }
105
+ interface BranchCondition {
106
+ /** Condition type: 'terms' or 'expression'. */
107
+ type: 'terms' | 'expression';
108
+ /** Condition configuration. */
109
+ config: TermCondition | ExpressionCondition;
110
+ }
111
+ interface Branch {
112
+ /** Unique branch identifier. */
113
+ id?: string;
114
+ /** Conditions to evaluate — if empty, acts as 'else'. */
115
+ when: BranchCondition[];
116
+ /** Action groups to execute when conditions are met. */
117
+ then: BranchActionGroup[];
118
+ /** Whether to execute this branch regardless of previous matches (default: false). */
119
+ executeAnyway?: boolean;
120
+ /** Optional shake-limit (debounce) configuration for this branch. */
121
+ shakeLimit?: ShakeLimitConfig;
122
+ }
123
+ interface BranchEvaluationResult {
124
+ /** Index of the matched branch (or -1 if none matched). */
125
+ branchIndex: number;
126
+ /** Branch id if specified. */
127
+ branchId?: string;
128
+ /** Whether the branch conditions were met. */
129
+ matched: boolean;
130
+ /** Action groups to execute. */
131
+ actionGroups: BranchActionGroup[];
132
+ }
133
+ declare class BranchEvaluator {
134
+ private readonly logger;
135
+ private readonly termsEvaluator;
136
+ private readonly expressionEvaluator;
137
+ private readonly shakeLimitMap;
138
+ /**
139
+ * Evaluate branches against data.
140
+ * Implements if/else-if/else semantics with executeAnyway support.
141
+ *
142
+ * Returns all branches that should fire (respecting executeAnyway and
143
+ * if/else-if ordering).
144
+ */
145
+ evaluate(branches: Branch[], data: Record<string, unknown>): BranchEvaluationResult[];
146
+ private evaluateConditions;
147
+ /** Reset all shake limiters. */
148
+ resetShakeLimits(): void;
149
+ }
150
+
151
+ /**
152
+ * Rule instance lifecycle states — mirrors jetlinks RuleInstanceState.
153
+ */
154
+ declare enum RuleInstanceState {
155
+ /** Rule is started and actively processing. */
156
+ STARTED = "started",
157
+ /** Rule is disabled / stopped. */
158
+ DISABLED = "disabled",
159
+ /** Rule is paused (can be resumed without re-init). */
160
+ PAUSED = "paused"
161
+ }
162
+
163
+ /** Types of conditions that can be evaluated in a rule. */
164
+ declare enum RuleConditionType {
165
+ TERMS = "TERMS",
166
+ EXPRESSION = "EXPRESSION"
167
+ }
168
+ declare enum RuleTriggerType {
169
+ EVENT = "EVENT",
170
+ TIMER = "TIMER",
171
+ MANUAL = "MANUAL"
172
+ }
173
+ declare enum RuleActionType {
174
+ NOTIFY = "NOTIFY",
175
+ HTTP = "HTTP",
176
+ SCRIPT = "SCRIPT",
177
+ DELAY = "DELAY",
178
+ DATA_MAPPING = "DATA_MAPPING"
179
+ }
180
+ interface RuleCondition {
181
+ type: RuleConditionType;
182
+ config: Record<string, unknown>;
183
+ }
184
+ interface RuleAction {
185
+ type: string;
186
+ config: Record<string, unknown>;
187
+ /** Output filter conditions — for serial execution, data must pass to continue. */
188
+ terms?: TermCondition;
189
+ }
190
+ interface RuleTrigger {
191
+ type: RuleTriggerType;
192
+ config: Record<string, unknown>;
193
+ }
194
+ /** Complete definition of a rule including its triggers, conditions, and actions. */
195
+ interface RuleDefinition {
196
+ id: string;
197
+ name: string;
198
+ triggers: RuleTrigger[];
199
+ conditions: RuleCondition[];
200
+ /** Top-level actions (flat execution). */
201
+ actions: RuleAction[];
202
+ /** Conditional branches with action groups (when/then). */
203
+ branches?: Branch[];
204
+ /** Whether top-level actions run in parallel (default: false = serial). */
205
+ parallel?: boolean;
206
+ enabled: boolean;
207
+ }
208
+ /** Core service for registering, evaluating, and executing rules with event/timer triggers. */
209
+ declare class RuleEngineService implements OnModuleDestroy {
210
+ private readonly eventBus?;
211
+ private readonly logger;
212
+ private activeRules;
213
+ private termsEvaluator;
214
+ private expressionEvaluator;
215
+ private notifyAction;
216
+ private httpAction;
217
+ private scriptAction;
218
+ private delayAction;
219
+ private dataMappingAction;
220
+ /** Strategy map for action execution — replaces switch/case in executeAction. */
221
+ private readonly actionHandlers;
222
+ constructor(eventBus?: TopicEventBus | undefined);
223
+ onModuleDestroy(): void;
224
+ startRule(definition: RuleDefinition): Promise<void>;
225
+ stopRule(id: string): Promise<void>;
226
+ pauseRule(id: string): Promise<void>;
227
+ resumeRule(id: string): Promise<void>;
228
+ stopAll(): void;
229
+ executeRule(definition: RuleDefinition, data: Record<string, unknown>): Promise<void>;
230
+ /** Execute branch conditions and their associated action groups. */
231
+ private executeBranches;
232
+ /** Execute an action group (parallel or serial). */
233
+ private executeActionGroup;
234
+ /** Execute actions in parallel. */
235
+ private executeActionsParallel;
236
+ /** Execute actions serially, passing output from one to the next. */
237
+ private executeActionsSerial;
238
+ private executeAction;
239
+ /** Set up a single trigger (event or timer) for a rule. */
240
+ private setupTrigger;
241
+ /** Evaluate all conditions for a rule — returns true if all pass. */
242
+ private evaluateConditions;
243
+ /** Evaluate a single condition by type. */
244
+ private evaluateSingleCondition;
245
+ getActiveRules(): RuleDefinition[];
246
+ isRuleActive(id: string): boolean;
247
+ getRuleState(id: string): RuleInstanceState | undefined;
248
+ }
249
+
250
+ interface NotifyActionConfig {
251
+ notifyType: string;
252
+ templateId?: string;
253
+ recipients: string[];
254
+ title?: string;
255
+ message?: string;
256
+ /** 变量映射(对齐 jetlinks 通知模板变量绑定) */
257
+ variables?: Record<string, string>;
258
+ }
259
+ /**
260
+ * 通知事件结构 — 通过事件总线发布
261
+ */
262
+ interface NotifyEvent {
263
+ type: string;
264
+ templateId?: string;
265
+ recipients: string[];
266
+ title?: string;
267
+ message?: string;
268
+ data: Record<string, unknown>;
269
+ /** 解析后的变量值 */
270
+ resolvedVariables?: Record<string, unknown>;
271
+ }
272
+ /**
273
+ * 通知发送函数类型 — 由外部注入实现
274
+ */
275
+ type NotifySender = (event: NotifyEvent) => Promise<void>;
276
+ /**
277
+ * 通知动作执行器 — 对齐 jetlinks NotifyTaskExecutorProvider
278
+ *
279
+ * 增强:
280
+ * - 支持变量解析(从 data 中提取模板变量)
281
+ * - 支持外部注入通知发送器
282
+ */
283
+ declare class NotifyAction {
284
+ private readonly logger;
285
+ private sender?;
286
+ /**
287
+ * 设置通知发送器(由模块初始化时注入)
288
+ */
289
+ setSender(sender: NotifySender): void;
290
+ execute(config: NotifyActionConfig, data: Record<string, unknown>): Promise<void>;
291
+ /**
292
+ * 验证通知配置
293
+ */
294
+ validate(config: NotifyActionConfig): void;
295
+ /**
296
+ * 解析变量路径 — 对齐 jetlinks VariableSource 解析
297
+ */
298
+ private resolveVariable;
299
+ private interpolate;
300
+ }
301
+
302
+ interface HttpActionConfig {
303
+ url: string;
304
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
305
+ headers?: Record<string, string>;
306
+ body?: unknown;
307
+ timeout?: number;
308
+ /** 重试次数(默认 0 不重试) */
309
+ retryCount?: number;
310
+ /** 重试间隔(毫秒,默认 1000) */
311
+ retryDelay?: number;
312
+ }
313
+ /**
314
+ * HTTP 动作执行器 — 对齐 jetlinks 的数据推送能力
315
+ *
316
+ * 增强:
317
+ * - 支持重试机制
318
+ * - 模板表达式支持(在 URL、headers、body 中使用 ${variable})
319
+ * - 响应规范化
320
+ */
321
+ declare class HttpAction {
322
+ private readonly logger;
323
+ execute(config: HttpActionConfig, data: Record<string, unknown>): Promise<unknown>;
324
+ /**
325
+ * 验证配置有效性
326
+ */
327
+ validate(config: HttpActionConfig): void;
328
+ private doRequest;
329
+ /**
330
+ * 模板插值 — 对齐 jetlinks TemplateParser / applyValueExpression
331
+ * 支持 ${key} 和嵌套路径 ${a.b.c}
332
+ */
333
+ private interpolate;
334
+ private getNestedValue;
335
+ private delay;
336
+ }
337
+
338
+ interface ScriptActionConfig {
339
+ script: string;
340
+ /** 脚本语言(目前仅支持 js) — 对齐 jetlinks ScriptTaskExecutorProvider.Config.lang */
341
+ lang?: string;
342
+ timeout?: number;
343
+ }
344
+ /**
345
+ * 脚本动作执行器 — 对齐 jetlinks ScriptTaskExecutorProvider
346
+ *
347
+ * 增强:
348
+ * - 支持 handler 模式(脚本中定义 onMessage 回调)
349
+ * - 对脚本返回值进行规范化处理
350
+ */
351
+ declare class ScriptAction {
352
+ private readonly logger;
353
+ execute(config: ScriptActionConfig, data: Record<string, unknown>): Promise<unknown>;
354
+ /**
355
+ * 验证脚本配置 — 对齐 jetlinks executor validate()
356
+ */
357
+ validate(config: ScriptActionConfig): void;
358
+ /**
359
+ * 规范化脚本返回值 — 对齐 jetlinks convertToJavaType
360
+ * 确保返回的是可序列化的纯对象
361
+ */
362
+ private normalizeResult;
363
+ }
364
+
365
+ /**
366
+ * Delay action — mirrors jetlinks DelayTaskExecutorProvider.
367
+ *
368
+ * Supports multiple pause types:
369
+ * - fixed delay
370
+ * - random delay
371
+ * - upstream-specified delay (delayv)
372
+ * - rate limiting
373
+ */
374
+ type DelayPauseType = 'delay' | 'delayv' | 'random' | 'rate';
375
+ type DelayTimeUnit = 'milliseconds' | 'seconds' | 'minutes' | 'hours';
376
+ interface DelayActionConfig {
377
+ /** Type of delay behaviour. */
378
+ pauseType: DelayPauseType;
379
+ /** Fixed delay amount (for 'delay' type). */
380
+ timeout?: number;
381
+ /** Unit for timeout. */
382
+ timeoutUnits?: DelayTimeUnit;
383
+ /** Random delay lower bound (for 'random' type). */
384
+ randomFirst?: number;
385
+ /** Random delay upper bound (for 'random' type). */
386
+ randomLast?: number;
387
+ /** Unit for random delay. */
388
+ randomUnits?: DelayTimeUnit;
389
+ /** Rate limit: max events per window (for 'rate' type). */
390
+ rate?: number;
391
+ /** Rate window size. */
392
+ nbRateUnits?: number;
393
+ /** Rate window unit. */
394
+ rateUnits?: DelayTimeUnit;
395
+ }
396
+ declare class DelayAction {
397
+ private readonly logger;
398
+ /**
399
+ * Execute the delay according to the configured pause type.
400
+ * For 'delayv', the delay duration comes from `data.delay` (string parseable as ms).
401
+ * Returns the data after the delay completes.
402
+ */
403
+ execute(config: DelayActionConfig, data: Record<string, unknown>): Promise<Record<string, unknown>>;
404
+ private calculateDelay;
405
+ }
406
+
407
+ /**
408
+ * Data-mapping action — mirrors jetlinks DataMappingTaskExecutorProvider.
409
+ *
410
+ * Transforms data by mapping source fields to target fields with optional
411
+ * type conversion, supporting expression-based source references.
412
+ */
413
+ interface DataMapping {
414
+ /** Target field name in output. */
415
+ target: string;
416
+ /** Source field name or expression (supports ${expr} interpolation). */
417
+ source: string;
418
+ /** Optional type coercion: 'string' | 'number' | 'boolean' | 'integer' | 'decimal'. */
419
+ type?: string;
420
+ }
421
+ interface DataMappingActionConfig {
422
+ /** Field mappings. */
423
+ mappings: DataMapping[];
424
+ /** Whether to keep all source data and merge mappings on top. */
425
+ keepSourceData?: boolean;
426
+ }
427
+ declare class DataMappingAction {
428
+ private readonly logger;
429
+ execute(config: DataMappingActionConfig, data: Record<string, unknown>): Record<string, unknown>;
430
+ private doMapping;
431
+ private resolveSource;
432
+ private getNestedValue;
433
+ }
434
+
435
+ interface EventTriggerConfig {
436
+ topic: string;
437
+ }
438
+ declare class EventTrigger {
439
+ private readonly logger;
440
+ private subscription?;
441
+ start(config: EventTriggerConfig, eventBus: TopicEventBus, handler: (payload: unknown) => void | Promise<void>): void;
442
+ stop(): void;
443
+ isRunning(): boolean;
444
+ }
445
+
446
+ interface TimerTriggerConfig {
447
+ cron: string;
448
+ timezone?: string;
449
+ /** 执行次数限制(0 = 无限) */
450
+ maxTimes?: number;
451
+ }
452
+ /**
453
+ * 定时触发器 — 对齐 jetlinks TimerTaskExecutor
454
+ * 增加执行次数追踪和验证
455
+ */
456
+ declare class TimerTrigger {
457
+ private readonly logger;
458
+ private intervalId?;
459
+ private running;
460
+ private executionCount;
461
+ private lastExecutionTime?;
462
+ private config?;
463
+ start(config: TimerTriggerConfig, handler: () => void | Promise<void>): void;
464
+ stop(): void;
465
+ isRunning(): boolean;
466
+ /** 获取已执行次数 — 对齐 jetlinks TimerTaskExecutor 中的 times 传递 */
467
+ getExecutionCount(): number;
468
+ /** 获取最后执行时间 */
469
+ getLastExecutionTime(): Date | undefined;
470
+ /**
471
+ * 重新加载配置 — 对齐 jetlinks TimerTaskExecutor.reload()
472
+ */
473
+ reload(config: TimerTriggerConfig, handler: () => void | Promise<void>): void;
474
+ /**
475
+ * 验证配置 — 对齐 jetlinks TimerTaskExecutor.validate()
476
+ */
477
+ validate(config?: TimerTriggerConfig): void;
478
+ private parseCronToInterval;
479
+ }
480
+
481
+ /**
482
+ * RuleData wraps data flowing through the rule engine graph,
483
+ * carrying context headers alongside the payload — mirrors
484
+ * jetlinks RuleData / RuleDataHelper.
485
+ */
486
+ interface RuleDataHeaders {
487
+ /** Originating rule instance id */
488
+ ruleId?: string;
489
+ /** Node that produced this data */
490
+ nodeId?: string;
491
+ /** Arbitrary context passed between nodes */
492
+ [key: string]: unknown;
493
+ }
494
+ declare class RuleData {
495
+ readonly id: string;
496
+ private _data;
497
+ private readonly _headers;
498
+ private readonly _contextMap;
499
+ constructor(data: unknown, headers?: RuleDataHeaders);
500
+ static of(data: unknown): RuleData;
501
+ /** Create a new RuleData sharing headers but replacing the payload. */
502
+ newData(data: unknown): RuleData;
503
+ getData(): unknown;
504
+ setData(data: unknown): void;
505
+ getHeader(key: string): unknown;
506
+ setHeader(key: string, value: unknown): void;
507
+ getHeaders(): Readonly<RuleDataHeaders>;
508
+ /** Record current data into headers under `key` (used for serial chaining). */
509
+ recordToHeader(key: string): void;
510
+ /** Get a context map entry. */
511
+ getContextEntry(key: string): unknown;
512
+ /** Set a context map entry — mirrors jetlinks RuleDataHelper.setContextData(). */
513
+ setContextEntry(key: string, value: unknown): void;
514
+ /** Retrieve the full context map (plain object view of data).
515
+ * Merges data + headers + contextMap — aligned with jetlinks RuleDataHelper.toContextMap(). */
516
+ toContextMap(): Record<string, unknown>;
517
+ private static _counter;
518
+ private static generateId;
519
+ }
520
+
521
+ /**
522
+ * Mirrors jetlinks ExecutionContext — provides input/output channels,
523
+ * logging, error handling, and event firing for a TaskExecutor.
524
+ */
525
+ interface ExecutionContext {
526
+ /** The logger scoped to this execution context. */
527
+ getLogger(): Logger;
528
+ /** Create a new RuleData wrapping the given payload, inheriting context. */
529
+ newRuleData(data: unknown): RuleData;
530
+ /** Input channel — receives data from upstream nodes. */
531
+ getInput(): InputChannel;
532
+ /** Output channel — sends data to downstream nodes. */
533
+ getOutput(): OutputChannel;
534
+ /** Fire a named event (e.g. 'result', 'error', 'complete'). */
535
+ fireEvent(event: string, data: RuleData): Promise<void>;
536
+ /** Report an error that occurred during execution. */
537
+ onError(error: Error, data: RuleData | null): Promise<void>;
538
+ /** Job / node configuration. */
539
+ getJob(): JobContext;
540
+ }
541
+ interface InputChannel {
542
+ /** Subscribe to incoming data. Returns an unsubscribe function. */
543
+ accept(handler: (data: RuleData) => void | Promise<void>): () => void;
544
+ }
545
+ interface OutputChannel {
546
+ /** Write data to downstream nodes. */
547
+ write(data: RuleData): Promise<void>;
548
+ }
549
+ interface JobContext {
550
+ /** The executor type identifier. */
551
+ getExecutor(): string;
552
+ /** Node-level configuration map. */
553
+ getConfiguration(): Record<string, unknown>;
554
+ /** Get a specific rule-level configuration value. */
555
+ getRuleConfiguration(key: string): unknown | undefined;
556
+ /** The node ID this job belongs to. */
557
+ getNodeId(): string;
558
+ /** The rule instance ID. */
559
+ getRuleId(): string;
560
+ }
561
+
562
+ /**
563
+ * Rule engine constants — mirrors jetlinks RuleConstants.
564
+ */
565
+ declare const RuleConstants: {
566
+ readonly Event: {
567
+ readonly result: "result";
568
+ readonly error: "error";
569
+ readonly complete: "complete";
570
+ };
571
+ };
572
+ /**
573
+ * Extended execution context for task executors — adds rule-engine specific
574
+ * methods like data creation and event firing on top of the base ExecutionContext.
575
+ *
576
+ * Mirrors the combined capabilities of jetlinks ExecutionContext + RuleDataHelper.
577
+ */
578
+ interface TaskExecutionContext {
579
+ /** The logger scoped to this execution context. */
580
+ getLogger(): Logger;
581
+ /** Node-level configuration map. */
582
+ getConfiguration(): Record<string, unknown>;
583
+ /** Create a new RuleData from an existing one with new payload data. */
584
+ newRuleDataFrom(source: RuleData, data: unknown): RuleData;
585
+ /** Fire a named event (e.g. 'result', 'error', 'complete'). */
586
+ fireEvent(event: string, data: RuleData): Promise<void>;
587
+ /** Report an error that occurred during execution. */
588
+ onError(error: Error, data: RuleData | null): Promise<void>;
589
+ }
590
+ /**
591
+ * TaskExecutor lifecycle — mirrors jetlinks AbstractTaskExecutor.
592
+ *
593
+ * Lifecycle: create -> init -> start -> (pause / reload / shutdown)
594
+ */
595
+ declare enum TaskState {
596
+ IDLE = "idle",
597
+ RUNNING = "running",
598
+ PAUSED = "paused",
599
+ SHUTDOWN = "shutdown"
600
+ }
601
+ interface TaskExecutor {
602
+ /** Human-readable name of this executor instance. */
603
+ getName(): string;
604
+ /** Current lifecycle state. */
605
+ getState(): TaskState;
606
+ /** Initialise from configuration (called once after creation). */
607
+ init(): Promise<void> | void;
608
+ /** Start (or resume) execution. */
609
+ start(): Promise<void> | void;
610
+ /** Pause execution without releasing resources. */
611
+ pause(): Promise<void> | void;
612
+ /** Reload configuration and restart. */
613
+ reload(): Promise<void> | void;
614
+ /** Permanently shut down and release all resources. */
615
+ shutdown(): Promise<void> | void;
616
+ /** Validate configuration before starting. Throws on invalid config. */
617
+ validate(): void;
618
+ }
619
+ /**
620
+ * Factory that creates TaskExecutor instances for a given executor type.
621
+ * Mirrors jetlinks TaskExecutorProvider.
622
+ */
623
+ interface TaskExecutorProvider {
624
+ /** The executor identifier (e.g. 'timer', 'delay', 'script'). */
625
+ getExecutor(): string;
626
+ /** Create a new TaskExecutor for the given execution context. */
627
+ createTask(context: ExecutionContext): Promise<TaskExecutor>;
628
+ }
629
+ /**
630
+ * Base class providing common lifecycle management for TaskExecutors.
631
+ */
632
+ declare abstract class AbstractTaskExecutor implements TaskExecutor {
633
+ protected readonly context: ExecutionContext;
634
+ protected state: TaskState;
635
+ protected disposables: Array<() => void>;
636
+ constructor(context: ExecutionContext);
637
+ abstract getName(): string;
638
+ getState(): TaskState;
639
+ init(): Promise<void>;
640
+ start(): Promise<void>;
641
+ protected abstract doStart(): Promise<(() => void) | void> | (() => void) | void;
642
+ pause(): Promise<void>;
643
+ reload(): Promise<void>;
644
+ shutdown(): Promise<void>;
645
+ validate(): void;
646
+ /** Register a cleanup function to be called on shutdown. */
647
+ protected addDisposable(fn: () => void): void;
648
+ }
649
+
650
+ /**
651
+ * 任务执行器注册表 — 对齐 jetlinks @Component 自动注册的 TaskExecutorProvider 集合
652
+ * 在 NestJS 中通过 DI 手动注册 provider
653
+ */
654
+ declare class TaskExecutorRegistry {
655
+ private readonly logger;
656
+ private readonly providers;
657
+ /**
658
+ * 注册任务执行器提供者
659
+ */
660
+ register(provider: TaskExecutorProvider): void;
661
+ /**
662
+ * 注销任务执行器提供者
663
+ */
664
+ unregister(executorType: string): void;
665
+ /**
666
+ * 根据执行器类型创建任务
667
+ */
668
+ createTask(executorType: string, context: ExecutionContext): Promise<TaskExecutor>;
669
+ /**
670
+ * 获取所有已注册的执行器类型
671
+ */
672
+ getRegisteredTypes(): string[];
673
+ /**
674
+ * 检查是否存在指定类型的执行器
675
+ */
676
+ hasProvider(executorType: string): boolean;
677
+ }
678
+
679
+ /**
680
+ * Graph-based rule model — mirrors jetlinks RuleModel / RuleNodeModel / RuleLink.
681
+ *
682
+ * A RuleModel is a directed acyclic graph (DAG) of RuleNodeModels connected
683
+ * by RuleLinks. Each node has an executor type and configuration; links
684
+ * may carry conditions that gate data flow.
685
+ */
686
+ interface ConditionSpec {
687
+ type: string;
688
+ configuration: Record<string, unknown>;
689
+ }
690
+ /**
691
+ * A directed edge between two nodes in the rule graph.
692
+ */
693
+ interface RuleLink {
694
+ /** Unique link id. */
695
+ id: string;
696
+ /** Source node id. */
697
+ source: string;
698
+ /** Target node id. */
699
+ target: string;
700
+ /** Link type (e.g. 'output', 'error'). */
701
+ type: string;
702
+ /** Optional condition that must evaluate to true for data to flow. */
703
+ condition?: ConditionSpec;
704
+ }
705
+ /**
706
+ * A single node in the rule graph.
707
+ */
708
+ interface RuleNodeModel {
709
+ /** Unique node id within the model. */
710
+ id: string;
711
+ /** Human-readable node name. */
712
+ name: string;
713
+ /** Executor type identifier (e.g. 'timer', 'delay', 'script', 'notify'). */
714
+ executor: string;
715
+ /** Executor-specific configuration. */
716
+ configuration: Record<string, unknown>;
717
+ /** Input link descriptors (populated by the engine). */
718
+ inputs?: RuleLink[];
719
+ /** Output link descriptors (populated by the engine). */
720
+ outputs?: RuleLink[];
721
+ }
722
+ type ExecutionMode = 'parallel' | 'serial';
723
+ /**
724
+ * The complete rule model — a DAG of nodes and links.
725
+ */
726
+ declare class RuleModel {
727
+ id: string;
728
+ name: string;
729
+ type: string;
730
+ /** All nodes in the graph. */
731
+ readonly nodes: RuleNodeModel[];
732
+ /** All links in the graph. */
733
+ readonly links: RuleLink[];
734
+ /** Default execution mode for action groups. */
735
+ executionMode: ExecutionMode;
736
+ constructor(id: string, name: string, type?: string);
737
+ /** Add a node to the model. */
738
+ addNode(node: RuleNodeModel): void;
739
+ /** Create a link between two nodes and add it to the model. Returns the link. */
740
+ link(source: RuleNodeModel, target: RuleNodeModel, type?: string): RuleLink;
741
+ /** Find a node by id. */
742
+ getNode(id: string): RuleNodeModel | undefined;
743
+ /** Remove a node and all its connected links — mirrors jetlinks RuleModel management. */
744
+ removeNode(nodeId: string): boolean;
745
+ /** Remove a specific link by id. */
746
+ removeLink(linkId: string): boolean;
747
+ /** Get all downstream node ids from a given node. */
748
+ getDownstream(nodeId: string): string[];
749
+ /** Get all upstream node ids from a given node. */
750
+ getUpstream(nodeId: string): string[];
751
+ /** Get topologically sorted node ids (for serial execution ordering). */
752
+ topologicalSort(): string[];
753
+ /** Validate the model (no cycles, all link targets exist). */
754
+ validate(): string[];
755
+ }
756
+
757
+ /**
758
+ * 规则版本管理。
759
+ */
760
+ interface RuleVersion {
761
+ ruleId: string;
762
+ version: number;
763
+ definition: RuleDefinition;
764
+ createdAt: number;
765
+ createdBy?: string;
766
+ changeLog?: string;
767
+ /** 是否为当前活跃版本 */
768
+ active: boolean;
769
+ }
770
+ declare class RuleVersionManager {
771
+ private readonly logger;
772
+ private readonly versions;
773
+ /** 保存规则新版本 */
774
+ saveVersion(ruleId: string, definition: RuleDefinition, options?: {
775
+ createdBy?: string;
776
+ changeLog?: string;
777
+ }): RuleVersion;
778
+ /** 获取规则的所有历史版本 */
779
+ getVersions(ruleId: string): RuleVersion[];
780
+ /** 获取规则的当前活跃版本 */
781
+ getActiveVersion(ruleId: string): RuleVersion | undefined;
782
+ /** 获取指定版本 */
783
+ getVersion(ruleId: string, version: number): RuleVersion | undefined;
784
+ /** 回滚到指定版本 */
785
+ rollback(ruleId: string, targetVersion: number): RuleVersion | undefined;
786
+ /** 比较两个版本的差异 */
787
+ diff(ruleId: string, v1: number, v2: number): {
788
+ added: string[];
789
+ removed: string[];
790
+ modified: string[];
791
+ } | undefined;
792
+ }
793
+ /**
794
+ * 规则测试框架 — 验证规则定义的正确性。
795
+ */
796
+ interface RuleTestCase {
797
+ name: string;
798
+ /** 输入数据 */
799
+ input: Record<string, unknown>;
800
+ /** 期望的输出/结果 */
801
+ expected: {
802
+ /** 期望触发的 action 名称列表 */
803
+ triggeredActions?: string[];
804
+ /** 期望的条件评估结果 */
805
+ conditionResult?: boolean;
806
+ /** 期望的输出数据 */
807
+ output?: Record<string, unknown>;
808
+ };
809
+ }
810
+ interface RuleTestResult {
811
+ testCase: string;
812
+ passed: boolean;
813
+ actual: Record<string, unknown>;
814
+ expected: Record<string, unknown>;
815
+ error?: string;
816
+ duration: number;
817
+ }
818
+ declare class RuleTestRunner {
819
+ private readonly logger;
820
+ /** 运行单个测试用例 */
821
+ runTest(definition: RuleDefinition, testCase: RuleTestCase, executor: {
822
+ execute: (input: Record<string, unknown>) => Promise<Record<string, unknown>>;
823
+ }): Promise<RuleTestResult>;
824
+ /** 运行多个测试用例 */
825
+ runTests(definition: RuleDefinition, testCases: RuleTestCase[], executor: {
826
+ execute: (input: Record<string, unknown>) => Promise<Record<string, unknown>>;
827
+ }): Promise<{
828
+ results: RuleTestResult[];
829
+ passed: number;
830
+ failed: number;
831
+ total: number;
832
+ }>;
833
+ private compareResults;
834
+ }
835
+
836
+ declare class ZuckerRuleEngineModule {
837
+ }
838
+
839
+ export { AbstractTaskExecutor, type Branch, type BranchAction, type BranchActionGroup, type BranchCondition, type BranchEvaluationResult, BranchEvaluator, type ConditionSpec, type DataMapping, DataMappingAction, type DataMappingActionConfig, DelayAction, type DelayActionConfig, type DelayPauseType, type DelayTimeUnit, EventTrigger, type EventTriggerConfig, type ExecutionContext, type ExecutionMode, type ExpressionCondition, ExpressionEvaluator, HttpAction, type HttpActionConfig, type InputChannel, type JobContext, NotifyAction, type NotifyActionConfig, type NotifyEvent, type NotifySender, type OutputChannel, type RuleAction, RuleActionType, type RuleCondition, RuleConditionType, RuleConstants, RuleData, type RuleDataHeaders, type RuleDefinition, RuleEngineService, RuleInstanceState, type RuleLink, RuleModel, type RuleNodeModel, type RuleTestCase, type RuleTestResult, RuleTestRunner, type RuleTrigger, RuleTriggerType, type RuleVersion, RuleVersionManager, ScriptAction, type ScriptActionConfig, type ShakeLimitConfig, type ShakeLimitResult, type TaskExecutionContext, type TaskExecutor, type TaskExecutorProvider, TaskExecutorRegistry, TaskState, type Term, type TermCondition, TermsEvaluator, TimerTrigger, type TimerTriggerConfig, ZuckerRuleEngineModule, createShakeLimit };