diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000000000000000000000000000000000..08012e88dcedff56c24e3231c56b7e2210c8e2ff --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "endOfLine": "auto", + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "arrowParens": "avoid" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..1ff546f0035cfae6d157728a4e164dd0d74ffcd4 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,46 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll": true, + "source.organizeImports": true + }, + "editor.tabSize": 2, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "cSpell.words": [ + "Abonnement", + "acces", + "Agregat", + "Agregats", + "apikey", + "arret", + "Arret", + "backoffice", + "Corrigees", + "cozyclient", + "criteres", + "Derniere", + "Detaillees", + "enedissgegrandlyon", + "Etage", + "etat", + "faultstring", + "firstname", + "Generales", + "grandlyon", + "HISTO", + "insee", + "konnector", + "konnectors", + "lastname", + "maxpower", + "numero", + "Perimetre", + "periodicite", + "PMAX", + "Recurrente", + "Releve", + "resultat", + "Retour", + "soapenv", + "Valeur" + ] +} diff --git a/package.json b/package.json index d0d348b39b38c37eb3beb3fa155515e37461d613..9c45bb20e1515f9c1c85b0bf760aae6e32398893 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,8 @@ "travisDeployKey": "./bin/generate_travis_deploy_key" }, "dependencies": { + "@sentry/node": "^7.23.0", + "@sentry/tracing": "^7.23.0", "cozy-konnector-libs": "4.42.3", "moment": "^2.24.0", "moment-timezone": "^0.5.26" diff --git a/src/helpers/env.js b/src/helpers/env.js new file mode 100644 index 0000000000000000000000000000000000000000..3774726683f7bf1c44882d9aeb62a7c43c31819f --- /dev/null +++ b/src/helpers/env.js @@ -0,0 +1,20 @@ +function isLocal() { + return ( + process.env.NODE_ENV === 'development' || + process.env.NODE_ENV === 'local' || + process.env.NODE_ENV === 'standalone' + ) +} + +/** + * Verify if it's an alpha URL + * @returns {boolean} + */ +function isDev() { + return ( + process.env.COZY_URL.includes('alpha') || + process.env.COZY_URL.includes('cozy.tools') + ) +} + +module.exports = { isLocal, isDev } diff --git a/src/index.js b/src/index.js index 051c17909c2254d3d9ee62dbdfe3826809c49d5b..000768dcff4fc7751d9e7e041f4fa21351f76487 100644 --- a/src/index.js +++ b/src/index.js @@ -4,81 +4,117 @@ const { errors, addData, hydrateAndFilter, - cozyClient -} = require("cozy-konnector-libs"); + cozyClient, +} = require('cozy-konnector-libs') -// const fetch = require('node-fetch') -const rp = require("request-promise"); -const moment = require("moment"); -require("moment-timezone"); +const rp = require('request-promise') +const moment = require('moment') +require('moment-timezone') -moment.locale("fr"); // set the language -moment.tz.setDefault("Europe/Paris"); // set the timezone +moment.locale('fr') // set the language +moment.tz.setDefault('Europe/Paris') // set the timezone + +const Sentry = require('@sentry/node') +// eslint-disable-next-line +const Tracing = require('@sentry/tracing') // Needed for tracking performance in Sentry +const { version } = require('../package.json') +const { isDev } = require('./helpers/env') const manualExecution = - process.env.COZY_JOB_MANUAL_EXECUTION === "true" ? true : false; + process.env.COZY_JOB_MANUAL_EXECUTION === 'true' ? true : false const startDate = manualExecution ? moment() - .subtract(1, "year") - .format("MM/DD/YYYY") + .subtract(1, 'year') + .format('MM/DD/YYYY') : moment() - .subtract(3, "year") - .format("MM/DD/YYYY"); + .subtract(3, 'year') + .format('MM/DD/YYYY') -const endDate = moment().format("MM/DD/YYYY"); -// const timeRange = ['day', 'month', 'year'] +const endDate = moment().format('MM/DD/YYYY') const rangeDate = { day: { - doctype: "com.grandlyon.egl.day", - keys: ["year", "month", "day"] + doctype: 'com.grandlyon.egl.day', + keys: ['year', 'month', 'day'], }, month: { - doctype: "com.grandlyon.egl.month", - keys: ["year", "month"] + doctype: 'com.grandlyon.egl.month', + keys: ['year', 'month'], }, year: { - doctype: "com.grandlyon.egl.year", - keys: ["year"] - } -}; + doctype: 'com.grandlyon.egl.year', + keys: ['year'], + }, +} + +module.exports = new BaseKonnector(start) +/** + * Sentry + */ +Sentry.init({ + dsn: + 'https://3f97baf46c2b44c2bd9e0c371abe3e05@grandlyon.errors.cozycloud.cc/2', -module.exports = new BaseKonnector(start); + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + // We recommend adjusting this value in production + tracesSampleRate: 1.0, + release: version, + environment: isDev() ? 'development' : 'production', + debug: isDev(), + integrations: [ + // enable HTTP calls tracing + new Sentry.Integrations.Http({ tracing: true }), + ], +}) // 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, +// 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) { + const transaction = Sentry.startTransaction({ + op: 'konnector', + name: 'EGL Konnector', + }) + transaction.startChild({ op: 'Konnector starting' }) + 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 ..."); + const baseUrl = cozyParameters.secret.eglBaseURL + const apiAuthKey = cozyParameters.secret.eglAPIAuthKey + log('info', 'Authenticating ...') const response = await authenticate( fields.login, fields.password, baseUrl, apiAuthKey - ); - log("info", "Successfully logged in"); + ) + log('info', 'Successfully logged in') - const eglData = await getData(response, baseUrl, apiAuthKey); + const eglData = await getData(response, baseUrl, apiAuthKey) if (eglData) { - log("debug", "Process egl daily data"); + 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); + ) + log('debug', 'Aggregate egl load data for month and year') + await aggregateMonthAndYearData(processedLoadData) } else { - log("debug", "No data found"); + log('debug', 'No data found') } + transaction.setStatus(Tracing.SpanStatus.Ok) + transaction.finish() } catch (error) { - throw new Error(error.message); + log('error', error) + Sentry.captureException(error) + transaction.setStatus(Tracing.SpanStatus.Aborted) + transaction.finish() + await Sentry.flush() + throw error } } @@ -89,217 +125,223 @@ async function start(fields, cozyParameters) { * Return the list of filtered data */ async function processData(data, doctype, filterKeys) { - // const formatedData = await formateData(data) - log("debug", "processData - data formated"); + log('debug', 'processData - data formatted') // Remove data for existing days into the DB const filteredData = await hydrateAndFilter(data, doctype, { - keys: filterKeys - }); - log("debug", "processData - data filtered"); + keys: filterKeys, + }) + log('debug', 'processData - data filtered') // Store new day data - await storeData(filteredData, doctype, filterKeys); - return filteredData; + await storeData(filteredData, doctype, filterKeys) + return filteredData } /** - * Agregate data from daily data to monthly and yearly data + * Aggregate data from daily data to monthly and yearly data */ -async function agregateMonthAndYearData(data) { +async function aggregateMonthAndYearData(data) { // Sum year and month values into object with year or year-month as keys if (data && data.length !== 0) { - let monthData = {}; - let yearData = {}; + 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( + const monthDataKey = element.year + '-' + element.month + if (monthDataKey in monthData) { + monthData[monthDataKey] += element.load + } else { + monthData[monthDataKey] = element.load + } + + const yearDataKey = element.year + if (yearDataKey in yearData) { + yearData[yearDataKey] += element.load + } else { + yearData[yearDataKey] = element.load + } + }) + // Aggregation for Month data + const aggregatedMonthData = await buildAggregatedData( monthData, - "com.grandlyon.egl.month" - ); - await storeData(agregatedMonthData, "com.grandlyon.egl.month", [ - "year", - "month" - ]); - // Agregation for Year data - const agregatedYearData = await buildAgregatedData( + 'com.grandlyon.egl.month' + ) + await storeData(aggregatedMonthData, 'com.grandlyon.egl.month', [ + 'year', + 'month', + ]) + // Aggregation for Year data + const aggregatedYearData = await buildAggregatedData( yearData, - "com.grandlyon.egl.year" - ); - await storeData(agregatedYearData, "com.grandlyon.egl.year", ["year"]); + 'com.grandlyon.egl.year' + ) + await storeData(aggregatedYearData, 'com.grandlyon.egl.year', ['year']) } } /** * Retrieve and remove old data for a specific doctype - * Return an Array of agregated data + * Return an Array of aggregated data */ -async function buildAgregatedData(data, doctype) { - log("info", "entering buildAgregatedData"); - let agregatedData = []; +async function buildAggregatedData(data, doctype) { + log('info', 'entering buildAggregatedData') + let aggregatedData = [] 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); + const data = await buildDataFromKey(doctype, key, value) + const oldValue = await resetInProgressAggregatedData(data, doctype) + log('info', 'Data load + old value is ' + data.load + ' + ' + oldValue) + data.load += oldValue + aggregatedData.push(data) } - return agregatedData; + return aggregatedData } async function authenticate(login, password, baseUrl, apiAuthKey) { const authRequest = { - method: "POST", - uri: baseUrl + "/connect.aspx", + method: 'POST', + uri: baseUrl + '/connect.aspx', headers: { AuthKey: apiAuthKey, - "Content-Type": "application/x-www-form-urlencoded" + 'Content-Type': 'application/x-www-form-urlencoded', }, formData: { login: login, - pass: password + pass: password, }, - json: true - }; + json: true, + } let response = {} try { - response = await rp(authRequest); - } catch(e) { - log("error", e) - } - - if (response.codeRetour === 100) { - return response; - } else { - throw new Error(errors.LOGIN_FAILED); + response = await rp(authRequest) + if (response.codeRetour === 100) { + return response + } else { + Sentry.captureException(JSON.stringify(response)) + throw new Error() + } + } catch (error) { + throw new Error(errors.LOGIN_FAILED) } } async function getData(response, baseUrl, apiAuthKey) { - log("debug", "Start date : " + startDate); - log("debug", "End date : " + endDate); + log('debug', 'Start date : ' + startDate) + log('debug', 'End date : ' + endDate) const dataRequest = { - method: "POST", - uri: baseUrl + "/getAllAgregatsByAbonnement.aspx", + method: 'POST', + uri: baseUrl + '/getAllAgregatsByAbonnement.aspx', headers: { AuthKey: apiAuthKey, - "Content-Type": "application/x-www-form-urlencoded" + 'Content-Type': 'application/x-www-form-urlencoded', }, form: { token: response.resultatRetour.token, num_abt: response.resultatRetour.num_abt, date_debut: startDate, - date_fin: endDate + date_fin: endDate, }, - json: true - }; + json: true, + } 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; - }); + return new Date(a.DateReleve) - new Date(b.DateReleve) + }) + return eglRawData + }) switch (responseEgl.codeRetour) { case 100: - return format(responseEgl); + return format(responseEgl) case -2: - throw errors.LOGIN_FAILED; + throw errors.LOGIN_FAILED case -1: - throw errors.VENDOR_DOWN; + throw errors.VENDOR_DOWN default: - throw errors.UNKNOWN_ERROR; + throw errors.UNKNOWN_ERROR } } catch (error) { - log("debug", "Error from getAllAgregatsByAbonnement"); - throw new Error(errors.VENDOR_DOWN); + log('debug', 'Error from getAllAgregatsByAbonnement') + throw new Error(errors.VENDOR_DOWN) } } function format(response) { - log("info", "origin response size is : " + response.resultatRetour.length); + log('info', 'origin response size is : ' + response.resultatRetour.length) // Store first value as reference for index processing - let refValue = response.resultatRetour[0]; + let refValue = response.resultatRetour[0] // Create copy of data without first value const data = response.resultatRetour .slice(1) - .filter(value => value.ValeurIndex); - log("info", "filtered size is : " + data.length); + .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) { + const time = moment(value.DateReleve, moment.ISO_8601) + const processedLoad = value.ValeurIndex - refValue.ValeurIndex + if (processedLoad < 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; + 'error', + `processing load for day ${parseInt(time.format('D'))}/${parseInt( + time.format('M') + )}/${parseInt(time.format('YYYY'))}, value is : ${processedLoad}` + ) + throw errors.VENDOR_DOWN } // Change index ref value - refValue = value; + refValue = value return { - load: procesedLoad, - year: parseInt(time.format("YYYY")), - month: parseInt(time.format("M")), - day: parseInt(time.format("D")), + load: processedLoad, + year: parseInt(time.format('YYYY')), + month: parseInt(time.format('M')), + day: parseInt(time.format('D')), hour: 0, minute: 0, - type: value.TypeAgregat - }; - }); + type: value.TypeAgregat, + } + }) } /** * 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); + 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); - // }); + // 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); + 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" + * 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; + 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]; + const split = key.split('-') + year = split[0] + month = split[1] + day = split[2] + hour = split[3] } return { load: Math.round(value * 10000) / 10000, @@ -307,8 +349,8 @@ async function buildDataFromKey(doctype, key, value) { month: parseInt(month), day: parseInt(day), hour: parseInt(hour), - minute: 0 - }; + minute: 0, + } } /** @@ -320,21 +362,21 @@ async function buildDataFromKey(doctype, key, value) { */ 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); + 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") { + let 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") { + return el.year == data.year + }) + } else if (doctype === 'com.grandlyon.egl.month') { // Monthly case filtered = result.filter(function(el) { - return el.year == data.year && el.month == data.month; - }); + return el.year == data.year && el.month == data.month + }) } else { // Hourly case filtered = result.filter(function(el) { @@ -343,17 +385,17 @@ async function resetInProgressAggregatedData(data, doctype) { el.month == data.month && el.day == data.day && el.hour == data.hour - ); - }); + ) + }) } // Remove data - let sum = 0.0; + 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); + sum += doc.load + log('debug', 'Removing this entry for ' + doc.load) + await cozyClient.data.delete(doctype, doc) } - return sum; + return sum } - return 0.0; + return 0.0 } diff --git a/webpack.config.js b/webpack.config.js index bf6f80d7ed4960d2cea08151f39740c3938f3ecd..e60d80f45c206a0e2888cbc79899add29262d6a6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -12,9 +12,9 @@ const readManifest = () => const svgo = new SvgoInstance({ plugins: [ { - inlineStyles: { onlyMatchedOnce: false } - } - ] + inlineStyles: { onlyMatchedOnce: false }, + }, + ], }) let iconName @@ -33,30 +33,30 @@ module.exports = { mode: 'none', output: { path: path.join(__dirname, 'build'), - filename: 'index.js' + filename: 'index.js', }, plugins: [ new CopyPlugin({ - patterns: [ - { from: 'manifest.konnector' }, - { from: 'package.json' }, - { from: 'README.md' }, - { from: 'assets', transform: optimizeSVGIcon }, - { from: '.travis.yml' }, - { from: 'LICENSE' } - ] + patterns: [ + { from: 'manifest.konnector' }, + { from: 'package.json' }, + { from: 'README.md' }, + { from: 'assets', transform: optimizeSVGIcon }, + { from: '.travis.yml' }, + { from: 'LICENSE' }, + ], }), new webpack.DefinePlugin({ - __WEBPACK_PROVIDED_MANIFEST__: JSON.stringify(readManifest()) - }) + __WEBPACK_PROVIDED_MANIFEST__: JSON.stringify(readManifest()), + }), ], module: { // to ignore the warnings like : // WARNING in ../libs/node_modules/bindings/bindings.js 76:22-40 // Critical dependency: the request of a dependency is an expression // Since we cannot change this dependency. I think it won't hide more important messages - exprContextCritical: false - } + exprContextCritical: false, + }, } function optimizeSVGIcon(buffer, path) { diff --git a/yarn.lock b/yarn.lock index b3e2163bd8022d5c51ee728070eaa0a03162e72d..a6598c8a844397d0ae6abc0387b9b34c31a88e0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -241,6 +241,51 @@ qs "^6.7.0" url-parse "^1.4.7" +"@sentry/core@7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.23.0.tgz#d320b2b6e5620b41f345bc01d69b547cdf28f78d" + integrity sha512-oNLGsscSdMs1urCbpwe868NsoJWyeTOQXOm5w2e78yE7G6zm2Ra473NQio3lweaEvjQgSGpFyEfAn/3ubZbtPw== + dependencies: + "@sentry/types" "7.23.0" + "@sentry/utils" "7.23.0" + tslib "^1.9.3" + +"@sentry/node@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.23.0.tgz#a9573a1a93994b6dc7ed3539c27cb8faf7bacfb2" + integrity sha512-w6J+5YRsQEn55508yQYT43ahMP5IHruxq8XnFqYMFZvRohVxrZ1qTz7AMoSgc8fDcHr+LKhs1PxJIqqNwkWrFA== + dependencies: + "@sentry/core" "7.23.0" + "@sentry/types" "7.23.0" + "@sentry/utils" "7.23.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-7.23.0.tgz#9b6c5d3761d7664b6e40c476912281589d7cbe43" + integrity sha512-sbwvf6gjLgUTkBwZQOV7RkZPah7KnnpeVcwnNl+vigq6FNgNtejz53FFCo6t4mNGZSerfWbEy/c3C1LMX9AaXw== + dependencies: + "@sentry/core" "7.23.0" + "@sentry/types" "7.23.0" + "@sentry/utils" "7.23.0" + tslib "^1.9.3" + +"@sentry/types@7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.23.0.tgz#5d2ce94d81d7c1fad702645306f3c0932708cad5" + integrity sha512-fZ5XfVRswVZhKoCutQ27UpIHP16tvyc6ws+xq+njHv8Jg8gFBCoOxlJxuFhegD2xxylAn1aiSHNAErFWdajbpA== + +"@sentry/utils@7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.23.0.tgz#5f38640fe49f5abac88f048b92d3e83375d7ddf7" + integrity sha512-ad/XXH03MfgDH/7N7FjKEOVaKrfQWdMaE0nCxZCr2RrvlitlmGQmPpms95epr1CpzSU3BDRImlILx6+TlrXOgg== + dependencies: + "@sentry/types" "7.23.0" + tslib "^1.9.3" + "@sindresorhus/fnv1a@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@sindresorhus/fnv1a/-/fnv1a-1.2.0.tgz#d554da64c406f3b62ad06dfce9efd537a4a55de4" @@ -619,6 +664,13 @@ acorn@^8.2.1: version "8.5.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1489,6 +1541,11 @@ cookie@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -1912,6 +1969,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" +debug@4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" @@ -3269,6 +3333,14 @@ https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3982,6 +4054,11 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + macos-release@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac" @@ -6316,9 +6393,10 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" -tslib@^1.9.0: +tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.2.0: version "2.3.1"