All files / if-run/builtins/divide index.ts

100% Statements 30/30
100% Branches 15/15
100% Functions 6/6
100% Lines 30/30

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 884x     4x 4x   4x   4x   4x 4x   4x   10x 1x     9x           9x     9x   9x           8x 1x     7x     9x     7x   7x 7x         7x                       4x               7x   7x   7x   7x 1x 1x     6x    
import {z} from 'zod';
 
import {ConfigParams, PluginParams} from '@grnsft/if-core/types';
import {PluginFactory} from '@grnsft/if-core/interfaces';
import {ERRORS} from '@grnsft/if-core/utils';
 
import {validate} from '../../../common/util/validations';
 
import {STRINGS} from '../../config';
 
const {MissingInputDataError, ConfigError} = ERRORS;
const {MISSING_INPUT_DATA, ZERO_DIVISION, MISSING_CONFIG} = STRINGS;
 
export const Divide = PluginFactory({
  configValidation: (config: ConfigParams) => {
    if (!config || !Object.keys(config)?.length) {
      throw new ConfigError(MISSING_CONFIG);
    }
 
    const schema = z.object({
      numerator: z.string().min(1),
      denominator: z.string().or(z.number()),
      output: z.string(),
    });
 
    return validate<z.infer<typeof schema>>(schema, config);
  },
  inputValidation: (input: PluginParams, config: ConfigParams) => {
    const {numerator, denominator} = config;
 
    const schema = z
      .object({
        [numerator]: z.number(),
        [denominator]: z.number().optional(),
      })
      .refine(() => {
        if (typeof denominator === 'string' && !input[denominator]) {
          throw new MissingInputDataError(MISSING_INPUT_DATA(denominator));
        }
 
        return true;
      });
 
    return validate<z.infer<typeof schema>>(schema, input);
  },
  implementation: async (inputs: PluginParams[], config: ConfigParams) => {
    const {numerator, denominator, output} = config;
 
    return inputs.map((input, index) => {
      const calculatedResult = calculateDivide(input, index, {
        numerator: input.numerator || numerator,
        denominator: input.denominator || denominator,
      });
 
      return {
        ...input,
        [output]: calculatedResult,
      };
    });
  },
  allowArithmeticExpressions: ['numerator', 'denominator'],
});
 
/**
 * Calculates the division of the given parameter.
 */
const calculateDivide = (
  input: PluginParams,
  index: number,
  params: {
    numerator: number | string;
    denominator: number | string;
  }
) => {
  const {denominator, numerator} = params;
  const finalDenominator =
    typeof denominator === 'number' ? denominator : input[denominator];
  const finalNumerator =
    typeof numerator === 'number' ? numerator : input[numerator];
 
  if (finalDenominator === 0) {
    console.warn(ZERO_DIVISION(Divide.name, index));
    return finalNumerator;
  }
 
  return finalNumerator / finalDenominator;
};