]> git.r.bdr.sh - rbdr/cologne/commitdiff
Update the code.
authorRuben Beltran del Rio <redacted>
Sun, 20 Sep 2020 23:00:19 +0000 (01:00 +0200)
committerRuben Beltran del Rio <redacted>
Sun, 20 Sep 2020 23:00:19 +0000 (01:00 +0200)
19 files changed:
lib/cologne.js
lib/formatters/simple.js [moved from lib/cologne/formatter/simple.js with 51% similarity]
lib/formatters/token.js [moved from lib/cologne/formatter/token.js with 59% similarity]
lib/loggers/console.js [moved from lib/cologne/logger/console.js with 52% similarity]
lib/loggers/file.js [moved from lib/cologne/logger/file.js with 53% similarity]
lib/utilities.js [moved from lib/cologne/log_utilities.js with 67% similarity]
package-lock.json [new file with mode: 0644]
package.json
test/cologne.js
test/cologne/formatter/simple.js [deleted file]
test/cologne/formatter/token.js [deleted file]
test/cologne/log_utilities.js [deleted file]
test/cologne/logger/console.js [deleted file]
test/cologne/logger/file.js [deleted file]
test/formatters/simple.js [new file with mode: 0644]
test/formatters/token.js [new file with mode: 0644]
test/loggers/console.js [new file with mode: 0644]
test/loggers/file.js [new file with mode: 0644]
test/utilities.js [new file with mode: 0644]

index 646fe79fc368f1515ee1a05256ad9246b5730dfb..392b452210ccd3fc07fdb732e9eac21e9d9591ba 100644 (file)
@@ -1,49 +1,64 @@
 'use strict';
 
-let LogUtilities = require('./cologne/log_utilities');
+const Utilities = require('./utilities');
+
+const internals = {
+
+  // Maps log levels to their syslog labels
+
+  kLevelStrings: [
+    'emerg',
+    'alert',
+    'crit',
+    'error',
+    'warning',
+    'notice',
+    'info',
+    'debug'
+  ],
+
+  // Version of the Cologne Log Format used
+
+  kLogVersion: '2.0.0'
+};
 
 /** TYPE DEFINITIONS **/
 
 /**
  * Main interface for Cologne Loggers
  *
- * @memberof Cologne
  * @interface ILogger
  */
 
 /**
  * Receives any number of cologne log objects and logs them.
  *
- * @memberof Cologne.ILogger
+ * @memberof ILogger
  * @function
  * @name log
- * @returns {undefined}
  */
 
 /**
  * Main interface for Cologne Formatters
  *
- * @memberof Cologne
  * @interface IFormatter
  */
 
 /**
  * Receives a cologne log object and returns a formatted string.
  *
- * @memberof Cologne.IFormatter
+ * @memberof IFormatter
  * @function
  * @name format
- * @param {Cologne.tCologneLog} logObject the log to be formatted
+ * @param {tCologneLog} logObject the log to be formatted
  * @returns {string} the formatted log
  */
 
 /**
  * The main cologne log format.
  *
- * @memberof Cologne
  * @typedef {object} tCologneLog
- * @property {Number} _timestamp the timestamp in miliseconds with decimal
- * numbers representing fractions of miliseconds
+ * @property {Bigint} _timestamp the timestamp in nanoseconds
  * @property {String} _cologneLog main identifier, encodes the version of the
  * cologne log format being used.
  * @property {String} _from the origin of the log message.
@@ -54,32 +69,14 @@ let LogUtilities = require('./cologne/log_utilities');
  */
 
 /**
- * Cologne is a logger multiplexer that works mainly with a JSON format. It
- * can be instantiated with several loggers, or they can be changed after
- * the fact.
- *
- * ## Usage
- *
- * ```
- * require('cologne');
- *
- * let co = new Cologne({
- *   from: "Special Worker Logger",
- *   loggers: [
- *     new Cologne.Logger.Console({
- *       formatter: new Cologne.Formatter.Token({
- *         formatString: '[{{_timestamp}}]{{_from}}: {{message}}'
- *       })
- *     })
- *   ]
- * });
- * ```
+ * The main logger class. It can be instantiated with loggers in order to
+ * send messages to different destinations.
  *
  * @class Cologne
  */
