all files / src/ dumper.js

93.55% Statements 58/62
81.82% Branches 18/22
100% Functions 4/4
93.55% Lines 58/62
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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141                         21×                     28×   28× 28×   28×     10× 10× 10× 10×   16×         12× 38×       38× 38× 38×   38×     12×                     54× 54×   54× 54×         16× 16× 16×       15× 15× 15×                 54×                         38× 38×   38× 38× 14×   24×     38×        
const kindOf = require('kind-of');
const {decycle} = require('cycle');
const {red, cyan, blue, black, green, magenta, bold} = require('kleur');
 
/**
 * Generate structured information about one or more objects that
 * includes each item type and value.
 *
 * @author Zeeshan Ahmad <ziishaned@gmail.com>
 */
class Dumper {
  /**
   * @param {int} indentCount Number of spaces to indent the object with
   */
  constructor(indentCount = 4) {
    this.spaces = ' '.repeat(indentCount);
  }
 
  /**
   * Iterates over each property of the provided object and make the output.
   *
   * @param {*} toDump
   * @param {string|null} indent
   * @return {string}
   */
  generateDump(toDump, indent = '') {
    let dump = '';
 
    let startWith = '';
    let endWith = '';
 
    switch (kindOf(toDump)) {
      case 'array':
        startWith = `${bold().black('array')} (size=${toDump.length}) [\n`;
        endWith = `${indent}]`;
        break;
      case 'object':
        toDump = decycle(toDump);
        startWith = `${bold().black('object')} (size=${Object.keys(toDump).length}) {\n`;
        endWith = `${indent}}`;
        break;
      default:
        return this.prepareValueDump(indent, toDump);
    }
 
    // For each key of the object, keep
    // preparing the inspection output
    for (const itemKey in toDump) {
      Iif (!Object.prototype.hasOwnProperty.call(toDump, itemKey)) {
        continue;
      }
 
      const originalValue = toDump[itemKey];
      const originalParamType = kindOf(originalValue);
      const valueDump = this.prepareValueDump(indent, originalValue);
 
      dump += this.makeArrowString(originalParamType, indent, itemKey, valueDump);
    }
 
    return startWith + dump + endWith;
  }
 
  /**
   * Prepare the dump output for the given value
   *
   * @param indent
   * @param originalValue
   * @return {*|string}
   */
  prepareValueDump(indent, originalValue) {
    let displayType = '';
    let displayValue = '';
 
    const paramType = kindOf(originalValue);
    switch (paramType) {
      case 'array':
      case 'object':
        displayType = '';
        displayValue = this.generateDump(originalValue, `${indent}${this.spaces}`);
        break;
      case 'boolean':
        displayType = 'boolean';
        displayValue = magenta(`${originalValue}`);
        break;
      case 'string':
        displayType = 'string';
        displayValue = `${red(`"${originalValue}"`)} (length=${originalValue.length})`;
        break;
      case 'null':
        displayValue = blue('null');
        break;
      case 'undefined':
        displayValue = blue('undefined');
        break;
      case 'number':
        displayType = Number.isInteger(originalValue) ? 'int' : 'float';
        displayValue = green(originalValue);
        break;
      case 'function':
        displayType = '';
        displayValue = 'function () {}';
        break;
      case 'regexp':
        displayType = '';
        displayValue = blue(originalValue);
        break;
      default:
        displayType = '';
        displayValue = originalValue;
        break;
    }
 
    return `${cyan(displayType)} ${displayValue}`;
  }
 
  /**
   * Make the arrow string.
   *
   * @param {string} paramType
   * @param {string} indent
   * @param {string|number} key
   * @param {*} valueDump
   * @return {string}
   */
  makeArrowString(paramType, indent, key, valueDump) {
    const startWith = `${indent}${this.spaces}`;
    const valuePart = `${valueDump},\n`;
 
    let keyPart;
    if (Number.isInteger(parseInt(key)) || (paramType === 'array' && typeof key !== 'string')) {
      keyPart = `[${key}]`;
    } else {
      keyPart = `'${key}'`;
    }
 
    return `${startWith + keyPart} => ${valuePart}`;
  }
}
 
module.exports = Dumper;