All files / builtins/subtract index.ts

96.96% Statements 32/33
50% Branches 1/2
100% Functions 10/10
96.87% Lines 31/32

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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 994x 4x             4x   4x   4x 4x   4x 2x             2x 3x         3x                 2x       3x 6x 5x     2x     2x 6x 1x       2x 5x               2x       3x   3x 3x   2x                   2x 2x   2x 3x         2x          
import {z} from 'zod';
import {ERRORS} from '@grnsft/if-core/utils';
import {
  ExecutePlugin,
  PluginParams,
  SubtractConfig,
} from '@grnsft/if-core/types';
 
import {validate} from '../../util/validations';
 
import {STRINGS} from '../../config';
 
const {InputValidationError} = ERRORS;
const {MISSING_INPUT_DATA, NOT_NUMERIC_VALUE} = STRINGS;
 
export const Subtract = (globalConfig: SubtractConfig): ExecutePlugin => {
  const metadata = {
    kind: 'execute',
  };
 
  /**
   * Checks global config value are valid.
   */
  const validateGlobalConfig = () => {
    const globalConfigSchema = z.object({
      'input-parameters': z.array(z.string()),
      'output-parameter': z.string().min(1),
    });
 
    return validate<z.infer<typeof globalConfigSchema>>(
      globalConfigSchema,
      globalConfig
    );
  };
 
  /**
   * Checks for required fields in input.
   */
  const validateSingleInput = (
    input: PluginParams,
    inputParameters: string[]
  ) => {
    inputParameters.forEach(metricToSubtract => {
      validateParamExists(input, metricToSubtract);
      validateNumericString(input[metricToSubtract]);
    });
 
    return input;
  };
 
  const validateParamExists = (input: PluginParams, param: string) => {
    if (input[param] === undefined) {
      throw new InputValidationError(MISSING_INPUT_DATA(param));
    }
  };
 
  const validateNumericString = (str: string) => {
    Iif (isNaN(+Number(str))) {
      throw new InputValidationError(NOT_NUMERIC_VALUE(str));
    }
  };
 
  /**
   * Subtract items from inputParams[1..n] from inputParams[0] and write the result in a new param outputParam.
   */
  const execute = (inputs: PluginParams[]): PluginParams[] => {
    const {
      'input-parameters': inputParameters,
      'output-parameter': outputParameter,
    } = validateGlobalConfig();
 
    return inputs.map(input => {
      validateSingleInput(input, inputParameters);
 
      return {
        ...input,
        [outputParameter]: calculateDiff(input, inputParameters),
      };
    });
  };
 
  /**
   * Calculates the diff between the 1st item in the inputs nad the rest of the items
   */
  const calculateDiff = (input: PluginParams, inputParameters: string[]) => {
    const [firstItem, ...restItems] = inputParameters;
 
    return restItems.reduce(
      (accumulator, metricToSubtract) => accumulator - input[metricToSubtract],
      input[firstItem] // Starting accumulator with the value of the first item
    );
  };
 
  return {
    metadata,
    execute,
  };
};