-let Cologne = class Cologne {
+const Cologne = class Cologne {
 
-  constructor (config) {
+  constructor(config) {
 
     /**
      * The name of this logger, useful to distinguish between different
@@ -99,12 +96,12 @@ let Cologne = class Cologne {
      * @name loggers
      * @instance
      * @memberof Cologne
-     * @type Cologne.ILogger[]
+     * @type ILogger[]
      * @default []
      */
     this.loggers = [];
 
-    Object.assign(this, config || {});
+    Object.assign(this, config);
   }
 
   /**
@@ -113,10 +110,10 @@ let Cologne = class Cologne {
    * @function addLogger
    * @instance
    * @memberof Cologne
-   * @param {Cologne.ILogger} logger the logger to add
-   * @return {undefined}
+   * @param {ILogger} logger the logger to add
    */
-  addLogger (logger) {
+  addLogger(logger) {
+
     this.loggers.push(logger);
   }
 
@@ -126,55 +123,58 @@ let Cologne = class Cologne {
    * @function removeLogger
    * @instance
    * @memberof Cologne
-   * @param {Cologne.ILogger} logger the logger to remove
-   * @return {Cologne.ILogger[]} the removed log, inside an array.
+   * @param {ILogger} logger the logger to remove
+   * @return {ILogger[]} the removed log, inside an array.
    */
-  removeLogger (logger) {
-    let index;
+  removeLogger(logger) {
 
-    index = this.loggers.indexOf(logger);
+    const index = this.loggers.indexOf(logger);
     if (index >= 0) {
       this.loggers.splice(index, 1);
     }
   }
 
   /**
-   * Given an item, it builds a cologne log object. this is done
-   * automatically by the logger, though this is useful if you need
-   * to attach metadata before logging.
+   * Given a message, it builds a cologne log object without logging it.
+   * If you send a cologne log object, it will only update the level.
+   *
+   * If the message is an object, the log object will be extended with
+   * its properties.
    *
    * @function buildLog
    * @instance
    * @memberof Cologne
-   * @param {*} item The item to log
-   * @return {Cologne.tCologneLog} a cologne log object
+   * @param {*} message The message to log
+   * @param {number} [level=6] The level of the message to log
+   * @return {tCologneLog} a cologne log object
    */
-  buildLog (item, level, meta) {
-    let logObject;
+  buildLog(rawMessage, level) {
+
+    if (typeof rawMessage === 'undefined' || rawMessage === null || !rawMessage._cologneLog) {
 
-    logObject = {};
+      const message = typeof rawMessage === 'object' ? Utilities.stringify(rawMessage) : rawMessage;
 
-    if (typeof item === 'undefined' || item === null || !item._cologneLog) {
-      logObject.message = item;
-      logObject._cologneLog = this.constructor._version;
-      logObject._from = this.from;
-      logObject._level = level || 6;
-      logObject._levelString = this._levelString(logObject._level);
-      logObject._timestamp = LogUtilities.now();
+      const logObject = {
+        message: String(message),
+        _cologneLog: internals.kLogVersion,
+        _from: this.from,
+        _level: level || 6,
+        _timestamp: Utilities.now()
+      };
 
-      if (meta && typeof meta === 'object') {
-        Object.assign(logObject, meta);
+      logObject._levelString = internals.kLevelStrings[logObject._level];
+
+      if (typeof rawMessage === 'object') {
+        Object.assign(logObject, rawMessage);
       }
 
       return logObject;
     }
 
-    if (item._cologneLog) {
-      item._level = level || item._level || 6;
-      item._levelString = this._levelString(item._level);
-    }
+    rawMessage._level = level || rawMessage._level;
+    rawMessage._levelString = internals.kLevelStrings[rawMessage._level];
 
-    return item;
+    return rawMessage;
   }
 
   /**
@@ -184,10 +184,10 @@ let Cologne = class Cologne {
    * @function log
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  log () {
-    this._log.apply(this, [null].concat(Array.prototype.slice.call(arguments)));
+  log(...logs) {
+
+    this._log(null, ...logs);
   }
 
   /**
@@ -196,10 +196,10 @@ let Cologne = class Cologne {
    * @function debug
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  debug () {
-    this._log.apply(this, [7].concat(Array.prototype.slice.call(arguments)));
+  debug(...logs) {
+
+    this._log(7, ...logs);
   }
 
   /**
@@ -208,10 +208,10 @@ let Cologne = class Cologne {
    * @function info
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  info () {
-    this._log.apply(this, [6].concat(Array.prototype.slice.call(arguments)));
+  info(...logs) {
+
+    this._log(6, ...logs);
   }
 
   /**
@@ -220,10 +220,10 @@ let Cologne = class Cologne {
    * @function notice
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  notice () {
-    this._log.apply(this, [5].concat(Array.prototype.slice.call(arguments)));
+  notice(...logs) {
+
+    this._log(5, ...logs);
   }
 
   /**
@@ -232,10 +232,10 @@ let Cologne = class Cologne {
    * @function warn
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  warn () {
-    this._log.apply(this, [4].concat(Array.prototype.slice.call(arguments)));
+  warn(...logs) {
+
+    this._log(4, ...logs);
   }
 
   /**
@@ -244,85 +244,45 @@ let Cologne = class Cologne {
    * @function error
    * @instance
    * @memberof Cologne
-   * @return {undefined}
    */
-  error () {
-    this._log.apply(this, [3].concat(Array.prototype.slice.call(arguments)));
+  error(...logs) {
+
+    this._log(3, ...logs);
   }
 
   // Private method that builds all the logs and sends them to the loggers.
-  _log (severity) {
-    let remainingArguments, logObjectArray, log, logger;
-
-    remainingArguments = Array.prototype.slice.call(arguments, 1);
-    logObjectArray = [];
-
-    for (log of remainingArguments) {
-      if (typeof log === 'undefined') {
-        logObjectArray.push(this.buildLog('undefined', severity));
-        continue;
-      }
-
-      if (log === null) {
-        logObjectArray.push(this.buildLog('null', severity));
-        continue;
-      }
 
-      logObjectArray.push(this.buildLog(log, severity));
-    }
+  _log(level, ...logs) {
 
-    for (logger of this.loggers) {
-      logger.log.apply(logger, logObjectArray);
-    }
-  }
+    const structuredLogs = logs.map((log) => this.buildLog(log, level));
 
-  // Private utility method that will return the string for any given
-  // numerical severity level
-  _levelString (level) {
-    switch(level) {
-    case 0:
-      return 'emerg';
-    case 1:
-      return 'alert';
-    case 2:
-      return 'crit';
-    case 3:
-      return 'error';
-    case 4:
-      return 'warning';
-    case 5:
-      return 'notice';
-    case 6:
-      return 'info';
-    case 7:
-      return 'debug';
+    for (const logger of this.loggers) {
+      logger.log(...structuredLogs);
     }
   }
 };
 
-// Version of the Cologne Log Format used.
-Cologne._version = '1.0.0';
-
 /**
  * Namespace that includes the built-in formatters.
  *
- * @namespace Formatter
- * @memberof Cologne
+ * @namespace Formatters
  */
-Cologne.Formatter = {};
-Cologne.Formatter.Simple = require('./cologne/formatter/simple');
-Cologne.Formatter.Token = require('./cologne/formatter/token');
+const Formatters = {};
+Formatters.Simple = require('./formatters/simple');
+Formatters.Token = require('./formatters/token');
 
 /**
  * Namespace that includes the built-in loggers.
  *
- * @namespace Logger
- * @memberof Cologne
+ * @namespace Loggers
  */
-Cologne.Logger = {};
-Cologne.Logger.Console = require('./cologne/logger/console');
-Cologne.Logger.File = require('./cologne/logger/file');
-
-Cologne.LogUtilities = require('./cologne/log_utilities');
-
-module.exports = Cologne;
+const Loggers = {};
+Loggers.Console = require('./loggers/console');
+Loggers.File = require('./loggers/file');
+
+module.exports = {
+  Cologne,
+  Formatters,
+  Loggers,
+  Utilities
+};
similarity index 51%
rename from lib/cologne/formatter/simple.js
rename to lib/formatters/simple.js
index 48821fc597e1f1b12bc86c6f39e800dfd5ff327b..bfaa76c7dd068d9a28783e82917e473281e01dc6 100644 (file)
@@ -1,18 +1,18 @@
 'use strict';
 
-let LogUtilities = require('../log_utilities');
+const Utilities = require('../utilities');
 
 /**
  * Simple formatter. Outputs a predefined format:
  * `[{{_timestamp}}][{{_levelString}}] {{_from}}: {{message}}`;
  *
- * @memberof Cologne.Formatter
- * @implements Cologne.IFormatter
+ * @memberof Formatters
+ * @implements IFormatter
  * @class Simple
  */
-let SimpleFormatter = class SimpleFormatter {
+module.exports = class SimpleFormatter {
 
-  constructor (config) {
+  constructor(config) {
 
     /**
      * Flag that tells us whether or not to use ANSI color. Defaults to
@@ -20,7 +20,7 @@ let SimpleFormatter = class SimpleFormatter {
      *
      * @name colorize
      * @instance
-     * @memberof Cologne.Formatter.Simple
+     * @memberof Formatters.Simple
      * @type Boolean
      * @default false
      */
@@ -35,33 +35,28 @@ let SimpleFormatter = class SimpleFormatter {
    *
    * @function format
    * @instance
-   * @memberof Cologne.Formatter.Simple
-   * @param {Cologne.tCologneLog} logObjet the log to format
+   * @memberof Formatters.Simple
+   * @param {tCologneLog} logObjet the log to format
    * @return {String} the formatted object
    */
-  format (logObject) {
-    let date, levelString;
+  format(logObject) {
 
-    date = new Date(logObject._timestamp);
-    date = date.toISOString();
-    levelString = this._colorize(logObject._levelString, logObject._level);
+    const date = (new Date(Number(logObject._timestamp) / 1000000)).toISOString();
+    const levelString = this._colorize(logObject._levelString, logObject._level);
 
     return `[${date}][${levelString}] ${logObject._from}: ${logObject.message}`;
   }
 
-  _colorize (levelString, level) {
-    let escapeCode, color, reset;
+  _colorize(levelString, level) {
 
     if (!this.colorize) {
       return levelString;
     }
 
-    escapeCode = String.fromCharCode(27);
-    color = escapeCode + LogUtilities.getAnsiCode(LogUtilities.getLevelAnsi(level));
-    reset = escapeCode + LogUtilities.getAnsiCode('reset');
+    const escapeCode = String.fromCharCode(27);
+    const color = escapeCode + Utilities.getAnsiCode(Utilities.getLevelAnsi(level));
+    const reset = escapeCode + Utilities.getAnsiCode('reset');
 
     return color + levelString + reset;
   }
 };
-
-module.exports = SimpleFormatter;
similarity index 59%
rename from lib/cologne/formatter/token.js
rename to lib/formatters/token.js
index bb905ca260ed853fef0f521c6450c357e51303fa..2ec3a17af60f75a2c35fba944d1b709a415cb5d6 100644 (file)
@@ -1,17 +1,17 @@
 'use strict';
 
-let LogUtilities = require('../log_utilities');
+const Utilities = require('../utilities');
 
 /**
  * Token formatter. Given a format string it will attempt to output
  * a message.
  *
- * @memberof Cologne.Formatter
- * @implements Cologne.IFormatter
+ * @memberof Formatters
+ * @implements IFormatter
  * @class Token
  */
-let TokenFormatter = class TokenFormatter {
-  constructor (config) {
+module.exports = class TokenFormatter {
+  constructor(config) {
 
     /**
      * The string to use as a template string. By default, any property
@@ -21,7 +21,7 @@ let TokenFormatter = class TokenFormatter {
      *
      * @name formatString
      * @instance
-     * @memberof Cologne.Formatter.Token
+     * @memberof Formatters.Token
      * @type String
      * @default '{{message}}'
      */
@@ -32,7 +32,7 @@ let TokenFormatter = class TokenFormatter {
      *
      * @name replaceRule
      * @instance
-     * @memberof Cologne.Formatter.Token
+     * @memberof Formatters.Token
      * @type RegExp
      * @default /{{(.*)}}/g
      */
@@ -44,7 +44,7 @@ let TokenFormatter = class TokenFormatter {
      *
      * @name isoDate
      * @instance
-     * @memberof Cologne.Formatter.Token
+     * @memberof Formatters.Token
      * @type Boolean
      * @default true
      */
@@ -62,43 +62,32 @@ let TokenFormatter = class TokenFormatter {
    *
    * @function format
    * @instance
-   * @memberof Cologne.Formatter.Token
-   * @param {Cologne.tCologneLog} logObjet the log to format
+   * @memberof Formatters.Token
+   * @param {tCologneLog} log the log to format
    * @return {String} the formatted object
    */
-  format (logObject) {
-    let resultString, escapeCode;
+  format(log) {
 
-    escapeCode = String.fromCharCode(27);
-
-    resultString = this.formatString.replace(this.replaceRule, function (match, token) {
-      let date, ansiType;
+    const escapeCode = String.fromCharCode(27);
+    return this.formatString.replace(this.replaceRule, (match, token) => {
 
       if (token === '_timestamp' && this.isoDate) {
-        date = new Date(logObject._timestamp);
+        const date = new Date(Number(log._timestamp) / 1000000);
         return date.toISOString();
       }
 
       if (token.match(this._ansiRe)) {
-        ansiType = token.split(':')[1];
+        const ansiType = token.split(':')[1];
 
         // Smartish coloring
         if (ansiType === '_level') {
-          return escapeCode + LogUtilities.getAnsiCode(LogUtilities.getLevelAnsi(logObject._level));
+          return escapeCode + Utilities.getAnsiCode(Utilities.getLevelAnsi(log._level));
         }
 
-        return escapeCode + LogUtilities.getAnsiCode(ansiType);
-      }
-
-      if (!logObject.hasOwnProperty(token)) {
-        return match;
+        return escapeCode + Utilities.getAnsiCode(ansiType);
       }
 
-      return logObject[token];
-    }.bind(this));
-
-    return resultString;
+      return log[token] || match;
+    });
   }
 };
-
-module.exports = TokenFormatter;
similarity index 52%
rename from lib/cologne/logger/console.js
rename to lib/loggers/console.js
index 3a73e420b569690224ec75a2cdb0ea96b504ac05..116b04be195342823d745f7039d472f997244adb 100644 (file)
@@ -1,16 +1,15 @@
 'use strict';
 
-let LogUtilities = require('../log_utilities');
+const Utilities = require('../utilities');
 
 /**
  * Logger for the javascript console.
  *
- * @memberof Cologne.Logger
- * @implements Cologne.ILogger
+ * @implements ILogger
  * @class Console
  */
-let ConsoleLogger = class ConsoleLogger {
-  constructor (config) {
+module.exports = class ConsoleLogger {
+  constructor(config) {
 
     /**
      * The console it will write to, can be any object that looks
@@ -18,7 +17,7 @@ let ConsoleLogger = class ConsoleLogger {
      *
      * @name console
      * @instance
-     * @memberof Cologne.Logger.Console
+     * @memberof Loggers.Console
      * @type Object
      * @default global.console
      */
@@ -30,13 +29,13 @@ let ConsoleLogger = class ConsoleLogger {
      *
      * @name formatter
      * @instance
-     * @memberof Cologne.Logger.Console
-     * @type Cologne.IFormatter
+     * @memberof Loggers.Console
+     * @type IFormatter
      * @default null
      */
     this.formatter = null;
 
-    Object.assign(this, config || {});
+    Object.assign(this, config);
   }
 
 
@@ -46,50 +45,50 @@ let ConsoleLogger = class ConsoleLogger {
    *
    * @function log
    * @instance
-   * @memberof Cologne.Logger.Console
+   * @memberof Loggers.Console
    * @return {undefined}
    */
-  log () {
-    let logObject, messages, severity;
+  log(...logs) {
 
-    messages = [];
+    const formattedLogs = logs.map((log) => ({ log: this._format(log), level: log._level }));
 
-    for (logObject of arguments) {
-      messages.push(this._format(logObject));
-
-      if (!severity) {
-        severity = logObject._level;
-      }
+    for (const { log, level } of formattedLogs) {
+      this._log(log, level );
     }
 
-    switch(severity) {
+  }
+
+  // Routes an individual log to the appropriatet console
+
+  _log(log, level) {
+
+    switch (level) {
     case 0:
     case 1:
     case 2:
     case 3:
-      this.console.error.apply(this.console, messages);
+      this.console.error(log);
       break;
     case 4:
-      this.console.warn.apply(this.console, messages);
+      this.console.warn(log);
       break;
     case 5:
     case 6:
-      this.console.info.apply(this.console, messages);
+      this.console.info(log);
       break;
     case 7:
     default:
-      this.console.log.apply(this.console, messages);
+      this.console.log(log);
       break;
     }
   }
 
-  _format (logObject) {
+  _format(logObject) {
+
     if (this.formatter) {
       return this.formatter.format(logObject);
     }
 
-    return LogUtilities.stringify(logObject);
+    return Utilities.stringify(logObject);
   }
 };
-
-module.exports = ConsoleLogger;
similarity index 53%
rename from lib/cologne/logger/file.js
rename to lib/loggers/file.js
index e9a56e72071d1fdd658738a68d9809f51bf1a741..50a251e1c58ab7a500b322c1aa76de91c990e324 100644 (file)
@@ -1,25 +1,24 @@
 'use strict';
 
-let fs = require('fs');
-
-let LogUtilities = require('../log_utilities');
+const Fs = require('fs');
+const Utilities = require('../utilities');
 
 /**
  * Logger for files.
  *
- * @memberof Cologne.Logger
- * @implements Cologne.ILogger
+ * @memberof Loggers
+ * @implements ILogger
  * @class File
  */
-let FileLogger = class FileLogger {
-  constructor (config) {
+module.exports = class FileLogger {
+  constructor(config) {
 
     /**
      * Path to the file it will write to, must be readable.
      *
      * @name file
      * @instance
-     * @memberof Cologne.Logger.File
+     * @memberof Loggers.File
      * @type string
      * @default null
      */
@@ -31,15 +30,15 @@ let FileLogger = class FileLogger {
      *
      * @name formatter
      * @instance
-     * @memberof Cologne.Logger.File
-     * @type Cologne.IFormatter
+     * @memberof Loggers.File
+     * @type IFormatter
      * @default null
      */
     this.formatter = null;
 
-    Object.assign(this, config || {});
+    Object.assign(this, config);
 
-    this._stream = fs.createWriteStream(this.file, {flags: 'a'});
+    this._stream = Fs.createWriteStream(this.file, { flags: 'a' });
   }
 
   /**
@@ -48,24 +47,22 @@ let FileLogger = class FileLogger {
    *
    * @function log
    * @instance
-   * @memberof Cologne.Logger.File
+   * @memberof Loggers.File
    * @return {undefined}
    */
-  log () {
-    let logObject;
+  log(...logs) {
 
-    for (logObject of arguments) {
-      this._stream.write(this.format(logObject) + '\n');
+    for (const log of logs) {
+      this._stream.write(this._format(log) + '\n');
     }
   }
 
-  format (logObject) {
+  _format(logObject) {
+
     if (this.formatter) {
       return this.formatter.format(logObject);
     }
 
-    return LogUtilities.stringify(logObject);
+    return Utilities.stringify(logObject);
   }
 };
-
-module.exports = FileLogger;
similarity index 67%
rename from lib/cologne/log_utilities.js
rename to lib/utilities.js
index fc15a8aec0ef0eeb77348810e5687824f6f6dacd..1c930afd54301887cd17192a2434ef90506589f4 100644 (file)
@@ -1,63 +1,81 @@
 'use strict';
 
-let microtime = require('microtime');
+const internals = {
+  kCircularString: '[Circular]',
+
+  // Get High Res time depending on platform. Currently only supporting node.
+
+  getHighResTime() {
+
+    return process.hrtime.bigint();
+  }
+};
+
+// Initialise relative time.
+
+internals.initialTimestamp = BigInt(Date.now()) * 1000000n;
+internals.initialHighResTime = internals.getHighResTime();
 
 /**
  * Container object for utilities used by loggers.
  *
- * @memberof Cologne
- * @class LogUtilities
+ * @class Utilities
  */
-let LogUtilities = {
+module.exports = {
 
   /**
-   * Returns the current timestamp in miliseconds as a floating point that
-   * includes fractions (ie. microseconds)
+   * Returns the current timestamp in nanoseconds as a bigint.
    *
    * @function now
-   * @memberof Cologne.LogUtilities
-   * @return {Number} current time in miliseconds, including fractions.
+   * @memberof Utilities
+   * @return {bigint} current time in nanoseconds, including fractions.
    */
-  now: function now() {
-    return microtime.nowDouble() * 1000;
+  now() {
+
+    return internals.initialTimestamp + internals.getHighResTime() - internals.initialHighResTime;
   },
 
   /**
    * Stringifies objects, avoiding circular references.
    *
    * @function stringify
-   * @memberof Cologne.LogUtilities
+   * @memberof Utilities
    * @param {Object} object the object to stringify
    * @return {String} the stringified object
    */
-  stringify: function stringify(object) {
-    let cache;
+  stringify(object) {
 
-    cache = [];
+    const cache = new Set();
+
+    return JSON.stringify(object, (key, value) => {
+
+      if (typeof value === 'bigint') {
+        return String(value) + 'n';
+      }
 
-    return JSON.stringify(object, function (key, value) {
       if (typeof value === 'object' && value !== null) {
-        if (cache.indexOf(value) !== -1) {
-          return this._circularString;
+        if (cache.has(value)) {
+          return internals.kCircularString;
         }
 
-        cache.push(value);
+        cache.add(value);
       }
 
       return value;
-    }.bind(this));
+    });
   },
 
   /**
    * Given an ansi keyword, it will return the appropriate code.
    *
    * @function getAnsiCode
-   * @memberof Cologne.LogUtilities
+   * @memberof Utilities
    * @param {String} ansiString the name of the desired code
    * @return {String} the ansi code
    */
-  getAnsiCode: function getAnsiCode(ansiString) {
-    switch(ansiString) {
+  getAnsiCode(ansiString) {
+
+    switch (ansiString) {
     case 'bold':
       return '[1m';
     case 'italics':
@@ -125,12 +143,13 @@ let LogUtilities = {
    * to it.
    *
    * @function getLevelAnsi
-   * @memberof Cologne.LogUtilities
+   * @memberof Utilities
    * @param {number} level the level of the log
    * @return {String} the ansi keyword
    */
-  getLevelAnsi: function getLevelAnsi(level) {
-    switch(level) {
+  getLevelAnsi(level) {
+
+    switch (level) {
     case 0:
     case 1:
     case 2:
@@ -148,8 +167,3 @@ let LogUtilities = {
     }
   }
 };
-
-// String used as default circular reference.
-LogUtilities._circularString = '[Circular]';
-
-module.exports = LogUtilities;
diff --git a/package-lock.json b/package-lock.json
new file mode 100644 (file)
index 0000000..873e389
--- /dev/null
@@ -0,0 +1,4635 @@
+{
+  "name": "cologne",
+  "version": "2.0.0-build1",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "@babel/code-frame": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
+      "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
+      "dev": true,
+      "requires": {
+        "@babel/highlight": "^7.10.4"
+      }
+    },
+    "@babel/generator": {
+      "version": "7.11.6",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz",
+      "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.11.5",
+        "jsesc": "^2.5.1",
+        "source-map": "^0.5.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "dev": true
+        }
+      }
+    },
+    "@babel/helper-function-name": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz",
+      "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-get-function-arity": "^7.10.4",
+        "@babel/template": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "@babel/helper-get-function-arity": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz",
+      "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "@babel/helper-split-export-declaration": {
+      "version": "7.11.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz",
+      "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.11.0"
+      }
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
+      "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
+      "dev": true
+    },
+    "@babel/highlight": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
+      "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "chalk": "^2.0.0",
+        "js-tokens": "^4.0.0"
+      },
+      "dependencies": {
+        "chalk": {
+          "version": "2.4.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        }
+      }
+    },
+    "@babel/parser": {
+      "version": "7.11.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz",
+      "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==",
+      "dev": true
+    },
+    "@babel/template": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz",
+      "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/parser": "^7.10.4",
+        "@babel/types": "^7.10.4"
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.11.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz",
+      "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.10.4",
+        "@babel/generator": "^7.11.5",
+        "@babel/helper-function-name": "^7.10.4",
+        "@babel/helper-split-export-declaration": "^7.11.0",
+        "@babel/parser": "^7.11.5",
+        "@babel/types": "^7.11.5",
+        "debug": "^4.1.0",
+        "globals": "^11.1.0",
+        "lodash": "^4.17.19"
+      },
+      "dependencies": {
+        "globals": {
+          "version": "11.12.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+          "dev": true
+        }
+      }
+    },
+    "@babel/types": {
+      "version": "7.11.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz",
+      "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.10.4",
+        "lodash": "^4.17.19",
+        "to-fast-properties": "^2.0.0"
+      }
+    },
+    "@eslint/eslintrc": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.1.3.tgz",
+      "integrity": "sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.12.4",
+        "debug": "^4.1.1",
+        "espree": "^7.3.0",
+        "globals": "^12.1.0",
+        "ignore": "^4.0.6",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^3.13.1",
+        "lodash": "^4.17.19",
+        "minimatch": "^3.0.4",
+        "strip-json-comments": "^3.1.1"
+      }
+    },
+    "@hapi/eslint-config-hapi": {
+      "version": "13.0.2",
+      "resolved": "https://registry.npmjs.org/@hapi/eslint-config-hapi/-/eslint-config-hapi-13.0.2.tgz",
+      "integrity": "sha512-LtTYBSWdBmv9JfMWAtXfJ4nm8TURPdqWY2ER9cfQxqPEF1jrfv5T4GmPE/GmFy4WJs+s13j8DKsWifOAxgGLRw==",
+      "dev": true
+    },
+    "@hapi/eslint-plugin-hapi": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmjs.org/@hapi/eslint-plugin-hapi/-/eslint-plugin-hapi-4.3.6.tgz",
+      "integrity": "sha512-fmoLInkoAhuBPrV0OCGz9+DLq0PyarKxCp5s4ytNxDgZy5g33xVZpA1v0NCkQcQxTboP1AzbG2SLS8zAXjIWrQ==",
+      "dev": true
+    },
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
+    },
+    "acorn": {
+      "version": "7.4.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
+      "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
+      "dev": true
+    },
+    "acorn-jsx": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
+      "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
+      "dev": true
+    },
+    "ajv": {
+      "version": "6.12.5",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
+      "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ansi-colors": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+      "dev": true
+    },
+    "ansi-escape-sequences": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz",
+      "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==",
+      "dev": true,
+      "requires": {
+        "array-back": "^3.0.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
+          "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
+          "dev": true
+        }
+      }
+    },
+    "ansi-regex": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^1.9.0"
+      }
+    },
+    "anymatch": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
+      "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "append-transform": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+      "dev": true,
+      "requires": {
+        "default-require-extensions": "^2.0.0"
+      }
+    },
+    "archy": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+      "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
+      "dev": true
+    },
+    "arg": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+      "dev": true
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "array-back": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz",
+      "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==",
+      "dev": true
+    },
+    "asn1": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
+      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": "~2.1.0"
+      }
+    },
+    "assert-plus": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+      "dev": true
+    },
+    "astral-regex": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+      "dev": true
+    },
+    "async-hook-domain": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/async-hook-domain/-/async-hook-domain-1.1.3.tgz",
+      "integrity": "sha512-ZovMxSbADV3+biB7oR1GL5lGyptI24alp0LWHlmz1OFc5oL47pz3EiIF6nXOkDW7yLqih4NtsiYduzdDW0i+Wg==",
+      "dev": true,
+      "requires": {
+        "source-map-support": "^0.5.11"
+      }
+    },
+    "asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+      "dev": true
+    },
+    "aws-sign2": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+      "dev": true
+    },
+    "aws4": {
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
+      "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+      "dev": true
+    },
+    "bcrypt-pbkdf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+      "dev": true,
+      "requires": {
+        "tweetnacl": "^0.14.3"
+      }
+    },
+    "binary-extensions": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
+      "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
+      "dev": true
+    },
+    "bind-obj-methods": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.0.tgz",
+      "integrity": "sha512-3/qRXczDi2Cdbz6jE+W3IflJOutRVica8frpBn14de1mBOkzDo+6tY33kNhvkw54Kn3PzRRD2VnGbGPcTAk4sw==",
+      "dev": true
+    },
+    "bluebird": {
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+      "dev": true
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dev": true,
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "browser-process-hrtime": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
+      "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
+      "dev": true
+    },
+    "buffer-from": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+      "dev": true
+    },
+    "cache-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz",
+      "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "fs-then-native": "^2.0.0",
+        "mkdirp2": "^1.0.4"
+      }
+    },
+    "caching-transform": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz",
+      "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==",
+      "dev": true,
+      "requires": {
+        "hasha": "^3.0.0",
+        "make-dir": "^2.0.0",
+        "package-hash": "^3.0.0",
+        "write-file-atomic": "^2.4.2"
+      },
+      "dependencies": {
+        "write-file-atomic": {
+          "version": "2.4.3",
+          "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz",
+          "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==",
+          "dev": true,
+          "requires": {
+            "graceful-fs": "^4.1.11",
+            "imurmurhash": "^0.1.4",
+            "signal-exit": "^3.0.2"
+          }
+        }
+      }
+    },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
+    "camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true
+    },
+    "caseless": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+      "dev": true
+    },
+    "catharsis": {
+      "version": "0.8.11",
+      "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz",
+      "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.14"
+      }
+    },
+    "chalk": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
+      "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
+          "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "chokidar": {
+      "version": "3.4.2",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz",
+      "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==",
+      "dev": true,
+      "requires": {
+        "anymatch": "~3.1.1",
+        "braces": "~3.0.2",
+        "fsevents": "~2.1.2",
+        "glob-parent": "~5.1.0",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.4.0"
+      }
+    },
+    "cliui": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+      "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+      "dev": true,
+      "requires": {
+        "string-width": "^2.1.1",
+        "strip-ansi": "^4.0.0",
+        "wrap-ansi": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        },
+        "string-width": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+          "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+          "dev": true,
+          "requires": {
+            "is-fullwidth-code-point": "^2.0.0",
+            "strip-ansi": "^4.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^3.0.0"
+          }
+        }
+      }
+    },
+    "code-point-at": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+      "dev": true
+    },
+    "collect-all": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.3.tgz",
+      "integrity": "sha512-0y0rBgoX8IzIjBAUnO73SEtSb4Mhk3IoceWJq5zZSxb9mWORhWH8xLYo4EDSOE1jRBk1LhmfjqWFFt10h/+MEA==",
+      "dev": true,
+      "requires": {
+        "stream-connect": "^1.0.2",
+        "stream-via": "^1.0.4"
+      }
+    },
+    "color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "dev": true,
+      "requires": {
+        "color-name": "1.1.3"
+      }
+    },
+    "color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+      "dev": true
+    },
+    "color-support": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+      "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+      "dev": true
+    },
+    "combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "dev": true,
+      "requires": {
+        "delayed-stream": "~1.0.0"
+      }
+    },
+    "command-line-args": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz",
+      "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==",
+      "dev": true,
+      "requires": {
+        "array-back": "^3.0.1",
+        "find-replace": "^3.0.0",
+        "lodash.camelcase": "^4.3.0",
+        "typical": "^4.0.0"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
+          "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
+          "dev": true
+        },
+        "typical": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
+          "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==",
+          "dev": true
+        }
+      }
+    },
+    "command-line-tool": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz",
+      "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==",
+      "dev": true,
+      "requires": {
+        "ansi-escape-sequences": "^4.0.0",
+        "array-back": "^2.0.0",
+        "command-line-args": "^5.0.0",
+        "command-line-usage": "^4.1.0",
+        "typical": "^2.6.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
+          "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.1"
+          }
+        }
+      }
+    },
+    "command-line-usage": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz",
+      "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==",
+      "dev": true,
+      "requires": {
+        "ansi-escape-sequences": "^4.0.0",
+        "array-back": "^2.0.0",
+        "table-layout": "^0.4.2",
+        "typical": "^2.6.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
+          "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.1"
+          }
+        }
+      }
+    },
+    "common-sequence": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.0.tgz",
+      "integrity": "sha512-f0QqPLpRTgMQn/pQIynf+SdE73Lw5Q1jn4hjirHLgH/NJ71TiHjXusV16BmOyuK5rRQ1W2f++II+TFZbQOh4hA==",
+      "dev": true
+    },
+    "commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+      "dev": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "config-master": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz",
+      "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=",
+      "dev": true,
+      "requires": {
+        "walk-back": "^2.0.1"
+      },
+      "dependencies": {
+        "walk-back": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz",
+          "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=",
+          "dev": true
+        }
+      }
+    },
+    "convert-source-map": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
+      "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.1.1"
+      },
+      "dependencies": {
+        "safe-buffer": {
+          "version": "5.1.2",
+          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+          "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+          "dev": true
+        }
+      }
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+      "dev": true
+    },
+    "coveralls": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz",
+      "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==",
+      "dev": true,
+      "requires": {
+        "js-yaml": "^3.13.1",
+        "lcov-parse": "^1.0.0",
+        "log-driver": "^1.2.7",
+        "minimist": "^1.2.5",
+        "request": "^2.88.2"
+      }
+    },
+    "cp-file": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz",
+      "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "make-dir": "^2.0.0",
+        "nested-error-stacks": "^2.0.0",
+        "pify": "^4.0.1",
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "cross-spawn": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "dev": true,
+      "requires": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      }
+    },
+    "dashdash": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "debug": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz",
+      "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==",
+      "dev": true,
+      "requires": {
+        "ms": "2.1.2"
+      }
+    },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+      "dev": true
+    },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
+    "deep-is": {
+      "version": "0.1.3",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+      "dev": true
+    },
+    "default-require-extensions": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+      "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+      "dev": true,
+      "requires": {
+        "strip-bom": "^3.0.0"
+      }
+    },
+    "delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+      "dev": true
+    },
+    "diff": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+      "dev": true
+    },
+    "diff-frag": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/diff-frag/-/diff-frag-1.0.1.tgz",
+      "integrity": "sha512-6/v2PC/6UTGcWPPetb9acL8foberUg/CtPdALeJUdD1B/weHNvzftoo00gYznqHGRhHEbykUGzqfG9RWOSr5yw==",
+      "dev": true
+    },
+    "dmd": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/dmd/-/dmd-5.0.2.tgz",
+      "integrity": "sha512-npXsE2+/onRPk/LCrUmx7PcUSqcSVnbrDDMi2nBSawNZ8QXlHE/8xaEZ6pNqPD1lQZv8LGr1xEIpyxP336xyfw==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "cache-point": "^2.0.0",
+        "common-sequence": "^2.0.0",
+        "file-set": "^4.0.1",
+        "handlebars": "^4.7.6",
+        "marked": "^1.1.0",
+        "object-get": "^2.1.1",
+        "reduce-flatten": "^3.0.0",
+        "reduce-unique": "^2.0.1",
+        "reduce-without": "^1.0.1",
+        "test-value": "^3.0.0",
+        "walk-back": "^4.0.0"
+      },
+      "dependencies": {
+        "reduce-flatten": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz",
+          "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==",
+          "dev": true
+        }
+      }
+    },
+    "doctrine": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+      "dev": true,
+      "requires": {
+        "esutils": "^2.0.2"
+      }
+    },
+    "ecc-jsbn": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+      "dev": true,
+      "requires": {
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.1.0"
+      }
+    },
+    "emoji-regex": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+      "dev": true
+    },
+    "enquirer": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+      "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+      "dev": true,
+      "requires": {
+        "ansi-colors": "^4.1.1"
+      }
+    },
+    "entities": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
+      "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==",
+      "dev": true
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "es6-error": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+      "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+      "dev": true
+    },
+    "eslint": {
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.9.0.tgz",
+      "integrity": "sha512-V6QyhX21+uXp4T+3nrNfI3hQNBDa/P8ga7LoQOenwrlEFXrEnUEE+ok1dMtaS3b6rmLXhT1TkTIsG75HMLbknA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "@eslint/eslintrc": "^0.1.3",
+        "ajv": "^6.10.0",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
+        "debug": "^4.0.1",
+        "doctrine": "^3.0.0",
+        "enquirer": "^2.3.5",
+        "eslint-scope": "^5.1.0",
+        "eslint-utils": "^2.1.0",
+        "eslint-visitor-keys": "^1.3.0",
+        "espree": "^7.3.0",
+        "esquery": "^1.2.0",
+        "esutils": "^2.0.2",
+        "file-entry-cache": "^5.0.1",
+        "functional-red-black-tree": "^1.0.1",
+        "glob-parent": "^5.0.0",
+        "globals": "^12.1.0",
+        "ignore": "^4.0.6",
+        "import-fresh": "^3.0.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "js-yaml": "^3.13.1",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.4.1",
+        "lodash": "^4.17.19",
+        "minimatch": "^3.0.4",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.1",
+        "progress": "^2.0.0",
+        "regexpp": "^3.1.0",
+        "semver": "^7.2.1",
+        "strip-ansi": "^6.0.0",
+        "strip-json-comments": "^3.1.0",
+        "table": "^5.2.3",
+        "text-table": "^0.2.0",
+        "v8-compile-cache": "^2.0.3"
+      }
+    },
+    "eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "dev": true,
+      "requires": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "eslint-utils": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+      "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+      "dev": true,
+      "requires": {
+        "eslint-visitor-keys": "^1.1.0"
+      }
+    },
+    "eslint-visitor-keys": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+      "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+      "dev": true
+    },
+    "esm": {
+      "version": "3.2.25",
+      "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
+      "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
+      "dev": true
+    },
+    "espree": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz",
+      "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==",
+      "dev": true,
+      "requires": {
+        "acorn": "^7.4.0",
+        "acorn-jsx": "^5.2.0",
+        "eslint-visitor-keys": "^1.3.0"
+      }
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "dev": true
+    },
+    "esquery": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
+      "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^5.1.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
+      }
+    },
+    "esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "requires": {
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
+          "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
+          "dev": true
+        }
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true
+    },
+    "esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true
+    },
+    "events-to-array": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz",
+      "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=",
+      "dev": true
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+      "dev": true
+    },
+    "extsprintf": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+      "dev": true
+    },
+    "fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true
+    },
+    "fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+      "dev": true
+    },
+    "file-entry-cache": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+      "dev": true,
+      "requires": {
+        "flat-cache": "^2.0.1"
+      }
+    },
+    "file-set": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.1.tgz",
+      "integrity": "sha512-tRzX4kGPmxS2HDK2q2L4qcPopTl/gcyahve2/O8l8hHNJgJ7m+r/ZncCJ1MmFWEMp1yHxJGIU9gAcsWu5jPMpg==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "glob": "^7.1.6"
+      }
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dev": true,
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "find-cache-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+      "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+      "dev": true,
+      "requires": {
+        "commondir": "^1.0.1",
+        "make-dir": "^2.0.0",
+        "pkg-dir": "^3.0.0"
+      }
+    },
+    "find-replace": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
+      "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
+      "dev": true,
+      "requires": {
+        "array-back": "^3.0.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
+          "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==",
+          "dev": true
+        }
+      }
+    },
+    "find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dev": true,
+      "requires": {
+        "locate-path": "^3.0.0"
+      }
+    },
+    "findit": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/findit/-/findit-2.0.0.tgz",
+      "integrity": "sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4=",
+      "dev": true
+    },
+    "flat-cache": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+      "dev": true,
+      "requires": {
+        "flatted": "^2.0.0",
+        "rimraf": "2.6.3",
+        "write": "1.0.3"
+      }
+    },
+    "flatted": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
+      "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+      "dev": true
+    },
+    "flow-parser": {
+      "version": "0.134.0",
+      "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.134.0.tgz",
+      "integrity": "sha512-VmRba5YXKmVqIH3xNzUJ4pNobxXEOl6h36m+0f5dZ6/av9YlRpls/yBnPESQ4qBUbyyp7iqoc1Feo1lFw3u1YQ==",
+      "dev": true
+    },
+    "flow-remove-types": {
+      "version": "2.134.0",
+      "resolved": "https://registry.npmjs.org/flow-remove-types/-/flow-remove-types-2.134.0.tgz",
+      "integrity": "sha512-NVtghveE8GbU+980DRZQ0NZYGE7l7FIZm/UU8Ft7QoFgpsU8Tauv/WRLX+Exj4WT+GbAndmyUWZFOtcBfeT+gg==",
+      "dev": true,
+      "requires": {
+        "flow-parser": "^0.134.0",
+        "pirates": "^3.0.2",
+        "vlq": "^0.2.1"
+      }
+    },
+    "foreground-child": {
+      "version": "1.5.6",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz",
+      "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=",
+      "dev": true,
+      "requires": {
+        "cross-spawn": "^4",
+        "signal-exit": "^3.0.0"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "4.0.2",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
+          "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
+          "dev": true,
+          "requires": {
+            "lru-cache": "^4.0.1",
+            "which": "^1.2.9"
+          }
+        },
+        "which": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
+    "forever-agent": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+      "dev": true
+    },
+    "form-data": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+      "dev": true,
+      "requires": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.6",
+        "mime-types": "^2.1.12"
+      }
+    },
+    "fs-exists-cached": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs-exists-cached/-/fs-exists-cached-1.0.0.tgz",
+      "integrity": "sha1-zyVVTKBQ3EmuZla0HeQiWJidy84=",
+      "dev": true
+    },
+    "fs-then-native": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz",
+      "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=",
+      "dev": true
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
+      "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
+      "dev": true,
+      "optional": true
+    },
+    "function-loop": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/function-loop/-/function-loop-1.0.2.tgz",
+      "integrity": "sha512-Iw4MzMfS3udk/rqxTiDDCllhGwlOrsr50zViTOO/W6lS/9y6B1J0BD2VZzrnWUYBJsl3aeqjgR5v7bWWhZSYbA==",
+      "dev": true
+    },
+    "functional-red-black-tree": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+      "dev": true
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true
+    },
+    "getpass": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0"
+      }
+    },
+    "glob": {
+      "version": "7.1.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
+      "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
+      "dev": true,
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "globals": {
+      "version": "12.4.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+      "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^0.8.1"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
+      "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
+      "dev": true
+    },
+    "handlebars": {
+      "version": "4.7.6",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
+      "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.5",
+        "neo-async": "^2.6.0",
+        "source-map": "^0.6.1",
+        "uglify-js": "^3.1.4",
+        "wordwrap": "^1.0.0"
+      }
+    },
+    "har-schema": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+      "dev": true
+    },
+    "har-validator": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.12.3",
+        "har-schema": "^2.0.0"
+      }
+    },
+    "has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "dev": true
+    },
+    "hasha": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz",
+      "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=",
+      "dev": true,
+      "requires": {
+        "is-stream": "^1.0.1"
+      }
+    },
+    "hosted-git-info": {
+      "version": "2.8.8",
+      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
+      "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
+      "dev": true
+    },
+    "html-escaper": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+      "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+      "dev": true
+    },
+    "http-signature": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "jsprim": "^1.2.2",
+        "sshpk": "^1.7.0"
+      }
+    },
+    "ignore": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
+      "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+      "dev": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dev": true,
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "dev": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+      "dev": true
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dev": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true
+    },
+    "is-stream": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+      "dev": true
+    },
+    "is-typedarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+      "dev": true
+    },
+    "isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+      "dev": true
+    },
+    "isstream": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+      "dev": true
+    },
+    "istanbul-lib-coverage": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+      "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+      "dev": true
+    },
+    "istanbul-lib-hook": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
+      "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+      "dev": true,
+      "requires": {
+        "append-transform": "^1.0.0"
+      }
+    },
+    "istanbul-lib-instrument": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+      "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+      "dev": true,
+      "requires": {
+        "@babel/generator": "^7.4.0",
+        "@babel/parser": "^7.4.3",
+        "@babel/template": "^7.4.0",
+        "@babel/traverse": "^7.4.3",
+        "@babel/types": "^7.4.0",
+        "istanbul-lib-coverage": "^2.0.5",
+        "semver": "^6.0.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
+    "istanbul-lib-processinfo": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz",
+      "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==",
+      "dev": true,
+      "requires": {
+        "archy": "^1.0.0",
+        "cross-spawn": "^6.0.5",
+        "istanbul-lib-coverage": "^2.0.3",
+        "rimraf": "^2.6.3",
+        "uuid": "^3.3.2"
+      },
+      "dependencies": {
+        "cross-spawn": {
+          "version": "6.0.5",
+          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+          "dev": true,
+          "requires": {
+            "nice-try": "^1.0.4",
+            "path-key": "^2.0.1",
+            "semver": "^5.5.0",
+            "shebang-command": "^1.2.0",
+            "which": "^1.2.9"
+          }
+        },
+        "path-key": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+          "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+          "dev": true
+        },
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        },
+        "shebang-command": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+          "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+          "dev": true,
+          "requires": {
+            "shebang-regex": "^1.0.0"
+          }
+        },
+        "shebang-regex": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+          "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+          "dev": true
+        },
+        "which": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
+    "istanbul-lib-report": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+      "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+      "dev": true,
+      "requires": {
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "supports-color": "^6.1.0"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        }
+      }
+    },
+    "istanbul-lib-source-maps": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+      "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.1",
+        "istanbul-lib-coverage": "^2.0.5",
+        "make-dir": "^2.1.0",
+        "rimraf": "^2.6.3",
+        "source-map": "^0.6.1"
+      }
+    },
+    "istanbul-reports": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz",
+      "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==",
+      "dev": true,
+      "requires": {
+        "html-escaper": "^2.0.0"
+      }
+    },
+    "jackspeak": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-1.4.0.tgz",
+      "integrity": "sha512-VDcSunT+wcccoG46FtzuBAyQKlzhHjli4q31e1fIHGOsRspqNUFjVzGb+7eIFDlTvqLygxapDHPHS0ouT2o/tw==",
+      "dev": true,
+      "requires": {
+        "cliui": "^4.1.0"
+      }
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "dev": true
+    },
+    "js-yaml": {
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+      "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "js2xmlparser": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz",
+      "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==",
+      "dev": true,
+      "requires": {
+        "xmlcreate": "^2.0.3"
+      }
+    },
+    "jsbn": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+      "dev": true
+    },
+    "jsdoc": {
+      "version": "3.6.6",
+      "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz",
+      "integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==",
+      "dev": true,
+      "requires": {
+        "@babel/parser": "^7.9.4",
+        "bluebird": "^3.7.2",
+        "catharsis": "^0.8.11",
+        "escape-string-regexp": "^2.0.0",
+        "js2xmlparser": "^4.0.1",
+        "klaw": "^3.0.0",
+        "markdown-it": "^10.0.0",
+        "markdown-it-anchor": "^5.2.7",
+        "marked": "^0.8.2",
+        "mkdirp": "^1.0.4",
+        "requizzle": "^0.2.3",
+        "strip-json-comments": "^3.1.0",
+        "taffydb": "2.6.2",
+        "underscore": "~1.10.2"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+          "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+          "dev": true
+        },
+        "marked": {
+          "version": "0.8.2",
+          "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz",
+          "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==",
+          "dev": true
+        },
+        "mkdirp": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
+        }
+      }
+    },
+    "jsdoc-api": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-6.0.0.tgz",
+      "integrity": "sha512-zvfB63nAc9e+Rv2kKmJfE6tmo4x8KFho5vKr6VfYTlCCgqtrfPv0McCdqT4betUT9rWtw0zGkNUVkVqeQipY6Q==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "cache-point": "^2.0.0",
+        "collect-all": "^1.0.3",
+        "file-set": "^4.0.1",
+        "fs-then-native": "^2.0.0",
+        "jsdoc": "^3.6.4",
+        "object-to-spawn-args": "^2.0.0",
+        "temp-path": "^1.0.0",
+        "walk-back": "^4.0.0"
+      }
+    },
+    "jsdoc-parse": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-5.0.0.tgz",
+      "integrity": "sha512-Khw8c3glrTeA3/PfUJUBvhrMhWpSClORBUvL4pvq2wFcqvUVmA96wxnMkCno2GfZY4pnd8BStK5WGKGyn4Vckg==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "lodash.omit": "^4.5.0",
+        "lodash.pick": "^4.4.0",
+        "reduce-extract": "^1.0.0",
+        "sort-array": "^4.1.1",
+        "test-value": "^3.0.0"
+      }
+    },
+    "jsdoc-to-markdown": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-6.0.1.tgz",
+      "integrity": "sha512-hUI2PAR5n/KlmQU3mAWO9i3D7jVbhyvUHfQ6oYVBt+wnnsyxpsAuhCODY1ryLOb2U9OPJd4GIK9mL2hqy7fHDg==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "command-line-tool": "^0.8.0",
+        "config-master": "^3.1.0",
+        "dmd": "^5.0.1",
+        "jsdoc-api": "^6.0.0",
+        "jsdoc-parse": "^5.0.0",
+        "walk-back": "^4.0.0"
+      }
+    },
+    "jsesc": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+      "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+      "dev": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "dev": true
+    },
+    "json-schema": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+      "dev": true
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+      "dev": true
+    },
+    "json-stringify-safe": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+      "dev": true
+    },
+    "jsprim": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "1.0.0",
+        "extsprintf": "1.3.0",
+        "json-schema": "0.2.3",
+        "verror": "1.10.0"
+      }
+    },
+    "klaw": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
+      "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.9"
+      }
+    },
+    "lcov-parse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz",
+      "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=",
+      "dev": true
+    },
+    "levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      }
+    },
+    "linkify-it": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+      "dev": true,
+      "requires": {
+        "uc.micro": "^1.0.1"
+      }
+    },
+    "load-json-file": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+      "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.2",
+        "parse-json": "^4.0.0",
+        "pify": "^3.0.0",
+        "strip-bom": "^3.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
+    "locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "requires": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      }
+    },
+    "lodash": {
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
+      "dev": true
+    },
+    "lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
+      "dev": true
+    },
+    "lodash.flattendeep": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+      "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
+      "dev": true
+    },
+    "lodash.omit": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
+      "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=",
+      "dev": true
+    },
+    "lodash.padend": {
+      "version": "4.6.1",
+      "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz",
+      "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=",
+      "dev": true
+    },
+    "lodash.pick": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
+      "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=",
+      "dev": true
+    },
+    "log-driver": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz",
+      "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==",
+      "dev": true
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dev": true,
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "lru-cache": {
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+      "dev": true,
+      "requires": {
+        "pseudomap": "^1.0.2",
+        "yallist": "^2.1.2"
+      }
+    },
+    "make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "requires": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "make-error": {
+      "version": "1.3.6",
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+      "dev": true
+    },
+    "markdown-it": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "entities": "~2.0.0",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      }
+    },
+    "markdown-it-anchor": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz",
+      "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==",
+      "dev": true
+    },
+    "marked": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-1.1.1.tgz",
+      "integrity": "sha512-mJzT8D2yPxoPh7h0UXkB+dBj4FykPJ2OIfxAWeIHrvoHDkFxukV/29QxoFQoPM6RLEwhIFdJpmKBlqVM3s2ZIw==",
+      "dev": true
+    },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+      "dev": true
+    },
+    "merge-source-map": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
+      "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
+      "dev": true,
+      "requires": {
+        "source-map": "^0.6.1"
+      }
+    },
+    "mime-db": {
+      "version": "1.44.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+      "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
+      "dev": true
+    },
+    "mime-types": {
+      "version": "2.1.27",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+      "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
+      "dev": true,
+      "requires": {
+        "mime-db": "1.44.0"
+      }
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+      "dev": true
+    },
+    "minipass": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
+      "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
+      "dev": true,
+      "requires": {
+        "yallist": "^4.0.0"
+      },
+      "dependencies": {
+        "yallist": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+          "dev": true
+        }
+      }
+    },
+    "mkdirp": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+      "dev": true,
+      "requires": {
+        "minimist": "^1.2.5"
+      }
+    },
+    "mkdirp2": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz",
+      "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==",
+      "dev": true
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+      "dev": true
+    },
+    "natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+      "dev": true
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "nested-error-stacks": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz",
+      "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==",
+      "dev": true
+    },
+    "nice-try": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+      "dev": true
+    },
+    "node-modules-regexp": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz",
+      "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=",
+      "dev": true
+    },
+    "normalize-package-data": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+      "dev": true,
+      "requires": {
+        "hosted-git-info": "^2.1.4",
+        "resolve": "^1.10.0",
+        "semver": "2 || 3 || 4 || 5",
+        "validate-npm-package-license": "^3.0.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "5.7.1",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+          "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+          "dev": true
+        }
+      }
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "dev": true
+    },
+    "number-is-nan": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+      "dev": true
+    },
+    "nyc": {
+      "version": "14.1.1",
+      "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz",
+      "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==",
+      "dev": true,
+      "requires": {
+        "archy": "^1.0.0",
+        "caching-transform": "^3.0.2",
+        "convert-source-map": "^1.6.0",
+        "cp-file": "^6.2.0",
+        "find-cache-dir": "^2.1.0",
+        "find-up": "^3.0.0",
+        "foreground-child": "^1.5.6",
+        "glob": "^7.1.3",
+        "istanbul-lib-coverage": "^2.0.5",
+        "istanbul-lib-hook": "^2.0.7",
+        "istanbul-lib-instrument": "^3.3.0",
+        "istanbul-lib-report": "^2.0.8",
+        "istanbul-lib-source-maps": "^3.0.6",
+        "istanbul-reports": "^2.2.4",
+        "js-yaml": "^3.13.1",
+        "make-dir": "^2.1.0",
+        "merge-source-map": "^1.1.0",
+        "resolve-from": "^4.0.0",
+        "rimraf": "^2.6.3",
+        "signal-exit": "^3.0.2",
+        "spawn-wrap": "^1.4.2",
+        "test-exclude": "^5.2.3",
+        "uuid": "^3.3.2",
+        "yargs": "^13.2.2",
+        "yargs-parser": "^13.0.0"
+      }
+    },
+    "oauth-sign": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+      "dev": true
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+      "dev": true
+    },
+    "object-get": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz",
+      "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==",
+      "dev": true
+    },
+    "object-to-spawn-args": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.0.tgz",
+      "integrity": "sha512-ZMT4owlXg3JGegecLlAgAA/6BsdKHn63R3ayXcAa3zFkF7oUBHcSb0oxszeutYe0FO2c1lT5pwCuidLkC4Gx3g==",
+      "dev": true
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "opener": {
+      "version": "1.5.2",
+      "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+      "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+      "dev": true
+    },
+    "optionator": {
+      "version": "0.9.1",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+      "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+      "dev": true,
+      "requires": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.3"
+      }
+    },
+    "os-homedir": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+      "dev": true
+    },
+    "own-or": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/own-or/-/own-or-1.0.0.tgz",
+      "integrity": "sha1-Tod/vtqaLsgAD7wLyuOWRe6L+Nw=",
+      "dev": true
+    },
+    "own-or-env": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/own-or-env/-/own-or-env-1.0.1.tgz",
+      "integrity": "sha512-y8qULRbRAlL6x2+M0vIe7jJbJx/kmUTzYonRAa2ayesR2qWLswninkVyeJe4x3IEXhdgoNodzjQRKAoEs6Fmrw==",
+      "dev": true,
+      "requires": {
+        "own-or": "^1.0.0"
+      }
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dev": true,
+      "requires": {
+        "p-limit": "^2.0.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true
+    },
+    "package-hash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz",
+      "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==",
+      "dev": true,
+      "requires": {
+        "graceful-fs": "^4.1.15",
+        "hasha": "^3.0.0",
+        "lodash.flattendeep": "^4.4.0",
+        "release-zalgo": "^1.0.0"
+      }
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+      "dev": true,
+      "requires": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      }
+    },
+    "path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+      "dev": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "dev": true
+    },
+    "path-type": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+      "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+      "dev": true,
+      "requires": {
+        "pify": "^3.0.0"
+      },
+      "dependencies": {
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        }
+      }
+    },
+    "performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+      "dev": true
+    },
+    "picomatch": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
+      "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
+      "dev": true
+    },
+    "pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true
+    },
+    "pirates": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/pirates/-/pirates-3.0.2.tgz",
+      "integrity": "sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==",
+      "dev": true,
+      "requires": {
+        "node-modules-regexp": "^1.0.0"
+      }
+    },
+    "pkg-dir": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+      "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+      "dev": true,
+      "requires": {
+        "find-up": "^3.0.0"
+      }
+    },
+    "prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true
+    },
+    "progress": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+      "dev": true
+    },
+    "prop-types": {
+      "version": "15.7.2",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
+      "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
+      "dev": true,
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.8.1"
+      }
+    },
+    "pseudomap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+      "dev": true
+    },
+    "psl": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
+      "dev": true
+    },
+    "punycode": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+      "dev": true
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+      "dev": true
+    },
+    "react": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
+      "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
+      "dev": true,
+      "requires": {
+        "loose-envify": "^1.1.0",
+        "object-assign": "^4.1.1",
+        "prop-types": "^15.6.2"
+      }
+    },
+    "react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+      "dev": true
+    },
+    "read-pkg": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+      "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
+      "dev": true,
+      "requires": {
+        "load-json-file": "^4.0.0",
+        "normalize-package-data": "^2.3.2",
+        "path-type": "^3.0.0"
+      }
+    },
+    "read-pkg-up": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+      "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+      "dev": true,
+      "requires": {
+        "find-up": "^3.0.0",
+        "read-pkg": "^3.0.0"
+      }
+    },
+    "readdirp": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
+      "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
+      "dev": true,
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
+    "reduce-extract": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz",
+      "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=",
+      "dev": true,
+      "requires": {
+        "test-value": "^1.0.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz",
+          "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.0"
+          }
+        },
+        "test-value": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz",
+          "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=",
+          "dev": true,
+          "requires": {
+            "array-back": "^1.0.2",
+            "typical": "^2.4.2"
+          }
+        }
+      }
+    },
+    "reduce-flatten": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz",
+      "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=",
+      "dev": true
+    },
+    "reduce-unique": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz",
+      "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==",
+      "dev": true
+    },
+    "reduce-without": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz",
+      "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=",
+      "dev": true,
+      "requires": {
+        "test-value": "^2.0.0"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz",
+          "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.0"
+          }
+        },
+        "test-value": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz",
+          "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=",
+          "dev": true,
+          "requires": {
+            "array-back": "^1.0.3",
+            "typical": "^2.6.0"
+          }
+        }
+      }
+    },
+    "regexpp": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
+      "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==",
+      "dev": true
+    },
+    "release-zalgo": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+      "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=",
+      "dev": true,
+      "requires": {
+        "es6-error": "^4.0.1"
+      }
+    },
+    "request": {
+      "version": "2.88.2",
+      "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+      "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+      "dev": true,
+      "requires": {
+        "aws-sign2": "~0.7.0",
+        "aws4": "^1.8.0",
+        "caseless": "~0.12.0",
+        "combined-stream": "~1.0.6",
+        "extend": "~3.0.2",
+        "forever-agent": "~0.6.1",
+        "form-data": "~2.3.2",
+        "har-validator": "~5.1.3",
+        "http-signature": "~1.2.0",
+        "is-typedarray": "~1.0.0",
+        "isstream": "~0.1.2",
+        "json-stringify-safe": "~5.0.1",
+        "mime-types": "~2.1.19",
+        "oauth-sign": "~0.9.0",
+        "performance-now": "^2.1.0",
+        "qs": "~6.5.2",
+        "safe-buffer": "^5.1.2",
+        "tough-cookie": "~2.5.0",
+        "tunnel-agent": "^0.6.0",
+        "uuid": "^3.3.2"
+      }
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
+    },
+    "require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "dev": true
+    },
+    "requizzle": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz",
+      "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==",
+      "dev": true,
+      "requires": {
+        "lodash": "^4.17.14"
+      }
+    },
+    "resolve": {
+      "version": "1.17.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+      "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+      "dev": true,
+      "requires": {
+        "path-parse": "^1.0.6"
+      }
+    },
+    "resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true
+    },
+    "rimraf": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "7.3.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
+      "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
+      "dev": true
+    },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+      "dev": true
+    },
+    "shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "requires": {
+        "shebang-regex": "^3.0.0"
+      }
+    },
+    "shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
+      "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
+      "dev": true
+    },
+    "slice-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^3.2.0",
+        "astral-regex": "^1.0.0",
+        "is-fullwidth-code-point": "^2.0.0"
+      }
+    },
+    "sort-array": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.2.tgz",
+      "integrity": "sha512-G5IUpM+OcVnyaWHMv84Y/RQYiFQoSu6eUtJZu840iM6nR7zeY/eOGny2epkr5VKqCGDkOj3UBzOluDZ7hFpljA==",
+      "dev": true,
+      "requires": {
+        "array-back": "^4.0.1",
+        "typical": "^6.0.1"
+      },
+      "dependencies": {
+        "typical": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz",
+          "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==",
+          "dev": true
+        }
+      }
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "dev": true
+    },
+    "source-map-support": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
+      "dev": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "spawn-wrap": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz",
+      "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==",
+      "dev": true,
+      "requires": {
+        "foreground-child": "^1.5.6",
+        "mkdirp": "^0.5.0",
+        "os-homedir": "^1.0.1",
+        "rimraf": "^2.6.2",
+        "signal-exit": "^3.0.2",
+        "which": "^1.3.0"
+      },
+      "dependencies": {
+        "which": {
+          "version": "1.3.1",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+          "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+          "dev": true,
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
+    "spdx-correct": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
+      "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+      "dev": true,
+      "requires": {
+        "spdx-expression-parse": "^3.0.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-exceptions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "dev": true
+    },
+    "spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dev": true,
+      "requires": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
+    "spdx-license-ids": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz",
+      "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==",
+      "dev": true
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "dev": true
+    },
+    "sshpk": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+      "dev": true,
+      "requires": {
+        "asn1": "~0.2.3",
+        "assert-plus": "^1.0.0",
+        "bcrypt-pbkdf": "^1.0.0",
+        "dashdash": "^1.12.0",
+        "ecc-jsbn": "~0.1.1",
+        "getpass": "^0.1.1",
+        "jsbn": "~0.1.0",
+        "safer-buffer": "^2.0.2",
+        "tweetnacl": "~0.14.0"
+      }
+    },
+    "stack-utils": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz",
+      "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==",
+      "dev": true
+    },
+    "stream-connect": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz",
+      "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=",
+      "dev": true,
+      "requires": {
+        "array-back": "^1.0.2"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "1.0.4",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz",
+          "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.0"
+          }
+        }
+      }
+    },
+    "stream-via": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz",
+      "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==",
+      "dev": true
+    },
+    "string-width": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+      "dev": true,
+      "requires": {
+        "emoji-regex": "^7.0.1",
+        "is-fullwidth-code-point": "^2.0.0",
+        "strip-ansi": "^5.1.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
+      }
+    },
+    "strip-ansi": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
+      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^5.0.0"
+      }
+    },
+    "strip-bom": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+      "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+      "dev": true
+    },
+    "strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true
+    },
+    "supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^3.0.0"
+      }
+    },
+    "table": {
+      "version": "5.4.6",
+      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+      "dev": true,
+      "requires": {
+        "ajv": "^6.10.2",
+        "lodash": "^4.17.14",
+        "slice-ansi": "^2.1.0",
+        "string-width": "^3.0.0"
+      }
+    },
+    "table-layout": {
+      "version": "0.4.5",
+      "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz",
+      "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==",
+      "dev": true,
+      "requires": {
+        "array-back": "^2.0.0",
+        "deep-extend": "~0.6.0",
+        "lodash.padend": "^4.6.1",
+        "typical": "^2.6.1",
+        "wordwrapjs": "^3.0.0"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
+          "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.1"
+          }
+        }
+      }
+    },
+    "taffydb": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
+      "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=",
+      "dev": true
+    },
+    "tap": {
+      "version": "14.10.8",
+      "resolved": "https://registry.npmjs.org/tap/-/tap-14.10.8.tgz",
+      "integrity": "sha512-aamkWefJ0G8GGf9t5LWFtrNF5tfVd8ut/tDUianLF6N4621ERITIl0qkocWCVEnsM6hZnaMKa+SggSAaBlC2tA==",
+      "dev": true,
+      "requires": {
+        "@types/react": "^16.9.16",
+        "async-hook-domain": "^1.1.3",
+        "bind-obj-methods": "^2.0.0",
+        "browser-process-hrtime": "^1.0.0",
+        "chokidar": "^3.3.0",
+        "color-support": "^1.1.0",
+        "coveralls": "^3.0.11",
+        "diff": "^4.0.1",
+        "esm": "^3.2.25",
+        "findit": "^2.0.0",
+        "flow-remove-types": "^2.112.0",
+        "foreground-child": "^1.3.3",
+        "fs-exists-cached": "^1.0.0",
+        "function-loop": "^1.0.2",
+        "glob": "^7.1.6",
+        "import-jsx": "^3.1.0",
+        "ink": "^2.6.0",
+        "isexe": "^2.0.0",
+        "istanbul-lib-processinfo": "^1.0.0",
+        "jackspeak": "^1.4.0",
+        "minipass": "^3.1.1",
+        "mkdirp": "^0.5.4",
+        "nyc": "^14.1.1",
+        "opener": "^1.5.1",
+        "own-or": "^1.0.0",
+        "own-or-env": "^1.0.1",
+        "react": "^16.12.0",
+        "rimraf": "^2.7.1",
+        "signal-exit": "^3.0.0",
+        "source-map-support": "^0.5.16",
+        "stack-utils": "^1.0.2",
+        "tap-mocha-reporter": "^5.0.0",
+        "tap-parser": "^10.0.1",
+        "tap-yaml": "^1.0.0",
+        "tcompare": "^3.0.0",
+        "treport": "^1.0.2",
+        "trivial-deferred": "^1.0.1",
+        "ts-node": "^8.5.2",
+        "typescript": "^3.7.2",
+        "which": "^2.0.2",
+        "write-file-atomic": "^3.0.1",
+        "yaml": "^1.7.2",
+        "yapool": "^1.0.0"
+      },
+      "dependencies": {
+        "@babel/code-frame": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/highlight": "^7.10.4"
+          }
+        },
+        "@babel/core": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.10.4",
+            "@babel/generator": "^7.10.5",
+            "@babel/helper-module-transforms": "^7.10.5",
+            "@babel/helpers": "^7.10.4",
+            "@babel/parser": "^7.10.5",
+            "@babel/template": "^7.10.4",
+            "@babel/traverse": "^7.10.5",
+            "@babel/types": "^7.10.5",
+            "convert-source-map": "^1.7.0",
+            "debug": "^4.1.0",
+            "gensync": "^1.0.0-beta.1",
+            "json5": "^2.1.2",
+            "lodash": "^4.17.19",
+            "resolve": "^1.3.2",
+            "semver": "^5.4.1",
+            "source-map": "^0.5.0"
+          },
+          "dependencies": {
+            "source-map": {
+              "version": "0.5.7",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "@babel/generator": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.5",
+            "jsesc": "^2.5.1",
+            "source-map": "^0.5.0"
+          },
+          "dependencies": {
+            "source-map": {
+              "version": "0.5.7",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "@babel/helper-annotate-as-pure": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-builder-react-jsx": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-builder-react-jsx-experimental": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-annotate-as-pure": "^7.10.4",
+            "@babel/helper-module-imports": "^7.10.4",
+            "@babel/types": "^7.10.5"
+          }
+        },
+        "@babel/helper-function-name": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.10.4",
+            "@babel/template": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-get-function-arity": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-member-expression-to-functions": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.5"
+          }
+        },
+        "@babel/helper-module-imports": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-module-transforms": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-module-imports": "^7.10.4",
+            "@babel/helper-replace-supers": "^7.10.4",
+            "@babel/helper-simple-access": "^7.10.4",
+            "@babel/helper-split-export-declaration": "^7.10.4",
+            "@babel/template": "^7.10.4",
+            "@babel/types": "^7.10.5",
+            "lodash": "^4.17.19"
+          }
+        },
+        "@babel/helper-optimise-call-expression": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-plugin-utils": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true
+        },
+        "@babel/helper-replace-supers": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-member-expression-to-functions": "^7.10.4",
+            "@babel/helper-optimise-call-expression": "^7.10.4",
+            "@babel/traverse": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-simple-access": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/template": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-split-export-declaration": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/helper-validator-identifier": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true
+        },
+        "@babel/helpers": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/template": "^7.10.4",
+            "@babel/traverse": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/highlight": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "chalk": "^2.0.0",
+            "js-tokens": "^4.0.0"
+          }
+        },
+        "@babel/parser": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true
+        },
+        "@babel/plugin-proposal-object-rest-spread": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.10.4",
+            "@babel/plugin-syntax-object-rest-spread": "^7.8.0",
+            "@babel/plugin-transform-parameters": "^7.10.4"
+          }
+        },
+        "@babel/plugin-syntax-jsx": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.10.4"
+          }
+        },
+        "@babel/plugin-syntax-object-rest-spread": {
+          "version": "7.8.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.8.0"
+          }
+        },
+        "@babel/plugin-transform-destructuring": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-plugin-utils": "^7.10.4"
+          }
+        },
+        "@babel/plugin-transform-parameters": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-get-function-arity": "^7.10.4",
+            "@babel/helper-plugin-utils": "^7.10.4"
+          }
+        },
+        "@babel/plugin-transform-react-jsx": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-builder-react-jsx": "^7.10.4",
+            "@babel/helper-builder-react-jsx-experimental": "^7.10.4",
+            "@babel/helper-plugin-utils": "^7.10.4",
+            "@babel/plugin-syntax-jsx": "^7.10.4"
+          }
+        },
+        "@babel/template": {
+          "version": "7.10.4",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.10.4",
+            "@babel/parser": "^7.10.4",
+            "@babel/types": "^7.10.4"
+          }
+        },
+        "@babel/traverse": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/code-frame": "^7.10.4",
+            "@babel/generator": "^7.10.5",
+            "@babel/helper-function-name": "^7.10.4",
+            "@babel/helper-split-export-declaration": "^7.10.4",
+            "@babel/parser": "^7.10.5",
+            "@babel/types": "^7.10.5",
+            "debug": "^4.1.0",
+            "globals": "^11.1.0",
+            "lodash": "^4.17.19"
+          }
+        },
+        "@babel/types": {
+          "version": "7.10.5",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/helper-validator-identifier": "^7.10.4",
+            "lodash": "^4.17.19",
+            "to-fast-properties": "^2.0.0"
+          }
+        },
+        "@types/color-name": {
+          "version": "1.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "@types/prop-types": {
+          "version": "15.7.3",
+          "bundled": true,
+          "dev": true
+        },
+        "@types/react": {
+          "version": "16.9.43",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@types/prop-types": "*",
+            "csstype": "^2.2.0"
+          }
+        },
+        "@types/yoga-layout": {
+          "version": "1.9.2",
+          "bundled": true,
+          "dev": true
+        },
+        "ansi-escapes": {
+          "version": "4.3.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "type-fest": "^0.11.0"
+          }
+        },
+        "ansi-regex": {
+          "version": "5.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "ansi-styles": {
+          "version": "3.2.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "color-convert": "^1.9.0"
+          }
+        },
+        "ansicolors": {
+          "version": "0.3.2",
+          "bundled": true,
+          "dev": true
+        },
+        "arrify": {
+          "version": "2.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "astral-regex": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "auto-bind": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "caller-callsite": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "callsites": "^2.0.0"
+          }
+        },
+        "caller-path": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "caller-callsite": "^2.0.0"
+          }
+        },
+        "callsites": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "cardinal": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansicolors": "~0.3.2",
+            "redeyed": "~2.1.0"
+          }
+        },
+        "chalk": {
+          "version": "2.4.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.1",
+            "escape-string-regexp": "^1.0.5",
+            "supports-color": "^5.3.0"
+          }
+        },
+        "ci-info": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "cli-cursor": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "restore-cursor": "^3.1.0"
+          }
+        },
+        "cli-truncate": {
+          "version": "2.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "slice-ansi": "^3.0.0",
+            "string-width": "^4.2.0"
+          }
+        },
+        "color-convert": {
+          "version": "1.9.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "color-name": "1.1.3"
+          }
+        },
+        "color-name": {
+          "version": "1.1.3",
+          "bundled": true,
+          "dev": true
+        },
+        "convert-source-map": {
+          "version": "1.7.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "safe-buffer": "~5.1.1"
+          },
+          "dependencies": {
+            "safe-buffer": {
+              "version": "5.1.2",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "csstype": {
+          "version": "2.6.11",
+          "bundled": true,
+          "dev": true
+        },
+        "debug": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "escape-string-regexp": {
+          "version": "1.0.5",
+          "bundled": true,
+          "dev": true
+        },
+        "esprima": {
+          "version": "4.0.1",
+          "bundled": true,
+          "dev": true
+        },
+        "events-to-array": {
+          "version": "1.1.2",
+          "bundled": true,
+          "dev": true
+        },
+        "gensync": {
+          "version": "1.0.0-beta.1",
+          "bundled": true,
+          "dev": true
+        },
+        "globals": {
+          "version": "11.12.0",
+          "bundled": true,
+          "dev": true
+        },
+        "has-flag": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "import-jsx": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@babel/core": "^7.5.5",
+            "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
+            "@babel/plugin-transform-destructuring": "^7.5.0",
+            "@babel/plugin-transform-react-jsx": "^7.3.0",
+            "caller-path": "^2.0.0",
+            "resolve-from": "^3.0.0"
+          }
+        },
+        "ink": {
+          "version": "2.7.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^4.2.1",
+            "arrify": "^2.0.1",
+            "auto-bind": "^4.0.0",
+            "chalk": "^3.0.0",
+            "cli-cursor": "^3.1.0",
+            "cli-truncate": "^2.1.0",
+            "is-ci": "^2.0.0",
+            "lodash.throttle": "^4.1.1",
+            "log-update": "^3.0.0",
+            "prop-types": "^15.6.2",
+            "react-reconciler": "^0.24.0",
+            "scheduler": "^0.18.0",
+            "signal-exit": "^3.0.2",
+            "slice-ansi": "^3.0.0",
+            "string-length": "^3.1.0",
+            "widest-line": "^3.1.0",
+            "wrap-ansi": "^6.2.0",
+            "yoga-layout-prebuilt": "^1.9.3"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "4.2.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "@types/color-name": "^1.1.1",
+                "color-convert": "^2.0.1"
+              }
+            },
+            "chalk": {
+              "version": "3.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+              }
+            },
+            "color-convert": {
+              "version": "2.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "color-name": "~1.1.4"
+              }
+            },
+            "color-name": {
+              "version": "1.1.4",
+              "bundled": true,
+              "dev": true
+            },
+            "has-flag": {
+              "version": "4.0.0",
+              "bundled": true,
+              "dev": true
+            },
+            "supports-color": {
+              "version": "7.1.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "has-flag": "^4.0.0"
+              }
+            }
+          }
+        },
+        "is-ci": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ci-info": "^2.0.0"
+          }
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "js-tokens": {
+          "version": "4.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "jsesc": {
+          "version": "2.5.2",
+          "bundled": true,
+          "dev": true
+        },
+        "json5": {
+          "version": "2.1.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "minimist": "^1.2.5"
+          }
+        },
+        "lodash": {
+          "version": "4.17.19",
+          "bundled": true,
+          "dev": true
+        },
+        "lodash.throttle": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "log-update": {
+          "version": "3.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-escapes": "^3.2.0",
+            "cli-cursor": "^2.1.0",
+            "wrap-ansi": "^5.0.0"
+          },
+          "dependencies": {
+            "ansi-escapes": {
+              "version": "3.2.0",
+              "bundled": true,
+              "dev": true
+            },
+            "ansi-regex": {
+              "version": "4.1.0",
+              "bundled": true,
+              "dev": true
+            },
+            "cli-cursor": {
+              "version": "2.1.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "restore-cursor": "^2.0.0"
+              }
+            },
+            "emoji-regex": {
+              "version": "7.0.3",
+              "bundled": true,
+              "dev": true
+            },
+            "is-fullwidth-code-point": {
+              "version": "2.0.0",
+              "bundled": true,
+              "dev": true
+            },
+            "mimic-fn": {
+              "version": "1.2.0",
+              "bundled": true,
+              "dev": true
+            },
+            "onetime": {
+              "version": "2.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "mimic-fn": "^1.0.0"
+              }
+            },
+            "restore-cursor": {
+              "version": "2.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "onetime": "^2.0.0",
+                "signal-exit": "^3.0.2"
+              }
+            },
+            "string-width": {
+              "version": "3.1.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "emoji-regex": "^7.0.1",
+                "is-fullwidth-code-point": "^2.0.0",
+                "strip-ansi": "^5.1.0"
+              }
+            },
+            "strip-ansi": {
+              "version": "5.2.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^4.1.0"
+              }
+            },
+            "wrap-ansi": {
+              "version": "5.1.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-styles": "^3.2.0",
+                "string-width": "^3.0.0",
+                "strip-ansi": "^5.0.0"
+              }
+            }
+          }
+        },
+        "loose-envify": {
+          "version": "1.4.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "js-tokens": "^3.0.0 || ^4.0.0"
+          }
+        },
+        "mimic-fn": {
+          "version": "2.1.0",
+          "bundled": true,
+          "dev": true
+        },
+        "minimist": {
+          "version": "1.2.5",
+          "bundled": true,
+          "dev": true
+        },
+        "minipass": {
+          "version": "3.1.3",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          },
+          "dependencies": {
+            "yallist": {
+              "version": "4.0.0",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "ms": {
+          "version": "2.1.2",
+          "bundled": true,
+          "dev": true
+        },
+        "object-assign": {
+          "version": "4.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "onetime": {
+          "version": "5.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "mimic-fn": "^2.1.0"
+          }
+        },
+        "path-parse": {
+          "version": "1.0.6",
+          "bundled": true,
+          "dev": true
+        },
+        "prop-types": {
+          "version": "15.7.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "loose-envify": "^1.4.0",
+            "object-assign": "^4.1.1",
+            "react-is": "^16.8.1"
+          }
+        },
+        "punycode": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true
+        },
+        "react-is": {
+          "version": "16.13.1",
+          "bundled": true,
+          "dev": true
+        },
+        "react-reconciler": {
+          "version": "0.24.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "loose-envify": "^1.1.0",
+            "object-assign": "^4.1.1",
+            "prop-types": "^15.6.2",
+            "scheduler": "^0.18.0"
+          }
+        },
+        "redeyed": {
+          "version": "2.1.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "esprima": "~4.0.0"
+          }
+        },
+        "resolve": {
+          "version": "1.17.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "path-parse": "^1.0.6"
+          }
+        },
+        "resolve-from": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "restore-cursor": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "onetime": "^5.1.0",
+            "signal-exit": "^3.0.2"
+          }
+        },
+        "rimraf": {
+          "version": "2.7.1",
+          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+          "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+          "dev": true,
+          "requires": {
+            "glob": "^7.1.3"
+          }
+        },
+        "scheduler": {
+          "version": "0.18.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "loose-envify": "^1.1.0",
+            "object-assign": "^4.1.1"
+          }
+        },
+        "semver": {
+          "version": "5.7.1",
+          "bundled": true,
+          "dev": true
+        },
+        "signal-exit": {
+          "version": "3.0.3",
+          "bundled": true,
+          "dev": true
+        },
+        "slice-ansi": {
+          "version": "3.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "astral-regex": "^2.0.0",
+            "is-fullwidth-code-point": "^3.0.0"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "4.2.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "@types/color-name": "^1.1.1",
+                "color-convert": "^2.0.1"
+              }
+            },
+            "color-convert": {
+              "version": "2.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "color-name": "~1.1.4"
+              }
+            },
+            "color-name": {
+              "version": "1.1.4",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "string-length": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "astral-regex": "^1.0.0",
+            "strip-ansi": "^5.2.0"
+          },
+          "dependencies": {
+            "ansi-regex": {
+              "version": "4.1.0",
+              "bundled": true,
+              "dev": true
+            },
+            "astral-regex": {
+              "version": "1.0.0",
+              "bundled": true,
+              "dev": true
+            },
+            "strip-ansi": {
+              "version": "5.2.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^4.1.0"
+              }
+            }
+          }
+        },
+        "string-width": {
+          "version": "4.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^5.0.0"
+          }
+        },
+        "supports-color": {
+          "version": "5.5.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "has-flag": "^3.0.0"
+          }
+        },
+        "tap-parser": {
+          "version": "10.0.1",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "events-to-array": "^1.0.1",
+            "minipass": "^3.0.0",
+            "tap-yaml": "^1.0.0"
+          }
+        },
+        "tap-yaml": {
+          "version": "1.0.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "yaml": "^1.5.0"
+          }
+        },
+        "to-fast-properties": {
+          "version": "2.0.0",
+          "bundled": true,
+          "dev": true
+        },
+        "treport": {
+          "version": "1.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "cardinal": "^2.1.1",
+            "chalk": "^3.0.0",
+            "import-jsx": "^3.1.0",
+            "ink": "^2.6.0",
+            "ms": "^2.1.2",
+            "string-length": "^3.1.0",
+            "tap-parser": "^10.0.1",
+            "unicode-length": "^2.0.2"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "4.2.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "@types/color-name": "^1.1.1",
+                "color-convert": "^2.0.1"
+              }
+            },
+            "chalk": {
+              "version": "3.0.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+              }
+            },
+            "color-convert": {
+              "version": "2.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "color-name": "~1.1.4"
+              }
+            },
+            "color-name": {
+              "version": "1.1.4",
+              "bundled": true,
+              "dev": true
+            },
+            "has-flag": {
+              "version": "4.0.0",
+              "bundled": true,
+              "dev": true
+            },
+            "supports-color": {
+              "version": "7.1.0",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "has-flag": "^4.0.0"
+              }
+            }
+          }
+        },
+        "type-fest": {
+          "version": "0.11.0",
+          "bundled": true,
+          "dev": true
+        },
+        "unicode-length": {
+          "version": "2.0.2",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "punycode": "^2.0.0",
+            "strip-ansi": "^3.0.1"
+          },
+          "dependencies": {
+            "ansi-regex": {
+              "version": "2.1.1",
+              "bundled": true,
+              "dev": true
+            },
+            "strip-ansi": {
+              "version": "3.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "ansi-regex": "^2.0.0"
+              }
+            }
+          }
+        },
+        "widest-line": {
+          "version": "3.1.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "string-width": "^4.0.0"
+          }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          },
+          "dependencies": {
+            "ansi-styles": {
+              "version": "4.2.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "@types/color-name": "^1.1.1",
+                "color-convert": "^2.0.1"
+              }
+            },
+            "color-convert": {
+              "version": "2.0.1",
+              "bundled": true,
+              "dev": true,
+              "requires": {
+                "color-name": "~1.1.4"
+              }
+            },
+            "color-name": {
+              "version": "1.1.4",
+              "bundled": true,
+              "dev": true
+            }
+          }
+        },
+        "yaml": {
+          "version": "1.10.0",
+          "bundled": true,
+          "dev": true
+        },
+        "yoga-layout-prebuilt": {
+          "version": "1.9.6",
+          "bundled": true,
+          "dev": true,
+          "requires": {
+            "@types/yoga-layout": "1.9.2"
+          }
+        }
+      }
+    },
+    "tap-mocha-reporter": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-5.0.1.tgz",
+      "integrity": "sha512-1knFWOwd4khx/7uSEnUeaP9IPW3w+sqTgJMhrwah6t46nZ8P25atOKAjSvVDsT67lOPu0nfdOqUwoyKn+3E5pA==",
+      "dev": true,
+      "requires": {
+        "color-support": "^1.1.0",
+        "debug": "^4.1.1",
+        "diff": "^4.0.1",
+        "escape-string-regexp": "^2.0.0",
+        "glob": "^7.0.5",
+        "tap-parser": "^10.0.0",
+        "tap-yaml": "^1.0.0",
+        "unicode-length": "^2.0.2"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+          "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+          "dev": true
+        }
+      }
+    },
+    "tap-parser": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-10.1.0.tgz",
+      "integrity": "sha512-FujQeciDaOiOvaIVGS1Rpb0v4R6XkOjvWCWowlz5oKuhPkEJ8U6pxgqt38xuzYhPt8dWEnfHn2jqpZdJEkW7pA==",
+      "dev": true,
+      "requires": {
+        "events-to-array": "^1.0.1",
+        "minipass": "^3.0.0",
+        "tap-yaml": "^1.0.0"
+      }
+    },
+    "tap-yaml": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/tap-yaml/-/tap-yaml-1.0.0.tgz",
+      "integrity": "sha512-Rxbx4EnrWkYk0/ztcm5u3/VznbyFJpyXO12dDBHKWiDVxy7O2Qw6MRrwO5H6Ww0U5YhRY/4C/VzWmFPhBQc4qQ==",
+      "dev": true,
+      "requires": {
+        "yaml": "^1.5.0"
+      }
+    },
+    "tcompare": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/tcompare/-/tcompare-3.0.4.tgz",
+      "integrity": "sha512-Q3TitMVK59NyKgQyFh+857wTAUE329IzLDehuPgU4nF5e8g+EUQ+yUbjUy1/6ugiNnXztphT+NnqlCXolv9P3A==",
+      "dev": true,
+      "requires": {
+        "diff-frag": "^1.0.1"
+      }
+    },
+    "temp-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz",
+      "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=",
+      "dev": true
+    },
+    "test-exclude": {
+      "version": "5.2.3",
+      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+      "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
+      "dev": true,
+      "requires": {
+        "glob": "^7.1.3",
+        "minimatch": "^3.0.4",
+        "read-pkg-up": "^4.0.0",
+        "require-main-filename": "^2.0.0"
+      }
+    },
+    "test-value": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz",
+      "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==",
+      "dev": true,
+      "requires": {
+        "array-back": "^2.0.0",
+        "typical": "^2.6.1"
+      },
+      "dependencies": {
+        "array-back": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz",
+          "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==",
+          "dev": true,
+          "requires": {
+            "typical": "^2.6.1"
+          }
+        }
+      }
+    },
+    "text-table": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+      "dev": true
+    },
+    "to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+      "dev": true
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "tough-cookie": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+      "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+      "dev": true,
+      "requires": {
+        "psl": "^1.1.28",
+        "punycode": "^2.1.1"
+      }
+    },
+    "trivial-deferred": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.0.1.tgz",
+      "integrity": "sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM=",
+      "dev": true
+    },
+    "ts-node": {
+      "version": "8.10.2",
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
+      "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
+      "dev": true,
+      "requires": {
+        "arg": "^4.1.0",
+        "diff": "^4.0.1",
+        "make-error": "^1.1.1",
+        "source-map-support": "^0.5.17",
+        "yn": "3.1.1"
+      }
+    },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "tweetnacl": {
+      "version": "0.14.5",
+      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+      "dev": true
+    },
+    "type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "requires": {
+        "prelude-ls": "^1.2.1"
+      }
+    },
+    "type-fest": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+      "dev": true
+    },
+    "typedarray-to-buffer": {
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+      "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+      "dev": true,
+      "requires": {
+        "is-typedarray": "^1.0.0"
+      }
+    },
+    "typescript": {
+      "version": "3.9.7",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
+      "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
+      "dev": true
+    },
+    "typical": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz",
+      "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=",
+      "dev": true
+    },
+    "uc.micro": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+      "dev": true
+    },
+    "uglify-js": {
+      "version": "3.10.4",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.4.tgz",
+      "integrity": "sha512-kBFT3U4Dcj4/pJ52vfjCSfyLyvG9VYYuGYPmrPvAxRw/i7xHiT4VvCev+uiEMcEEiu6UNB6KgWmGtSUYIWScbw==",
+      "dev": true,
+      "optional": true
+    },
+    "underscore": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
+      "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==",
+      "dev": true
+    },
+    "unicode-length": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.0.2.tgz",
+      "integrity": "sha512-Ph/j1VbS3/r77nhoY2WU0GWGjVYOHL3xpKp0y/Eq2e5r0mT/6b649vm7KFO6RdAdrZkYLdxphYVgvODxPB+Ebg==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.0.0",
+        "strip-ansi": "^3.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "uri-js": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
+      "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
+      "dev": true,
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "uuid": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+      "dev": true
+    },
+    "v8-compile-cache": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
+      "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
+      "dev": true
+    },
+    "validate-npm-package-license": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+      "dev": true,
+      "requires": {
+        "spdx-correct": "^3.0.0",
+        "spdx-expression-parse": "^3.0.0"
+      }
+    },
+    "verror": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+      "dev": true,
+      "requires": {
+        "assert-plus": "^1.0.0",
+        "core-util-is": "1.0.2",
+        "extsprintf": "^1.2.0"
+      }
+    },
+    "vlq": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
+      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
+      "dev": true
+    },
+    "walk-back": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-4.0.0.tgz",
+      "integrity": "sha512-kudCA8PXVQfrqv2mFTG72vDBRi8BKWxGgFLwPpzHcpZnSwZk93WMwUDVcLHWNsnm+Y0AC4Vb6MUNRgaHfyV2DQ==",
+      "dev": true
+    },
+    "which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "requires": {
+        "isexe": "^2.0.0"
+      }
+    },
+    "which-module": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+      "dev": true
+    },
+    "word-wrap": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+      "dev": true
+    },
+    "wordwrap": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+      "dev": true
+    },
+    "wordwrapjs": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz",
+      "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==",
+      "dev": true,
+      "requires": {
+        "reduce-flatten": "^1.0.1",
+        "typical": "^2.6.1"
+      }
+    },
+    "wrap-ansi": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+      "dev": true,
+      "requires": {
+        "string-width": "^1.0.1",
+        "strip-ansi": "^3.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+          "dev": true
+        },
+        "is-fullwidth-code-point": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+          "dev": true,
+          "requires": {
+            "number-is-nan": "^1.0.0"
+          }
+        },
+        "string-width": {
+          "version": "1.0.2",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+          "dev": true,
+          "requires": {
+            "code-point-at": "^1.0.0",
+            "is-fullwidth-code-point": "^1.0.0",
+            "strip-ansi": "^3.0.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^2.0.0"
+          }
+        }
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    },
+    "write": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+      "dev": true,
+      "requires": {
+        "mkdirp": "^0.5.1"
+      }
+    },
+    "write-file-atomic": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+      "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "^0.1.4",
+        "is-typedarray": "^1.0.0",
+        "signal-exit": "^3.0.2",
+        "typedarray-to-buffer": "^3.1.5"
+      }
+    },
+    "xmlcreate": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz",
+      "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==",
+      "dev": true
+    },
+    "y18n": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+      "dev": true
+    },
+    "yallist": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+      "dev": true
+    },
+    "yaml": {
+      "version": "1.10.0",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz",
+      "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==",
+      "dev": true
+    },
+    "yapool": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/yapool/-/yapool-1.0.0.tgz",
+      "integrity": "sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o=",
+      "dev": true
+    },
+    "yargs": {
+      "version": "13.3.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
+      "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
+      "dev": true,
+      "requires": {
+        "cliui": "^5.0.0",
+        "find-up": "^3.0.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^3.0.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^13.1.2"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
+        },
+        "cliui": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+          "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+          "dev": true,
+          "requires": {
+            "string-width": "^3.1.0",
+            "strip-ansi": "^5.2.0",
+            "wrap-ansi": "^5.1.0"
+          }
+        },
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        },
+        "wrap-ansi": {
+          "version": "5.1.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+          "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^3.2.0",
+            "string-width": "^3.0.0",
+            "strip-ansi": "^5.0.0"
+          }
+        }
+      }
+    },
+    "yargs-parser": {
+      "version": "13.1.2",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
+      "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
+      "dev": true,
+      "requires": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      }
+    },
+    "yn": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+      "dev": true
+    }
+  }
+}
index 6f7b73dce9090c601b63fbf3a0d136fc69b3e31b..24baddbb5d61203a85ae4c6c1c38437fd2fd0669 100644 (file)
@@ -1,29 +1,26 @@
 {
   "name": "cologne",
   "description": "Logger + multiplexer for JSON based logs",
-  "author": {
-    "name": "Ben Beltran",
-    "email": "ben@nsovocal.com",
-    "url": "http://unlimited.pizza"
-  },
+  "author": "Rubén Beltrán del Río <ruben@unlimited.pizza>",
   "repository": {
     "type": "git",
-    "url": "https://github.com/rbdr/cologne.git"
+    "url": "git+ssh://git@gitlab.com/rbdr/cologne.git"
   },
-  "version": "1.1.0",
-  "dependencies": {
-    "microtime": "2.0.x"
+  "bugs": {
+    "url": "https://gitlab.com/rbdr/cologne/issues"
   },
+  "version": "2.0.0-build1",
   "devDependencies": {
-    "tap": "5.1.x",
-    "jsdoc-augmented-template": "rbdr/jsdoc-augmented-template"
-  },
-  "engines": {
-    "node": ">= 4.0.0"
+    "@hapi/eslint-config-hapi": "^13.0.2",
+    "@hapi/eslint-plugin-hapi": "^4.3.6",
+    "eslint": "^7.9.0",
+    "tap": "^14.10.8",
+    "jsdoc-to-markdown": "^6.0.1"
   },
   "scripts": {
-    "test": "node_modules/tap/bin/run.js test/*.js test/**/*.js test/**/**/*.js",
-    "document": "jsdoc -c ./config/jsdoc.json lib"
+    "document": "jsdoc2md lib/**/*.js > doc/README.md; tap -R markdown > doc/COVERAGE.md",
+    "lint": "eslint .",
+    "test": "tap"
   },
   "main": "./lib/cologne.js"
 }
index f5a6c6e813875b467156632b35f064e8cfeade51..3f06763209a6a7e2877b11a8593d7147b73ea132 100644 (file)
 'use strict';
 
-let tap = require('tap');
+const Tap = require('tap');
 
-let Cologne = require('../lib/cologne');
+const { Cologne } = require('..');
 
-let dummyLogger = {
-  values : null,
-  log : function () {
-    let logObject;
+// Utility Functions
 
-    this.values = [];
+const createDummyLogger = function () {
 
-    for (logObject of arguments) {
-      this.values.push(logObject);
+  return {
+    values: null,
+    log(...logs) {
+
+      this.values = [];
+
+      for (const log of logs) {
+        this.values.push(log);
+      }
     }
-  }
+  };
+};
+
+const levelChecker = function (level) {
+
+  return (count, log) => (log._level === level ? ++count : count);
 };
 
+
 // Prepare the test
-let dummyLoggerA, dummyLoggerB, dummyLoggerC,
-  co, params, builtLog, meta,
-  valueCheck, levelCheck;
 
-tap.plan(18);
+Tap.plan(19);
 
-dummyLoggerA = Object.assign({}, dummyLogger);
-dummyLoggerB = Object.assign({}, dummyLogger);
-dummyLoggerC = Object.assign({}, dummyLogger);
+const dummyLoggerA = createDummyLogger();
+const dummyLoggerB = createDummyLogger();
+const dummyLoggerC = createDummyLogger();
 
-co = new Cologne({
-  loggers : [
+const co = new Cologne({
+  loggers: [
     dummyLoggerA,
     dummyLoggerB
   ]
 });
 
-meta = {
-  rainbows: true
-};
-
-params = ['example1', null, undefined, 1, {example: true}];
+const logs = ['example1', null, undefined, 1, { example: true }];
 
 /**
  * TEST: #log()
  */
-co.log.apply(co, params);
+co.log(...logs);
 
 // Calculate values
-valueCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (typeof current._cologneLog === 'string') {
-    previous++;
-  }
-  return previous;
-}, 0);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 6) {
-    previous++;
-  }
-  return previous;
-}, 0);
+const valueCheck = dummyLoggerA.values.reduce((count, log) => (typeof log._cologneLog === 'string' ? ++count : count), 0);
+let levelCheck = dummyLoggerA.values.reduce(levelChecker(6), 0);
 
 // Now check the values
 
-tap.equal(dummyLoggerA.values.length, params.length,
-          '#log() should send every argument to the loggers');
+Tap.equal(dummyLoggerA.values.length, logs.length,
+  '#log() should send every argument to the loggers');
 
-tap.similar(dummyLoggerA.values, dummyLoggerB.values,
-            '#log() should send the same arguments to all the loggers');
+Tap.similar(dummyLoggerA.values, dummyLoggerB.values,
+  '#log() should send the same arguments to all the loggers');
 
-tap.equal(valueCheck, params.length,
-          '#log() should send all objects in cologne log format');
+Tap.equal(valueCheck, logs.length,
+  '#log() should send all objects in cologne log format');
 
-tap.equal(levelCheck, params.length,
-          '#log() should default to level 6');
+Tap.equal(levelCheck, logs.length,
+  '#log() should default to level 6');
 
 /**
  * TEST: #debug()
  */
-co.debug.apply(co, params);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 7) {
-    previous++;
-  }
-  return previous;
-}, 0);
+co.debug(...logs);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(7), 0);
 
