All files / util aggregation-helper.ts

100% Statements 28/28
100% Branches 9/9
100% Functions 4/4
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 692x     2x   2x       2x 2x 2x           2x 14x 14x   14x 1x                     2x         14x 13x   13x 25x 73x 1x       72x 48x 20x     24x 24x     24x 12x 1x           24x      
import {ERRORS} from '@grnsft/if-core/utils';
import {PluginParams} from '@grnsft/if-core/types';
 
import {parameterize} from '../lib/parameterize';
 
import {CONFIG, STRINGS} from '../config';
 
import {AggregationResult} from '../types/aggregation';
 
const {InvalidAggregationMethodError, MissingAggregationParamError} = ERRORS;
const {INVALID_AGGREGATION_METHOD, METRIC_MISSING} = STRINGS;
const {AGGREGATION_ADDITIONAL_PARAMS} = CONFIG;
 
/**
 * Validates metrics array before applying aggregator.
 * If aggregation method is `none`, then throws error.
 */
const checkIfMetricsAreValid = (metrics: string[]) => {
  metrics.forEach(metric => {
    const method = parameterize.getAggregationMethod(metric);
 
    if (method === 'none') {
      throw new InvalidAggregationMethodError(
        INVALID_AGGREGATION_METHOD(metric)
      );
    }
  });
};
 
/**
 * Aggregates child node level metrics. Validates if metric aggregation type is `none`, then rejects with error.
 * Appends aggregation additional params to metrics. Otherwise iterates over inputs by aggregating per given `metrics`.
 */
export const aggregateInputsIntoOne = (
  inputs: PluginParams[],
  metrics: string[],
  isTemporal?: boolean
) => {
  checkIfMetricsAreValid(metrics);
  const extendedMetrics = [...metrics, ...AGGREGATION_ADDITIONAL_PARAMS];
 
  return inputs.reduce((acc, input, index) => {
    for (const metric of extendedMetrics) {
      if (!(metric in input)) {
        throw new MissingAggregationParamError(METRIC_MISSING(metric, index));
      }
 
      /** Checks if metric is timestamp or duration, then adds to aggregated value. */
      if (AGGREGATION_ADDITIONAL_PARAMS.includes(metric)) {
        if (isTemporal) {
          acc[metric] = input[metric];
        }
      } else {
        acc[metric] = acc[metric] ?? 0;
        acc[metric] += parseFloat(input[metric]);
 
        /** Checks for the last iteration. */
        if (index === inputs.length - 1) {
          if (parameterize.getAggregationMethod(metric) === 'avg') {
            acc[metric] /= inputs.length;
          }
        }
      }
    }
 
    return acc;
  }, {} as AggregationResult);
};