diff --git a/Dockerfile b/Dockerfile index daaa1910c5..11c83a2b9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,7 @@ ENV YARN_VERSION 1.22.17 ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD 1 RUN yarn policies set-version $YARN_VERSION ENV CHROME_BIN /usr/bin/chromium +ENV PUPPETEER_EXECUTABLE_PATH /usr/bin/chromium # define working directory inside the container WORKDIR /usr/src/app diff --git a/client/src/i18n/en/odk.json b/client/src/i18n/en/odk.json new file mode 100644 index 0000000000..c090045969 --- /dev/null +++ b/client/src/i18n/en/odk.json @@ -0,0 +1,11 @@ +{ + "ODK" : { + "LOAD_FOSA_DATA" : "Load data of FOSA", + "TOTAL_FOUND" : "Total records found", + "NO_RECORD_FOUND" : "No record found", + "IMPORTED_SUCCESSFULLY" : "Records successfully imported", + "ODK_CENTRAL_URL" : "ODK Central Server URL", + "ODK_ADMIN_USER" : "ODK Central Admin Email", + "ODK_ADMIN_PASSWORD" : "ODK Central Admin Password" + } +} diff --git a/client/src/i18n/en/stock.json b/client/src/i18n/en/stock.json index 85cfa57a43..36355356a2 100644 --- a/client/src/i18n/en/stock.json +++ b/client/src/i18n/en/stock.json @@ -265,6 +265,10 @@ "TOGGLE_EXPIRY_RISKS_HELP_TEXT" : "This will display the lots at risk, whose average monthly consumption will not allow total consumption before the expiration date." }, "SETTINGS" : { + "CONSUMPTION_AND_REORDER_SETTINGS" : "Stock Consumption and Reorder Settings", + "ACCOUNTING_INTEGRATION_SETTINGS" : "Stock Accounting Integration", + "ODK_INTEGRATION_SETTINGS" : "ODK Integration Settings", + "OTHER_SETTINGS" : "Other Settings", "DEFAULT_MIN_MONTHS_SECURITY_STOCK": "Default minimum number of months of security stock for depots", "DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT": "The stock supply should provide at least this many months of stock for the depot involved.", "DEFAULT_PURCHASE_ORDER_INTERVAL" : "Default Purchase order interval (In Month)", diff --git a/client/src/i18n/fr/odk.json b/client/src/i18n/fr/odk.json new file mode 100644 index 0000000000..890508f511 --- /dev/null +++ b/client/src/i18n/fr/odk.json @@ -0,0 +1,11 @@ +{ + "ODK" : { + "LOAD_FOSA_DATA" : "Chargement des données des FOSA", + "TOTAL_FOUND" : "Total des enregistrements trouvés", + "NO_RECORD_FOUND" : "Aucun enregistrement trouvé", + "IMPORTED_SUCCESSFULLY" : "Données importées avec succès", + "ODK_CENTRAL_URL" : "URL du serveur ODK Central", + "ODK_ADMIN_USER" : "Adressse mail de l'administrateur", + "ODK_ADMIN_PASSWORD" : "Mot de passe de l'administrateur" + } +} diff --git a/client/src/i18n/fr/stock.json b/client/src/i18n/fr/stock.json index 4f975b0439..fd0ed91051 100644 --- a/client/src/i18n/fr/stock.json +++ b/client/src/i18n/fr/stock.json @@ -265,6 +265,10 @@ "TOGGLE_EXPIRY_RISKS_HELP_TEXT" : "Ceci permettra d'afficher les lots à risque, dont la consommation moyenne mensuel ne permettra pas la consommation total avant la date de peremption" }, "SETTINGS" : { + "CONSUMPTION_AND_REORDER_SETTINGS" : "Consommation de stock et de réapprovisionnement", + "ACCOUNTING_INTEGRATION_SETTINGS" : "Intégration de la comptabilité des stocks", + "ODK_INTEGRATION_SETTINGS" : "Paramètres d'intégration ODK", + "OTHER_SETTINGS" : "Autres paramètres", "DEFAULT_MIN_MONTHS_SECURITY_STOCK": "Nombre minimum de mois par défaut de stock de sécurité pour les dépôts", "DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT": "L'approvisionnement en stock devrait fournir au moins ce nombre de mois de stock pour le dépôt concerné.", "DEFAULT_PURCHASE_ORDER_INTERVAL" : "Intervalle de commande par défaut (En mois)", diff --git a/client/src/modules/stock/settings/stock-settings.html b/client/src/modules/stock/settings/stock-settings.html index 1b52676232..c79819f3de 100644 --- a/client/src/modules/stock/settings/stock-settings.html +++ b/client/src/modules/stock/settings/stock-settings.html @@ -2,184 +2,261 @@
  1. TREE.STOCK
  2. -
  3. TREE.STOCK_SETTINGS
  4. +
  5. TREE.SETTINGS