-tap.equal(levelCheck, params.length,
-          '#debug() should set to level 7');
+Tap.equal(levelCheck, logs.length,
+  '#debug() should set to level 7');
 
 /**
  * TEST: #info()
  */
-co.info.apply(co, params);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 6) {
-    previous++;
-  }
-  return previous;
-}, 0);
+co.info(...logs);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(6), 0);
 
-tap.equal(levelCheck, params.length,
-          '#info() should set to level 6');
+Tap.equal(levelCheck, logs.length,
+  '#info() should set to level 6');
 
 /**
  * TEST: #notice()
  */
-co.notice.apply(co, params);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 5) {
-    previous++;
-  }
-  return previous;
-}, 0);
+co.notice(...logs);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(5), 0);
 
-tap.equal(levelCheck, params.length,
-          '#notice() should set to level 5');
+Tap.equal(levelCheck, logs.length,
+  '#notice() should set to level 5');
 
 /**
  * TEST: #warn()
  */
-co.warn.apply(co, params);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 4) {
-    previous++;
-  }
-  return previous;
-}, 0);
+co.warn(...logs);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(4), 0);
 
-tap.equal(levelCheck, params.length,
-          '#warn() should set to level 4');
+Tap.equal(levelCheck, logs.length,
+  '#warn() should set to level 4');
 
 /**
  * TEST: #error()
  */
