diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index df1f30c8..bc52825d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -23,7 +23,8 @@ jobs: run: | set -e setSegmentKey="setpath([\"segmentKey\"]; \"${{ secrets.ANALITYCS_KEY }}\")" - jqCommands="${setSegmentKey}" + setConfigcatKey="setpath([\"configcatKey\"]; \"${{ secrets.CONFIGCAT_KEY }}\")" + jqCommands="${setSegmentKey} | ${setConfigcatKey}" cat package.json | jq "${jqCommands}" > package.json.tmp mv package.json.tmp package.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 85dd4364..ab750373 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,8 @@ jobs: run: | set -e setSegmentKey="setpath([\"segmentKey\"]; \"${{ secrets.ANALITYCS_KEY }}\")" - jqCommands="${setSegmentKey}" + setConfigcatKey="setpath([\"configcatKey\"]; \"${{ secrets.CONFIGCAT_KEY }}\")" + jqCommands="${setSegmentKey} | ${setConfigcatKey}" cat package.json | jq "${jqCommands}" > package.json.tmp mv package.json.tmp package.json diff --git a/package.json b/package.json index 7c2e74b3..bbbe3b1f 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ }, "main": "./out/extension.js", "segmentKey": "YErmvd89wPsrCuGcVnF2XAl846W9WIGl", + "configcatKey": "WBLaCPtkjkqKHlHedziE9g/LEAOCNkbuUKiqUZAcVg7dw", "scripts": { "vscode:prepublish": "webpack --mode production", "webpack": "webpack --mode development", @@ -145,7 +146,8 @@ "@gitpod/gitpod-protocol": "main", "@gitpod/local-app-api-grpcweb": "main", "@improbable-eng/grpc-web-node-http-transport": "^0.14.0", - "analytics-node": "^6.0.0", + "analytics-node": "^6.2.0", + "configcat-node": "^8.0.0", "js-yaml": "^4.1.0", "node-fetch": "2.6.7", "pkce-challenge": "^3.0.0", diff --git a/src/common/logger.ts b/src/common/logger.ts index 869aba0c..e41ac4e2 100644 --- a/src/common/logger.ts +++ b/src/common/logger.ts @@ -40,8 +40,11 @@ export default class Log { this.logLevel('Warn', message, data); } + /** + * @deprecated Use `Log.trace` instead + */ public log(message: string, data?: any): void { - this.logLevel('Log', message, data); + this.trace(message, data); } public logLevel(level: LogLevel, message: string, data?: any): void { diff --git a/src/experiments.ts b/src/experiments.ts new file mode 100644 index 00000000..7b08fd37 --- /dev/null +++ b/src/experiments.ts @@ -0,0 +1,90 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Gitpod. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as configcat from 'configcat-node'; +import * as configcatcommon from 'configcat-common'; +import * as semver from 'semver'; +import Log from './common/logger'; + +const EXPERTIMENTAL_SETTINGS = [ + 'gitpod.remote.useLocalApp' +]; + +export class ExperimentalSettings { + private configcatClient: configcatcommon.IConfigCatClient; + private extensionVersion: semver.SemVer; + + constructor(key: string, extensionVersion: string, private logger: Log) { + this.configcatClient = configcat.createClientWithLazyLoad(key, { + logger: { + debug(): void { }, + log(): void { }, + info(): void { }, + warn(message: string): void { logger.warn(`ConfigCat: ${message}`); }, + error(message: string): void { logger.error(`ConfigCat: ${message}`); } + }, + requestTimeoutMs: 1500, + cacheTimeToLiveSeconds: 60 + }); + this.extensionVersion = new semver.SemVer(extensionVersion); + } + + async get(key: string, userId?: string): Promise { + const config = vscode.workspace.getConfiguration('gitpod'); + const values = config.inspect(key.substring('gitpod.'.length)); + if (!values || !EXPERTIMENTAL_SETTINGS.includes(key)) { + this.logger.error(`Cannot get invalid experimental setting '${key}'`); + return values?.globalValue ?? values?.defaultValue; + } + if (this.isPreRelease()) { + // PreRelease versions always have experiments enabled by default + return values.globalValue ?? values.defaultValue; + } + if (values.globalValue !== undefined) { + // User setting have priority over configcat so return early + return values.globalValue; + } + + const user = userId ? new configcatcommon.User(userId) : undefined; + const configcatKey = key.replace(/\./g, '_'); // '.' are not allowed in configcat + const experimentValue = (await this.configcatClient.getValueAsync(configcatKey, undefined, user)) as T | undefined; + + return experimentValue ?? values.defaultValue; + } + + async inspect(key: string, userId?: string): Promise<{ key: string; defaultValue?: T; globalValue?: T; experimentValue?: T } | undefined> { + const config = vscode.workspace.getConfiguration('gitpod'); + const values = config.inspect(key.substring('gitpod.'.length)); + if (!values || !EXPERTIMENTAL_SETTINGS.includes(key)) { + this.logger.error(`Cannot inspect invalid experimental setting '${key}'`); + return values; + } + + const user = userId ? new configcatcommon.User(userId) : undefined; + const configcatKey = key.replace(/\./g, '_'); // '.' are not allowed in configcat + const experimentValue = (await this.configcatClient.getValueAsync(configcatKey, undefined, user)) as T | undefined; + + return { key, defaultValue: values.defaultValue, globalValue: values.globalValue, experimentValue }; + } + + isUserOverride(key: string): boolean { + const config = vscode.workspace.getConfiguration('gitpod'); + const values = config.inspect(key.substring('gitpod.'.length)); + return values?.globalValue !== undefined; + } + + forceRefreshAsync(): Promise { + return this.configcatClient.forceRefreshAsync(); + } + + private isPreRelease() { + return this.extensionVersion.minor % 2 === 1; + } + + dispose(): void { + this.configcatClient.dispose(); + } +} diff --git a/src/extension.ts b/src/extension.ts index c84c3c3c..968e6fc1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -13,6 +13,7 @@ import GitpodServer from './gitpodServer'; import TelemetryReporter from './telemetryReporter'; import { exportLogs } from './exportLogs'; import { registerReleaseNotesView } from './releaseNotes'; +import { ExperimentalSettings } from './experiments'; const FIRST_INSTALL_KEY = 'gitpod-desktop.firstInstall'; @@ -26,6 +27,9 @@ export async function activate(context: vscode.ExtensionContext) { const logger = new Log('Gitpod'); logger.info(`${extensionId}/${packageJSON.version} (${os.release()} ${os.platform()} ${os.arch()}) vscode/${vscode.version} (${vscode.env.appName})`); + const experiments = new ExperimentalSettings(packageJSON.configcatKey, packageJSON.version, logger); + context.subscriptions.push(experiments); + telemetry = new TelemetryReporter(extensionId, packageJSON.version, packageJSON.segmentKey); context.subscriptions.push(vscode.commands.registerCommand('gitpod.exportLogs', async () => { @@ -41,7 +45,7 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(new SettingsSync(logger, telemetry)); const authProvider = new GitpodAuthenticationProvider(context, logger, telemetry); - remoteConnector = new RemoteConnector(context, logger, telemetry); + remoteConnector = new RemoteConnector(context, experiments, logger, telemetry); context.subscriptions.push(authProvider); context.subscriptions.push(vscode.window.registerUriHandler({ handleUri(uri: vscode.Uri) { diff --git a/src/remoteConnector.ts b/src/remoteConnector.ts index 7372afd9..f0ea24ee 100644 --- a/src/remoteConnector.ts +++ b/src/remoteConnector.ts @@ -29,6 +29,7 @@ import { getGitpodVersion, isFeatureSupported } from './featureSupport'; import SSHConfiguration from './ssh/sshConfig'; import { isWindows } from './common/platform'; import { untildify } from './common/files'; +import { ExperimentalSettings } from './experiments'; interface SSHConnectionParams { workspaceId: string; @@ -118,7 +119,12 @@ export default class RemoteConnector extends Disposable { private heartbeatManager: HeartbeatManager | undefined; - constructor(private readonly context: vscode.ExtensionContext, private readonly logger: Log, private readonly telemetry: TelemetryReporter) { + constructor( + private readonly context: vscode.ExtensionContext, + private readonly experiments: ExperimentalSettings, + private readonly logger: Log, + private readonly telemetry: TelemetryReporter + ) { super(); if (isGitpodRemoteWindow(context)) { @@ -770,11 +776,13 @@ export default class RemoteConnector extends Disposable { this.logger.info('Opening Gitpod workspace', uri.toString()); + const userOverride = this.experiments.isUserOverride('gitpod.remote.useLocalApp'); const forceUseLocalApp = vscode.workspace.getConfiguration('gitpod').get('remote.useLocalApp')!; + // const forceUseLocalApp = (await this.experiments.get('gitpod.remote.useLocalApp', session.account.id))!; let sshDestination: string | undefined; if (!forceUseLocalApp) { try { - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'connecting', ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'connecting', ...params, gitpodVersion: gitpodVersion.raw, userOverride }); const { destination, password } = await this.getWorkspaceSSHDestination(session.accessToken, params); sshDestination = destination; @@ -783,9 +791,9 @@ export default class RemoteConnector extends Disposable { await this.showSSHPasswordModal(password, params); } - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'connected', ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'connected', ...params, gitpodVersion: gitpodVersion.raw, userOverride }); } catch (e) { - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'failed', reason: e.toString(), ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'gateway', status: 'failed', reason: e.toString(), ...params, gitpodVersion: gitpodVersion.raw, userOverride }); if (e instanceof NoSSHGatewayError) { this.logger.error('No SSH gateway:', e); vscode.window.showWarningMessage(`${e.host} does not support [direct SSH access](https://github.com/gitpod-io/gitpod/blob/main/install/installer/docs/workspace-ssh-access.md), connecting via the deprecated SSH tunnel over WebSocket.`); @@ -817,15 +825,15 @@ export default class RemoteConnector extends Disposable { let localAppSSHConfigPath: string | undefined; if (!usingSSHGateway) { try { - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'connecting', ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'connecting', ...params, gitpodVersion: gitpodVersion.raw, userOverride }); const localAppDestData = await this.getWorkspaceLocalAppSSHDestination(params); sshDestination = localAppDestData.localAppSSHDest; localAppSSHConfigPath = localAppDestData.localAppSSHConfigPath; - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'connected', ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'connected', ...params, gitpodVersion: gitpodVersion.raw, userOverride }); } catch (e) { - this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'failed', reason: e.toString(), ...params, gitpodVersion: gitpodVersion.raw }); + this.telemetry.sendRawTelemetryEvent('vscode_desktop_ssh', { kind: 'local-app', status: 'failed', reason: e.toString(), ...params, gitpodVersion: gitpodVersion.raw, userOverride }); this.logger.error(`Failed to connect ${params.workspaceId} Gitpod workspace:`, e); if (e instanceof LocalAppError) { const seeLogs = 'See Logs'; diff --git a/yarn.lock b/yarn.lock index 260e4268..30423bb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,16 +23,17 @@ strip-json-comments "^3.1.1" "@gitpod/gitpod-protocol@main": - version "0.1.5-main.3891" - resolved "https://registry.yarnpkg.com/@gitpod/gitpod-protocol/-/gitpod-protocol-0.1.5-main.3891.tgz#59f8e6e7a6d883a5188fb73543c0b9601f1f5d83" - integrity sha512-6skfczMYFoVd5McPJM0213toT+66ISBtymvByQD5GhQIC167Yx3bgCvWkKVqELb0kKy2Pf74GB1Ex9ECgoOVFQ== + version "0.1.5-main.4288" + resolved "https://registry.yarnpkg.com/@gitpod/gitpod-protocol/-/gitpod-protocol-0.1.5-main.4288.tgz#94eef0b19d7ab2d9bd0d7e66b403178a456f31bb" + integrity sha512-MlFKLCbO+F/uwZFsawx2NiFJTjs1nKX3l+NMEGmgpAJ5mBa4N9DxWtGyxg5bnu78DHytr0T8wNyl9yOd3muRiw== dependencies: "@types/react" "17.0.32" ajv "^6.5.4" analytics-node "^6.0.0" - configcat-node "^7.0.0" + configcat-node "^8.0.0" cookie "^0.4.2" express "^4.17.3" + google-protobuf "^3.18.0-rc.2" inversify "^5.1.1" jaeger-client "^3.18.1" js-yaml "^3.10.0" @@ -129,18 +130,6 @@ component-type "^1.2.1" join-component "^1.1.0" -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - "@types/analytics-node@^3.1.9": version "3.1.9" resolved "https://registry.yarnpkg.com/@types/analytics-node/-/analytics-node-3.1.9.tgz#1b71e485658dc5501f72a35fdcf30b857a90db9c" @@ -572,6 +561,20 @@ analytics-node@^6.0.0: remove-trailing-slash "^0.1.0" uuid "^8.3.2" +analytics-node@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/analytics-node/-/analytics-node-6.2.0.tgz#8ae2ebc73d85e5b2aac8d366b974ad36996f629d" + integrity sha512-NLU4tCHlWt0tzEaFQL7NIoWhq2KmQSmz0JvyS2lYn6fc4fEjTMSabhJUx8H1r5995FX8fE3rZ15uIHU6u+ovlQ== + dependencies: + "@segment/loosely-validate-event" "^2.0.0" + axios "^0.27.2" + axios-retry "3.2.0" + lodash.isstring "^4.0.1" + md5 "^2.2.1" + ms "^2.0.0" + remove-trailing-slash "^0.1.0" + uuid "^8.3.2" + ansi-color@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a" @@ -650,6 +653,14 @@ axios@^0.21.4: dependencies: follow-redirects "^1.14.0" +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -768,19 +779,6 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - call-bind@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -855,13 +853,6 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== - dependencies: - mimic-response "^1.0.0" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -916,13 +907,12 @@ configcat-common@^6.0.0: resolved "https://registry.yarnpkg.com/configcat-common/-/configcat-common-6.0.0.tgz#ccdb9bdafcb6a89144cac17faaab60ac960fed2a" integrity sha512-C/lCeTKiFk9kPElRF3f4zIkvVCLKgPJuzrKbIMHCru89mvfH5t4//hZ9TW8wPJOAje6xB6ZALutDiIxggwUvWA== -configcat-node@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/configcat-node/-/configcat-node-7.0.0.tgz#50dc0f8fc866d7017e93fa3d478b7a3fe08ec815" - integrity sha512-zPU+6d/uHP4SxpBgdduI5AiPetAByGnBrF+Chpg+CuC2EmY6N4qKe5f8eWaot3NE+X4m5ylq1OMy6Li9ePIb6w== +configcat-node@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/configcat-node/-/configcat-node-8.0.0.tgz#6a7d2072a848552971d91e2e44c424bfda606d21" + integrity sha512-4n4yLMpXWEiB4vmj0HuV3ArgImOEHgT+ZhP+y6N6zdwP1Z4KhQHA3btbDtZbqNw1meaVzhQMjRnpV+k/3Zr8XQ== dependencies: configcat-common "^6.0.0" - got "^9.6.0" tunnel "0.0.6" content-disposition@0.5.4: @@ -1008,23 +998,11 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== - dependencies: - mimic-response "^1.0.0" - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -1059,11 +1037,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -duplexer3@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" - integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1084,13 +1057,6 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - enhanced-resolve@^5.0.0, enhanced-resolve@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" @@ -1436,7 +1402,7 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -follow-redirects@^1.14.0: +follow-redirects@^1.14.0, follow-redirects@^1.14.9: version "1.15.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== @@ -1450,6 +1416,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -1494,20 +1469,6 @@ get-intrinsic@^1.0.2: has "^1.0.3" has-symbols "^1.0.3" -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -1575,27 +1536,10 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -google-protobuf@^3.19.1: - version "3.20.1" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.20.1.tgz#1b255c2b59bcda7c399df46c65206aa3c7a0ce8b" - integrity sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw== - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" +google-protobuf@^3.18.0-rc.2, google-protobuf@^3.19.1: + version "3.21.0" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.0.tgz#8dfa3fca16218618d373d414d3c1139e28034d6e" + integrity sha512-byR7MBTK4tZ5PZEb+u5ZTzpt4SfrTxv5682MjPlHN16XeqgZE2/8HOIWeiXe8JKnT9OVbtBGhbq8mtvkK8cd5g== graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.10" @@ -1634,11 +1578,6 @@ hexer@^1.5.0: process "^0.10.0" xtend "^4.0.0" -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -1844,11 +1783,6 @@ jsdoctypeparser@^6.1.0: resolved "https://registry.yarnpkg.com/jsdoctypeparser/-/jsdoctypeparser-6.1.0.tgz#acfb936c26300d98f1405cb03e20b06748e512a8" integrity sha512-UCQBZ3xCUBv/PLfwKAJhp6jmGOSLFNKzrotXGNgbKhWvz27wPsCsVeP7gIcHPElQw2agBmynAitXqhxR58XAmA== -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== - json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -1864,13 +1798,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -1943,16 +1870,6 @@ loose-envify@^1.1.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2024,11 +1941,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - minimatch@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -2138,11 +2050,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== - npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -2172,7 +2079,7 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -2203,11 +2110,6 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -2312,11 +2214,6 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== - process@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/process/-/process-0.10.1.tgz#842457cc51cfed72dc775afeeafb8c6034372725" @@ -2337,14 +2234,6 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -2479,13 +2368,6 @@ resolve@^1.9.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== - dependencies: - lowercase-keys "^1.0.0" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2791,11 +2673,6 @@ tmp@^0.2.1: dependencies: rimraf "^3.0.0" -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2889,13 +2766,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== - dependencies: - prepend-http "^2.0.0" - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -3086,12 +2956,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ws@^7.4.6: - version "7.5.8" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a" - integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== xorshift@^1.1.1: version "1.2.0"