All files / src/chain chainMethod.js

100% Statements 35/35
100% Branches 24/24
100% Functions 10/10
100% Lines 35/35

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                              506x 506x 506x 506x 506x 506x 506x 506x       47x 38x     9x 16x 16x         498x       65x           46x 1x   45x             45x 66x   25x   5x 5x   25x 20x       41x     45x       42x 42x 19x   23x     22x 22x     1x 1x        
/**
 * @file method on chain
 * @author atom-yang
 */
import { isFunction, noop, isBoolean } from '../util/utils';
 
export default class ChainMethod {
  constructor({
    name,
    call,
    method = 'GET',
    params = [],
    inputFormatter = [],
    outputFormatter = null,
  }) {
    this.name = name;
    this.call = call;
    this.requestMethod = method;
    this.params = params;
    this.inputFormatter = inputFormatter;
    this.outputFormatter = outputFormatter;
    this.requestManager = null;
    this.run = this.run.bind(this);
  }
 
  formatInput(args) {
    if (!this.inputFormatter || this.inputFormatter.length === 0) {
      return args;
    }
 
    return args.map((arg, index) => {
      const formatter = this.inputFormatter[index];
      return formatter ? formatter(arg) : arg;
    });
  }
 
  setRequestManager(manager) {
    this.requestManager = manager;
  }
 
  formatOutput(result) {
    return this.outputFormatter && result
      ? this.outputFormatter(result)
      : result;
  }
 
  extractArgumentsIntoObject(args) {
    if (args.length < this.params.length) {
      throw new Error(`should supply enough parameters for ${this.call}`);
    }
    const result = {
      method: this.call,
      requestMethod: this.requestMethod,
      isSync: false,
      callback: noop,
      params: {},
    };
    this.formatInput(args).forEach((arg, index) => {
      if (index > this.params.length - 1) {
        // if index is greater than params.length, that means arg is an extra argument
        if (isFunction(arg)) {
          // if there is a callback, user want to be in async mode, set isSync to false
          result.callback = arg;
          result.isSync = false;
        }
        if (isBoolean(arg?.sync)) {
          result.isSync = arg.sync;
        }
      } else {
        // if index is less than or equal to params.length, that means arg is one of the params
        result.params[this.params[index]] = arg;
      }
    });
    return result;
  }
 
  run(...args) {
    const argsObj = this.extractArgumentsIntoObject(args);
    if (argsObj.isSync) {
      return this.formatOutput(this.requestManager.send(argsObj));
    }
    return this.requestManager
      .sendAsync(argsObj)
      .then(result => {
        argsObj.callback(null, this.formatOutput(result));
        return this.formatOutput(result);
      })
      .catch(err => {
        argsObj.callback(err);
        throw err;
      });
  }
}