-co.error.apply(co, params);
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 3) {
-    previous++;
-  }
-  return previous;
-}, 0);
+co.error(...logs);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(3), 0);
 
-tap.equal(levelCheck, params.length,
-          '#error() should set to level 3');
+Tap.equal(levelCheck, logs.length,
+  '#error() should set to level 3');
 
 /**
  * TEST: #buildLog()
  */
-builtLog = co.buildLog('example');
+let builtLog = co.buildLog('example');
 
 // With the default level
-tap.equal(typeof builtLog._cologneLog, 'string',
-          '#buildLog() should return a cologne log');
-tap.equal(builtLog._level, 6,
-          '#buildLog() should default to level 6');
+Tap.equal(typeof builtLog._cologneLog, 'string',
+  '#buildLog() should return a cologne log');
+Tap.equal(builtLog._level, 6,
+  '#buildLog() should default to level 6');
 
 // Now with a specific value
 builtLog = co.buildLog('example', 1);
 
-tap.equal(builtLog._level, 1,
-          '#buildLog() should use the specified level');
+Tap.equal(builtLog._level, 1,
+  '#buildLog() should use the specified level');
 
-// Now with meta
-builtLog = co.buildLog('example', 1, meta);
+// Extending object properties
+builtLog = co.buildLog({ message: 'example', rainbows: true }, 1);
 
