import { findIndex, isBoolean } from '../../utils/lang'; import { ILogger } from '../../logger/types'; import { thenable } from '../../utils/promise/thenable'; import { UNSUPPORTED_MATCHER_TYPE } from '../../utils/labels'; import { CONTROL } from '../../utils/constants'; import SplitIO from '../../../types/splitio'; import { IEvaluation, IEvaluator, ISplitEvaluator } from '../types'; import { ENGINE_COMBINER_IFELSEIF, ENGINE_COMBINER_IFELSEIF_NO_TREATMENT, ERROR_ENGINE_COMBINER_IFELSEIF } from '../../logger/constants'; export function ifElseIfCombinerContext(log: ILogger, predicates: IEvaluator[]): IEvaluator { function unexpectedInputHandler() { log.error(ERROR_ENGINE_COMBINER_IFELSEIF); return { treatment: CONTROL, label: UNSUPPORTED_MATCHER_TYPE }; } function computeEvaluation(predicateResults: Array): IEvaluation | boolean | undefined { for (let i = 0, len = predicateResults.length; i < len; i++) { const evaluation = predicateResults[i]; if (evaluation !== undefined) { if (!isBoolean(evaluation)) log.debug(ENGINE_COMBINER_IFELSEIF, [evaluation.treatment]); return evaluation; } } log.debug(ENGINE_COMBINER_IFELSEIF_NO_TREATMENT); return undefined; } function ifElseIfCombiner(key: SplitIO.SplitKeyObject, seed?: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) { // In Async environments we are going to have async predicates. There is none way to know // before hand so we need to evaluate all the predicates, verify for thenables, and finally, // define how to return the treatment (wrap result into a Promise or not). const predicateResults = predicates.map(evaluator => evaluator(key, seed, trafficAllocation, trafficAllocationSeed, attributes, splitEvaluator)); // if we find a thenable if (findIndex(predicateResults, thenable) !== -1) { return Promise.all(predicateResults).then(results => computeEvaluation(results)); } return computeEvaluation(predicateResults as IEvaluation[]); } // if there is none predicates, then there was an error in parsing phase if (!Array.isArray(predicates) || predicates.length === 0) { return unexpectedInputHandler; } else { return ifElseIfCombiner; } }