import * as plugins from './smartrule.plugins'; import { Rule, TCheckFunc, TActionFunc, TTreeActionResult } from './smartrule.classes.rule'; export class SmartRule { public rules: Array> = []; /** * makes a decision based on the given obect and the given rules * @param objectArg */ public async makeDecision(objectArg: T) { // lets sort the rules this.rules = this.rules.sort((a,b) => { if (a.priority > b.priority) { return 1; } else { return 0; } }); // gets the next batch with the same priority const getNextParallelBatch = (priorityStart: number) => { return this.rules.filter(rule => { return rule.priority === priorityStart; }); }; // lets run the checks const runNextBatch = async (startPriority: number, runRulesAmount: number): Promise => { const nextBatch = getNextParallelBatch(startPriority); runRulesAmount = runRulesAmount + nextBatch.length; const outcomes: TTreeActionResult[] = []; for (const rule of nextBatch) { const checkResult = await rule.checkFunction(objectArg); if (checkResult.startsWith("apply")) { await rule.actionFunction(objectArg); // here the action function is run } outcomes.push(checkResult); } if (outcomes.length > 0) { const finalOutcomeOfBatch: TTreeActionResult = outcomes.reduce((previous, current, index, array) => { if (current.includes('continue') || previous.includes('continue')) { return 'continue'; } else { return 'stop'; } }); if (finalOutcomeOfBatch === 'stop') { return; } } if (runRulesAmount < this.rules.length) { await runNextBatch((startPriority + 1), runRulesAmount); } else { return; } }; await runNextBatch(0,0); } public createRule(priorityArg: number, checkFunctionArg: TCheckFunc, actionFunctionArg: TActionFunc) { const rule = new Rule(this, priorityArg, checkFunctionArg, actionFunctionArg); this.rules.push(rule); } }