Skip to content
Snippets Groups Projects
index.js 7.33 MiB
Newer Older
  • Learn to ignore specific revisions
  • Romain CREY's avatar
    Romain CREY committed
    /******/ (function(modules) { // webpackBootstrap
    /******/ 	// The module cache
    /******/ 	var installedModules = {};
    /******/
    /******/ 	// 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;
    /******/ 	}
    /******/
    /******/
    /******/ 	// 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 = "";
    /******/
    /******/
    /******/ 	// 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__(24)
    const moment = __webpack_require__(1492)
    
    __webpack_require__(1630)
    
    
    moment.locale('fr') // set the language
    moment.tz.setDefault('Europe/Paris') // set the timezone
    
    const manualExecution =
      process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false
    
    const startDate = manualExecution
    
      ? moment()
          .subtract(1, 'year')
          .format('MM/DD/YYYY')
      : moment()
          .subtract(3, 'year')
          .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 {
    
        // Local debug data
    
        // const baseUrl = fields.eglBaseURL
        // const apiAuthKey = fields.eglAPIAuthKey
        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')
    
    
        const eglData = await getData(response, baseUrl, apiAuthKey)
        if (eglData) {
    
          log('debug', 'Process egl daily data')
    
          const processedLoadData = await processData(
            eglData,
            rangeDate.day.doctype,
            rangeDate.day.keys
    
          log('debug', 'Agregate egl load data for month and year')
    
          await agregateMonthAndYearData(processedLoadData)
        } else {
    
          log('debug', 'No data found')
    
    Romain CREY's avatar
    Romain CREY committed
      } catch (error) {
    
        throw new Error(error.message)
    
    Romain CREY's avatar
    Romain CREY committed
      }
    }
    
    /**
     * Parse data
     * Remove existing data from DB using hydrateAndFilter
     * Store filtered data
     * Return the list of filtered data
     */
    async function processData(data, doctype, filterKeys) {
      // const formatedData = await formateData(data)
    
      log('debug', 'processData - data formated')
    
      // Remove data for existing days into the DB
      const filteredData = await hydrateAndFilter(data, doctype, {
        keys: filterKeys
      })
    
      log('debug', 'processData - data filtered')
    
      // Store new day data
      await storeData(filteredData, doctype, filterKeys)
      return filteredData
    }
    
    /**
     * Agregate data from daily data to monthly and yearly data
     */
    async function agregateMonthAndYearData(data) {
      // Sum year and month values into object with year or year-month as keys
      if (data && data.length !== 0) {
        let monthData = {}
        let yearData = {}
    
        data.forEach(element => {
          element.year + '-' + element.month in monthData
            ? (monthData[element.year + '-' + element.month] += element.load)
            : (monthData[element.year + '-' + element.month] = element.load)
          element.year in yearData
            ? (yearData[element.year] += element.load)
            : (yearData[element.year] = element.load)
        })
        // Agregation for Month data
        const agregatedMonthData = await buildAgregatedData(
          monthData,
          'com.grandlyon.egl.month'
        )
        await storeData(agregatedMonthData, 'com.grandlyon.egl.month', [
          'year',
          'month'
        ])
        // Agregation for Year data
        const agregatedYearData = await buildAgregatedData(
          yearData,
          'com.grandlyon.egl.year'
        )
        await storeData(agregatedYearData, 'com.grandlyon.egl.year', ['year'])
      }
    }
    
    /**
     * Retrieve and remove old data for a specific doctype
     * Return an Array of agregated data
     */
    async function buildAgregatedData(data, doctype) {
    
      log('info', 'entering buildAgregatedData')
    
      let agregatedData = []
      for (let [key, value] of Object.entries(data)) {
        const data = await buildDataFromKey(doctype, key, value)
        const oldValue = await resetInProgressAggregatedData(data, doctype)
    
        log('info', 'Dataload + oldvalue is ' + data.load + ' + ' + oldValue)
    
        data.load += oldValue
        agregatedData.push(data)
      }
      return agregatedData
    }
    
    
    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
        },
    
    Romain CREY's avatar
    Romain CREY committed
          login: login,
          pass: password
        },
        json: true
    
      }
      const response = await rp(authRequest)
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      if (response.codeRetour === 100) {
    
        return response
    
    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 {
    
        // Sort data by date
        const responseEgl = await rp(dataRequest).then(eglRawData => {
          eglRawData.resultatRetour.sort(function(a, b) {
            return new Date(a.DateReleve) - new Date(b.DateReleve)
          })
          return eglRawData
        })
    
    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 errors.LOGIN_FAILED
    
    Romain CREY's avatar
    Romain CREY committed
          case -1:
    
            throw errors.VENDOR_DOWN
    
    Romain CREY's avatar
    Romain CREY committed
          default:
    
            throw 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) {
    
      log('info', 'origin response size is : ' + response.resultatRetour.length)
    
      // Store first value as reference for index processing
      let refValue = response.resultatRetour[0]
      // Create copy of data without first value
    
    Yoan VALLET's avatar
    Yoan VALLET committed
      const data = response.resultatRetour
    
        .slice(1)
        .filter(value => value.ValeurIndex)
    
      log('info', 'filtered size is : ' + data.length)
      return data.map(value => {
    
        const time = moment(value.DateReleve, moment.ISO_8601)
    
        const procesedLoad = value.ValeurIndex - refValue.ValeurIndex
        if (procesedLoad < 0) {
          log(
            'error',
            `processing load for day ${parseInt(time.format('D'))}/${parseInt(
              time.format('M')
            )}/${parseInt(time.format('YYYY'))}, value is : ${procesedLoad}`
          )
          throw errors.VENDOR_DOWN
        }
        // Change index ref value
        refValue = value
        return {
          load: procesedLoad,
          year: parseInt(time.format('YYYY')),
          month: parseInt(time.format('M')),
          day: parseInt(time.format('D')),
          hour: 0,
          minute: 0,
          type: value.TypeAgregat
    
    Yoan VALLET's avatar
    Yoan VALLET committed
        }
    
    
    /**
     * Save data in the right doctype db and prevent duplicated keys
     */
    async function storeData(data, doctype, filterKeys) {
    
      log('debug', 'Store into ' + doctype)
      log('debug', 'Store into keys : ' + filterKeys)
    
      // data.map(v => {
      //   log("info", "Saving data " + v.load + " for " + v.day + "/" + v.month + "/" + v.year);
      // });
    
      const filteredDocuments = await hydrateAndFilter(data, doctype, {
        keys: filterKeys
      })
      return await addData(filteredDocuments, doctype)
    }
    
    /**
     * Format an entry for DB storage
     * using key and value
     * For year doctype: key = "YYYY"
     * For month doctype: key = "YYYY-MM"
     */
    async function buildDataFromKey(doctype, key, value) {
      let year, month, day, hour
      if (doctype === 'com.grandlyon.egl.year') {
        year = key
        month = 1
        day = 0
        hour = 0
      } else if (doctype === 'com.grandlyon.egl.month') {
        const split = key.split('-')
        year = split[0]
        month = split[1]
        day = 0
        hour = 0
    
      } else {
    
        const split = key.split('-')
        year = split[0]
        month = split[1]
        day = split[2]
        hour = split[3]
    
      return {
        load: Math.round(value * 10000) / 10000,
        year: parseInt(year),
        month: parseInt(month),
        day: parseInt(day),
        hour: parseInt(hour),
        minute: 0
    
    /**
     * 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 egl data reprocess
    
    async function resetInProgressAggregatedData(data, doctype) {
    
      // /!\ Warning: cannot use mongo queries because not supported for dev by cozy-konnectors-libs
    
      log('debug', 'Remove aggregated data for ' + doctype)
    
      const result = await cozyClient.data.findAll(doctype)
      if (result && result.length > 0) {
    
        // Filter data to remove
    
        var filtered = []
        if (doctype === 'com.grandlyon.egl.year') {
    
          // Yearly case
          filtered = result.filter(function(el) {
    
            return el.year == data.year
          })
        } else if (doctype === 'com.grandlyon.egl.month') {
    
          filtered = result.filter(function(el) {
            return el.year == data.year && el.month == data.month
          })
        } else {
          // Hourly case
    
          filtered = result.filter(function(el) {
            return (
    
              el.year == data.year &&
              el.month == data.month &&
              el.day == data.day &&
              el.hour == data.hour
            )
          })
    
        }
        // Remove data
    
        let sum = 0.0
    
        for (const doc of filtered) {
    
          sum += doc.load
    
          log('debug', 'Removing this entry for ' + doc.load)
    
          await cozyClient.data.delete(doctype, doc)
    
        return sum
    
    Romain CREY's avatar
    Romain CREY committed
      }
    
      return 0.0
    
    Romain CREY's avatar
    Romain CREY committed
    }
    
    
    /***/ }),
    /* 1 */
    /***/ (function(module, exports, __webpack_require__) {
    
    
    const log = __webpack_require__(2).namespace('cozy-konnector-libs');
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    const requestFactory = __webpack_require__(22);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    const hydrateAndFilter = __webpack_require__(371);
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    const categorization = __webpack_require__(1130);
    
    Romain CREY's avatar
    Romain CREY committed
    
    module.exports = {
    
      BaseKonnector: __webpack_require__(1402),
      CookieKonnector: __webpack_require__(1485),
      cozyClient: __webpack_require__(487),
      errors: __webpack_require__(1408),
    
    Romain CREY's avatar
    Romain CREY committed
      log,
    
      saveFiles: __webpack_require__(1404),
      saveBills: __webpack_require__(1403),
      saveIdentity: __webpack_require__(1451),
      linkBankOperations: __webpack_require__(1425),
      addData: __webpack_require__(1424),
    
    Romain CREY's avatar
    Romain CREY committed
      hydrateAndFilter,
    
      htmlToPDF: __webpack_require__(1486).htmlToPDF,
      createCozyPDFDocument: __webpack_require__(1486).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__(1450),
    
    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__(1405),
      wrapIfSentrySetUp: __webpack_require__(1452).wrapIfSentrySetUp,
      Document: __webpack_require__(1487),
      signin: __webpack_require__(1447),
      submitForm: __webpack_require__(1447),
      scrape: __webpack_require__(1489),
      mkdirp: __webpack_require__(1407),
      normalizeFilename: __webpack_require__(1490),
      utils: __webpack_require__(486),
      solveCaptcha: __webpack_require__(1491),
    
    Romain CREY's avatar
    Romain CREY committed
      createCategorizer: categorization.createCategorizer,
      categorize: categorization.categorize,
    
      manifest: __webpack_require__(845)
    
    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 { filterLevel, filterSecrets } = __webpack_require__(3)
    const Secret = __webpack_require__(4)
    const { LOG_LEVEL } = process.env
    
    Romain CREY's avatar
    Romain CREY committed
    let level = LOG_LEVEL || 'debug'
    
    const format = __webpack_require__(5)
    
    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 levels = {
      secret: 0,
      debug: 10,
      info: 20,
      warn: 30,
      error: 40,
      ok: 50,
      critical: 50
    
    const Secret = __webpack_require__(4)
    
    const filterSecrets = function(level, type, message) {
      if (type !== 'secret' && message instanceof Secret) {
        throw new Error('You should log a secret with log.secret')
      }
    }
    
    const filterLevel = function(level, type) {
      return levels[type] >= levels[level]
    }
    
    module.exports = {
      filterSecrets,
      filterLevel
    }
    
    
    /***/ }),
    /* 4 */
    /***/ (function(module, exports) {
    
    const Secret = function(data) {
      Object.assign(this, data)
      return this
    
    Romain CREY's avatar
    Romain CREY committed
    }
    
    
    Secret.prototype.toString = function() {
      throw new Error('Cannot convert Secret to string')
    }
    
    module.exports = Secret
    
    
    /***/ }),
    /* 5 */
    /***/ (function(module, exports, __webpack_require__) {
    
    const prodFormat = __webpack_require__(6)
    const devFormat = __webpack_require__(8)
    
    switch ("none") {
      case 'production':
        module.exports = prodFormat
        break
      case 'development':
        module.exports = devFormat
        break
      case 'standalone':
        module.exports = devFormat
        break
      case 'test':
        module.exports = devFormat
        break
      default:
        module.exports = prodFormat
    }
    
    
    /***/ }),
    /* 6 */
    /***/ (function(module, exports, __webpack_require__) {
    
    const stringify = __webpack_require__(7)
    
    const LOG_LENGTH_LIMIT = 64 * 1024 - 1
    
    
    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
    }
    
    
    module.exports = prodFormat
    
    
    /***/ }),
    /* 7 */
    /***/ (function(module, exports) {
    
    exports = module.exports = stringify
    exports.getSerialize = serializer
    
    function stringify(obj, replacer, spaces, cycleReplacer) {
      return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces)
    }
    
    function serializer(replacer, cycleReplacer) {
      var stack = [], keys = []
    
      if (cycleReplacer == null) cycleReplacer = function(key, value) {
        if (stack[0] === value) return "[Circular ~]"
        return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]"
      }
    
      return function(key, value) {
        if (stack.length > 0) {
          var thisPos = stack.indexOf(this)
          ~thisPos ? stack.splice(thisPos + 1) : stack.push(this)
          ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
          if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value)
        }
        else stack.push(value)
    
        return replacer == null ? value : replacer.call(this, key, value)
      }
    }
    
    
    /***/ }),
    /* 8 */
    /***/ (function(module, exports, __webpack_require__) {
    
    const util = __webpack_require__(9)
    const chalk = __webpack_require__(10)
    
    if (util && util.inspect && util.inspect.defaultOptions) {
      util.inspect.defaultOptions.maxArrayLength = null
      util.inspect.defaultOptions.depth = 2
      util.inspect.defaultOptions.colors = true
    }
    
    const type2color = {
      debug: 'cyan',
      warn: 'yellow',
      info: 'blue',
      error: 'red',
      ok: 'green',
      secret: 'red',
      critical: 'red'
    }
    
    
    Romain CREY's avatar
    Romain CREY committed
    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}`
    }
    
    
    module.exports = devFormat
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    
    /***/ }),
    /* 9 */
    /***/ (function(module, exports) {
    
    module.exports = require("util");
    
    Romain CREY's avatar
    Romain CREY committed
    
    /***/ }),
    
    /* 10 */
    
    Romain CREY's avatar
    Romain CREY committed
    /***/ (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    
    const escapeStringRegexp = __webpack_require__(11);
    const ansiStyles = __webpack_require__(12);
    const stdoutColor = __webpack_require__(18).stdout;
    
    Romain CREY's avatar
    Romain CREY committed
    
    
    const template = __webpack_require__(21);
    
    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(''));
    }