+
-
-
-
- TREE.STOCK_SETTINGS -
-
- -
- - - - SETTINGS.DEFINE_MONTH_AVERAGE_CONSUMPTION_HELP_TEXT - -
-
-
+
+
+
+ SETTINGS.CONSUMPTION_AND_REORDER_SETTINGS
-
- - - - SETTINGS.DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT - -
-
+
+
+ + + + SETTINGS.DEFINE_MONTH_AVERAGE_CONSUMPTION_HELP_TEXT + +
+
+
-
-
- - - - SETTINGS.MIN_PURCHASE_DELAY_HELP_TEXT - -
-
+
+ + + + SETTINGS.DEFAULT_MIN_MONTHS_SECURITY_STOCK_HELP_TEXT + +
+
+
-
-
- - - - SETTINGS.DEFAULT_PURCHASE_ORDER_INTERVAL_TEXT - -
-
+
+ + + + SETTINGS.MIN_PURCHASE_DELAY_HELP_TEXT + +
+
+
-
- - - - - - - - - - - - - - - - - - - -
- -
-
+
+ +
+
+
+ + SETTINGS.ACCOUNTING_INTEGRATION_SETTINGS +
+
+ + + + + + - -
- - - - SETTINGS.DEFAULT_COST_CENTER_FOR_STOCK_LOSS_HELP_TEXT - -
-
+ + + + + +
+ + + + SETTINGS.DEFAULT_COST_CENTER_FOR_STOCK_LOSS_HELP_TEXT + +
+
+
+
+
+ +
+
+
+ + SETTINGS.OTHER_SETTINGS +
+
+ + + + + + +
+
+ +
+
+
+ + SETTINGS.ODK_INTEGRATION_SETTINGS +
+
+
+ + +
+
+
+
-
diff --git a/client/src/modules/stock/settings/stock-settings.js b/client/src/modules/stock/settings/stock-settings.js index 889f267eca..96a3107951 100644 --- a/client/src/modules/stock/settings/stock-settings.js +++ b/client/src/modules/stock/settings/stock-settings.js @@ -15,7 +15,7 @@ function StockSettingsController( const vm = this; vm.enterprise = {}; - vm.settings = {}; + vm.settings = { odk : {} }; let $touched = false; diff --git a/package.json b/package.json index 12c7d94588..722047e397 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ ], "dependencies": { "@ima-worldhealth/coral": "^2.9.0", + "@ima-worldhealth/odk-central-api": "^1.2.1", "@ima-worldhealth/tree": "^2.5.1", "@types/angular": "^1.8.4", "@uirouter/angularjs": "^1.0.29", diff --git a/server/controllers/stock/setting/index.js b/server/controllers/stock/setting/index.js index c796b5fbed..5391dfcd04 100644 --- a/server/controllers/stock/setting/index.js +++ b/server/controllers/stock/setting/index.js @@ -12,12 +12,8 @@ const NotFound = require('../../../lib/errors/NotFound'); // Get the current stock settings for the Enterprise // If req.query.enterprise_id is set, it will use that, // otherwise it will look up the entry for Enterprise.id=1 -exports.list = function list(req, res, next) { - let enterpriseId = req.session.enterprise.id; - if (req.params.id) { - // If the enterprise was passed in as a parameter, use it - enterpriseId = req.params.id; - } +exports.list = async function list(req, res, next) { + const enterpriseId = req.params.id || req.session.enterprise.id; const sql = ` SELECT month_average_consumption, default_min_months_security_stock, @@ -30,39 +26,59 @@ exports.list = function list(req, res, next) { WHERE enterprise_id = ? LIMIT 1; `; - db.exec(sql, [enterpriseId]) - .then(rows => { - if (rows.length === 1) { - res.status(200).json(rows); - } else { - throw new NotFound(`Could not find stock_setting data with enterprise id ${req.params.id} (get)`); - } - - }) - .catch(next) - .done(); + try { + const rows = await db.exec(sql, [enterpriseId]); + + if (rows.length !== 1) { + throw new NotFound(`Could not find stock_setting data with enterprise id ${req.params.id} (get)`); + } + + const [settings] = rows; + + const odkSettings = await db.exec('SELECT * FROM odk_central_integration WHERE enterprise_id = ?;', [enterpriseId]); + + // merge in the settings if they are defined + if (odkSettings.length > 0) { + settings.odk = odkSettings.pop(); + } + + res.status(200).json([settings]); + } catch (e) { + next(e); + } }; // PUT /stock/setting/:id // // Update the settings in stock_settings for the settings // with enterprise_id given by the 'id' parameter -exports.update = function update(req, res, next) { +exports.update = async function update(req, res, next) { const sql = 'UPDATE stock_setting SET ? WHERE enterprise_id = ?'; const { settings } = req.body; + const { odk } = settings; - db.exec(sql, [settings, req.params.id]) - .then((row) => { - if (!row.affectedRows) { - throw new NotFound(`Could not find stock_setting row with enterprise id ${req.params.id} (put)`); - } - // Get the updated values - return db.exec('UPDATE stock_setting SET ? WHERE enterprise_id = ?', - [settings, req.params.id]); - }) - .then((updatedSettings) => { - res.status(200).json(updatedSettings); - }) - .catch(next) - .done(); + delete settings.odk; + + try { + + const { affectedRows } = await db.exec(sql, [settings, req.params.id]); + + if (!affectedRows) { + throw new NotFound(`Could not find stock_setting row with enterprise id ${req.params.id} (put)`); + } + + const updatedSettings = await db.exec( + 'UPDATE stock_setting SET ? WHERE enterprise_id = ?', + [settings, req.params.id]); + + // update the ODK settings + if (odk) { + await db.exec('DELETE FROM odk_central_integration WHERE enterprise_id = ?', [req.params.id]); + await db.exec('INSERT INTO odk_central_integration SET ?;', [{ ...odk, enterprise_id : req.params.id }]); + } + + res.status(200).json(updatedSettings); + } catch (e) { + next(e); + } }; diff --git a/server/models/migrations/next/migrate.sql b/server/models/migrations/next/migrate.sql index e69de29bb2..60afbed18d 100644 --- a/server/models/migrations/next/migrate.sql +++ b/server/models/migrations/next/migrate.sql @@ -0,0 +1,15 @@ +/* migration file for next release */ + +ALTER TABLE `enterprise_setting` ADD COLUMN `enable_odk_central_integration` BOOLEAN NOT NULL DEFAULT FALSE; + + +DROP TABLE IF EXISTS `odk_central_integration`; +CREATE TABLE `odk_central_integration` ( + `enterprise_id` SMALLINT(5) UNSIGNED NOT NULL, + `odk_central_url` TEXT NOT NULL, + `odk_admin_user` TEXT NOT NULL, + `odk_admin_password` TEXT NOT NULL, + `odk_project_id` INTEGER UNSIGNED NULL, + KEY `enterprise_id` (`enterprise_id`), + CONSTRAINT `odk_central__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci; diff --git a/server/models/schema.sql b/server/models/schema.sql index 2a4dc6dd9b..68e46b9f0a 100644 --- a/server/models/schema.sql +++ b/server/models/schema.sql @@ -592,6 +592,7 @@ CREATE TABLE `enterprise_setting` ( `base_index_growth_rate` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0, `posting_payroll_cost_center_mode` VARCHAR(100) NOT NULL DEFAULT 'default', -- With this function, transactions related to employee payment are done in bulk and require that each expense account be linked to a cost center `enable_require_cost_center_for_posting` TINYINT(1) NOT NULL DEFAULT 0, + `enable_odk_central_integration` BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (`enterprise_id`), CONSTRAINT `enterprise_setting__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci; @@ -2633,4 +2634,15 @@ CREATE TABLE `cost_center_aggregate` ( CONSTRAINT `cost_center_aggregate__cost_center_id` FOREIGN KEY (`cost_center_id`) REFERENCES `cost_center` (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci; +DROP TABLE IF EXISTS `odk_central_integration`; +CREATE TABLE `odk_central_integration` ( + `enterprise_id` SMALLINT(5) UNSIGNED NOT NULL, + `odk_central_url` TEXT NOT NULL, + `odk_admin_user` TEXT NOT NULL, + `odk_admin_password` TEXT NOT NULL, + `odk_project_id` INTEGER UNSIGNED NULL, + KEY `enterprise_id` (`enterprise_id`), + CONSTRAINT `odk_central__enterprise` FOREIGN KEY (`enterprise_id`) REFERENCES `enterprise` (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci; + SET foreign_key_checks = 1; diff --git a/yarn.lock b/yarn.lock index 006f9e23a2..b23494dc57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -81,6 +81,15 @@ puppeteer "^13.0.0" puppeteer-cluster "^0.22.0" +"@ima-worldhealth/odk-central-api@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@ima-worldhealth/odk-central-api/-/odk-central-api-1.2.1.tgz#2f98746349e0db0bc238557de5991fcf3db7efa7" + integrity sha512-6NGlFqGuyOXdc1/g5DvgxvYIuDgfU6tzNONGyjiswK95aCYEO/z0ZndVd1KJpzDrUxz3VjNteYuBXkdfKk1bLg== + dependencies: + debug "^4.3.3" + dotenv "^14.1.0" + got "^12.0.0" + "@ima-worldhealth/rewire@^4.1.0": version "4.1.0" resolved "https://registry.npmjs.org/@ima-worldhealth/rewire/-/rewire-4.1.0.tgz#6c50920a0e305a8c7d270b153710d0538b9f4db1" @@ -227,6 +236,11 @@ resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz#667bfc6186ae7c9e0b45a08960c551437176e1ca" integrity sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw== +"@sindresorhus/is@^4.2.0": + version "4.3.0" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.3.0.tgz#344fd9bf808a84567ba563d00cc54b2f428dbab1" + integrity sha512-wwOvh0eO3PiTEivGJWiZ+b946SlMSb4pe+y+Ur/4S87cwo09pYi+FWHHnbrM3W9W7cBYKDqQXcrFYjYUCOJUEQ== + "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3": version "1.8.3" resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -276,6 +290,13 @@ dependencies: defer-to-connect "^2.0.0" +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" @@ -286,7 +307,7 @@ resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.8.4.tgz#a2cc163e508389c51d4c4119ebff6b9395cec472" integrity sha512-wPS/ncJWhyxJsndsW1B6Ta8D4mi97x1yItSu+rkLDytU3oRIh2CFAjMuJceYwFAh9+DIohndWM0QBA9OU2Hv0g== -"@types/cacheable-request@^6.0.1": +"@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": version "6.0.2" resolved "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA== @@ -1207,6 +1228,11 @@ cacheable-lookup@^5.0.3: resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== +cacheable-lookup@^6.0.4: + version "6.0.4" + resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz#65c0e51721bb7f9f2cb513aed6da4a1b93ad7dc8" + integrity sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A== + cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -2316,7 +2342,7 @@ defer-to-connect@^1.0.1: resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -defer-to-connect@^2.0.0: +defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== @@ -2564,6 +2590,11 @@ dotenv@^14.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-14.0.0.tgz#a993719c572eb39066922fa2031f0bc40ad88311" integrity sha512-lO8c74ruYOG0hCK6fWT7t/PVxqcLKhfOqTahXZQN2UCyfN+ZTJmu48wRUVpkBAXsUGjPOG+ndTh8rjZxyf2xqw== +dotenv@^14.1.0: + version "14.1.0" + resolved "https://registry.npmjs.org/dotenv/-/dotenv-14.1.0.tgz#66e9c0c448501b006f4dd9f08080c9011c7a5e6c" + integrity sha512-h8V+Yfa8m0YSjf3Rgbno51cxWldb4PEixIJVL55VmW7uAfeLQKiaPrEUiBps+ARK9MeqjJgTf269OMmu6lOODQ== + dotgitignore@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -3534,6 +3565,11 @@ fork-stream@^0.0.4: resolved "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70" integrity sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA= +form-data-encoder@1.7.1: + version "1.7.1" + resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== + form-data@4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -3697,7 +3733,7 @@ get-stream@^5.0.0, get-stream@^5.1.0: dependencies: pump "^3.0.0" -get-stream@^6.0.0: +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -3935,6 +3971,25 @@ got@11.8.3: p-cancelable "^2.0.0" responselike "^2.0.0" +got@^12.0.0: + version "12.0.1" + resolved "https://registry.npmjs.org/got/-/got-12.0.1.tgz#78747f1c5bc7069bbd739636ed8b70c7f2140a39" + integrity sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew== + dependencies: + "@sindresorhus/is" "^4.2.0" + "@szmarczak/http-timer" "^5.0.1" + "@types/cacheable-request" "^6.0.2" + "@types/responselike" "^1.0.0" + cacheable-lookup "^6.0.4" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + form-data-encoder "1.7.1" + get-stream "^6.0.1" + http2-wrapper "^2.1.9" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^2.0.0" + got@^9.6.0: version "9.6.0" resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -4327,6 +4382,14 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +http2-wrapper@^2.1.9: + version "2.1.10" + resolved "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.1.10.tgz#307cd0cee2564723692ad34c2d570d12f10e83be" + integrity sha512-QHgsdYkieKp+6JbXP25P+tepqiHYd+FVnDwXpxi/BlUcoIB0nsmTOymTNvETuTO+pDuwcSklPE72VR3DqV+Haw== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + https-proxy-agent@5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -5543,6 +5606,11 @@ lowercase-keys@^2.0.0: resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -6326,6 +6394,11 @@ p-cancelable@^2.0.0: resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -7447,7 +7520,7 @@ requires-port@^1.0.0: resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= -resolve-alpn@^1.0.0: +resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==