Skip to content
Snippets Groups Projects
index.js 6.97 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
    /******/ (function(modules) { // webpackBootstrap
    /******/ 	// The module cache
    /******/ 	var installedModules = {};
    /******/
    
    /******/ 	// object to store loaded chunks
    /******/ 	// "0" means "already loaded"
    /******/ 	var installedChunks = {
    /******/ 		0: 0
    /******/ 	};
    /******/
    
    Romain CREY's avatar
    Romain CREY committed
    /******/ 	// The require function
    /******/ 	function __webpack_require__(moduleId) {
    /******/
    /******/ 		// Check if module is in cache
    /******/ 		if(installedModules[moduleId]) {
    /******/ 			return installedModules[moduleId].exports;
    /******/ 		}
    /******/ 		// Create a new module (and put it into the cache)
    /******/ 		var module = installedModules[moduleId] = {
    /******/ 			i: moduleId,
    /******/ 			l: false,
    /******/ 			exports: {}
    /******/ 		};
    /******/
    /******/ 		// Execute the module function
    /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    /******/
    /******/ 		// Flag the module as loaded
    /******/ 		module.l = true;
    /******/
    /******/ 		// Return the exports of the module
    /******/ 		return module.exports;
    /******/ 	}
    /******/
    
    /******/ 	// This file contains only the entry chunk.
    /******/ 	// The chunk loading function for additional chunks
    /******/ 	__webpack_require__.e = function requireEnsure(chunkId) {
    /******/ 		var promises = [];
    /******/
    /******/
    /******/ 		// require() chunk loading for javascript
    /******/
    /******/ 		// "0" is the signal for "already loaded"
    /******/ 		if(installedChunks[chunkId] !== 0) {
    /******/ 			var chunk = require("./" + chunkId + ".index.js");
    /******/ 			var moreModules = chunk.modules, chunkIds = chunk.ids;
    /******/ 			for(var moduleId in moreModules) {
    /******/ 				modules[moduleId] = moreModules[moduleId];
    /******/ 			}
    /******/ 			for(var i = 0; i < chunkIds.length; i++)
    /******/ 				installedChunks[chunkIds[i]] = 0;
    /******/ 		}
    /******/ 		return Promise.all(promises);
    /******/ 	};
    
    Romain CREY's avatar
    Romain CREY committed
    /******/
    /******/ 	// expose the modules object (__webpack_modules__)
    /******/ 	__webpack_require__.m = modules;
    /******/
    /******/ 	// expose the module cache
    /******/ 	__webpack_require__.c = installedModules;
    /******/
    /******/ 	// define getter function for harmony exports
    /******/ 	__webpack_require__.d = function(exports, name, getter) {
    /******/ 		if(!__webpack_require__.o(exports, name)) {
    /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
    /******/ 		}
    /******/ 	};
    /******/
    /******/ 	// define __esModule on exports
    /******/ 	__webpack_require__.r = function(exports) {
    /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
    /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    /******/ 		}
    /******/ 		Object.defineProperty(exports, '__esModule', { value: true });
    /******/ 	};
    /******/
    /******/ 	// create a fake namespace object
    /******/ 	// mode & 1: value is a module id, require it
    /******/ 	// mode & 2: merge all properties of value into the ns
    /******/ 	// mode & 4: return value when already ns object
    /******/ 	// mode & 8|1: behave like require
    /******/ 	__webpack_require__.t = function(value, mode) {
    /******/ 		if(mode & 1) value = __webpack_require__(value);
    /******/ 		if(mode & 8) return value;
    /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
    /******/ 		var ns = Object.create(null);
    /******/ 		__webpack_require__.r(ns);
    /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
    /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
    /******/ 		return ns;
    /******/ 	};
    /******/
    /******/ 	// getDefaultExport function for compatibility with non-harmony modules
    /******/ 	__webpack_require__.n = function(module) {
    /******/ 		var getter = module && module.__esModule ?
    /******/ 			function getDefault() { return module['default']; } :
    /******/ 			function getModuleExports() { return module; };
    /******/ 		__webpack_require__.d(getter, 'a', getter);
    /******/ 		return getter;
    /******/ 	};
    /******/
    /******/ 	// Object.prototype.hasOwnProperty.call
    /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
    /******/
    /******/ 	// __webpack_public_path__
    /******/ 	__webpack_require__.p = "";
    /******/
    
    /******/ 	// uncaught error handler for webpack runtime
    /******/ 	__webpack_require__.oe = function(err) {
    /******/ 		process.nextTick(function() {
    /******/ 			throw err; // catch this error by using import().catch()
    /******/ 		});
    /******/ 	};
    /******/
    
    Romain CREY's avatar
    Romain CREY committed
    /******/
    /******/ 	// Load entry module and return exports
    /******/ 	return __webpack_require__(__webpack_require__.s = 0);
    /******/ })
    /************************************************************************/
    /******/ ([
    /* 0 */
    /***/ (function(module, exports, __webpack_require__) {
    
    const {
      BaseKonnector,
      log,
      errors,
      addData,
      hydrateAndFilter,
      cozyClient
    
    } = __webpack_require__(1);
    const rp = __webpack_require__(22);
    const moment = __webpack_require__(1045);
    __webpack_require__(1174);
    
    moment.locale("fr"); // set the language
    moment.tz.setDefault("Europe/Paris"); // set the timezone
    
    const startDate = moment()
      .startOf("year")
      // .subtract(3, "year")
      .subtract(6, "month")
      .subtract(1, "day")
      .format("MM/DD/YYYY");
    const endDate = moment().format("MM/DD/YYYY");
    const timeRange = ["day", "month", "year"];
    
    const rangeDate = {
      day: {
    
        doctype: "com.grandlyon.egl.day",
        keys: ["year", "month", "day"]
    
        doctype: "com.grandlyon.egl.month",
        keys: ["year", "month"]
    
        doctype: "com.grandlyon.egl.year",
        keys: ["year"]
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    module.exports = new BaseKonnector(start);
    
    Romain CREY's avatar
    Romain CREY committed
    
    // The start function is run by the BaseKonnector instance only when it got all the account
    // information (fields). When you run this connector yourself in "standalone" mode or "dev" mode,
    // the account information come from ./konnector-dev-config.json file
    async function start(fields, cozyParameters) {
      try {
        // resetting data for demo only
        // await resetData()
    
        const baseUrl = cozyParameters.secret.eglBaseURL;
        const apiAuthKey = cozyParameters.secret.eglAPIAuthKey;
        log("info", "Authenticating ...");
    
    Romain CREY's avatar
    Romain CREY committed
        const response = await authenticate(
          fields.login,
          fields.password,
          baseUrl,
          apiAuthKey
    
        );
        log("info", "Successfully logged in");
        Promise.all(
          timeRange.map(timeStep =>
            processData(timeStep, response, baseUrl, apiAuthKey)
    
    Romain CREY's avatar
    Romain CREY committed
      } catch (error) {
    
        throw new Error(error.message);
      }
    }
    async function processData(timeStep, response, baseUrl, apiAuthKey) {
      const doctype = rangeDate[timeStep].doctype;
      log("info", "Getting data TIMESTEP : " + timeStep);
      const loadProfile = await getData(response, baseUrl, apiAuthKey);
      log("info", "Saving data to Cozy");
      log("info", "Response length : " + loadProfile.length);
      if (doctype === rangeDate.day.doctype) {
        await storeData(loadProfile, rangeDate.day.doctype, rangeDate.day.keys);
      } else if (doctype === rangeDate.month.doctype) {
        await resetInProgressAggregatedData(rangeDate.month.doctype);
        const monthlyData = processMonthlyAggregation(loadProfile, rangeDate.month);
        log("info", "Saving monthly data");
        await storeData(monthlyData, rangeDate.month.doctype, rangeDate.month.keys);
      } else if (doctype === rangeDate.year.doctype) {
        await resetInProgressAggregatedData(rangeDate.year.doctype);
        const yearlyData = processYearAggregation(
          loadProfile,
          rangeDate.year.doctype
        );
        log("info", "Saving yearly data");
        await storeData(yearlyData, rangeDate.year.doctype, rangeDate.year.keys);
      } else {
        throw new Error("Unkonw range type: " + doctype);
    
    Romain CREY's avatar
    Romain CREY committed
      }
    }
    
    Romain CREY's avatar
    Romain CREY committed
    async function authenticate(login, password, baseUrl, apiAuthKey) {
      const authRequest = {
    
        method: "POST",
        uri: baseUrl + "/connect.aspx",
    
    Romain CREY's avatar
    Romain CREY committed
        headers: {
          AuthKey: apiAuthKey,
    
          "Content-Type": "application/x-www-form-urlencoded"
    
    Romain CREY's avatar
    Romain CREY committed
        },
        form: {
          login: login,
          pass: password
        },
        json: true
    
      };
      const response = await rp(authRequest);
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      if (response.codeRetour === 100) {
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      } else {
    
        throw new Error(errors.LOGIN_FAILED);
    
    Romain CREY's avatar
    Romain CREY committed
      }
    }
    
    async function getData(response, baseUrl, apiAuthKey) {
    
      log("debug", "Start date : " + startDate);
      log("debug", "End date : " + endDate);
    
    Romain CREY's avatar
    Romain CREY committed
      const dataRequest = {
    
        method: "POST",
        uri: baseUrl + "/getAllAgregatsByAbonnement.aspx",
    
    Romain CREY's avatar
    Romain CREY committed
        headers: {
          AuthKey: apiAuthKey,
    
          "Content-Type": "application/x-www-form-urlencoded"
    
    Romain CREY's avatar
    Romain CREY committed
        },
        form: {
          token: response.resultatRetour.token,
          num_abt: response.resultatRetour.num_abt,
          date_debut: startDate,
          date_fin: endDate
        },
        json: true
    
    Romain CREY's avatar
    Romain CREY committed
      try {
    
        const responseEgl = await rp(dataRequest);
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        switch (responseEgl.codeRetour) {
    
    Romain CREY's avatar
    Romain CREY committed
          case 100:
    
            return format(responseEgl);
    
    Romain CREY's avatar
    Romain CREY committed
          case -2:
    
            throw new Error(errors.LOGIN_FAILED);
    
    Romain CREY's avatar
    Romain CREY committed
          case -1:
    
            throw new Error(errors.VENDOR_DOWN);
    
    Romain CREY's avatar
    Romain CREY committed
          default:
    
            throw new Error(errors.UNKNOWN_ERROR);
    
    Romain CREY's avatar
    Romain CREY committed
        }
      } catch (error) {
    
        throw new Error(errors.VENDOR_DOWN);
    
    Romain CREY's avatar
    Romain CREY committed
      }
    }
    
    function format(response) {
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      const data = response.resultatRetour
        .slice(1)
    
        .filter(value => value.ValeurIndex);
      const dataLen = data.length;
      log("info", "filtered size is : " + dataLen);
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      const mapData = data.map((value, index) => {
    
        const time = moment(value.DateReleve, moment.ISO_8601);
        if (index + 1 < dataLen) {
          log(
            "info",
            "date is " +
              value.DateReleve +
              " SUBSTRACTING : " +
              data[index + 1].ValeurIndex +
              " - " +
              value.ValeurIndex
          );
    
    Yoan VALLET's avatar
    Yoan VALLET committed
          return {
    
            load: data[index + 1].ValeurIndex - value.ValeurIndex,
            year: parseInt(time.format("YYYY")),
            month: parseInt(time.format("M")),
            day: parseInt(time.format("D")),
    
    Yoan VALLET's avatar
    Yoan VALLET committed
            hour: 0,
            minute: 0,
            type: value.TypeAgregat
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        } else {
    
          log("info", "end of data - date is : " + value.DateReleve);
    
    Yoan VALLET's avatar
    Yoan VALLET committed
          return {
            load: null,
    
            year: parseInt(time.format("YYYY")),
            month: parseInt(time.format("M")),
            day: parseInt(time.format("D")),
    
    Yoan VALLET's avatar
    Yoan VALLET committed
            hour: 0,
            minute: 0,
            type: value.TypeAgregat
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        }
    
    Romain CREY's avatar
    Romain CREY committed
    }
    
    
    function processYearAggregation(data, doctype) {
      log("info", "Start aggregation for : " + doctype);
      const grouped = data.reduce(reduceYearFunction, {});
      return Object.values(grouped);
    }
    
    function processMonthlyAggregation(data, range) {
      log("info", "Start aggregation for : " + range.doctype);
      // Filter by year
      const tmpData = groupBy(data, "year");
      const keys = Object.keys(tmpData);
      var dataToStore = [];
      // Monthly aggregation
      for (const index in keys) {
        // Get daily data of a year
        var monthlyData = tmpData[keys[index]];
        // Monthly aggregation
        var aggregatedData = monthlyData.reduce(reduceMonthFunction, {});
        // Store it
        dataToStore = dataToStore.concat(Object.values(aggregatedData));
      }
      return dataToStore;
    }
    
    function groupBy(xs, key) {
      return xs.reduce(function(rv, x) {
        (rv[x[key]] = rv[x[key]] || []).push(x);
        return rv;
      }, {});
    }
    
    function reduceYearFunction(acc, x) {
      var id = acc[x.year];
      if (id) {
        id.load += x.load;
    
      } else {
    
      return acc;
    }
    
    function reduceMonthFunction(acc, x) {
      var id = acc[x.month];
      if (id) {
        id.load += x.load;
      } else {
        acc[x.month] = x;
    
      return acc;
    }
    
    async function storeData(data, doctype, keys) {
      log("debug", "Store into " + doctype);
      log("debug", "Store into keys : " + keys);
      data.map(v => {
        log("info", "Saving data " + v.load + " for " + v.day + "/" + v.month);
      });
      return hydrateAndFilter(data, doctype, {
        keys: keys
      }).then(filteredDocuments => {
        addData(filteredDocuments, doctype);
      });
    
    /**
     * Function handling special case.
     * The temporary aggregated data need to be remove in order for the most recent one te be saved.
    
    Yoan VALLET's avatar
    Yoan VALLET committed
     * ex for com.grandlyon.egl.month :
    
     * { load: 76.712, month: 2020, ... } need to be replace by
    
     * { load: 82.212, month: 2020, ... } after grdf data reprocess
    
    async function resetInProgressAggregatedData(doctype) {
    
      // /!\ Warning: cannot use mongo queries because not supported for dev by cozy-konnectors-libs
    
      log("debug", doctype, "Remove aggregated data for");
      const result = await cozyClient.data.findAll(doctype);
      if (result.error || result.length <= 0) {
        // eslint-disable-next-line no-console
        console.warn("Error while fetching loads, doctype not found ");
      } else {
        const currentDate = moment();
    
        // Filter data to remove
    
        var filtered = [];
        if (doctype === rangeDate.year.doctype) {
    
          // Yearly case
          filtered = result.filter(function(el) {
    
            return el.year == currentDate.year();
          });
    
        } else {
    
          filtered = result.filter(function(el) {
            return (
    
              el.year == currentDate.year() &&
              el.month == parseInt(moment().format("M"))
            );
          });
    
        }
        // Remove data
        for (const doc of filtered) {
    
          log("debug", doc, "Removing this entry for " + doctype);
          await cozyClient.data.delete(doctype, doc);
    
    Romain CREY's avatar
    Romain CREY committed
      }
    }
    
    
    /***/ }),
    /* 1 */
    /***/ (function(module, exports, __webpack_require__) {
    
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    
    const log = __webpack_require__(2).namespace('cozy-konnector-libs');
    const requestFactory = __webpack_require__(20);
    const hydrateAndFilter = __webpack_require__(586);
    const categorization = __webpack_require__(795);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    __webpack_require__(863);
    
    Romain CREY's avatar
    Romain CREY committed
    
    module.exports = {
    
      BaseKonnector: __webpack_require__(864),
      CookieKonnector: __webpack_require__(893),
      cozyClient: __webpack_require__(628),
      errors: __webpack_require__(865),
    
    Romain CREY's avatar
    Romain CREY committed
      log,
    
      saveFiles: __webpack_require__(897),
      saveBills: __webpack_require__(901),
      linkBankOperations: __webpack_require__(903),
      addData: __webpack_require__(902),
    
    Romain CREY's avatar
    Romain CREY committed
      hydrateAndFilter,
    
      htmlToPDF: __webpack_require__(923).htmlToPDF,
      createCozyPDFDocument: __webpack_require__(923).createCozyPDFDocument,
    
    Romain CREY's avatar
    Romain CREY committed
      filterData: deprecate(hydrateAndFilter, 'Use hydrateAndFilter now. filterData will be removed in cozy-konnector-libs@4'),
    
      updateOrCreate: __webpack_require__(1037),
    
    Romain CREY's avatar
    Romain CREY committed
      request: deprecate(requestFactory, 'Use requestFactory instead of request. It will be removed in cozy-konnector-libs@4'),
      requestFactory,
    
      retry: __webpack_require__(898),
      wrapIfSentrySetUp: __webpack_require__(866).wrapIfSentrySetUp,
      Document: __webpack_require__(1038),
      signin: __webpack_require__(894),
      submitForm: __webpack_require__(894),
      scrape: __webpack_require__(1040),
      mkdirp: __webpack_require__(1041),
      normalizeFilename: __webpack_require__(1042),
      utils: __webpack_require__(627),
      solveCaptcha: __webpack_require__(1043),
    
    Romain CREY's avatar
    Romain CREY committed
      createCategorizer: categorization.createCategorizer,
      categorize: categorization.categorize,
    
      manifest: __webpack_require__(1044)
    
    Romain CREY's avatar
    Romain CREY committed
    };
    
    function deprecate(wrapped, message) {
      return function () {
        log('warn', message);
        return wrapped.apply(this, arguments);
      };
    }
    
    /***/ }),
    /* 2 */
    /***/ (function(module, exports, __webpack_require__) {
    
    
    const { env2formats } = __webpack_require__(3)
    const { filterLevel, filterSecrets } = __webpack_require__(18)
    const Secret = __webpack_require__(19)
    const { NODE_ENV, LOG_LEVEL } = process.env
    const env = (env2formats[NODE_ENV] && NODE_ENV) || 'production'
    
    
    Romain CREY's avatar
    Romain CREY committed
    let level = LOG_LEVEL || 'debug'
    
    const format = env2formats[env]
    
    Romain CREY's avatar
    Romain CREY committed
    const filters = [filterLevel, filterSecrets]
    
    const filterOut = function() {
      for (const filter of filters) {
        if (filter.apply(null, arguments) === false) {
          return true
        }
      }
      return false
    }
    
    /**
     * Use it to log messages in your konnector. Typical types are
     *
     * - `debug`
     * - `warning`
     * - `info`
     * - `error`
     * - `ok`
     *
     *
     * @example
     *
     * They will be colored in development mode. In production mode, those logs are formatted in JSON to be interpreted by the stack and possibly sent to the client. `error` will stop the konnector.
     *
     * ```js
     * logger = log('my-namespace')
     * logger('debug', '365 bills')
     * // my-namespace : debug : 365 bills
     * logger('info', 'Page fetched')
     * // my-namespace : info : Page fetched
     * ```
     * @param  {string} type
     * @param  {string} message
     * @param  {string} label
     * @param  {string} namespace
     */
    function log(type, message, label, namespace) {
      if (filterOut(level, type, message, label, namespace)) {
        return
      }
      // eslint-disable-next-line no-console
      console.log(format(type, message, label, namespace))
    }
    
    log.addFilter = function(filter) {
      return filters.push(filter)
    }
    
    log.setLevel = function(lvl) {
      level = lvl
    }
    
    // Short-hands
    const methods = ['debug', 'info', 'warn', 'error', 'ok', 'critical']
    methods.forEach(level => {
      log[level] = function(message, label, namespace) {
        return log(level, message, label, namespace)
      }
    })
    
    module.exports = log
    
    log.setNoRetry = obj => {
      if (obj) obj.no_retry = true
      else obj = { no_retry: true }
      return obj.no_retry
    }
    log.Secret = Secret
    log.namespace = function(namespace) {
      return function(type, message, label, ns = namespace) {
        log(type, message, label, ns)
      }
    }
    
    
    /***/ }),
    /* 3 */
    /***/ (function(module, exports, __webpack_require__) {
    
    
    const chalk = __webpack_require__(4)
    const util = __webpack_require__(16)
    const stringify = __webpack_require__(17)
    if (util && util.inspect && util.inspect.defaultOptions) {
      util.inspect.defaultOptions.maxArrayLength = null
      util.inspect.defaultOptions.depth = 2
      util.inspect.defaultOptions.colors = true
    
    const LOG_LENGTH_LIMIT = 64 * 1024 - 1
    
    const type2color = {
      debug: 'cyan',
      warn: 'yellow',
      info: 'blue',
      error: 'red',
      ok: 'green',
      secret: 'red',
      critical: 'red'
    
    Romain CREY's avatar
    Romain CREY committed
    }
    
    function prodFormat(type, message, label, namespace) {
      const log = { time: new Date(), type, label, namespace }
    
      if (typeof message === 'object') {
        if (message && message.no_retry) {
          log.no_retry = message.no_retry
        }
        if (message && message.message) {
          log.message = message.message
        }
      } else {
        log.message = message
      }
    
      // properly display error messages
      if (log.message && log.message.stack) {
        log.message = log.message.stack
      }
    
      // cut the string to avoid a fail in the stack
      let result = log
      try {
        result = stringify(log).substr(0, LOG_LENGTH_LIMIT)
      } catch (err) {
        // eslint-disable-next-line no-console
        console.log(err.message, 'cozy-logger: Failed to convert message to JSON')
      }
      return result
    }
    
    function devFormat(type, message, label, namespace) {
      let formatmessage = message
    
      if (typeof formatmessage !== 'string') {
        formatmessage = util.inspect(formatmessage)
      }
    
      let formatlabel = label ? ` : "${label}" ` : ''
      let formatnamespace = namespace ? chalk.magenta(`${namespace}: `) : ''
    
      let color = type2color[type]
      let formattype = color ? chalk[color](type) : type
    
      return `${formatnamespace}${formattype}${formatlabel} : ${formatmessage}`
    }
    
    
    const env2formats = {
      production: prodFormat,
      development: devFormat,
      standalone: devFormat,
      test: devFormat
    }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    module.exports = { prodFormat, devFormat, env2formats }
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    
    const escapeStringRegexp = __webpack_require__(5);
    const ansiStyles = __webpack_require__(6);
    const stdoutColor = __webpack_require__(12).stdout;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    const template = __webpack_require__(15);
    
    Romain CREY's avatar
    Romain CREY committed
    
    const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
    
    // `supportsColor.level` → `ansiStyles.color[name]` mapping
    const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m'];
    
    // `color-convert` models to exclude from the Chalk API due to conflicts and such
    const skipModels = new Set(['gray']);
    
    const styles = Object.create(null);
    
    function applyOptions(obj, options) {
    	options = options || {};
    
    	// Detect level if not set manually
    	const scLevel = stdoutColor ? stdoutColor.level : 0;
    	obj.level = options.level === undefined ? scLevel : options.level;
    	obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0;
    }
    
    function Chalk(options) {
    	// We check for this.template here since calling `chalk.constructor()`
    	// by itself will have a `this` of a previously constructed chalk object
    	if (!this || !(this instanceof Chalk) || this.template) {
    		const chalk = {};
    		applyOptions(chalk, options);
    
    		chalk.template = function () {
    			const args = [].slice.call(arguments);
    			return chalkTag.apply(null, [chalk.template].concat(args));
    		};
    
    		Object.setPrototypeOf(chalk, Chalk.prototype);
    		Object.setPrototypeOf(chalk.template, chalk);
    
    		chalk.template.constructor = Chalk;
    
    		return chalk.template;
    	}
    
    	applyOptions(this, options);
    }
    
    // Use bright blue on Windows as the normal blue color is illegible
    if (isSimpleWindowsTerm) {
    	ansiStyles.blue.open = '\u001B[94m';
    }
    
    for (const key of Object.keys(ansiStyles)) {
    	ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
    
    	styles[key] = {
    		get() {
    			const codes = ansiStyles[key];
    			return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key);
    		}
    	};
    }
    
    styles.visible = {
    	get() {
    		return build.call(this, this._styles || [], true, 'visible');
    	}
    };
    
    ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g');
    for (const model of Object.keys(ansiStyles.color.ansi)) {
    	if (skipModels.has(model)) {
    		continue;
    	}
    
    	styles[model] = {
    		get() {
    			const level = this.level;
    			return function () {
    				const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments);
    				const codes = {
    					open,
    					close: ansiStyles.color.close,
    					closeRe: ansiStyles.color.closeRe
    				};
    				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
    			};
    		}
    	};
    }
    
    ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g');
    for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
    	if (skipModels.has(model)) {
    		continue;
    	}
    
    	const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
    	styles[bgModel] = {
    		get() {
    			const level = this.level;
    			return function () {
    				const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments);
    				const codes = {
    					open,
    					close: ansiStyles.bgColor.close,
    					closeRe: ansiStyles.bgColor.closeRe
    				};
    				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
    			};
    		}
    	};
    }
    
    const proto = Object.defineProperties(() => {}, styles);
    
    function build(_styles, _empty, key) {
    	const builder = function () {
    		return applyStyle.apply(builder, arguments);
    	};
    
    	builder._styles = _styles;
    	builder._empty = _empty;
    
    	const self = this;
    
    	Object.defineProperty(builder, 'level', {
    		enumerable: true,
    		get() {
    			return self.level;
    		},
    		set(level) {
    			self.level = level;
    		}
    	});
    
    	Object.defineProperty(builder, 'enabled', {
    		enumerable: true,
    		get() {
    			return self.enabled;
    		},
    		set(enabled) {
    			self.enabled = enabled;
    		}
    	});
    
    	// See below for fix regarding invisible grey/dim combination on Windows
    	builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey';
    
    	// `__proto__` is used because we must return a function, but there is
    	// no way to create a function with a different prototype
    	builder.__proto__ = proto; // eslint-disable-line no-proto
    
    	return builder;
    }
    
    function applyStyle() {
    	// Support varags, but simply cast to string in case there's only one arg
    	const args = arguments;
    	const argsLen = args.length;
    	let str = String(arguments[0]);
    
    	if (argsLen === 0) {
    		return '';
    	}
    
    	if (argsLen > 1) {
    		// Don't slice `arguments`, it prevents V8 optimizations
    		for (let a = 1; a < argsLen; a++) {
    			str += ' ' + args[a];
    		}
    	}
    
    	if (!this.enabled || this.level <= 0 || !str) {
    		return this._empty ? '' : str;
    	}
    
    	// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
    	// see https://github.com/chalk/chalk/issues/58
    	// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
    	const originalDim = ansiStyles.dim.open;
    	if (isSimpleWindowsTerm && this.hasGrey) {
    		ansiStyles.dim.open = '';
    	}
    
    	for (const code of this._styles.slice().reverse()) {
    		// Replace any instances already present with a re-opening code
    		// otherwise only the part of the string until said closing code
    		// will be colored, and the rest will simply be 'plain'.
    		str = code.open + str.replace(code.closeRe, code.open) + code.close;
    
    		// Close the styling before a linebreak and reopen
    		// after next line to fix a bleed issue on macOS
    		// https://github.com/chalk/chalk/pull/92
    		str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`);
    	}
    
    	// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue
    	ansiStyles.dim.open = originalDim;
    
    	return str;
    }
    
    function chalkTag(chalk, strings) {
    	if (!Array.isArray(strings)) {
    		// If chalk() was called by itself or with a string,
    		// return the string itself as a string.
    		return [].slice.call(arguments, 1).join(' ');
    	}
    
    	const args = [].slice.call(arguments, 2);
    	const parts = [strings.raw[0]];
    
    	for (let i = 1; i < strings.length; i++) {
    		parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&'));
    		parts.push(String(strings.raw[i]));
    	}
    
    	return template(chalk, parts.join(''));
    }
    
    Object.defineProperties(Chalk.prototype, styles);
    
    module.exports = Chalk(); // eslint-disable-line new-cap
    module.exports.supportsColor = stdoutColor;
    module.exports.default = module.exports; // For TypeScript
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    
    var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
    
    module.exports = function (str) {
    	if (typeof str !== 'string') {
    		throw new TypeError('Expected a string');
    	}
    
    	return str.replace(matchOperatorsRe, '\\$&');
    };
    
    
    /***/ }),
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    /* WEBPACK VAR INJECTION */(function(module) {
    
    const colorConvert = __webpack_require__(8);
    
    Romain CREY's avatar
    Romain CREY committed
    
    const wrapAnsi16 = (fn, offset) => function () {
    	const code = fn.apply(colorConvert, arguments);
    	return `\u001B[${code + offset}m`;
    };
    
    const wrapAnsi256 = (fn, offset) => function () {
    	const code = fn.apply(colorConvert, arguments);
    	return `\u001B[${38 + offset};5;${code}m`;
    };
    
    const wrapAnsi16m = (fn, offset) => function () {
    	const rgb = fn.apply(colorConvert, arguments);
    	return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
    };
    
    function assembleStyles() {
    	const codes = new Map();
    	const styles = {
    		modifier: {
    			reset: [0, 0],
    			// 21 isn't widely supported and 22 does the same thing
    			bold: [1, 22],
    			dim: [2, 22],
    			italic: [3, 23],
    			underline: [4, 24],
    			inverse: [7, 27],
    			hidden: [8, 28],
    			strikethrough: [9, 29]
    		},
    		color: {
    			black: [30, 39],
    			red: [31, 39],
    			green: [32, 39],
    			yellow: [33, 39],
    			blue: [34, 39],
    			magenta: [35, 39],
    			cyan: [36, 39],
    			white: [37, 39],
    			gray: [90, 39],
    
    			// Bright color
    			redBright: [91, 39],
    			greenBright: [92, 39],
    			yellowBright: [93, 39],
    			blueBright: [94, 39],
    			magentaBright: [95, 39],
    			cyanBright: [96, 39],
    			whiteBright: [97, 39]
    		},
    		bgColor: {
    			bgBlack: [40, 49],
    			bgRed: [41, 49],
    			bgGreen: [42, 49],
    			bgYellow: [43, 49],
    			bgBlue: [44, 49],
    			bgMagenta: [45, 49],
    			bgCyan: [46, 49],
    			bgWhite: [47, 49],
    
    			// Bright color
    			bgBlackBright: [100, 49],
    			bgRedBright: [101, 49],
    			bgGreenBright: [102, 49],
    			bgYellowBright: [103, 49],
    			bgBlueBright: [104, 49],
    			bgMagentaBright: [105, 49],
    			bgCyanBright: [106, 49],
    			bgWhiteBright: [107, 49]
    		}
    	};
    
    	// Fix humans
    	styles.color.grey = styles.color.gray;
    
    	for (const groupName of Object.keys(styles)) {
    		const group = styles[groupName];
    
    		for (const styleName of Object.keys(group)) {
    			const style = group[styleName];
    
    			styles[styleName] = {
    				open: `\u001B[${style[0]}m`,
    				close: `\u001B[${style[1]}m`
    			};
    
    			group[styleName] = styles[styleName];
    
    			codes.set(style[0], style[1]);
    		}
    
    		Object.defineProperty(styles, groupName, {
    			value: group,
    			enumerable: false
    		});
    
    		Object.defineProperty(styles, 'codes', {
    			value: codes,