From 01cf7502bf07fa34d813fb2584510aaecb7e19d0 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 14 Aug 2024 12:10:57 +0200 Subject: [PATCH] feat(preferences): add app settings for new proxy options COMPASS-8141 (#6099) --- configs/mocha-config-compass/main-process.js | 4 +- package-lock.json | 1279 ++++++++++++----- packages/compass-e2e-tests/helpers/compass.ts | 3 +- .../compass-e2e-tests/helpers/selectors.ts | 2 +- .../tests/atlas-login.test.ts | 10 +- .../tests/auto-connect.test.ts | 4 +- .../tests/global-preferences.test.ts | 10 +- .../compass-preferences-model/package.json | 1 + .../src/compass-utils.ts | 6 +- .../src/feature-flags.ts | 12 + .../compass-preferences-model/src/index.ts | 8 +- .../preferences-persistent-storage.spec.ts | 56 +- .../src/preferences-persistent-storage.ts | 57 +- .../src/preferences-schema.ts | 78 + .../src/preferences.ts | 2 +- .../compass-preferences-model/src/provider.ts | 3 + .../compass-preferences-model/src/react.ts | 17 +- .../src/setup-preferences.ts | 6 +- .../compass-preferences-model/src/utils.ts | 21 + .../compass-preferences-model/tsconfig.json | 3 +- .../src/components/modal.spec.tsx | 16 +- .../compass-settings/src/components/modal.tsx | 48 +- .../settings/proxy-settings-custom.spec.tsx | 92 ++ .../settings/proxy-settings-custom.tsx | 202 +++ .../settings/proxy-settings.spec.tsx | 62 + .../components/settings/proxy-settings.tsx | 156 ++ .../src/components/sidebar.spec.tsx | 16 +- .../src/components/sidebar.tsx | 27 +- packages/compass-settings/src/index.ts | 2 + packages/compass-settings/src/stores/index.ts | 11 +- .../compass-settings/src/stores/settings.ts | 185 ++- packages/compass/src/app/components/home.tsx | 5 +- packages/compass/src/app/index.tsx | 5 +- packages/compass/src/main/application.ts | 5 +- packages/mongodb-explain-compat/package.json | 4 +- 35 files changed, 1949 insertions(+), 469 deletions(-) create mode 100644 packages/compass-settings/src/components/settings/proxy-settings-custom.spec.tsx create mode 100644 packages/compass-settings/src/components/settings/proxy-settings-custom.tsx create mode 100644 packages/compass-settings/src/components/settings/proxy-settings.spec.tsx create mode 100644 packages/compass-settings/src/components/settings/proxy-settings.tsx diff --git a/configs/mocha-config-compass/main-process.js b/configs/mocha-config-compass/main-process.js index 34013c7d304..4544b5c58e7 100644 --- a/configs/mocha-config-compass/main-process.js +++ b/configs/mocha-config-compass/main-process.js @@ -1,6 +1,6 @@ 'use strict'; const { initialize, enable } = require('@electron/remote/main'); -const { app } = require('electron'); +const { app, safeStorage } = require('electron'); app.on('web-contents-created', function (_, webContents) { enable(webContents); }); @@ -14,4 +14,4 @@ initialize(); process.env.COMPASS_TEST_USE_PREFERENCES_SANDBOX = process.env.COMPASS_TEST_USE_PREFERENCES_SANDBOX ?? 'true'; // NB: Not adding this as a dep in package.json to avoid circular dependency -require('compass-preferences-model').setupPreferences(); +require('compass-preferences-model').setupPreferences(undefined, safeStorage); diff --git a/package-lock.json b/package-lock.json index a61761c0100..7eedff4fe3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4160,6 +4160,18 @@ "node": ">= 10" } }, + "node_modules/@electron/rebuild/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@electron/rebuild/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4337,6 +4349,19 @@ "node": ">= 6" } }, + "node_modules/@electron/rebuild/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@electron/rebuild/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -6358,6 +6383,19 @@ "node": ">= 10" } }, + "node_modules/@lerna/create/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@lerna/create/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6650,6 +6688,20 @@ "node": ">= 6" } }, + "node_modules/@lerna/create/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@lerna/create/node_modules/ignore-walk": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", @@ -7864,6 +7916,78 @@ "node": ">= 16" } }, + "node_modules/@mongodb-js/devtools-proxy-support": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.4.tgz", + "integrity": "sha512-+KqoTzqLdA0MOpaqxJH6VDWzsHEWLnt1GFfuaFrGmJLUgU7sC1QEP8la61eOAC4fR1W6S86ipZZaQNdJbrXWVw==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/socksv5": "^0.0.10", + "agent-base": "^7.1.1", + "debug": "^4.3.6", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "lru-cache": "^11.0.0", + "node-fetch": "^3.3.2", + "pac-proxy-agent": "^7.0.2", + "socks-proxy-agent": "^8.0.4", + "ssh2": "^1.15.0", + "system-ca": "^2.0.0" + } + }, + "node_modules/@mongodb-js/devtools-proxy-support/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@mongodb-js/devtools-proxy-support/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@mongodb-js/devtools-proxy-support/node_modules/lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@mongodb-js/devtools-proxy-support/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/@mongodb-js/dl-center": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.0.1.tgz", @@ -8628,6 +8752,18 @@ "ssh2": "^1.15.0" } }, + "node_modules/@mongodb-js/socksv5": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@mongodb-js/socksv5/-/socksv5-0.0.10.tgz", + "integrity": "sha512-JDz2fLKsjMiSNUxKrCpGptsgu7DzsXfu4gnUQ3RhUaBS1d4YbLrt6HejpckAiHIAa+niBpZAeiUsoop0IihWsw==", + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@mongodb-js/ssh-tunnel": { "resolved": "packages/ssh-tunnel", "link": true @@ -9163,6 +9299,18 @@ "node": ">= 10" } }, + "node_modules/@npmcli/arborist/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@npmcli/arborist/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -9324,6 +9472,19 @@ "node": ">= 6" } }, + "node_modules/@npmcli/arborist/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@npmcli/arborist/node_modules/ignore-walk": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.0.tgz", @@ -10110,6 +10271,18 @@ "node": ">= 10" } }, + "node_modules/@npmcli/metavuln-calculator/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@npmcli/metavuln-calculator/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -10240,6 +10413,19 @@ "node": ">= 6" } }, + "node_modules/@npmcli/metavuln-calculator/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@npmcli/metavuln-calculator/node_modules/ignore-walk": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.0.tgz", @@ -11762,6 +11948,19 @@ "node": ">= 10" } }, + "node_modules/@sigstore/sign/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@sigstore/sign/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -11876,6 +12075,20 @@ "node": ">= 6" } }, + "node_modules/@sigstore/sign/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@sigstore/sign/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -13115,6 +13328,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", "engines": { "node": ">= 6" } @@ -13122,8 +13336,7 @@ "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "node_modules/@tsconfig/node10": { "version": "1.0.8", @@ -14955,14 +15168,15 @@ } }, "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", "dependencies": { - "debug": "4" + "debug": "^4.3.4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 14" } }, "node_modules/agentkeepalive": { @@ -16373,7 +16587,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "dependencies": { "tslib": "^2.0.1" }, @@ -16389,8 +16602,7 @@ "node_modules/ast-types/node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/astral-regex": { "version": "1.0.0", @@ -16988,7 +17200,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -19416,7 +19627,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, "engines": { "node": ">= 14" } @@ -20071,7 +20281,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "dependencies": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -24136,7 +24345,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, "funding": [ { "type": "github", @@ -24467,7 +24675,6 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, "dependencies": { "fetch-blob": "^3.1.2" }, @@ -25076,18 +25283,6 @@ "node": "^16.13 || >=18 || >=20" } }, - "node_modules/geckodriver/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/geckodriver/node_modules/data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", @@ -25109,32 +25304,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/geckodriver/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/geckodriver/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/geckodriver/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -25562,7 +25731,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "dev": true, "dependencies": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -25577,7 +25745,6 @@ "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -26612,16 +26779,16 @@ } }, "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/http-signature": { @@ -26662,15 +26829,16 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "license": "MIT", "dependencies": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/human-signals": { @@ -28193,6 +28361,18 @@ "acorn-walk": "^8.0.2" } }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/jsdom/node_modules/entities": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", @@ -29229,6 +29409,19 @@ "node": ">= 10" } }, + "node_modules/lerna/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/lerna/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -29521,6 +29714,20 @@ "node": ">= 6" } }, + "node_modules/lerna/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/lerna/node_modules/ignore-walk": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", @@ -31448,6 +31655,63 @@ "node": ">= 10" } }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/map-obj": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", @@ -33048,7 +33312,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, "engines": { "node": ">= 0.4.0" } @@ -33105,7 +33368,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true, "funding": [ { "type": "github", @@ -33174,6 +33436,19 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/node-gyp/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -33216,6 +33491,35 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, + "node_modules/node-gyp/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/node-gyp/node_modules/make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -33530,6 +33834,18 @@ "node": ">= 10" } }, + "node_modules/npm-registry-fetch/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/npm-registry-fetch/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -33655,6 +33971,19 @@ "node": ">= 6" } }, + "node_modules/npm-registry-fetch/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/npm-registry-fetch/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -34925,7 +35254,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", - "dev": true, + "license": "MIT", "dependencies": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -34940,63 +35269,10 @@ "node": ">= 14" } }, - "node_modules/pac-proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, "dependencies": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -35058,6 +35334,45 @@ "node": ">=10" } }, + "node_modules/pacote/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/pacote/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pacote/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/pacote/node_modules/make-fetch-happen": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.0.3.tgz", @@ -35100,6 +35415,20 @@ "node": ">=10" } }, + "node_modules/pacote/node_modules/socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -37230,44 +37559,6 @@ "node": ">= 14" } }, - "node_modules/proxy-agent/node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -37277,20 +37568,6 @@ "node": ">=12" } }, - "node_modules/proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -37451,6 +37728,19 @@ } } }, + "node_modules/puppeteer/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/puppeteer/node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -39409,6 +39699,19 @@ "node": ">= 10" } }, + "node_modules/sigstore/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/sigstore/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -39523,6 +39826,20 @@ "node": ">= 6" } }, + "node_modules/sigstore/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/sigstore/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -39982,16 +40299,17 @@ } }, "node_modules/socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/socksv5": { @@ -41601,6 +41919,19 @@ "node": ">= 10" } }, + "node_modules/tuf-js/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/tuf-js/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -41715,6 +42046,20 @@ "node": ">= 6" } }, + "node_modules/tuf-js/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/tuf-js/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -42545,7 +42890,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true, "engines": { "node": ">= 8" } @@ -46180,6 +46524,7 @@ "dependencies": { "@mongodb-js/compass-logging": "^1.4.3", "@mongodb-js/compass-user-data": "^0.3.3", + "@mongodb-js/devtools-proxy-support": "^0.3.4", "bson": "^6.7.0", "hadron-app-registry": "^9.2.2", "hadron-ipc": "^3.2.20", @@ -50339,6 +50684,18 @@ "node": ">= 10" } }, + "scripts/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "scripts/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -50430,6 +50787,19 @@ "node": ">= 6" } }, + "scripts/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "scripts/node_modules/lru-cache": { "version": "7.10.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", @@ -53045,6 +53415,14 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -53182,6 +53560,15 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -54844,6 +55231,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -55058,6 +55454,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "ignore-walk": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", @@ -57567,6 +57973,14 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -57642,6 +58056,15 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.10.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", @@ -59108,6 +59531,54 @@ "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-github-repo/-/devtools-github-repo-1.4.1.tgz", "integrity": "sha512-wpVbM7MTft2mFc66ZOulAW4TnyK9fzYL/dqhcUk7DMcdwO8TcR1VZPkh55fRugSXgkfCUcxfZmqmuSSAudLGjA==" }, + "@mongodb-js/devtools-proxy-support": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.3.4.tgz", + "integrity": "sha512-+KqoTzqLdA0MOpaqxJH6VDWzsHEWLnt1GFfuaFrGmJLUgU7sC1QEP8la61eOAC4fR1W6S86ipZZaQNdJbrXWVw==", + "requires": { + "@mongodb-js/socksv5": "^0.0.10", + "agent-base": "^7.1.1", + "debug": "^4.3.6", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "lru-cache": "^11.0.0", + "node-fetch": "^3.3.2", + "pac-proxy-agent": "^7.0.2", + "socks-proxy-agent": "^8.0.4", + "ssh2": "^1.15.0", + "system-ca": "^2.0.0" + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "requires": { + "ms": "2.1.2" + } + }, + "lru-cache": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz", + "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + } + } + }, "@mongodb-js/dl-center": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@mongodb-js/dl-center/-/dl-center-1.0.1.tgz", @@ -59871,6 +60342,14 @@ "ssh2": "^1.15.0" } }, + "@mongodb-js/socksv5": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@mongodb-js/socksv5/-/socksv5-0.0.10.tgz", + "integrity": "sha512-JDz2fLKsjMiSNUxKrCpGptsgu7DzsXfu4gnUQ3RhUaBS1d4YbLrt6HejpckAiHIAa+niBpZAeiUsoop0IihWsw==", + "requires": { + "ip-address": "^9.0.5" + } + }, "@mongodb-js/ssh-tunnel": { "version": "file:packages/ssh-tunnel", "requires": { @@ -60700,6 +61179,14 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -60819,6 +61306,15 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "ignore-walk": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.0.tgz", @@ -61416,6 +61912,14 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -61519,6 +62023,15 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "ignore-walk": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.0.tgz", @@ -62645,6 +63158,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -62733,6 +63255,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -63744,8 +64276,7 @@ "@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" }, "@tsconfig/node10": { "version": "1.0.8", @@ -65325,11 +65856,11 @@ } }, "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "requires": { - "debug": "4" + "debug": "^4.3.4" } }, "agentkeepalive": { @@ -66512,7 +67043,6 @@ "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, "requires": { "tslib": "^2.0.1" }, @@ -66520,8 +67050,7 @@ "tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" } } }, @@ -66986,8 +67515,7 @@ "basic-ftp": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==" }, "batch": { "version": "0.6.1", @@ -68268,6 +68796,7 @@ "requires": { "@mongodb-js/compass-logging": "^1.4.3", "@mongodb-js/compass-user-data": "^0.3.3", + "@mongodb-js/devtools-proxy-support": "^0.3.4", "@mongodb-js/eslint-config-compass": "^1.1.4", "@mongodb-js/mocha-config-compass": "^1.3.10", "@testing-library/react": "^12.1.5", @@ -69194,8 +69723,7 @@ "data-uri-to-buffer": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==" }, "data-urls": { "version": "3.0.2", @@ -69660,7 +70188,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, "requires": { "ast-types": "^0.13.4", "escodegen": "^2.1.0", @@ -72861,7 +73388,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, "requires": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -73106,7 +73632,6 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, "requires": { "fetch-blob": "^3.1.2" } @@ -73598,15 +74123,6 @@ "which": "^4.0.0" }, "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, "data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", @@ -73619,26 +74135,6 @@ "integrity": "sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==", "dev": true }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, "isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -73958,7 +74454,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", - "dev": true, "requires": { "basic-ftp": "^5.0.2", "data-uri-to-buffer": "^6.0.2", @@ -73970,7 +74465,6 @@ "version": "11.2.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -75578,13 +76072,12 @@ } }, "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" } }, "http-signature": { @@ -75614,11 +76107,11 @@ } }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "requires": { - "agent-base": "6", + "agent-base": "^7.0.2", "debug": "4" } }, @@ -76718,6 +77211,14 @@ "acorn-walk": "^8.0.2" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "entities": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", @@ -77557,6 +78058,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -77771,6 +78281,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "ignore-walk": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", @@ -79422,6 +79942,49 @@ "promise-retry": "^2.0.1", "socks-proxy-agent": "^5.0.0", "ssri": "^8.0.0" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } + } } }, "map-obj": { @@ -80922,8 +81485,7 @@ "netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==" }, "next-tick": { "version": "1.1.0", @@ -80973,8 +81535,7 @@ "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "dev": true + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" }, "node-fetch": { "version": "2.6.7", @@ -81002,6 +81563,15 @@ "which": "^2.0.2" }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -81035,6 +81605,27 @@ "wide-align": "^1.1.5" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -81291,6 +81882,14 @@ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -81387,6 +81986,15 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -82325,7 +82933,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", - "dev": true, "requires": { "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.0.2", @@ -82335,55 +82942,12 @@ "https-proxy-agent": "^7.0.5", "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.4" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } - } } }, "pac-resolver": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, "requires": { "degenerator": "^5.0.0", "netmask": "^2.0.2" @@ -82433,6 +82997,33 @@ "tar": "^6.1.0" }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "make-fetch-happen": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.0.3.tgz", @@ -82468,6 +83059,16 @@ "minizlib": "^2.0.0", "npm-package-arg": "^8.0.0" } + }, + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } } } }, @@ -84099,51 +84700,11 @@ "socks-proxy-agent": "^8.0.2" }, "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - }, - "http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "requires": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - } - }, - "https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "requires": { - "agent-base": "^7.0.2", - "debug": "4" - } - }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true - }, - "socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", - "dev": true, - "requires": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - } } } }, @@ -84241,6 +84802,15 @@ "ws": "8.8.0" }, "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -85776,6 +86346,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -85864,6 +86443,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -86223,13 +86812,13 @@ } }, "socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", "requires": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" } }, "socksv5": { @@ -87487,6 +88076,15 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -87575,6 +88173,16 @@ "debug": "4" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -88222,8 +88830,7 @@ "web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" }, "web-vitals": { "version": "2.1.2", diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index b03ef09fa5a..c2ccbc862c5 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -481,7 +481,8 @@ async function getCompassExecutionParameters(): Promise<{ ); const binary = testPackagedApp ? getCompassBinPath(await getCompassBuildMetadata()) - : require('electron'); + : // eslint-disable-next-line @typescript-eslint/no-var-requires + (require('electron') as unknown as string); return { testPackagedApp, binary }; } diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 9c3f08f8ff4..61a67d14a31 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -14,7 +14,7 @@ export const CloseSettingsModalButton = `${SettingsModal} [aria-label="Close mod export const SaveSettingsButton = `${SettingsModal} [data-testid="submit-button"]`; export const SettingsModalTabSelector = (name: string) => `${SettingsModal} [data-testid="sidebar-${name}-item"]`; -export const GeneralSettingsButton = SettingsModalTabSelector('General'); +export const GeneralSettingsButton = SettingsModalTabSelector('general'); export const GeneralSettingsContent = `${SettingsModal} [data-testid="general-settings"]`; export const SettingsInputElement = (settingName: string): string => { diff --git a/packages/compass-e2e-tests/tests/atlas-login.test.ts b/packages/compass-e2e-tests/tests/atlas-login.test.ts index 4264952a558..33bec50a466 100644 --- a/packages/compass-e2e-tests/tests/atlas-login.test.ts +++ b/packages/compass-e2e-tests/tests/atlas-login.test.ts @@ -149,7 +149,7 @@ describe('Atlas Login', function () { describe('in settings', function () { it('should sign in user when clicking on "Log in with Atlas" button', async function () { - await browser.openSettingsModal('Artificial Intelligence'); + await browser.openSettingsModal('ai'); await browser.clickVisible(Selectors.LogInWithAtlasButton); @@ -180,7 +180,7 @@ describe('Atlas Login', function () { ); expect(atlasUserIdBefore).to.not.exist; - await browser.openSettingsModal('Artificial Intelligence'); + await browser.openSettingsModal('ai'); await browser.clickVisible(Selectors.LogInWithAtlasButton); @@ -206,7 +206,7 @@ describe('Atlas Login', function () { }); it('should sign out user when "Disconnect" clicked', async function () { - await browser.openSettingsModal('Artificial Intelligence'); + await browser.openSettingsModal('ai'); await browser.clickVisible(Selectors.LogInWithAtlasButton); const loginStatus = browser.$(Selectors.AtlasLoginStatus); @@ -228,7 +228,7 @@ describe('Atlas Login', function () { }); it('should sign in user when disconnected and clicking again on "Log in with Atlas" button', async function () { - await browser.openSettingsModal('Artificial Intelligence'); + await browser.openSettingsModal('ai'); await browser.clickVisible(Selectors.LogInWithAtlasButton); let loginStatus = browser.$(Selectors.AtlasLoginStatus); @@ -259,7 +259,7 @@ describe('Atlas Login', function () { return Promise.reject(new Error('Auth failed')); }; - await browser.openSettingsModal('Artificial Intelligence'); + await browser.openSettingsModal('ai'); await browser.clickVisible(Selectors.LogInWithAtlasButton); const errorToast = browser.$(Selectors.AtlasLoginErrorToast); diff --git a/packages/compass-e2e-tests/tests/auto-connect.test.ts b/packages/compass-e2e-tests/tests/auto-connect.test.ts index bb02397f2ce..a88a1dc33ad 100644 --- a/packages/compass-e2e-tests/tests/auto-connect.test.ts +++ b/packages/compass-e2e-tests/tests/auto-connect.test.ts @@ -273,7 +273,9 @@ describe('Automatically connecting from the command line', function () { }); await browser.execute(() => { // eslint-disable-next-line @typescript-eslint/no-var-requires - require('electron').ipcRenderer.call('test:show-connect-window'); + (require('electron').ipcRenderer as any).call( + 'test:show-connect-window' + ); }); // Switch to the other window diff --git a/packages/compass-e2e-tests/tests/global-preferences.test.ts b/packages/compass-e2e-tests/tests/global-preferences.test.ts index edae3141b1d..f9c4339d16a 100644 --- a/packages/compass-e2e-tests/tests/global-preferences.test.ts +++ b/packages/compass-e2e-tests/tests/global-preferences.test.ts @@ -60,7 +60,7 @@ describe('Global preferences', function () { }); const browser = compass.browser; try { - await browser.openSettingsModal('Privacy'); + await browser.openSettingsModal('privacy'); { const { disabled, value, bannerText } = await getCheckboxAndBannerState( browser, @@ -91,7 +91,7 @@ describe('Global preferences', function () { const compass = await init(this.test?.fullTitle()); const browser = compass.browser; try { - await browser.openSettingsModal('Privacy'); + await browser.openSettingsModal('privacy'); { const { disabled, value, bannerText } = await getCheckboxAndBannerState( browser, @@ -122,7 +122,7 @@ describe('Global preferences', function () { const compass = await init(this.test?.fullTitle()); const browser = compass.browser; try { - await browser.openSettingsModal('Privacy'); + await browser.openSettingsModal('privacy'); { const { disabled, value, bannerText } = await getCheckboxAndBannerState( browser, @@ -153,7 +153,7 @@ describe('Global preferences', function () { const compass = await init(this.test?.fullTitle()); const browser = compass.browser; try { - await browser.openSettingsModal('Privacy'); + await browser.openSettingsModal('privacy'); const { disabled, value, bannerText } = await getCheckboxAndBannerState( browser, 'enableMaps' @@ -177,7 +177,7 @@ describe('Global preferences', function () { // section so we can have some level of confidence that toggling the // setting did something and that it would be detected by our assertions // below. - await browser.openSettingsModal('Privacy'); + await browser.openSettingsModal('privacy'); await browser.clickVisible(Selectors.GeneralSettingsButton); { const { disabled, value, bannerText } = await getCheckboxAndBannerState( diff --git a/packages/compass-preferences-model/package.json b/packages/compass-preferences-model/package.json index 43d2e8e0279..8e2f7e6a951 100644 --- a/packages/compass-preferences-model/package.json +++ b/packages/compass-preferences-model/package.json @@ -51,6 +51,7 @@ "dependencies": { "@mongodb-js/compass-logging": "^1.4.3", "@mongodb-js/compass-user-data": "^0.3.3", + "@mongodb-js/devtools-proxy-support": "^0.3.4", "bson": "^6.7.0", "hadron-app-registry": "^9.2.2", "hadron-ipc": "^3.2.20", diff --git a/packages/compass-preferences-model/src/compass-utils.ts b/packages/compass-preferences-model/src/compass-utils.ts index 89f80d90377..c97dd18f131 100644 --- a/packages/compass-preferences-model/src/compass-utils.ts +++ b/packages/compass-preferences-model/src/compass-utils.ts @@ -4,11 +4,13 @@ import type { UserStorage } from './user-storage'; import { UserStorageImpl } from './user-storage'; import { getActiveUserId } from './utils'; import { setupPreferences } from './setup-preferences'; +import type { PreferencesSafeStorage } from './preferences-persistent-storage'; export async function setupPreferencesAndUser( - globalPreferences: ParsedGlobalPreferencesResult + globalPreferences: ParsedGlobalPreferencesResult, + safeStorage: PreferencesSafeStorage ): Promise<{ userStorage: UserStorage; preferences: PreferencesAccess }> { - const preferences = await setupPreferences(globalPreferences); + const preferences = await setupPreferences(globalPreferences, safeStorage); const userStorage = new UserStorageImpl(); const user = await userStorage.getOrCreate(getActiveUserId(preferences)); // update user info (telemetryAnonymousId and userCreatedAt) in preferences to diff --git a/packages/compass-preferences-model/src/feature-flags.ts b/packages/compass-preferences-model/src/feature-flags.ts index 3d129a8aab2..0e3c28a238e 100644 --- a/packages/compass-preferences-model/src/feature-flags.ts +++ b/packages/compass-preferences-model/src/feature-flags.ts @@ -20,6 +20,7 @@ export type FeatureFlags = { enableRenameCollectionModal: boolean; enableNewMultipleConnectionSystem: boolean; enableQueryHistoryAutocomplete: boolean; + enableProxySupport: boolean; }; export const featureFlags: Required<{ @@ -85,4 +86,15 @@ export const featureFlags: Required<{ 'Enables showing query history items in the query bar autocomplete.', }, }, + + /** + * Feature flag for explicit proxy configuration support. + */ + enableProxySupport: { + stage: 'development', + description: { + short: 'Enables support for explicit proxy configuration.', + long: 'Allows users to specify proxy configuration for the entire Compass application.', + }, + }, }; diff --git a/packages/compass-preferences-model/src/index.ts b/packages/compass-preferences-model/src/index.ts index 333f888eccf..87b6c902ec8 100644 --- a/packages/compass-preferences-model/src/index.ts +++ b/packages/compass-preferences-model/src/index.ts @@ -23,7 +23,12 @@ export { getExampleConfigFile, } from './global-config'; export type { ParsedGlobalPreferencesResult } from './global-config'; -export { getActiveUser, isAIFeatureEnabled } from './utils'; +export { + getActiveUser, + isAIFeatureEnabled, + proxyPreferenceToProxyOptions, + proxyOptionsToProxyPreference, +} from './utils'; export { setupPreferencesAndUser } from './compass-utils'; export type { User, UserStorage } from './user-storage'; export type { PreferencesAccess }; @@ -33,3 +38,4 @@ export const defaultPreferencesInstance: PreferencesAccess = export function createSandboxFromDefaultPreferences(): Promise { return defaultPreferencesInstance.createSandbox(); } +export type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; diff --git a/packages/compass-preferences-model/src/preferences-persistent-storage.spec.ts b/packages/compass-preferences-model/src/preferences-persistent-storage.spec.ts index 3583845e371..146834860fb 100644 --- a/packages/compass-preferences-model/src/preferences-persistent-storage.spec.ts +++ b/packages/compass-preferences-model/src/preferences-persistent-storage.spec.ts @@ -1,9 +1,15 @@ import fs from 'fs/promises'; import path from 'path'; import os from 'os'; +import crypto from 'crypto'; import { PersistentStorage } from './preferences-persistent-storage'; import { getDefaultsForStoredPreferences } from './preferences-schema'; import { expect } from 'chai'; +import { + proxyOptionsToProxyPreference, + proxyPreferenceToProxyOptions, +} from './utils'; +import type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; const getPreferencesFolder = (tmpDir: string) => { return path.join(tmpDir, 'AppPreferences'); @@ -22,7 +28,7 @@ describe('PersistentStorage', function () { }); afterEach(async function () { - await fs.rmdir(tmpDir, { recursive: true }); + await fs.rm(tmpDir, { recursive: true, force: true }); }); it('sets up the storage', async function () { @@ -43,7 +49,7 @@ describe('PersistentStorage', function () { expect(async () => await fs.access(preferencesFile)).to.not.throw; expect( - JSON.parse((await fs.readFile(preferencesFile)).toString()) + JSON.parse(await fs.readFile(preferencesFile, 'utf8')) ).to.deep.equal(getDefaultsForStoredPreferences()); }); @@ -60,7 +66,7 @@ describe('PersistentStorage', function () { await storage.setup(); expect( - JSON.parse((await fs.readFile(preferencesFile)).toString()) + JSON.parse(await fs.readFile(preferencesFile, 'utf8')) ).to.deep.equal(getDefaultsForStoredPreferences()); }); @@ -126,4 +132,48 @@ describe('PersistentStorage', function () { getDefaultsForStoredPreferences() ); }); + + it('encrypts and decrypts sensitive fields', async function () { + const storage = new PersistentStorage(tmpDir, { + encryptString: (str: string) => + crypto + .createCipheriv('aes-256-gcm', 'asdf'.repeat(8), '0'.repeat(32)) + .update(str), + decryptString: (str: Buffer) => + crypto + .createDecipheriv('aes-256-gcm', 'asdf'.repeat(8), '0'.repeat(32)) + .update(str) + .toString('utf8'), + }); + await storage.setup(); + + const proxyOptions: DevtoolsProxyOptions = { + proxy: 'socks5://AzureDiamond:hunter2@example.com/', + sshOptions: { + identityKeyFile: 'asdf', + identityKeyPassphrase: 's3cr3t', + }, + }; + + await storage.updatePreferences({ + proxy: proxyOptionsToProxyPreference(proxyOptions), + }); + + const newPreferences = storage.getPreferences(); + + expect(proxyPreferenceToProxyOptions(newPreferences.proxy)).to.deep.equal( + proxyOptions + ); + + const preferencesFile = getPreferencesFile(tmpDir); + const onDisk = JSON.parse(await fs.readFile(preferencesFile, 'utf8')).proxy; + + // Non-secrets are visible, secrets are not + expect(onDisk).to.be.a('string'); + expect(onDisk).to.include('AzureDiamond'); + expect(onDisk).to.include('example.com'); + expect(onDisk).to.include('asdf'); + expect(onDisk).not.to.include('hunter2'); + expect(onDisk).not.to.include('s3cr3t'); + }); }); diff --git a/packages/compass-preferences-model/src/preferences-persistent-storage.ts b/packages/compass-preferences-model/src/preferences-persistent-storage.ts index 168f9e720da..d4973a32cd2 100644 --- a/packages/compass-preferences-model/src/preferences-persistent-storage.ts +++ b/packages/compass-preferences-model/src/preferences-persistent-storage.ts @@ -3,6 +3,7 @@ import { UserData } from '@mongodb-js/compass-user-data'; import { getDefaultsForStoredPreferences, getPreferencesValidator, + listEncryptedStoredPreferences, } from './preferences-schema'; import type { StoredPreferences, @@ -11,17 +12,25 @@ import type { import type { PreferencesStorage } from './preferences-storage'; +export type PreferencesSafeStorage = { + // ~ partial Electron.SafeStorage + decryptString(encrypted: Buffer): string; + encryptString(plainText: string): Buffer; +}; + export class PersistentStorage implements PreferencesStorage { private readonly file = 'General'; private readonly defaultPreferences = getDefaultsForStoredPreferences(); private readonly userData: UserData; private preferences: StoredPreferences = getDefaultsForStoredPreferences(); + private safeStorage?: PreferencesSafeStorage; - constructor(basePath?: string) { + constructor(basePath?: string, safeStorage?: PreferencesSafeStorage) { this.userData = new UserData(getPreferencesValidator(), { subdir: 'AppPreferences', basePath, }); + this.safeStorage = safeStorage; } async setup() { @@ -33,17 +42,57 @@ export class PersistentStorage implements PreferencesStorage { e instanceof SyntaxError // Invalid json ) { // Create the file for the first time - await this.userData.write(this.file, this.defaultPreferences); + await this.writePreferences(this.defaultPreferences); return; } throw e; } } + private async writePreferences( + preferences: z.input + ): Promise { + const copy = { ...preferences }; + for (const [key, { extract }] of listEncryptedStoredPreferences()) { + if (copy[key]) { + // The PreferenceDefinition typing ensures that only string properties can be encrypted + const { remainder, secrets } = extract(copy[key] as string); + (copy as any)[key] = JSON.stringify({ + remainder, + secrets: this.getSafeStorage() + .encryptString(secrets) + .toString('base64'), + }); + } + } + await this.userData.write(this.file, copy); + } + private async readPreferences(): Promise { - return await this.userData.readOne(this.file, { + const copy = await this.userData.readOne(this.file, { ignoreErrors: false, }); + for (const [key, { merge }] of listEncryptedStoredPreferences()) { + if (copy[key]) { + const { remainder, secrets } = JSON.parse(copy[key] as string); + (copy as any)[key] = merge({ + remainder, + secrets: this.getSafeStorage().decryptString( + Buffer.from(secrets, 'base64') + ), + }); + } + } + return copy; + } + + private getSafeStorage(): PreferencesSafeStorage { + if (!this.safeStorage) { + throw new Error( + 'This instance of PersistentStorage has not been configured with a safeStorage provider' + ); + } + return this.safeStorage; } getPreferences(): StoredPreferences { @@ -56,7 +105,7 @@ export class PersistentStorage implements PreferencesStorage { async updatePreferences( attributes: Partial> ) { - await this.userData.write(this.file, { + await this.writePreferences({ ...(await this.readPreferences()), ...attributes, }); diff --git a/packages/compass-preferences-model/src/preferences-schema.ts b/packages/compass-preferences-model/src/preferences-schema.ts index 35866942a8d..f7cfa99b9d5 100644 --- a/packages/compass-preferences-model/src/preferences-schema.ts +++ b/packages/compass-preferences-model/src/preferences-schema.ts @@ -5,6 +5,14 @@ import { featureFlags, } from './feature-flags'; import { parseRecord } from './parse-record'; +import { + extractProxySecrets, + mergeProxySecrets, +} from '@mongodb-js/devtools-proxy-support/proxy-options'; +import { + proxyOptionsToProxyPreference, + proxyPreferenceToProxyOptions, +} from './utils'; export const THEMES_VALUES = ['DARK', 'LIGHT', 'OS_THEME'] as const; export type THEMES = typeof THEMES_VALUES[number]; @@ -59,6 +67,8 @@ export type UserConfigurablePreferences = PermanentFeatureFlags & enablePerformanceAdvisorBanner: boolean; maximumNumberOfActiveConnections?: number; enableShowDialogOnQuit: boolean; + enableProxySupport: boolean; + proxy: string; }; export type InternalUserPreferences = { @@ -139,6 +149,11 @@ export type DeriveValueFunction = ( getState: (key: K) => PreferenceState ) => { value: T; state: PreferenceState }; +type SecretsConfiguration = { + extract(original: T): { remainder: string; secrets: string }; + merge(extracted: { remainder: string; secrets: string }): T; +}; + type PreferenceDefinition = { /** Whether the preference can be modified through the Settings UI */ ui: K extends keyof UserConfigurablePreferences ? true : false; @@ -175,6 +190,11 @@ type PreferenceDefinition = { AllPreferences[K] | undefined >; type: PreferenceType; + secrets?: K extends keyof UserPreferences + ? AllPreferences[K] extends string + ? SecretsConfiguration + : undefined + : undefined; }; export type PreferenceStateInformation = Partial< @@ -760,6 +780,52 @@ export const storedUserPreferencesProps: Required<{ type: 'boolean', }, + proxy: { + ui: true, + cli: true, + global: true, + description: { + short: 'Specify a proxy for Compass to use', + long: 'Specify a HTTP, HTTPS or Socks5 proxy to use for connecting to external services (default is picking proxies from environment variables)', + }, + // Internally either a URL or a DevtoolsProxyOptions object as JSON + validator: z + .union([ + z.string().url(), + z.literal(''), + z.custom((val) => { + if (typeof val !== 'string') return false; + try { + JSON.parse(val); + return true; + } catch { + return false; + } + }), + ]) + .default(''), + type: 'string', + secrets: { + extract(original) { + const { secrets, ...remainder } = extractProxySecrets( + proxyPreferenceToProxyOptions(original) + ); + return { + remainder: JSON.stringify(remainder), + secrets: JSON.stringify(secrets), + }; + }, + merge({ remainder, secrets }) { + return proxyOptionsToProxyPreference( + mergeProxySecrets({ + ...JSON.parse(remainder), + secrets: JSON.parse(secrets), + }) + ); + }, + }, + }, + ...allFeatureFlagsProps, }; @@ -999,6 +1065,18 @@ export function getDefaultsForStoredPreferences(): StoredPreferences { ); } +export function listEncryptedStoredPreferences(): [ + keyof StoredPreferences, + SecretsConfiguration +][] { + return Object.entries(storedUserPreferencesProps) + .filter(([, value]) => value.secrets) + .map(([key, { secrets }]) => [ + key as keyof typeof storedUserPreferencesProps, + secrets!, + ]); +} + export function getSettingDescription< Name extends Exclude >( diff --git a/packages/compass-preferences-model/src/preferences.ts b/packages/compass-preferences-model/src/preferences.ts index 08e5ba92726..5d7bf63cdd9 100644 --- a/packages/compass-preferences-model/src/preferences.ts +++ b/packages/compass-preferences-model/src/preferences.ts @@ -83,7 +83,7 @@ export class Preferences { } } - setupStorage() { + setupStorage(): Promise { return this._preferencesStorage.setup(); } diff --git a/packages/compass-preferences-model/src/provider.ts b/packages/compass-preferences-model/src/provider.ts index db93d5cefae..b5f3bfc92dc 100644 --- a/packages/compass-preferences-model/src/provider.ts +++ b/packages/compass-preferences-model/src/provider.ts @@ -4,8 +4,11 @@ export { useIsAIFeatureEnabled, isAIFeatureEnabled, useHasAIFeatureCloudRolloutAccess, + proxyPreferenceToProxyOptions, + proxyOptionsToProxyPreference, } from './utils'; export { capMaxTimeMSAtPreferenceLimit } from './maxtimems'; export { featureFlags } from './feature-flags'; export { getSettingDescription } from './preferences-schema'; export type { AllPreferences } from './preferences-schema'; +export type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; diff --git a/packages/compass-preferences-model/src/react.ts b/packages/compass-preferences-model/src/react.ts index f44a007e60a..2dc7caf8526 100644 --- a/packages/compass-preferences-model/src/react.ts +++ b/packages/compass-preferences-model/src/react.ts @@ -14,16 +14,19 @@ import { ReadOnlyPreferenceAccess } from './read-only-preferences-access'; import { createServiceLocator } from 'hadron-app-registry'; import { pick } from 'lodash'; -const PreferencesContext = createContext( - // Our context starts with our read-only preference access but we expect - // different runtimes to provide their own access implementation at render. - new ReadOnlyPreferenceAccess() -); +const PreferencesContext = createContext(null); +// Lazily initialized to avoid a cyclic dependency. +let defaultPreferences: ReadOnlyPreferenceAccess | null; export const PreferencesProvider = PreferencesContext.Provider; -export function usePreferencesContext() { - return useContext(PreferencesContext); +export function usePreferencesContext(): PreferencesAccess { + // We fall back to our read-only preference access but we expect + // different runtimes to provide their own access implementation at render. + return ( + useContext(PreferencesContext) ?? + (defaultPreferences ??= new ReadOnlyPreferenceAccess()) + ); } export const preferencesLocator = createServiceLocator( diff --git a/packages/compass-preferences-model/src/setup-preferences.ts b/packages/compass-preferences-model/src/setup-preferences.ts index fba1ccf521e..8ab2e3eeec4 100644 --- a/packages/compass-preferences-model/src/setup-preferences.ts +++ b/packages/compass-preferences-model/src/setup-preferences.ts @@ -10,6 +10,7 @@ import type { PreferenceSandboxProperties } from './preferences'; import type { ParsedGlobalPreferencesResult } from './global-config'; import { getActiveUser, type PreferencesAccess } from '.'; +import type { PreferencesSafeStorage } from './preferences-persistent-storage'; import { PersistentStorage } from './preferences-persistent-storage'; import { InMemoryStorage } from './preferences-in-memory-storage'; import { createLogger } from '@mongodb-js/compass-logging'; @@ -18,7 +19,8 @@ const compassPreferencesLogger = createLogger('COMPASS-PREFERENCES'); let preferencesSingleton: Preferences | undefined; export async function setupPreferences( - globalPreferences: ParsedGlobalPreferencesResult + globalPreferences: ParsedGlobalPreferencesResult, + safeStorage: PreferencesSafeStorage ): Promise { if (preferencesSingleton) { throw new Error('Preferences setup already been called!'); @@ -27,7 +29,7 @@ export async function setupPreferences( const preferencesStorage = process.env.COMPASS_TEST_USE_PREFERENCES_SANDBOX === 'true' ? new InMemoryStorage() - : new PersistentStorage(); + : new PersistentStorage(undefined, safeStorage); const preferences = (preferencesSingleton = new Preferences({ logger: compassPreferencesLogger, diff --git a/packages/compass-preferences-model/src/utils.ts b/packages/compass-preferences-model/src/utils.ts index 850c75f642b..287593f05d3 100644 --- a/packages/compass-preferences-model/src/utils.ts +++ b/packages/compass-preferences-model/src/utils.ts @@ -1,5 +1,6 @@ import { usePreference } from './react'; import type { AllPreferences, PreferencesAccess, User } from '.'; +import type { DevtoolsProxyOptions } from '@mongodb-js/devtools-proxy-support'; export function getActiveUserId( preferences: Pick @@ -56,3 +57,23 @@ export function useHasAIFeatureCloudRolloutAccess() { const cloudFeatureRolloutAccess = usePreference('cloudFeatureRolloutAccess'); return !!cloudFeatureRolloutAccess?.GEN_AI_COMPASS; } + +export function proxyPreferenceToProxyOptions( + proxy: string +): DevtoolsProxyOptions { + if (!proxy) + return { + useEnvironmentVariableProxies: true, + }; + try { + return JSON.parse(proxy); + } catch { + return { proxy: new URL(proxy).href, useEnvironmentVariableProxies: true }; + } +} + +export function proxyOptionsToProxyPreference( + proxyOptions: DevtoolsProxyOptions +): string { + return JSON.stringify(proxyOptions); +} diff --git a/packages/compass-preferences-model/tsconfig.json b/packages/compass-preferences-model/tsconfig.json index b2d3c80179f..e54a2e797cf 100644 --- a/packages/compass-preferences-model/tsconfig.json +++ b/packages/compass-preferences-model/tsconfig.json @@ -2,7 +2,8 @@ "extends": "@mongodb-js/tsconfig-compass/tsconfig.common.json", "compilerOptions": { "outDir": "dist", - "allowJs": true + "allowJs": true, + "moduleResolution": "node16" }, "include": ["src/**/*"], "exclude": ["./src/**/*.spec.*"] diff --git a/packages/compass-settings/src/components/modal.spec.tsx b/packages/compass-settings/src/components/modal.spec.tsx index f858962e428..01d1792c350 100644 --- a/packages/compass-settings/src/components/modal.spec.tsx +++ b/packages/compass-settings/src/components/modal.spec.tsx @@ -20,6 +20,7 @@ describe('SettingsModal', function () { let onCloseSpy: SinonSpy; let fetchSettingsSpy: SinonSpy; let onSaveSpy: SinonSpy; + let onSelectTabSpy: SinonSpy; let renderSettingsModal: ( props?: Partial> ) => void; @@ -28,6 +29,7 @@ describe('SettingsModal', function () { onCloseSpy = spy(); fetchSettingsSpy = stub().resolves(); onSaveSpy = spy(); + onSelectTabSpy = spy(); const store = configureStore(); renderSettingsModal = ( @@ -40,6 +42,7 @@ describe('SettingsModal', function () { onClose={onCloseSpy} fetchSettings={fetchSettingsSpy} onSave={onSaveSpy} + onSelectTab={onSelectTabSpy} loadingState="ready" hasChangedSettings={false} {...props} @@ -78,22 +81,27 @@ describe('SettingsModal', function () { it('navigates between settings', async function () { renderSettingsModal({ isOpen: true }); - let sidebar; + let sidebar!: HTMLElement; await waitFor(() => { const container = screen.getByTestId('settings-modal'); sidebar = within(container).getByTestId('settings-modal-sidebar'); expect(sidebar).to.exist; }); - ['Privacy'].forEach((option) => { + for (const option of ['privacy']) { const button = within(sidebar).getByTestId(`sidebar-${option}-item`); expect(button, `it renders ${option} button`).to.exist; userEvent.click(button); + + const selectedTab = onSelectTabSpy.lastCall.args[0]; + expect(selectedTab).to.equal(option); + cleanup(); + renderSettingsModal({ isOpen: true, selectedTab }); const tab = screen.getByTestId('settings-modal-content'); expect( tab.getAttribute('aria-labelledby'), `it renders ${option} tab` - ).to.equal(`${option} Tab`); - }); + ).to.equal(`${option}-tab`); + } }); }); diff --git a/packages/compass-settings/src/components/modal.tsx b/packages/compass-settings/src/components/modal.tsx index 86027b75527..38e7723b044 100644 --- a/packages/compass-settings/src/components/modal.tsx +++ b/packages/compass-settings/src/components/modal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef } from 'react'; import { connect } from 'react-redux'; import { @@ -9,6 +9,7 @@ import { } from '@mongodb-js/compass-components'; import GeneralSettings from './settings/general'; +import { ProxySettings } from './settings/proxy-settings'; import OIDCSettings from './settings/oidc-settings'; import GenAISettings from './settings/gen-ai-settings'; import PrivacySettings from './settings/privacy'; @@ -17,12 +18,14 @@ import FeaturePreviewSettings, { useShouldShowFeaturePreviewSettings, } from './settings/feature-preview'; import Sidebar from './sidebar'; -import { saveSettings, closeModal } from '../stores/settings'; +import type { SettingsTabId } from '../stores/settings'; +import { saveSettings, closeModal, selectTab } from '../stores/settings'; import type { RootState } from '../stores'; import { getUserInfo } from '../stores/atlas-login'; import { useHasAIFeatureCloudRolloutAccess } from 'compass-preferences-model/provider'; type Settings = { + tabId: SettingsTabId; name: string; component: React.ComponentType; }; @@ -31,9 +34,12 @@ type SettingsModalProps = { isAIFeatureEnabled: boolean; isOpen: boolean; isOIDCEnabled: boolean; + isProxySupportEnabled: boolean; + selectedTab: SettingsTabId | undefined; onMount?: () => void; onClose: () => void; onSave: () => void; + onSelectTab: (tab: SettingsTabId) => void; hasChangedSettings: boolean; }; @@ -59,10 +65,13 @@ const settingsStyles = css( export const SettingsModal: React.FunctionComponent = ({ isAIFeatureEnabled, + isProxySupportEnabled, isOpen, + selectedTab, onMount, onClose, onSave, + onSelectTab, isOIDCEnabled, hasChangedSettings, }) => { @@ -74,9 +83,9 @@ export const SettingsModal: React.FunctionComponent = ({ }, []); const settings: Settings[] = [ - { name: 'General', component: GeneralSettings }, - { name: 'Theme', component: ThemeSettings }, - { name: 'Privacy', component: PrivacySettings }, + { tabId: 'general', name: 'General', component: GeneralSettings }, + { tabId: 'theme', name: 'Theme', component: ThemeSettings }, + { tabId: 'privacy', name: 'Privacy', component: PrivacySettings }, ]; if ( @@ -85,6 +94,7 @@ export const SettingsModal: React.FunctionComponent = ({ isAIFeatureEnabled ) { settings.push({ + tabId: 'oidc', name: 'OIDC', component: OIDCSettings, }); @@ -92,22 +102,31 @@ export const SettingsModal: React.FunctionComponent = ({ if (aiFeatureHasCloudRolloutAccess) { settings.push({ + tabId: 'ai', name: 'Artificial Intelligence', component: GenAISettings, }); } + if (isProxySupportEnabled) { + settings.push({ + tabId: 'proxy', + name: 'Proxy Configuration', + component: ProxySettings, + }); + } + if (useShouldShowFeaturePreviewSettings()) { settings.push({ + tabId: 'preview', name: 'Feature Preview', component: FeaturePreviewSettings, }); } - const [selectedSetting, setSelectedSettings] = useState(settings[0].name); - + selectedTab ??= settings[0].tabId; const SettingComponent = - settings.find((x) => x.name === selectedSetting)?.component ?? null; + settings.find((x) => x.tabId === selectedTab)?.component ?? null; return ( = ({
x.name)} + activeItem={selectedTab} + onSelectItem={onSelectTab} + items={settings.map((x) => [x.tabId, x.name])} />
= ({ data-testid="settings-modal-content" role="tabpanel" tabIndex={0} - id={`${selectedSetting} Section`} - aria-labelledby={`${selectedSetting} Tab`} + id={`${selectedTab}-section`} + aria-labelledby={`${selectedTab}-tab`} > {SettingComponent && }
@@ -151,12 +170,15 @@ export default connect( state.settings.isModalOpen && state.settings.loadingState === 'ready', isAIFeatureEnabled: !!state.settings.settings.enableGenAIFeatures, isOIDCEnabled: !!state.settings.settings.enableOidc, + isProxySupportEnabled: !!state.settings.settings.enableProxySupport, hasChangedSettings: state.settings.updatedFields.length > 0, + selectedTab: state.settings.tab, }; }, { onMount: getUserInfo, onClose: closeModal, onSave: saveSettings, + onSelectTab: selectTab, } )(SettingsModal); diff --git a/packages/compass-settings/src/components/settings/proxy-settings-custom.spec.tsx b/packages/compass-settings/src/components/settings/proxy-settings-custom.spec.tsx new file mode 100644 index 00000000000..6598972334b --- /dev/null +++ b/packages/compass-settings/src/components/settings/proxy-settings-custom.spec.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { expect } from 'chai'; +import { ProxySettingsCustom } from './proxy-settings-custom'; +import type { DevtoolsProxyOptions } from 'compass-preferences-model'; +import sinon from 'sinon'; + +describe('ProxySettingsCustom', function () { + let container: HTMLElement; + let proxyOptions: DevtoolsProxyOptions; + let setProxyOptions: sinon.SinonStub; + + let urlTextbox: HTMLElement; + let usernameTextbox: HTMLElement; + let passwordTextbox: HTMLElement; + + beforeEach(function () { + proxyOptions = {}; + setProxyOptions = sinon + .stub() + .callsFake((arg: DevtoolsProxyOptions) => (proxyOptions = arg)); + const component = () => ( + + ); + render(component()); + container = screen.getByTestId('proxy-settings-custom'); + urlTextbox = within(container).getByTestId('proxy-url'); + usernameTextbox = within(container).getByTestId('proxy-username'); + passwordTextbox = within(container).getByTestId('proxy-password'); + }); + + afterEach(function () { + cleanup(); + }); + + it('can set a value for the proxy URL', function () { + userEvent.type(urlTextbox, 'http://example.com'); + expect(proxyOptions).to.deep.equal({ proxy: 'http://example.com/' }); + expect(urlTextbox).to.have.attribute('aria-invalid', 'false'); + }); + + it('will display a warning when the URL is invalid', function () { + userEvent.type(urlTextbox, 'http://'); + expect(proxyOptions).to.deep.equal({}); + expect(urlTextbox).to.have.attribute('aria-invalid', 'true'); + }); + + it('will fill username and password fields from url', function () { + userEvent.type(urlTextbox, 'http://username:p4ssw0rd@example.com'); + expect(proxyOptions).to.deep.equal({ + proxy: 'http://username:p4ssw0rd@example.com/', + }); + expect(urlTextbox).to.have.attribute('aria-invalid', 'false'); + expect(usernameTextbox).to.have.value('username'); + expect(passwordTextbox).to.have.value('p4ssw0rd'); + }); + + it('will add username and password fields from fields to url, but not in the UI', function () { + userEvent.type(urlTextbox, 'http://example.com'); + expect(proxyOptions).to.deep.equal({ proxy: 'http://example.com/' }); + userEvent.type(usernameTextbox, 'username'); + userEvent.type(passwordTextbox, 'p4ssw0rd'); + expect(proxyOptions).to.deep.equal({ + proxy: 'http://username:p4ssw0rd@example.com/', + }); + expect(urlTextbox).to.have.attribute('aria-invalid', 'false'); + expect(urlTextbox).to.have.value('http://example.com/'); + expect(usernameTextbox).to.have.value('username'); + expect(passwordTextbox).to.have.value('p4ssw0rd'); + }); + + it('will overwrite username and password if the url starts to contain one', function () { + userEvent.type(urlTextbox, 'http://example.com'); + expect(proxyOptions).to.deep.equal({ proxy: 'http://example.com/' }); + userEvent.type(usernameTextbox, 'username'); + userEvent.type(passwordTextbox, 'p4ssw0rd'); + userEvent.clear(urlTextbox); + userEvent.type(urlTextbox, 'http://foo:bar@otherhost.example.com'); + expect(proxyOptions).to.deep.equal({ + proxy: 'http://foo:bar@otherhost.example.com/', + }); + expect(urlTextbox).to.have.attribute('aria-invalid', 'false'); + expect(urlTextbox).to.have.value('http://foo:bar@otherhost.example.com'); + expect(usernameTextbox).to.have.value('foo'); + expect(passwordTextbox).to.have.value('bar'); + }); +}); diff --git a/packages/compass-settings/src/components/settings/proxy-settings-custom.tsx b/packages/compass-settings/src/components/settings/proxy-settings-custom.tsx new file mode 100644 index 00000000000..c3c7a85a5d4 --- /dev/null +++ b/packages/compass-settings/src/components/settings/proxy-settings-custom.tsx @@ -0,0 +1,202 @@ +import { + Description, + FormFieldContainer, + Label, + TextInput, +} from '@mongodb-js/compass-components'; +import type { DevtoolsProxyOptions } from 'compass-preferences-model'; +import type { ChangeEvent } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; + +function errorToString(err: unknown): string { + return err && typeof err === 'object' && 'message' in err + ? String(err.message) + : String(err); +} + +type CustomProxyOptions = { + proxyUrl: string; + proxyUrlState: 'none' | 'error'; + proxyUrlErrorMessage?: string | undefined; + proxyUsername: string; + proxyPassword: string; +}; + +function customProxyOptionsForFullURL( + url: string | undefined +): CustomProxyOptions { + try { + const parsed = url + ? new URL(url) + : { username: '', password: '', href: '' }; + const { username, password } = parsed; + parsed.username = ''; + parsed.password = ''; + + return { + proxyUrl: parsed.href, + proxyUrlState: 'none', + proxyUrlErrorMessage: undefined, + proxyUsername: username, + proxyPassword: password, + }; + } catch (err) { + return { + proxyUrl: url || '', + proxyUrlState: 'error', + proxyUrlErrorMessage: errorToString(err), + proxyUsername: '', + proxyPassword: '', + }; + } +} + +function fullURLForCustomProxyOptions(options: CustomProxyOptions): string { + if (!options.proxyUrl) return ''; + const reassembled = new URL(options.proxyUrl); + reassembled.username = options.proxyUsername; + reassembled.password = options.proxyPassword; + return reassembled.href; +} + +export interface ProxySettingsCustomProps { + disabled: boolean; + proxyOptions: DevtoolsProxyOptions; + setProxyOptions: (proxyOptions: DevtoolsProxyOptions) => void; +} + +export const ProxySettingsCustom: React.FunctionComponent< + ProxySettingsCustomProps +> = ({ disabled, proxyOptions, setProxyOptions }) => { + // Sync between the external (settings) state containing just a URL + // to represent these options, and the component-internal state + // that uses different fields to represent the different part of the URL. + const [customProxyOptions, _setCustomProxyOptions] = useState( + customProxyOptionsForFullURL(proxyOptions.proxy) + ); + useEffect(() => { + if ( + !proxyOptions.proxy || + fullURLForCustomProxyOptions(customProxyOptions) !== proxyOptions.proxy + ) { + _setCustomProxyOptions(customProxyOptionsForFullURL(proxyOptions.proxy)); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [proxyOptions.proxy]); + + const setCustomProxyOptions = useCallback( + (update: Partial, isURLAuthUpdate: boolean) => { + const newOptions = { ...customProxyOptions, ...update }; + if (!isURLAuthUpdate) { + try { + const url = new URL(newOptions.proxyUrl); + if (url.username || url.password) { + newOptions.proxyUsername = decodeURIComponent(url.username); + newOptions.proxyPassword = decodeURIComponent(url.password); + } + } catch { + // Not a valid URL yet + } + } + try { + const newFullURL = fullURLForCustomProxyOptions(newOptions); + const roundtripped = customProxyOptionsForFullURL(newFullURL); + if (isURLAuthUpdate) { + newOptions.proxyUrl = roundtripped.proxyUrl; + } + setProxyOptions({ ...proxyOptions, proxy: newFullURL }); + } catch (err) { + _setCustomProxyOptions({ + ...newOptions, + proxyUrlState: 'error', + proxyUrlErrorMessage: errorToString(err), + }); + return; + } + _setCustomProxyOptions({ + ...newOptions, + proxyUrlState: 'none', + proxyUrlErrorMessage: '', + }); + }, + [customProxyOptions, proxyOptions, setProxyOptions, _setCustomProxyOptions] + ); + + const { + proxyUrl, + proxyUrlState, + proxyUrlErrorMessage, + proxyUsername, + proxyPassword, + } = customProxyOptions; + const setProxyUrl = useCallback( + (ev: ChangeEvent) => + setCustomProxyOptions({ proxyUrl: ev.target.value.trim() }, false), + [setCustomProxyOptions] + ); + const setProxyUsername = useCallback( + (ev: ChangeEvent) => + setCustomProxyOptions({ proxyUsername: ev.target.value }, true), + [setCustomProxyOptions] + ); + const setProxyPassword = useCallback( + (ev: ChangeEvent) => + setCustomProxyOptions({ proxyPassword: ev.target.value }, true), + [setCustomProxyOptions] + ); + + return ( +
+ + + + Specify a http://, https://,{' '} + socks5:// + or pac+https:// URL. + + + + + + + + + + + +
+ ); +}; diff --git a/packages/compass-settings/src/components/settings/proxy-settings.spec.tsx b/packages/compass-settings/src/components/settings/proxy-settings.spec.tsx new file mode 100644 index 00000000000..9f0cc782c2b --- /dev/null +++ b/packages/compass-settings/src/components/settings/proxy-settings.spec.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { expect } from 'chai'; +import { Provider } from 'react-redux'; +import { ProxySettings } from './proxy-settings'; +import configureStore from '../../../test/configure-store'; +import { fetchSettings } from '../../stores/settings'; +import { proxyPreferenceToProxyOptions } from 'compass-preferences-model'; + +describe('ProxyOptions', function () { + let container: HTMLElement; + let store: ReturnType; + + function getSettings() { + return store.getState().settings.settings; + } + + beforeEach(async function () { + store = configureStore(); + await store.dispatch(fetchSettings()); + const component = () => ( + + + + ); + render(component()); + container = screen.getByTestId('proxy-settings'); + }); + + afterEach(function () { + cleanup(); + }); + + for (const [option, expected] of [ + ['no-proxy', { useEnvironmentVariableProxies: false }], + ['env', { useEnvironmentVariableProxies: true }], + ['custom', { proxy: '', useEnvironmentVariableProxies: true }], + ] as const) { + it(`renders ${option}`, function () { + expect(within(container).getByTestId(option + '-radio')).to.exist; + }); + it(`changed ${option} value when option is clicked`, function () { + const button = within(container).getByTestId(option + '-radio'); + userEvent.click(button, undefined, { + skipPointerEventsCheck: true, + }); + const proxyOptions = proxyPreferenceToProxyOptions(getSettings().proxy); + expect(proxyOptions).to.deep.equal(expected); + }); + } + + it('allows setting a no-proxy host list', function () { + const textbox = within(container).getByTestId('proxy-no-proxy-hosts'); + userEvent.type(textbox, 'localhost,example.com'); + const proxyOptions = proxyPreferenceToProxyOptions(getSettings().proxy); + expect(proxyOptions).to.deep.equal({ + noProxyHosts: 'localhost,example.com', + useEnvironmentVariableProxies: true, + }); + }); +}); diff --git a/packages/compass-settings/src/components/settings/proxy-settings.tsx b/packages/compass-settings/src/components/settings/proxy-settings.tsx new file mode 100644 index 00000000000..ee5c7a61afd --- /dev/null +++ b/packages/compass-settings/src/components/settings/proxy-settings.tsx @@ -0,0 +1,156 @@ +import type { ChangeEvent } from 'react'; +import React, { useCallback, useMemo } from 'react'; +import { changeFieldValue } from '../../stores/settings'; +import type { RootState } from '../../stores'; +import type { + PreferenceStateInformation, + DevtoolsProxyOptions, +} from 'compass-preferences-model'; +import { + proxyOptionsToProxyPreference, + proxyPreferenceToProxyOptions, +} from 'compass-preferences-model/provider'; +import { connect } from 'react-redux'; +import { + Description, + FormFieldContainer, + Label, + RadioBox, + RadioBoxGroup, + TextInput, +} from '@mongodb-js/compass-components'; +import { settingStateLabels } from './state-labels'; +import { ProxySettingsCustom } from './proxy-settings-custom'; + +interface ProxySettingsProps { + onChange: (key: 'proxy', value: string) => void; + proxy: string; + proxySettingsState: PreferenceStateInformation['proxy']; +} + +type ProxyType = 'custom' | 'env' | 'no-proxy'; + +const UnconnectedProxySettings: React.FunctionComponent = ({ + onChange, + proxy, + proxySettingsState, +}) => { + const [proxyOptions] = useMemo(() => { + const proxyOptions = proxyPreferenceToProxyOptions(proxy); + return [proxyOptions]; + }, [proxy]); + + const setProxyOptions = useCallback( + (options: DevtoolsProxyOptions) => { + onChange('proxy', proxyOptionsToProxyPreference(options)); + }, + [onChange] + ); + + const disabled = !!proxySettingsState; + const stateLabel = settingStateLabels[proxySettingsState ?? '']; + + const proxyType: ProxyType = + typeof proxyOptions.proxy === 'string' + ? 'custom' + : proxyOptions.useEnvironmentVariableProxies + ? 'env' + : 'no-proxy'; + const setProxyType = useCallback( + (ev: ChangeEvent) => { + const type = ev.target.value as ProxyType; + const update: Record> = { + env: { + proxy: undefined, + useEnvironmentVariableProxies: true, + }, + 'no-proxy': { + proxy: undefined, + useEnvironmentVariableProxies: false, + }, + custom: { + proxy: '', + useEnvironmentVariableProxies: true, + }, + }; + setProxyOptions({ ...proxyOptions, ...update[type] }); + }, + [proxyOptions, setProxyOptions] + ); + + const noProxyHosts = proxyOptions.noProxyHosts; + const setNoProxyHosts = useCallback( + (ev: ChangeEvent) => { + setProxyOptions({ ...proxyOptions, noProxyHosts: ev.target.value }); + }, + [proxyOptions, setProxyOptions] + ); + + return ( +
+ + + + No Proxy + + + System Proxy + + + Manual Configuration + + + + {proxyType === 'custom' && ( + + )} + {(proxyType === 'env' || proxyType === 'custom') && ( + + + + Comma-separated list of hostnames and IP addresses. Connections to + these hosts will not be forwarded through the proxy. + + + + )} + {stateLabel} +
+ ); +}; + +export const ProxySettings = connect( + (state: RootState) => { + const { + settings: { settings, preferenceStates }, + } = state; + + return { + proxy: settings.proxy, + proxySettingsState: preferenceStates.proxy, + }; + }, + { onChange: changeFieldValue } +)(UnconnectedProxySettings); diff --git a/packages/compass-settings/src/components/sidebar.spec.tsx b/packages/compass-settings/src/components/sidebar.spec.tsx index 57ad13be985..85f48852b58 100644 --- a/packages/compass-settings/src/components/sidebar.spec.tsx +++ b/packages/compass-settings/src/components/sidebar.spec.tsx @@ -15,29 +15,35 @@ describe('Sidebar', function () { render( {}} /> ); const sidebar = screen.getByTestId('settings-modal-sidebar'); expect(sidebar).to.exist; expect(within(sidebar).getByTestId('sidebar-theme-item')).to.exist; - expect(within(sidebar).getByTestId('sidebar-profile-item')).to.exist; + expect(within(sidebar).getByTestId('sidebar-general-item')).to.exist; }); - it('selects an items', function () { + it('selects items', function () { const onSelectItemSpy = spy(); render( ); expect(onSelectItemSpy.calledOnce).to.be.false; const sidebar = screen.getByTestId('settings-modal-sidebar'); - const profileItem = within(sidebar).getByTestId('sidebar-profile-item'); + const profileItem = within(sidebar).getByTestId('sidebar-general-item'); userEvent.click(profileItem); expect(onSelectItemSpy.calledOnce).to.be.true; }); diff --git a/packages/compass-settings/src/components/sidebar.tsx b/packages/compass-settings/src/components/sidebar.tsx index 6d24f465d6d..537285d9389 100644 --- a/packages/compass-settings/src/components/sidebar.tsx +++ b/packages/compass-settings/src/components/sidebar.tsx @@ -6,6 +6,7 @@ import { palette, useDarkMode, } from '@mongodb-js/compass-components'; +import type { SettingsTabId } from '../stores/settings'; const buttonStyles = css({ borderRadius: spacing[1], @@ -52,9 +53,9 @@ const activeStylesDark = css({ }); type SidebarProps = { - activeItem: string; - onSelectItem: (item: string) => void; - items: string[]; + activeItem: SettingsTabId; + onSelectItem: (item: SettingsTabId) => void; + items: [SettingsTabId, string][]; }; const SettingsSideNav: React.FunctionComponent = ({ @@ -69,24 +70,24 @@ const SettingsSideNav: React.FunctionComponent = ({ role="tablist" aria-labelledby="modal-title" > - {items.map((item) => ( + {items.map(([tabId, name]) => ( ))}
diff --git a/packages/compass-settings/src/index.ts b/packages/compass-settings/src/index.ts index 72195a9d0e3..0b0fdf3de70 100644 --- a/packages/compass-settings/src/index.ts +++ b/packages/compass-settings/src/index.ts @@ -6,6 +6,8 @@ import { preferencesLocator } from 'compass-preferences-model/provider'; import SettingsPlugin from './components/index'; import { onActivated } from './stores'; +export type { SettingsTabId } from './stores/settings'; + export const CompassSettingsPlugin = registerHadronPlugin( { name: 'CompassSettings', diff --git a/packages/compass-settings/src/stores/index.ts b/packages/compass-settings/src/stores/index.ts index f48a8bd1723..1a1ca4dee3f 100644 --- a/packages/compass-settings/src/stores/index.ts +++ b/packages/compass-settings/src/stores/index.ts @@ -7,6 +7,7 @@ import thunk from 'redux-thunk'; import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider'; import { PreferencesSandbox } from './preferences-sandbox'; +import type { SettingsTabId } from './settings'; import { openModal, reducer as settingsReducer } from './settings'; import atlasLoginReducer, { getUserInfo, @@ -87,17 +88,19 @@ const onActivated = (_: unknown, services: SettingsPluginServices) => { const store = configureStore(services); const { globalAppRegistry } = services; - const onOpenSettings = () => { - void store.dispatch(openModal()); + const onOpenSettings = (tabId?: SettingsTabId) => { + void store.dispatch(openModal(tabId)); }; - ipcRenderer?.on('window:show-settings', onOpenSettings); + ipcRenderer?.on('window:show-settings', () => onOpenSettings()); globalAppRegistry.on('open-compass-settings', onOpenSettings); return { store, deactivate() { - ipcRenderer?.removeListener('window:show-settings', onOpenSettings); + ipcRenderer?.removeListener('window:show-settings', () => + onOpenSettings() + ); globalAppRegistry.removeListener('open-compass-settings', onOpenSettings); }, }; diff --git a/packages/compass-settings/src/stores/settings.ts b/packages/compass-settings/src/stores/settings.ts index d48b7ce3d0a..aaa136876f3 100644 --- a/packages/compass-settings/src/stores/settings.ts +++ b/packages/compass-settings/src/stores/settings.ts @@ -1,4 +1,4 @@ -import type { Reducer } from 'redux'; +import type { Action, AnyAction, Reducer } from 'redux'; import type { SettingsThunkAction } from '.'; import type { PreferenceStateInformation, @@ -6,7 +6,16 @@ import type { } from 'compass-preferences-model'; import { cancelAtlasLoginAttempt } from './atlas-login'; -export type State = { isModalOpen: boolean } & ( +export type SettingsTabId = + | 'general' + | 'theme' + | 'privacy' + | 'oidc' + | 'ai' + | 'proxy' + | 'preview'; + +export type State = { isModalOpen: boolean; tab: undefined | SettingsTabId } & ( | { loadingState: 'loading'; settings: Record; @@ -27,6 +36,7 @@ export const INITIAL_STATE: State = { preferenceStates: {}, updatedFields: [], loadingState: 'loading', + tab: undefined, }; export enum ActionTypes { @@ -38,6 +48,7 @@ export enum ActionTypes { FieldUpdated = 'compass-settings/settingsFieldUpdated', SettingsSaved = 'compass-settings/settingsUpdated', OpenSettingsModal = 'compass-settings/OpenSettingsModal', + SelectTab = 'compass-settings/SelectTab', CloseSettingsModal = 'compass-settings/CloseSettingsModal', } @@ -52,51 +63,106 @@ type SaveSettingsAction = { type: ActionTypes.SettingsSaved; }; -export type Actions = SettingsFetchedAction | SaveSettingsAction; - -export const reducer: Reducer = (state = INITIAL_STATE, action) => { - switch (action.type) { - case ActionTypes.SettingsFetchedStart: - return { - // Updating settings to loading state that is the same as initial one - ...INITIAL_STATE, - // ... and preserving current modal state - isModalOpen: state.isModalOpen, - }; - case ActionTypes.OpenSettingsModal: - return { - ...state, - isModalOpen: true, - }; - case ActionTypes.CloseSettingsModal: - return { - ...state, - isModalOpen: false, - }; - case ActionTypes.ChangeFieldValue: - return { - ...state, - settings: { - ...state.settings, - [action.field]: action.value, - }, - }; - case ActionTypes.SettingsFetched: - return { - ...state, - loadingState: 'ready', - settings: action.settings, - preferenceStates: action.preferenceStates, - updatedFields: action.updatedFields, - }; - case ActionTypes.SettingsSaved: - return { - ...state, - isModalOpen: false, - }; - default: - return state; +type SettingsFetchStartAction = { + type: ActionTypes.SettingsFetchedStart; +}; + +type OpenSettingsModalAction = { + type: ActionTypes.OpenSettingsModal; + tab?: SettingsTabId; +}; + +type SelectTabAction = { + type: ActionTypes.SelectTab; + tab?: SettingsTabId; +}; + +type CloseSettingsModalAction = { + type: ActionTypes.CloseSettingsModal; +}; + +type ChangeFieldValueAction = { + type: ActionTypes.ChangeFieldValue; + field: K; + value: UserConfigurablePreferences[K]; +}; + +export function isAction( + action: AnyAction, + type: A['type'] +): action is A { + return action.type === type; +} + +export const reducer: Reducer = ( + state = INITIAL_STATE, + action +): State => { + if ( + isAction(action, ActionTypes.SettingsFetchedStart) + ) { + return { + // Updating settings to loading state that is the same as initial one + ...INITIAL_STATE, + // ... and preserving current modal state + isModalOpen: state.isModalOpen, + tab: state.tab, + }; + } + if ( + isAction(action, ActionTypes.OpenSettingsModal) + ) { + return { + ...state, + isModalOpen: true, + tab: action.tab, + }; + } + if (isAction(action, ActionTypes.SelectTab)) { + return { + ...state, + tab: action.tab ?? state.tab, + }; + } + if ( + isAction(action, ActionTypes.CloseSettingsModal) + ) { + return { + ...state, + isModalOpen: false, + }; } + if ( + isAction>( + action, + ActionTypes.ChangeFieldValue + ) + ) { + if (state.loadingState !== 'ready') return state; + return { + ...state, + settings: { + ...state.settings, + [action.field]: action.value, + }, + }; + } + if (isAction(action, ActionTypes.SettingsFetched)) { + return { + ...state, + loadingState: 'ready', + settings: action.settings, + preferenceStates: action.preferenceStates, + updatedFields: action.updatedFields, + }; + } + if (isAction(action, ActionTypes.SettingsSaved)) { + return { + ...state, + isModalOpen: false, + }; + } + return state; }; const syncSandboxStateToStore = (): SettingsThunkAction> => { @@ -116,7 +182,10 @@ const syncSandboxStateToStore = (): SettingsThunkAction> => { }; }; -export const fetchSettings = (): SettingsThunkAction> => { +export const fetchSettings = (): SettingsThunkAction< + Promise, + SettingsFetchStartAction +> => { return async ( dispatch, _getState, @@ -140,7 +209,7 @@ export const fetchSettings = (): SettingsThunkAction> => { export const changeFieldValue = ( field: K, value: UserConfigurablePreferences[K] -): SettingsThunkAction> => { +): SettingsThunkAction, ChangeFieldValueAction> => { return async ( dispatch, getState, @@ -173,21 +242,33 @@ export const changeFieldValue = ( }; }; -export const openModal = (): SettingsThunkAction> => { +export const openModal = ( + tab?: SettingsTabId +): SettingsThunkAction, OpenSettingsModalAction> => { return async (dispatch) => { - dispatch({ type: ActionTypes.OpenSettingsModal }); + dispatch({ type: ActionTypes.OpenSettingsModal, tab }); await dispatch(fetchSettings()); }; }; -export const closeModal = (): SettingsThunkAction => { +export const selectTab = (tab?: SettingsTabId): SelectTabAction => { + return { type: ActionTypes.SelectTab, tab }; +}; + +export const closeModal = (): SettingsThunkAction< + void, + CloseSettingsModalAction +> => { return (dispatch) => { dispatch(cancelAtlasLoginAttempt()); dispatch({ type: ActionTypes.CloseSettingsModal }); }; }; -export const saveSettings = (): SettingsThunkAction> => { +export const saveSettings = (): SettingsThunkAction< + Promise, + SaveSettingsAction +> => { return async ( dispatch, getState, diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 9f96d4a8757..8397c4c0017 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -17,6 +17,7 @@ import CompassConnections, { } from '@mongodb-js/compass-connections'; import { CompassFindInPagePlugin } from '@mongodb-js/compass-find-in-page'; import { useLogger } from '@mongodb-js/compass-logging/provider'; +import type { SettingsTabId } from '@mongodb-js/compass-settings'; import { CompassSettingsPlugin } from '@mongodb-js/compass-settings'; import { WelcomeModal } from '@mongodb-js/compass-welcome'; import * as hadronIpc from 'hadron-ipc'; @@ -141,7 +142,7 @@ export type HomeProps = { onDisconnect: () => void; showCollectionSubMenu: (args: { isReadOnly: boolean }) => void; hideCollectionSubMenu: () => void; - showSettings: () => void; + showSettings: (tab?: SettingsTabId) => void; connectionStorage: ConnectionStorage; __TEST_MONGODB_DATA_SERVICE_CONNECT_FN?: () => Promise; }; @@ -261,7 +262,7 @@ function Home({ (showSettingsModal?: boolean) => { setIsWelcomeOpen(false); if (showSettingsModal) { - showSettings(); + showSettings('privacy'); } }, [setIsWelcomeOpen, showSettings] diff --git a/packages/compass/src/app/index.tsx b/packages/compass/src/app/index.tsx index f71f34438fd..e8dd7771d80 100644 --- a/packages/compass/src/app/index.tsx +++ b/packages/compass/src/app/index.tsx @@ -85,6 +85,7 @@ import { CompassRendererConnectionStorage, type AutoConnectPreferences, } from '@mongodb-js/connection-storage/renderer'; +import type { SettingsTabId } from '@mongodb-js/compass-settings'; const { log, mongoLogId } = createLogger('COMPASS-APP'); const track = createIpcTrack(); @@ -107,8 +108,8 @@ function notifyMainProcessOfDisconnect() { void ipcRenderer?.call('compass:disconnected'); } -function showSettingsModal() { - ipcRenderer?.emit('window:show-settings'); +function showSettingsModal(tab?: SettingsTabId) { + globalAppRegistry?.emit('open-compass-settings', tab); } async function getWindowAutoConnectPreferences(): Promise { diff --git a/packages/compass/src/main/application.ts b/packages/compass/src/main/application.ts index fd9a670f6f3..957cc2dc5f1 100644 --- a/packages/compass/src/main/application.ts +++ b/packages/compass/src/main/application.ts @@ -76,7 +76,10 @@ class CompassApplication { } this.mode = mode; - const { preferences } = await setupPreferencesAndUser(globalPreferences); + const { preferences } = await setupPreferencesAndUser( + globalPreferences, + safeStorage + ); this.preferences = preferences; await this.setupLogging(); // need to happen after setupPreferencesAndUser diff --git a/packages/mongodb-explain-compat/package.json b/packages/mongodb-explain-compat/package.json index 85cf912891b..8c5c9a8e82c 100644 --- a/packages/mongodb-explain-compat/package.json +++ b/packages/mongodb-explain-compat/package.json @@ -11,11 +11,13 @@ "compass:main": "lib/index.js", "exports": { "import": "./.esm-wrapper.mjs", - "require": "./lib/index.js" + "require": "./lib/index.js", + "types": "./index.d.ts" }, "compass:exports": { ".": "./lib/index.js" }, + "types": "./index.d.ts", "files": [ "LICENSE", "lib",