Files
core2026/packages/logic/src/triggers/core.ts
T

79 lines
2.3 KiB
TypeScript

export const TriggerPriority = {
Min: 0,
Begin: 10000,
Pre: 20000,
Body: 30000,
Post: 40000,
Final: 50000,
} as const;
export type TriggerPriority = (typeof TriggerPriority)[keyof typeof TriggerPriority];
export interface Trigger<TContext, TEnv = Record<string, unknown>, TArg = unknown> {
readonly priority: number;
readonly uniqueId: string;
action(context: TContext, env: TEnv, arg?: TArg): TEnv;
}
export class TriggerCaller<TContext, TEnv = Record<string, unknown>, TArg = unknown> {
private readonly triggersByPriority = new Map<number, Map<string, Trigger<TContext, TEnv, TArg>>>();
constructor(...triggers: Array<Trigger<TContext, TEnv, TArg>>) {
if (triggers.length === 0) {
return;
}
for (const trigger of triggers) {
this.append(trigger);
}
}
isEmpty(): boolean {
return this.triggersByPriority.size === 0;
}
append(trigger: Trigger<TContext, TEnv, TArg>): this {
const priority = trigger.priority;
const uniqueId = trigger.uniqueId;
const bucket = this.triggersByPriority.get(priority) ?? new Map();
bucket.set(uniqueId, trigger);
this.triggersByPriority.set(priority, bucket);
return this;
}
merge(other: TriggerCaller<TContext, TEnv, TArg> | null | undefined): this {
if (!other) {
return this;
}
for (const [priority, otherBucket] of other.triggersByPriority.entries()) {
const bucket = this.triggersByPriority.get(priority) ?? new Map();
for (const [uniqueId, trigger] of otherBucket.entries()) {
bucket.set(uniqueId, trigger);
}
this.triggersByPriority.set(priority, bucket);
}
return this;
}
fire(context: TContext, env: TEnv, arg?: TArg): TEnv {
let currentEnv = env;
const priorities = Array.from(this.triggersByPriority.keys()).sort((a, b) => a - b);
for (const priority of priorities) {
const bucket = this.triggersByPriority.get(priority);
if (!bucket) {
continue;
}
for (const trigger of bucket.values()) {
currentEnv = trigger.action(context, currentEnv, arg);
}
}
return currentEnv;
}
}