-tap.equal(builtLog.rainbows, true,
-          '#buildLog() should extend the object with meta if available');
+Tap.equal(builtLog.message, 'example',
+  '#buildLog() should use the message property as the message if available');
+Tap.equal(builtLog.rainbows, true,
+  '#buildLog() should extend the object with its properties');
 
 /**
  * TEST: #log() with builtLog.
  */
 co.log(builtLog);
 
-levelCheck = dummyLoggerA.values.reduce(function (previous, current) {
-  if (current._level === 1) {
-    previous++;
-  }
-  return previous;
-}, 0);
+levelCheck = dummyLoggerA.values.reduce(levelChecker(1), 0);
 
-tap.equal(levelCheck, 1,
-          '#log() calls using a pre-built cologne log should maintain the log level');
+Tap.equal(levelCheck, 1,
+  '#log() calls using a pre-built cologne log should maintain the log level');
 
 
 /**
@@ -188,25 +153,25 @@ tap.equal(levelCheck, 1,
  */
 co.removeLogger(dummyLoggerC);
 
-tap.equal(co.loggers.length, 2,
-          '#removeLogger() should do nothing if it can\'t find a logger');
+Tap.equal(co.loggers.length, 2,
+  '#removeLogger() should do nothing if it can\'t find a logger');
 
