-
Couldn't load subscription status.
- Fork 505
Evaluation Interface #401
-
Thinking about a next version of this library and I think there needs to be a single type to encapsulate all the things rules and conditions can do. There are 2 potential versions of that.
Almanac on Steroids
This is an interface that encapsulates all the things we know the system can do:
interface Evaluation{ compare(operator: string, lhs: unknown, rhs: unknown): boolean; realizeCondition(condition: string): Promise<ConditionResult>; factValue(factName: string, params?: Record<string, unknown>): Promise<unknown>; getValue(value: unknown): Promise<unknown>; emitEvent(event: Event): void; }
This approach allows for fairly simple condition classes that read pretty clearly.
async evaluate(evaluation: Evaluation): Promise<ConditionResult> { const [factResult, valueResult ] = await Promsei.all([ evaluation.factValue(this.fact, this.params), evaluate.getValue(this.value) ]); const result = evaluation.compare(this.operator, factResult, valueResult); return { result, fact: this.fact, params: this.params, factResult, operation: this.operator, value: this.value, valueResult } }
Hyper Generic
If we really wanted to open up the rules engine to extension we could build it on a much more skeletal framework and allow anyone to extend it this could look something like this.
interface EvaluationTarget<TResult, TArgs extends any[]> { evaluate(evaluation: Evaluation, ...args: TArgs): TResult; } interface Evaluation { evaluate<TTarget extends EvaluationTarget<any, any[]>( target: TTarget, ...args: TTarget extends EvaluationTarget<any, infer TArgs> ? TArgs : never[] ): TTarget extends EvaluationTarget<infer TResult, any[]> ? TResult : never; }
Writing the condition would then be slightly more verbose.
// Evaluation Targets act like plugins import { factValue, getValue } from 'json-rules-engine/almanac'; import { comparison } from 'json-rules-engine/operator'; // Condition Class async evaluate(evaluation: Evaluation): Promise<ConditionResult> { const [ factResult, valueResult ] = await Promise.all([ evaluation.evaluate(factValue, this.fact, this.params), evaluation.evaluate(getValue, this.value) ]); const result = evaluation.evaluate(comparison, this.operator, factResult, valueResult); return { result, fact: this.fact, params: this.params, factResult, operation: this.operator, value: this.value, valueResult } }
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment
-
@emilefokkemanavara core idea for a totally new version
Beta Was this translation helpful? Give feedback.