-co.log.apply(co, params);
+co.log(...logs);
 co.removeLogger(dummyLoggerB);
 co.log(1);
 
-tap.equal(co.loggers.length, 1,
-          '#removeLogger() should remove a logger');
+Tap.equal(co.loggers.length, 1,
+  '#removeLogger() should remove a logger');
 
-tap.notEqual(dummyLoggerB.values.length, dummyLoggerA.values.length,
-            '#removeLogger() should no longer affect removed logs');
+Tap.notEqual(dummyLoggerB.values.length, dummyLoggerA.values.length,
+  '#removeLogger() should no longer affect removed logs');
 
 /**
  * TEST: #addLogger()
  */
 
 co.addLogger(dummyLoggerC);
-co.log.apply(co, params);
+co.log(...logs);
 
-tap.equal(dummyLoggerC.values.length, params.length,
-            '#addLogger() should add loggers after instance is live');
+Tap.equal(dummyLoggerC.values.length, logs.length,
+  '#addLogger() should add loggers after instance is live');
diff --git a/test/cologne/formatter/simple.js b/test/cologne/formatter/simple.js
deleted file mode 100644 (file)
index 8642541..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-'use strict';
-
-let tap = require('tap');
-
-let SimpleFormatter = require('../../../lib/cologne/formatter/simple');
-
-// Prepare the test
-let logObject, colorFormatter, plainFormatter, formattedString, isoDate;
-
-tap.plan(12);
-
-logObject = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 3,
-  _levelString: 'error',
-  message: 'testing stuff!'
-};
-isoDate = (new Date(logObject._timestamp)).toISOString();
-
-plainFormatter = new SimpleFormatter();
-colorFormatter = new SimpleFormatter({
-  colorize: true
-});
-
-/**
- * TEST: #format() - plain
- */
-
-formattedString = plainFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in plain mode');
-
-tap.ok(formattedString.match(logObject._from),
-         '#format() should include the from property in plain mode');
-
-tap.ok(formattedString.match(isoDate),
-         '#format() should include the timestamp property in iso format in plain mode');
-
-tap.ok(formattedString.match(logObject._levelString),
-         '#format() should include the level string property in plain mode');
-
-tap.ok(formattedString.match(logObject.message),
-         '#format() should include the message property in plain mode');
-
-/**
- * TEST: #format() - colorized
- */
-
-formattedString = colorFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in color mode');
-
-tap.ok(formattedString.match(logObject._from),
-         '#format() should include the from property in color mode');
-
-tap.ok(formattedString.match(isoDate),
-         '#format() should include the timestamp property in iso format in color mode');
-
-tap.ok(formattedString.match(logObject._levelString),
-         '#format() should include the level string property in color mode');
-
-tap.ok(formattedString.match(logObject.message),
-         '#format() should include the message property in color mode');
-
-tap.equal(formattedString.split(String.fromCharCode(27) + '[31m').length, 2,
-         '#format() should colorize the string');
-
-tap.equal(formattedString.split(String.fromCharCode(27) + '[0m').length, 2,
-         '#format() should colorize only a bit of the string');
diff --git a/test/cologne/formatter/token.js b/test/cologne/formatter/token.js
deleted file mode 100644 (file)
index 9bc473d..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-'use strict';
-
-let tap = require('tap');
-
-let TokenFormatter = require('../../../lib/cologne/formatter/token');
-
-// Prepare the test
-let logObject, defaultFormatter, customFormatter, ansiFormatter,
-  plainDateFormatter, customSearchFormatter, formattedString, isoDate;
-
-tap.plan(13);
-
-logObject = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 3,
-  _levelString: 'error',
-  message: 'testing stuff!'
-};
-isoDate = (new Date(logObject._timestamp)).toISOString();
-
-defaultFormatter = new TokenFormatter();
-customFormatter = new TokenFormatter({
-  formatString: '{{_level}} {{_cologneLog}} {{_timestamp}}'
-});
-ansiFormatter = new TokenFormatter({
-  formatString: 'string {{_ansi:red}}with color:{{_ansi:reset}} {{message}}'
-});
-plainDateFormatter = new TokenFormatter({
-  isoDate: false,
-  formatString: '{{_timestamp}}'
-});
-customSearchFormatter = new TokenFormatter({
-  formatString: '[[message]]',
-  replaceRule: /\[\[(.*?)\]\]/g
-});
-
-/**
- * TEST: #format() - default
- */
-
-formattedString = defaultFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in default mode');
-
-tap.equal(formattedString, logObject.message,
-         '#format() should include the message in default mode');
-
-/**
- * TEST: #format() - custom
- */
-
-formattedString = customFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in custom mode');
-
-tap.ok(formattedString.match(logObject._level),
-         '#format() with custom string should include the specified tokens (check 1)');
-
-tap.ok(formattedString.match(logObject._cologneLog),
-         '#format() with custom string should include the specified tokens (check 2)');
-
-tap.ok(formattedString.match(isoDate),
-         '#format() with iso date should include the timestamp as an iso date');
-
-/**
- * TEST: #format() - ansi
- */
-
-formattedString = ansiFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in ansi mode');
-
-tap.equal(formattedString.split(String.fromCharCode(27) + '[31m').length, 2,
-         '#format() with ansi tokens should colorize the string');
-
-tap.equal(formattedString.split(String.fromCharCode(27) + '[0m').length, 2,
-         '#format() with ansi reset should reset the string');
-
-
-/**
- * TEST: #format() - plain date
- */
-
-formattedString = plainDateFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in plain date mode');
-
-tap.equal(formattedString, logObject._timestamp.toString(),
-         '#format() with plain date should include the timestamp as-is');
-
-/**
- * TEST: #format() - custom search
- */
-
-formattedString = customSearchFormatter.format(logObject);
-
-tap.equal(typeof formattedString, 'string',
-         '#format() should output a string in custom search mode');
-
-tap.equal(formattedString, logObject.message,
-         '#format() with a custom search, should properly match the new tokens');
diff --git a/test/cologne/log_utilities.js b/test/cologne/log_utilities.js
deleted file mode 100644 (file)
index e372683..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-'use strict';
-
-let tap = require('tap');
-
-let LogUtilities = require('../../lib/cologne/log_utilities');
-
-// Prepare the test
-let t1, t2, preciseTime, regularObject, circularObject,
-  regularStringify, cologneStringify, circularStringify;
-
-tap.plan(7);
-
-regularObject = {
-  a: 1,
-  b: {
-    c: 'true',
-    d: false
-  }
-};
-
-circularObject = {
-  a: 1,
-  b: {
-    c: 'true',
-    d: false
-  }
-};
-circularObject.b.circular = circularObject;
-
-/**
- * TEST: ::now()
- */
-t1 = Date.now();
-preciseTime = LogUtilities.now();
-t2 = Date.now();
-
-// This test is sloppy :(
-tap.ok(Math.abs(t1 - preciseTime) < 1,
-       '::now() should give a precise timestamp (before)');
-tap.ok(Math.abs(t2 - preciseTime) < 1,
-       '::now() should give a precise timestamp (after)');
-
-/**
- * TEST: ::stringify()
- */
-
-regularStringify = JSON.stringify(regularObject);
-cologneStringify = LogUtilities.stringify(regularObject);
-circularStringify = LogUtilities.stringify(circularObject);
-
-tap.equal(regularStringify, cologneStringify,
-         '::stringify() should behave like JSON.stringify for non-circular objects');
-tap.equal(typeof JSON.parse(circularStringify).b.circular, 'string',
-         '::stringify() should replace circular references with a string');
-
-/**
- * TEST: ::getAnsiCode()
- */
-
-// NOTE: This isn't even trying to be a complete test... Just testing
-// that we get other than reset if valid, and the same as reset for all
-// invalid ones. knowing that reset is [0m
-
-tap.equal(LogUtilities.getAnsiCode('reset'), '[0m',
-          '::getAnsiCode is sending the correct reset code');
-tap.equal(LogUtilities.getAnsiCode('someRandomString'), LogUtilities.getAnsiCode('reset'),
-          '::getAnsiCode() should give us a reset code if something weird is sent');
-tap.notEqual(LogUtilities.getAnsiCode('red'), LogUtilities.getAnsiCode('reset'),
-          '::getAnsiCode() should give us a non-reset code if it\'s something real');
diff --git a/test/cologne/logger/console.js b/test/cologne/logger/console.js
deleted file mode 100644 (file)
index ffc1876..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-'use strict';
-
-let tap = require('tap');
-
-let ConsoleLogger = require('../../../lib/cologne/logger/console');
-
-// Prepare the test
-let dummyFormatter, dummyConsole, logObjectA, logObjectB, regularLogger,
-  overrideLogger, formattedLogger, params;
-
-dummyFormatter = {
-  values: [],
-  format: function (logObject) {
-    this.values.push(logObject);
-    return 'lol';
-  }
-};
-
-dummyConsole = {
-  values: {},
-  _log: function (type, args) {
-    this.values[type] = args;
-  },
-  log: function() {
-    this._log('log', Array.prototype.splice.call(arguments, [0]));
-  },
-  warn: function() {
-    this._log('warn', Array.prototype.splice.call(arguments, [0]));
-  },
-  error: function() {
-    this._log('error', Array.prototype.splice.call(arguments, [0]));
-  },
-  info: function() {
-    this._log('info', Array.prototype.splice.call(arguments, [0]));
-  }
-};
-
-logObjectA = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 6,
-  _levelString: 'info',
-  message: 'MessageOne'
-};
-
-logObjectB = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 6,
-  _levelString: 'info',
-  message: 'MessageTwo'
-};
-
-params = [logObjectA, logObjectB];
-
-regularLogger = new ConsoleLogger({});
-overrideLogger = new ConsoleLogger({
-  console: dummyConsole
-});
-formattedLogger = new ConsoleLogger({
-  console: dummyConsole,
-  formatter: dummyFormatter
-});
-
-/**
- * TEST: #log() - regular
- */
-
-tap.equal(regularLogger.console, global.console,
-          'It should default to the global console');
-
-/**
- * TEST: #log() - override
- */
-
-logObjectA._level = 5;
-logObjectB._level = 6;
-overrideLogger.log.apply(overrideLogger, params); // should go to info
-
-logObjectA._level = 4;
-logObjectB._level = 4;
-overrideLogger.log.apply(overrideLogger, params); // should go to warn
-
-logObjectA._level = 1;
-logObjectB._level = 3;
-overrideLogger.log.apply(overrideLogger, params); // should go to error
-
-logObjectA._level = 7;
-logObjectB._level = 7;
-overrideLogger.log.apply(overrideLogger, params); // should go to log
-
-tap.equal(dummyConsole.values.log.length, params.length,
-         'It should send debug messages to console\'s #log');
-tap.equal(dummyConsole.values.info.length, params.length,
-         'It should send info and notice messages to console\'s #info');
-tap.equal(dummyConsole.values.warn.length, params.length,
-         'It should send warn messages to console\'s #warn');
-tap.equal(dummyConsole.values.error.length, params.length,
-         'It should send error messages to console\'s #error');
-
-/**
- * TEST: #log() - with formatter
- */
-
-formattedLogger.log.apply(formattedLogger, params); // should go to log
-
-tap.similar(dummyFormatter.values, params,
-         'If available, it should send the objects to the formatter');
diff --git a/test/cologne/logger/file.js b/test/cologne/logger/file.js
deleted file mode 100644 (file)
index 01be09f..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-'use strict';
-
-let fs = require('fs');
-
-let tap = require('tap');
-
-let FileLogger = require('../../../lib/cologne/logger/file');
-
-// Prepare the test
-let logObjectA, logObjectB, rawFile, formatterFile, rawLogger, formatterLogger,
-  params, dummyFormatter, formatterString;
-
-rawFile = './raw.log';
-formatterFile = './formatter.log';
-formatterString = 'example';
-
-logObjectA = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 6,
-  _levelString: 'info',
-  message: 'MessageOne'
-};
-
-logObjectB = {
-  _timestamp: Date.now() + .134,
-  _cologneLog: '1.0.0',
-  _from: 'Dummy Logger',
-  _level: 6,
-  _levelString: 'info',
-  message: 'MessageTwo'
-};
-
-params = [logObjectA, logObjectB];
-
-
-dummyFormatter = {
-  values: [],
-  format: function (logObject) {
-    this.values.push(logObject);
-    return formatterString;
-  }
-};
-
-rawLogger = new FileLogger({
-  file: rawFile
-});
-formatterLogger = new FileLogger({
-  file: formatterFile,
-  formatter: dummyFormatter
-});
-
-/**
- * TEST: #log() - regular
- */
-
-rawLogger.log.apply(rawLogger, params);
-
-setTimeout(function () {
-  tap.test('raw file', function (t) {
-    fs.readFile(rawFile, {encoding: 'utf8'}, function (error, contents) {
-      let lines;
-
-      lines = contents.trim().split('\n');
-
-      tap.equal(lines.length, params.length,
-               'it should send all params to the file');
-
-      tap.equal(JSON.stringify(logObjectA), lines[0],
-               'it should log the raw json object');
-
-      fs.unlink(rawFile, function () {
-        t.end();
-      });
-    });
-  });
-}, 10); // allow for flush
-/**
- * TEST: #log() - formatter
- */
-
-formatterLogger.log.apply(formatterLogger, params);
-
-setTimeout(function () {
-  tap.test('formatted file', function (t) {
-    fs.readFile(formatterFile, {encoding: 'utf8'}, function (error, contents) {
-      let lines;
-
-      lines = contents.trim().split('\n');
-
-      tap.equal(lines.length, params.length,
-               'it should send all params to the file');
-
-      tap.equal(formatterString, lines[0],
-               'it should log the formatted object');
-
-      fs.unlink(formatterFile, function () {
-        t.end();
-      });
-    });
-  });
-}, 10);
diff --git a/test/formatters/simple.js b/test/formatters/simple.js
new file mode 100644 (file)
index 0000000..5829045
--- /dev/null
@@ -0,0 +1,72 @@
+'use strict';
+
+const Tap = require('tap');
+
+const SimpleFormatter = require('../../lib/formatters/simple');
+
+// Prepare the test
+
+Tap.plan(12);
+
+const logObject = {
+  _timestamp: BigInt(Date.now()) * 1000000n,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 3,
+  _levelString: 'error',
+  message: 'testing stuff!'
+};
+const isoDate = (new Date(Number(logObject._timestamp) / 1000000)).toISOString();
+
+const plainFormatter = new SimpleFormatter();
+const colorFormatter = new SimpleFormatter({
+  colorize: true
+});
+
+/**
+ * TEST: #format() - plain
+ */
+
+const plainFormattedString = plainFormatter.format(logObject);
+
+Tap.equal(typeof plainFormattedString, 'string',
+  '#format() should output a string in plain mode');
+
+Tap.ok(plainFormattedString.match(logObject._from),
+  '#format() should include the from property in plain mode');
+
+Tap.ok(plainFormattedString.match(isoDate),
+  '#format() should include the timestamp property in iso format in plain mode');
+
+Tap.ok(plainFormattedString.match(logObject._levelString),
+  '#format() should include the level string property in plain mode');
+
+Tap.ok(plainFormattedString.match(logObject.message),
+  '#format() should include the message property in plain mode');
+
+/**
+ * TEST: #format() - colorized
+ */
+
+const colorFormattedString = colorFormatter.format(logObject);
+
+Tap.equal(typeof colorFormattedString, 'string',
+  '#format() should output a string in color mode');
+
+Tap.ok(colorFormattedString.match(logObject._from),
+  '#format() should include the from property in color mode');
+
+Tap.ok(colorFormattedString.match(isoDate),
+  '#format() should include the timestamp property in iso format in color mode');
+
+Tap.ok(colorFormattedString.match(logObject._levelString),
+  '#format() should include the level string property in color mode');
+
+Tap.ok(colorFormattedString.match(logObject.message),
+  '#format() should include the message property in color mode');
+
+Tap.equal(colorFormattedString.split(String.fromCharCode(27) + '[31m').length, 2,
+  '#format() should colorize the string');
+
+Tap.equal(colorFormattedString.split(String.fromCharCode(27) + '[0m').length, 2,
+  '#format() should colorize only a bit of the string');
diff --git a/test/formatters/token.js b/test/formatters/token.js
new file mode 100644 (file)
index 0000000..e9baefd
--- /dev/null
@@ -0,0 +1,121 @@
+'use strict';
+
+const Tap = require('tap');
+
+const TokenFormatter = require('../../lib/formatters/token');
+
+// Prepare the test
+
+Tap.plan(15);
+
+const logObject = {
+  _timestamp: BigInt(Date.now()) * 1000000n,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 6,
+  _levelString: 'error',
+  message: 'testing stuff!'
+};
+const isoDate = (new Date(Number(logObject._timestamp) / 1000000)).toISOString();
+
+const defaultFormatter = new TokenFormatter();
+const customFormatter = new TokenFormatter({
+  formatString: '{{_level}} {{_cologneLog}} {{_timestamp}} {{_magic}}'
+});
+const ansiFormatter = new TokenFormatter({
+  formatString: 'string {{_ansi:red}}with color:{{_ansi:reset}} {{message}}'
+});
+const ansiLevelFormatter = new TokenFormatter({
+  formatString: 'string {{_ansi:_level}}with color:{{_ansi:reset}} {{message}}'
+});
+const plainDateFormatter = new TokenFormatter({
+  isoDate: false,
+  formatString: '{{_timestamp}}'
+});
+const customSearchFormatter = new TokenFormatter({
+  formatString: '[[message]]',
+  replaceRule: /\[\[(.*?)\]\]/g
+});
+
+/**
+ * TEST: #format() - default
+ */
+
+const defaultFormattedString = defaultFormatter.format(logObject);
+
+Tap.equal(typeof defaultFormattedString, 'string',
+  '#format() should output a string in default mode');
+
+Tap.equal(defaultFormattedString, logObject.message,
+  '#format() should include the message in default mode');
+
+/**
+ * TEST: #format() - custom
+ */
+
+const customFormattedString = customFormatter.format(logObject);
+
+Tap.equal(typeof customFormattedString, 'string',
+  '#format() should output a string in custom mode');
+
+Tap.ok(customFormattedString.match(logObject._level),
+  '#format() with custom string should include the specified tokens (check 1)');
+
+Tap.ok(customFormattedString.match(logObject._cologneLog),
+  '#format() with custom string should include the specified tokens (check 2)');
+
+Tap.ok(customFormattedString.match(isoDate),
+  '#format() with iso date should include the timestamp as an iso date');
+
+Tap.ok(customFormattedString.match('{{_magic}}'),
+  '#format() should not replace tokens that don\'t match');
+
+/**
+ * TEST: #format() - ansi
+ */
+
+const ansiFormattedString = ansiFormatter.format(logObject);
+
+Tap.equal(typeof ansiFormattedString, 'string',
+  '#format() should output a string in ansi mode');
+
+Tap.equal(ansiFormattedString.split(String.fromCharCode(27) + '[31m').length, 2,
+  '#format() with ansi tokens should colorize the string');
+
+Tap.equal(ansiFormattedString.split(String.fromCharCode(27) + '[0m').length, 2,
+  '#format() with ansi reset should reset the string');
+
+/**
+ * TEST: #format() - ansi based on level
+ */
+
+const ansiLevelFormattedString = ansiLevelFormatter.format(logObject);
+
+Tap.equal(ansiLevelFormattedString.split(String.fromCharCode(27) + '[34m').length, 2,
+  '#format() with ansi tokens should colorize the string based on level');
+
+
+
+/**
+ * TEST: #format() - plain date
+ */
+
+const plainDateFormattedString = plainDateFormatter.format(logObject);
+
+Tap.equal(typeof plainDateFormattedString, 'string',
+  '#format() should output a string in plain date mode');
+
+Tap.equal(plainDateFormattedString, logObject._timestamp.toString(),
+  '#format() with plain date should include the timestamp as-is');
+
+/**
+ * TEST: #format() - custom search
+ */
+
+const customSearchFormattedString = customSearchFormatter.format(logObject);
+
+Tap.equal(typeof customSearchFormattedString, 'string',
+  '#format() should output a string in custom search mode');
+
+Tap.equal(customSearchFormattedString, logObject.message,
+  '#format() with a custom search, should properly match the new tokens');
diff --git a/test/loggers/console.js b/test/loggers/console.js
new file mode 100644 (file)
index 0000000..3358837
--- /dev/null
@@ -0,0 +1,123 @@
+'use strict';
+
+const Tap = require('tap');
+
+const ConsoleLogger = require('../../lib/loggers/console');
+
+// Prepare the test
+
+const dummyFormatter = {
+  values: [],
+  format: function (log) {
+
+    this.values.push(log);
+    return 'lol';
+  }
+};
+
+const dummyConsole = {
+  values: {
+    log: 0,
+    warn: 0,
+    error: 0,
+    info: 0
+  },
+  _log: function (type, ...logs) {
+
+    this.values[type] += logs.length;
+  },
+  log: function (...logs) {
+
+    this._log('log', ...logs);
+  },
+  warn: function (...logs) {
+
+    this._log('warn', ...logs);
+  },
+  error: function (...logs) {
+
+    this._log('error', ...logs);
+  },
+  info: function (...logs) {
+
+    this._log('info', ...logs);
+  }
+};
+
+const logObjectA = {
+  _timestamp: Date.now() + .134,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 6,
+  _levelString: 'info',
+  message: 'MessageOne'
+};
+
+const logObjectB = {
+  _timestamp: Date.now() + .134,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 6,
+  _levelString: 'info',
+  message: 'MessageTwo'
+};
+
+const logs = [logObjectA, logObjectB];
+
+const regularLogger = new ConsoleLogger({});
+const overrideLogger = new ConsoleLogger({
+  console: dummyConsole
+});
+const formattedLogger = new ConsoleLogger({
+  console: dummyConsole,
+  formatter: dummyFormatter
+});
+
+/**
+ * TEST: #log() - regular
+ */
+
+Tap.equal(regularLogger.console, global.console,
+  'It should default to the global console');
+
+/**
+ * TEST: #log() - override
+ */
+
+logObjectA._level = 5;
+logObjectB._level = 6;
+overrideLogger.log(...logs); // should go to info
+
+logObjectA._level = 4;
+logObjectB._level = 4;
+overrideLogger.log(...logs); // should go to warn
+
+logObjectA._level = 1;
+logObjectB._level = 3;
+overrideLogger.log(...logs); // should go to error
+
+logObjectA._level = 0;
+logObjectB._level = 2;
+overrideLogger.log(...logs); // should go to error
+
+logObjectA._level = 7;
+logObjectB._level = 8;
+overrideLogger.log(...logs); // should go to log
+
+Tap.equal(dummyConsole.values.log, logs.length,
+  'It should send debug messages to console\'s #log');
+Tap.equal(dummyConsole.values.info, logs.length,
+  'It should send info and notice messages to console\'s #info');
+Tap.equal(dummyConsole.values.warn, logs.length,
+  'It should send warn messages to console\'s #warn');
+Tap.equal(dummyConsole.values.error, logs.length * 2,
+  'It should send error messages to console\'s #error');
+
+/**
+ * TEST: #log() - with formatter
+ */
+
+formattedLogger.log(...logs); // should go to log
+
+Tap.similar(dummyFormatter.values, logs,
+  'If available, it should send the objects to the formatter');
diff --git a/test/loggers/file.js b/test/loggers/file.js
new file mode 100644 (file)
index 0000000..5e73d82
--- /dev/null
@@ -0,0 +1,106 @@
+'use strict';
+
+const Fs = require('fs');
+
+const Tap = require('tap');
+
+const FileLogger = require('../../lib/loggers/file');
+
+// Prepare the test
+
+const rawFile = './raw.log';
+const formatterFile = './formatter.log';
+const formatterString = 'example';
+
+const logObjectA = {
+  _timestamp: Date.now() + .134,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 6,
+  _levelString: 'info',
+  message: 'MessageOne'
+};
+
+const logObjectB = {
+  _timestamp: Date.now() + .134,
+  _cologneLog: '1.0.0',
+  _from: 'Dummy Logger',
+  _level: 6,
+  _levelString: 'info',
+  message: 'MessageTwo'
+};
+
+const logs = [logObjectA, logObjectB];
+
+
+const dummyFormatter = {
+  values: [],
+  format: function (logObject) {
+
+    this.values.push(logObject);
+    return formatterString;
+  }
+};
+
+const rawLogger = new FileLogger({
+  file: rawFile
+});
+const formatterLogger = new FileLogger({
+  file: formatterFile,
+  formatter: dummyFormatter
+});
+
+/**
+ * TEST: #log() - regular
+ */
+
+rawLogger.log(...logs);
+
+setTimeout(() => {
+
+  Tap.test('raw file', (t) => {
+
+    Fs.readFile(rawFile, { encoding: 'utf8' }, (_, contents) => {
+
+      const lines = contents.trim().split('\n');
+
+      Tap.equal(lines.length, logs.length,
+        'it should send all params to the file');
+
+      Tap.equal(JSON.stringify(logObjectA), lines[0],
+        'it should log the raw json object');
+
+      Fs.unlink(rawFile, () => {
+
+        t.end();
+      });
+    });
+  });
+}, 10); // allow for flush
+/**
+ * TEST: #log() - formatter
+ */
+
+formatterLogger.log(...logs);
+
+setTimeout(() => {
+
+  Tap.test('formatted file', (t) => {
+
+    Fs.readFile(formatterFile, { encoding: 'utf8' }, (_, contents) => {
+
+      const lines = contents.trim().split('\n');
+
+      Tap.equal(lines.length, logs.length,
+        'it should send all params to the file');
+
+      Tap.equal(formatterString, lines[0],
+        'it should log the formatted object');
+
+      Fs.unlink(formatterFile, () => {
+
+        t.end();
+      });
+    });
+  });
+}, 10);
diff --git a/test/utilities.js b/test/utilities.js
new file mode 100644 (file)
index 0000000..2bff47f
--- /dev/null
@@ -0,0 +1,106 @@
+'use strict';
+
+const Tap = require('tap');
+
+const Utilities = require('../lib/utilities');
+
+// Prepare the test
+
+Tap.plan(17);
+
+/**
+ * TEST: ::now()
+ */
+const preciseTime = Utilities.now();
+
+// I don't think this test makes sense lol
+Tap.equal(typeof preciseTime, 'bigint',
+  '::now() should give a precise bigint timestamp');
+
+/**
+ * TEST: ::stringify()
+ */
+
+const regularObject = {
+  a: 1,
+  b: {
+    c: 'true',
+    d: false
+  }
+};
+
+const circularObject = {
+  a: 1,
+  b: {
+    c: 'true',
+    d: false
+  }
+};
+circularObject.b.circular = circularObject;
+
+const bigint = 666n;
+
+const regularStringify = JSON.stringify(regularObject);
+const cologneStringify = Utilities.stringify(regularObject);
+const circularStringify = Utilities.stringify(circularObject);
+const bigintStringify = Utilities.stringify(bigint);
+
+Tap.equal(regularStringify, cologneStringify,
+  '::stringify() should behave like JSON.stringify for non-circular objects');
+Tap.equal(typeof JSON.parse(circularStringify).b.circular, 'string',
+  '::stringify() should replace circular references with a string');
+Tap.equal(bigintStringify, '"666n"',
+  '::stringify() should convert bigint to string');
+
+/**
+ * TEST: ::getAnsiCode()
+ */
+
+// NOTE: This isn't even trying to be a complete test... Just testing
+// that we get distinct non-reset codes if valid, and the same as reset
+// for all invalid ones. knowing that reset is [0m
+
+Tap.equal(Utilities.getAnsiCode('reset'), '[0m',
+  '::getAnsiCode is sending the correct reset code');
+Tap.equal(Utilities.getAnsiCode('someRandomString'), Utilities.getAnsiCode('reset'),
+  '::getAnsiCode() should give us a reset code if something weird is sent');
+
+const supportedCodes = ['bold', 'italics', 'underline', 'inverse', 'strikethrough',
+  'bold_off', 'italics_off', 'underline_off', 'inverse_off', 'strikethrough_off',
+  'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default',
+  'black_bg', 'red_bg', 'green_bg', 'yellow_bg', 'blue_bg', 'magenta_bg',
+  'cyan_bg', 'white_bg', 'default_bg'];
+const resultingCodes = supportedCodes.map((code) => Utilities.getAnsiCode(code));
+const isThereReset = resultingCodes.some((code) => code === '[0m');
+
+Tap.equal((new Set(resultingCodes)).size, supportedCodes.length,
+  '::getAnsiCode() should not have duplicated non-reset codes');
+Tap.false(isThereReset,
+  '::getAnsiCode() should not return a reset code in any other supported code');
+
+/**
+ * TEST: ::getLevelAnsi()
+ */
+
+// NOTE: This isn't even trying to be a complete test... Just testing
+// that we get other than reset if valid, and the same as reset for all
+// invalid ones. knowing that reset is [0m
+
+Tap.equal(Utilities.getLevelAnsi(0), 'red',
+  '::gettLevelAnsi is red for emerg');
+Tap.equal(Utilities.getLevelAnsi(1), 'red',
+  '::gettLevelAnsi is red for alert');
+Tap.equal(Utilities.getLevelAnsi(2), 'red',
+  '::gettLevelAnsi is red for crit');
+Tap.equal(Utilities.getLevelAnsi(3), 'red',
+  '::gettLevelAnsi is red for error');
+Tap.equal(Utilities.getLevelAnsi(4), 'yellow',
+  '::gettLevelAnsi is yellow for warn');
+Tap.equal(Utilities.getLevelAnsi(5), 'blue',
+  '::gettLevelAnsi is blue for notice');
+Tap.equal(Utilities.getLevelAnsi(6), 'blue',
+  '::gettLevelAnsi is blue for info');
+Tap.equal(Utilities.getLevelAnsi(7), 'green',
+  '::gettLevelAnsi is green for debug');
+Tap.equal(Utilities.getLevelAnsi(8), 'default',
+  '::gettLevelAnsi is default for other values');