diff --git a/.gitignore b/.gitignore index 8db90f3e71..b1fc7924d1 100644 --- a/.gitignore +++ b/.gitignore @@ -353,4 +353,5 @@ preview-src .eslintcache .eslintcache.browser -*.tsbuildinfo \ No newline at end of file +*.tsbuildinfo +.vscode-test-web \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 053bc4a478..11e43af5f0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", - "--disable-extension=GitHub.vscode-pull-request-github-insiders" + "--disable-extension=GitHub.vscode-pull-request-github" ], "skipFiles": ["/**/*.js", "**/node_modules/**/*.js"], "smartStep": true, @@ -23,6 +23,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", + "--disable-extension=GitHub.vscode-pull-request-github", "--disable-extension=GitHub.vscode-pull-request-github-insiders" ], "skipFiles": ["/**/*.js", "**/node_modules/**/*.js"], @@ -37,7 +38,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", - "--disable-extension=GitHub.vscode-pull-request-github-insiders", + "--disable-extension=GitHub.vscode-pull-request-github", ], "skipFiles": ["/**/*.js", "**/node_modules/**/*.js"], "preLaunchTask": "npm: watch", @@ -53,7 +54,7 @@ "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", - "--disable-extension=GitHub.vscode-pull-request-github-insiders", + "--disable-extension=GitHub.vscode-pull-request-github", ], "skipFiles": ["/**/*.js", "**/node_modules/**/*.js"], "preLaunchTask": "npm: watch", @@ -77,6 +78,49 @@ "smartStep": true, "sourceMaps": true, "outFiles": ["${workspaceFolder}/out/src/test/**/*.js"] + }, + { + "type": "pwa-node", + "request": "launch", + "name": "Attach Web Test", + "program": "${workspaceFolder}/node_modules/@vscode/test-web/out/index.js", + "args": [ + "--extensionTestsPath=dist/browser/test/index.js", + "--extensionDevelopmentPath=.", + "--browserType=chromium", + "--attach=9229" + ], + "cascadeTerminateToConfigurations": [ + "Launch Web Test" + ], + "presentation": { + "hidden": true, + } + }, + { + "type": "pwa-chrome", + "request": "launch", + "name": "Launch Web Test", + "skipFiles": [ + "/**" + ], + "port": 9229, + "resolveSourceMapLocations": [ + "!**/vs/**", // exclude core vscode sources + "!**/static/build/extensions/**", // exclude built-in extensions + ], + "presentation": { + "hidden": true, + } + } + ], + "compounds": [ + { + "name": "Debug Web Test", + "configurations": [ + "Attach Web Test", + "Launch Web Test" + ] } ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 3123be48e8..d1539d052a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.2.0 +- Fixed [#68](https://github.com/ankitbko/vscode-pull-request-azdo/issues/68) - Changed the authentication mechanism from PAT to OAuth using vscode provided authentication session. This will require users to re-authenticate. + ## 0.0.25 - Removed explicit check of azdo url to resolve [#55](https://github.com/ankitbko/vscode-pull-request-azdo/issues/55) diff --git a/README.md b/README.md index ce2db1e28f..6bb85eac1f 100644 --- a/README.md +++ b/README.md @@ -28,23 +28,13 @@ It's easy to get started with Azure Devops Pull Requests for Visual Studio Code. 1. Reload VS Code after the installation (click the reload button next to the extension). 1. Open your desired Azure Devops repository. 1. You will need to configure the `azdoPullRequests.projectName` and `azdoPullRequests.orgUrl` setting. You can configure it in workspace settings and commit it so others in your team wouldn't need to do this configuration again. (Look at the next section to understand the format of these settings). -1. You will need to configure [PAT token in Azure Devops](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page) to login. Click on _show all scopes_ and select the following scopes for the token - `Code: Read & Write`, `Pull Request Threads: Read & Write`, `Work Items: Read & Write`, `Member Entitlement Management: Read`. Read more about these scope in next section. -1. A new tab would have appeared on the activity bar on the left. Open it and click on `Sign in` button. Enter the PAT token and press enter. +1. Signin to VS Code using same Microsoft account that you use to signin to Azure Devops. Authentication will work automatically. **PAT token is no longer required**. 1. You should be good to go! ## Features Learn all about different features of the extension in the [wiki](https://github.com/ankitbko/vscode-pull-request-azdo/wiki). -### Scopes required by PAT Token - -- **Minimum**: These scopes are required for extension to access Pull Requests and Threads. Without these scopes the extension will not even start. - - `Code: Read & Write`: Required to access repository metadata and pull requests. - - `Pull Request Threads: Read & Write`: Access Pull Request comment threads. -- **Additional**: These scopes are required to experience the extension in its completeness. Without these some functionality of extension may not work or the extension may cause errors. - - `Work Items: Read & Write`: Allow to read and associate work items to a PR. - - `Member Entitlement Management: Read`: Used to search for users when adding reviewers to PR. - ## Configuring the extension #### azdoPullRequests.orgUrl diff --git a/package.json b/package.json index 252ddf26a0..b7ac549d9d 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ }, "enableProposedApi": false, "preview": true, - "version": "0.0.25", + "version": "0.2.0", "publisher": "ankitbko", "engines": { - "vscode": "^1.53.0" + "vscode": "^1.79.0" }, "categories": [ "Other" @@ -29,7 +29,8 @@ "capabilities": { "untrustedWorkspaces": { "supported": true - } + }, + "virtualWorkspaces": true }, "contributes": { "configuration": { @@ -732,6 +733,8 @@ "scripts": { "postinstall": "yarn update-dts", "vscode:prepublish": "yarn run bundle", + "browsertest:preprocess": "yarn run compile && tsc ./src/test/browser/runTests.ts --outDir ./dist/browser/test --rootDir ./src/test/browser --target es6 --module commonjs", + "browsertest": "yarn run browsertest:preprocess && node ./dist/browser/test/runTests.js", "bundle": "webpack --mode production --env esbuild", "bundle:node": "webpack --mode production --config-name extension:node --config-name webviews", "bundle:web": "webpack --mode production --config-name extension:webworker --config-name webviews", @@ -763,12 +766,17 @@ "@types/sinon": "7.0.11", "@types/temp": "0.8.34", "@types/uuid": "^8.3.0", + "@types/vscode": "1.79.0", + "@types/webpack-env": "^1.16.0", "@typescript-eslint/eslint-plugin": "4.18.0", "@typescript-eslint/parser": "4.18.0", + "@vscode/test-electron": "^1.6.1", + "@vscode/test-web": "^0.0.8", "assert": "2.0.0", "browserify-zlib": "0.2.0", - "buffer": "6.0.3", + "buffer": "^6.0.3", "chai": "^4.2.0", + "constants-browserify": "^1.0.0", "crypto-browserify": "3.12.0", "css-loader": "5.1.3", "dotenv": "^8.2.0", @@ -779,7 +787,7 @@ "eslint-plugin-import": "2.22.1", "fork-ts-checker-webpack-plugin": "6.1.1", "glob": "7.1.6", - "https-browserify": "1.0.0", + "https-browserify": "^1.0.0", "jsdom": "16.4.0", "jsdom-global": "3.0.2", "json5": "2.2.0", @@ -791,13 +799,14 @@ "mocha-multi-reporters": "1.1.7", "path-browserify": "1.0.1", "prettier": "2.2.1", + "process": "^0.11.10", "raw-loader": "4.0.2", "react-testing-library": "7.0.1", "remark-gfm": "^1.0.0", "sinon": "9.0.0", "source-map-support": "0.5.19", "stream-browserify": "^3.0.0", - "stream-http": "3.1.1", + "stream-http": "^3.2.0", "style-loader": "2.0.0", "svg-inline-loader": "^0.8.2", "temp": "0.9.4", @@ -807,6 +816,7 @@ "tty": "1.0.1", "ttypescript": "^1.5.12", "typescript": "4.2.3", + "url": "^0.11.0", "util": "0.12.3", "vsce": "1.87.0", "vscode-test": "^1.5.1", @@ -831,6 +841,7 @@ "moment": "^2.22.1", "node-emoji": "^1.8.1", "node-fetch": "3.0.0-beta.9", + "os-browserify": "^0.3.0", "query-string": "^6.2.0", "react": "^16.12.0", "react-dom": "^16.12.0", diff --git a/src/@types/git.d.ts b/src/@types/git.d.ts index 40c8dfce69..af06c79c80 100644 --- a/src/@types/git.d.ts +++ b/src/@types/git.d.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ + import { Uri, Event, Disposable, ProviderResult } from 'vscode'; export { ProviderResult } from 'vscode'; @@ -14,6 +15,11 @@ export interface InputBox { value: string; } +export const enum ForcePushMode { + Force, + ForceWithLease +} + export const enum RefType { Head, RemoteHead, @@ -130,6 +136,16 @@ export interface CommitOptions { signoff?: boolean; signCommit?: boolean; empty?: boolean; + noVerify?: boolean; + requireUserConfig?: boolean; +} + +export interface FetchOptions { + remote?: string; + ref?: string; + all?: boolean; + prune?: boolean; + depth?: number; } export interface BranchQuery { @@ -190,9 +206,10 @@ export interface Repository { removeRemote(name: string): Promise; renameRemote(name: string, newName: string): Promise; + fetch(options?: FetchOptions): Promise; fetch(remote?: string, ref?: string, depth?: number): Promise; pull(unshallow?: boolean): Promise; - push(remoteName?: string, branchName?: string, setUpstream?: boolean): Promise; + push(remoteName?: string, branchName?: string, setUpstream?: boolean, force?: ForcePushMode): Promise; blame(path: string): Promise; log(options?: LogOptions): Promise; @@ -211,13 +228,34 @@ export interface RemoteSourceProvider { readonly icon?: string; // codicon name readonly supportsQuery?: boolean; getRemoteSources(query?: string): ProviderResult; + getBranches?(url: string): ProviderResult; + publishRepository?(repository: Repository): Promise; +} + +export interface Credentials { + readonly username: string; + readonly password: string; +} + +export interface CredentialsProvider { + getCredentials(host: Uri): ProviderResult; +} + +export interface PushErrorHandler { + handlePushError(repository: Repository, remote: Remote, refspec: string, error: Error & { gitErrorCode: GitErrorCodes }): Promise; } export type APIState = 'uninitialized' | 'initialized'; +export interface PublishEvent { + repository: Repository; + branch?: string; +} + export interface GitAPI { readonly state: APIState; readonly onDidChangeState: Event; + readonly onDidPublish: Event; readonly git: Git; readonly repositories: Repository[]; readonly onDidOpenRepository: Event; @@ -226,7 +264,11 @@ export interface GitAPI { toGitUri(uri: Uri, ref: string): Uri; getRepository(uri: Uri): Repository | null; init(root: Uri): Promise; + openRepository(root: Uri): Promise + registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable; + registerCredentialsProvider(provider: CredentialsProvider): Disposable; + registerPushErrorHandler(handler: PushErrorHandler): Disposable; } export interface GitExtension { @@ -264,6 +306,7 @@ export const enum GitErrorCodes { CantOpenResource = 'CantOpenResource', GitNotFound = 'GitNotFound', CantCreatePipe = 'CantCreatePipe', + PermissionDenied = 'PermissionDenied', CantAccessRemote = 'CantAccessRemote', RepositoryNotFound = 'RepositoryNotFound', RepositoryIsLocked = 'RepositoryIsLocked', @@ -282,4 +325,4 @@ export const enum GitErrorCodes { PatchDoesNotApply = 'PatchDoesNotApply', NoPathFound = 'NoPathFound', UnknownPath = 'UnknownPath', -} +} \ No newline at end of file diff --git a/src/@types/vscode-test-web.d.ts b/src/@types/vscode-test-web.d.ts new file mode 100644 index 0000000000..2d96b76cbe --- /dev/null +++ b/src/@types/vscode-test-web.d.ts @@ -0,0 +1,61 @@ +#!/usr/bin/env node +export declare type BrowserType = 'chromium' | 'firefox' | 'webkit'; +export declare type VSCodeVersion = 'insiders' | 'stable' | 'sources'; +export interface Options { + /** + * Browser to run the test against: 'chromium' | 'firefox' | 'webkit' + */ + browserType: BrowserType; + /** + * Absolute path to folder that contains one or more extensions (in subfolders). + * Extension folders include a `package.json` extension manifest. + */ + extensionDevelopmentPath?: string; + /** + * Absolute path to the extension tests runner module. + * Can be either a file path or a directory path that contains an `index.js`. + * The module is expected to have a `run` function of the following signature: + * + * ```ts + * function run(): Promise; + * ``` + * + * When running the extension test, the Extension Development Host will call this function + * that runs the test suite. This function should throws an error if any test fails. + */ + extensionTestsPath?: string; + /** + * The VS Code version to use. Valid versions are: + * - `'stable'` : The latest stable build + * - `'insiders'` : The latest insiders build + * - `'sources'`: From sources, served at localhost:8080 by running `yarn web` in the vscode repo + * + * Currently defaults to `insiders`, which is latest stable insiders. + */ + version?: VSCodeVersion; + /** + * Open the dev tools. + */ + devTools?: boolean; + /** + * Do not show the browser. Defaults to `true` if a extensionTestsPath is provided, `false` otherwise. + */ + headless?: boolean; + /** + * Expose browser debugging on this port number, and wait for the debugger to attach before running tests. + */ + waitForDebugger?: number; + /** + * The folder URI to open VSCode on + */ + folderUri?: string; +} +/** + * Runs the tests in a browser. + * + * @param options The options defining browser type, extension and test location. + */ +export declare function runTests(options: Options & { + extensionTestsPath: string; +}): Promise; +export declare function open(options: Options): Promise; \ No newline at end of file diff --git a/src/api/api.d.ts b/src/api/api.d.ts index 66ceafa995..d170b30349 100644 --- a/src/api/api.d.ts +++ b/src/api/api.d.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, Event, Uri } from 'vscode'; -import { APIState } from '../@types/git'; +import { APIState, PublishEvent } from '../@types/git'; export interface InputBox { value: string; @@ -223,6 +223,7 @@ export interface IGit { readonly repositories: Repository[]; readonly onDidOpenRepository: Event; readonly onDidCloseRepository: Event; + readonly onDidPublish?: Event; // Used by the actual git extension to indicate it has finished initializing state information readonly state?: APIState; diff --git a/src/api/api1.ts b/src/api/api1.ts index b836a1eabc..9c925c8bce 100644 --- a/src/api/api1.ts +++ b/src/api/api1.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { APIState } from '../@types/git'; +import { APIState, PublishEvent } from '../@types/git'; +import Logger from '../common/logger'; import { TernarySearchTree } from '../common/utils'; import { API, IGit, Repository } from './api'; @@ -83,21 +84,41 @@ export class GitApiImpl implements API, IGit, vscode.Disposable { readonly onDidCloseRepository: vscode.Event = this._onDidCloseRepository.event; private _onDidChangeState = new vscode.EventEmitter(); readonly onDidChangeState: vscode.Event = this._onDidChangeState.event; + private _onDidPublish = new vscode.EventEmitter(); + readonly onDidPublish: vscode.Event = this._onDidPublish.event; private _disposables: vscode.Disposable[]; constructor() { this._disposables = []; } + private _updateReposContext() { + const reposCount = Array.from(this._providers.values()).reduce((prev, current) => { + return prev + current.repositories.length; + }, 0); + vscode.commands.executeCommand('setContext', 'azdoOpenRepositoryCount', reposCount); + } + registerGitProvider(provider: IGit): vscode.Disposable { + Logger.appendLine(`Registering git provider`); const handler = this._nextHandle(); this._providers.set(handler, provider); this._disposables.push(provider.onDidCloseRepository(e => this._onDidCloseRepository.fire(e))); - this._disposables.push(provider.onDidOpenRepository(e => this._onDidOpenRepository.fire(e))); + this._disposables.push( + provider.onDidOpenRepository(e => { + Logger.appendLine(`Repository ${e.rootUri} has been opened`); + this._updateReposContext(); + this._onDidOpenRepository.fire(e); + }), + ); if (provider.onDidChangeState) { this._disposables.push(provider.onDidChangeState(e => this._onDidChangeState.fire(e))); } + if (provider.onDidPublish) { + this._disposables.push(provider.onDidPublish(e => this._onDidPublish.fire(e))); + } + this._updateReposContext(); provider.repositories.forEach(repository => { this._onDidOpenRepository.fire(repository); diff --git a/src/authentication/configuration.ts b/src/authentication/configuration.ts index 04bafb8563..e505b1bc84 100644 --- a/src/authentication/configuration.ts +++ b/src/authentication/configuration.ts @@ -5,12 +5,6 @@ export interface IHostConfiguration { token: string | undefined; } -export const AuthenticationScopes = ['499b84ac-1321-427f-aa17-267ca6975798/.default', 'offline_access']; - -export const AuthenticationOptions: vscode.AuthenticationGetSessionOptions = { - createIfNone: true, -}; - let USE_TEST_SERVER = false; export const HostHelper = class { diff --git a/src/azdo/azdoRepository.ts b/src/azdo/azdoRepository.ts index 03533e0741..8645116cc7 100644 --- a/src/azdo/azdoRepository.ts +++ b/src/azdo/azdoRepository.ts @@ -1,4 +1,9 @@ -import { GitPullRequestSearchCriteria, GitRepository, PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { + GitPullRequest, + GitPullRequestSearchCriteria, + GitRepository, + PullRequestStatus, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; import { Identity } from 'azure-devops-node-api/interfaces/IdentitiesInterfaces'; import * as vscode from 'vscode'; import Logger from '../common/logger'; @@ -148,6 +153,19 @@ export class AzdoRepository implements vscode.Disposable { return await this.getPullRequests({ sourceRefName: branch }); } + async createPullRequest(pullRequest: GitPullRequest): Promise { + Logger.debug(`Creating pull request`, AzdoRepository.ID); + try { + const metadata = await this.getMetadata(); + const gitApi = await this._hub?.connection?.getGitApi(); + const pullRequestModel = await gitApi?.createPullRequest(pullRequest, metadata?.id); + Logger.debug(`Created pull request`, AzdoRepository.ID); + return new PullRequestModel(this._telemetry, this, this.remote, pullRequestModel); + } catch (e) { + Logger.appendLine(`AzdoRepository> Creating pull request failed: ${e}`); + } + } + async getPullRequests(search: GitPullRequestSearchCriteria): Promise { try { Logger.debug(`Fetch pull requests for branch - enter`, AzdoRepository.ID); diff --git a/src/azdo/credentials.ts b/src/azdo/credentials.ts index fa2b2d760d..9bf9e75eb4 100644 --- a/src/azdo/credentials.ts +++ b/src/azdo/credentials.ts @@ -2,7 +2,6 @@ import * as azdev from 'azure-devops-node-api'; import { IRequestHandler } from 'azure-devops-node-api/interfaces/common/VsoBaseInterfaces'; import { Identity } from 'azure-devops-node-api/interfaces/IdentitiesInterfaces'; import * as vscode from 'vscode'; -import { AuthenticationOptions, AuthenticationScopes } from '../authentication/configuration'; import Logger from '../common/logger'; import { ITelemetry } from '../common/telemetry'; import { SETTINGS_NAMESPACE } from '../constants'; @@ -10,6 +9,9 @@ import { SETTINGS_NAMESPACE } from '../constants'; const CREDENTIALS_COMPONENT_ID = 'azdo_component'; const PROJECT_SETTINGS = 'projectName'; const ORGURL_SETTINGS = 'orgUrl'; +const TRY_AGAIN = vscode.l10n.t('Try again?'); +const CANCEL = vscode.l10n.t('Cancel'); +const ERROR = vscode.l10n.t('Error signing in to Azure DevOps'); export class Azdo { private _authHandler: IRequestHandler; @@ -17,7 +19,8 @@ export class Azdo { public authenticatedUser: Identity | undefined; constructor(public orgUrl: string, public projectName: string, token: string) { - this._authHandler = azdev.getPersonalAccessTokenHandler(token, true); + this._authHandler = azdev.getBearerHandler(token, true); + // this._authHandler = azdev.getPersonalAccessTokenHandler(token, true); this.connection = this.getNewWebApiClient(this.orgUrl); } @@ -33,22 +36,15 @@ export class CredentialStore implements vscode.Disposable { private _disposables: vscode.Disposable[]; private _onDidInitialize: vscode.EventEmitter = new vscode.EventEmitter(); public readonly onDidInitialize: vscode.Event = this._onDidInitialize.event; - - private static PAT_TOKEN_KEY = 'azdoRepo.pat.'; + private _sessionId: string | undefined; + private _sessionOptions: vscode.AuthenticationGetSessionOptions = { createIfNone: true }; constructor(private readonly _telemetry: ITelemetry, private readonly _secretStore: vscode.SecretStorage) { this._disposables = []; - // this._disposables.push(vscode.authentication.onDidChangeSessions(() => { - // if (!this.isAuthenticated()) { - // return this.initialize(); - // } - // })); - this._disposables.push( - _secretStore.onDidChange(e => { - const tokenKey = this.getTokenKey(); - if (e.key === tokenKey && !this.isAuthenticated()) { - return this.initialize(); + vscode.authentication.onDidChangeSessions(async () => { + if (!this.isAuthenticated()) { + return await this.initialize(); } }), ); @@ -59,7 +55,9 @@ export class CredentialStore implements vscode.Disposable { } public async reset() { - this._azdoAPI = undefined; + this._sessionOptions.forceNewSession = true; + this._sessionOptions.createIfNone = false; + this._sessionOptions.clearSessionPreference = true; await this.initialize(); } @@ -71,35 +69,11 @@ export class CredentialStore implements vscode.Disposable { return this._azdoAPI; } - private async requestPersonalAccessToken(): Promise { - // Based on https://github.com/microsoft/azure-repos-vscode/blob/6bc90f0853086623486d0e527e9fe5a577370e9b/src/team-extension.ts#L74 - - const session = await vscode.authentication.getSession('microsoft', AuthenticationScopes, AuthenticationOptions); - const token = session.accessToken; - - vscode.window.showInformationMessage('Successfully authorized extension in DevOps'); - - if (token) { - this._telemetry.sendTelemetryEvent('auth.manual'); - } - return token; - } - public async logout(): Promise { - // if (this._sessionId) { - // vscode.authentication.logout('github', this._sessionId); - // } - - await this._secretStore.delete(this.getTokenKey(this._orgUrl ?? '')); this._azdoAPI = undefined; - } - - public getTokenKey(orgUrl?: string): string { - let url = this._orgUrl ?? ''; - if (!!orgUrl) { - url = orgUrl; - } - return CredentialStore.PAT_TOKEN_KEY.concat(url); + this._sessionOptions.forceNewSession = true; + this._sessionOptions.createIfNone = false; + this._sessionOptions.clearSessionPreference = true; } public async login(): Promise { @@ -124,39 +98,69 @@ export class CredentialStore implements vscode.Disposable { } Logger.appendLine(`orgUrl is ${this._orgUrl}`, CredentialStore.ID); - const tokenKey = this.getTokenKey(this._orgUrl); - const token = await this.getToken(tokenKey); + let retry: boolean = true; - if (!token) { - Logger.appendLine('PAT token is not provided'); - this._telemetry.sendTelemetryEvent('auth.failed'); - return undefined; - } + while (retry) { + try + { + const session = await this.getSession(this._sessionOptions); + if (!session) { + Logger.appendLine('Auth> Unable to get session', CredentialStore.ID); + this._telemetry.sendTelemetryEvent('auth.failed'); + return undefined; + } + this._sessionId = session.id; + const token = await this.getToken(session); - try { - const azdo = new Azdo(this._orgUrl, projectName, token); - azdo.authenticatedUser = (await azdo.connection.connect()).authenticatedUser; + if (!token) { + Logger.appendLine('Auth> Unable to get token', CredentialStore.ID); + this._telemetry.sendTelemetryEvent('auth.failed'); + return undefined; + } - Logger.debug(`Auth> Successful: Logged userid: ${azdo?.authenticatedUser?.id}`, CredentialStore.ID); - this._telemetry.sendTelemetryEvent('auth.success'); + const azdo = new Azdo(this._orgUrl, projectName, token); + azdo.authenticatedUser = (await azdo.connection.connect()).authenticatedUser; + + Logger.debug(`Auth> Successful: Logged userid: ${azdo?.authenticatedUser?.id}`, CredentialStore.ID); + this._telemetry.sendTelemetryEvent('auth.success'); + this._sessionOptions.forceNewSession = false; + this._sessionOptions.createIfNone = true; + this._sessionOptions.clearSessionPreference = false; + + return azdo; + } catch (e) { + Logger.appendLine(`Auth> Failed: ${e.message}`, CredentialStore.ID); + this._telemetry.sendTelemetryEvent('auth.failed'); + if (e instanceof Error && e.stack) { + Logger.appendLine(e.stack); + } + if (e.message === 'User canceled authentication') { + return undefined; + } + } - return azdo; - } catch (e) { - await this._secretStore.delete(tokenKey); - vscode.window.showErrorMessage('Unable to authenticate. Signout and try again.'); - return undefined; + retry = (await vscode.window.showErrorMessage(ERROR, TRY_AGAIN, CANCEL)) === TRY_AGAIN; + if (retry) { + this._sessionOptions.forceNewSession = true; + this._sessionOptions.createIfNone = false; + this._sessionOptions.clearSessionPreference = true; + } } } - private async getToken(tokenKey: string): Promise { - let token = await this._secretStore.get(tokenKey); - if (!token) { - token = await this.requestPersonalAccessToken(); - if (!!token) { - this._secretStore.store(tokenKey, token); - } - } - return token; + private async getSession(sessionOptions: vscode.AuthenticationGetSessionOptions): Promise { + return await vscode.authentication.getSession( + // Specifies the Microsoft Auth Provider + 'microsoft', + // This GUID is the Azure DevOps GUID and you basically ask for a token that can be used to interact with AzDO. This is publicly documented all over + ['499b84ac-1321-427f-aa17-267ca6975798/.default', 'offline_access'], + sessionOptions + ); + } + + + private async getToken(session: vscode.AuthenticationSession): Promise { + return session?.accessToken; } public getAuthenticatedUser(): Identity | undefined { diff --git a/src/azdo/repositoriesManager.ts b/src/azdo/repositoriesManager.ts index 50df9a8a0f..15ea5b7eba 100644 --- a/src/azdo/repositoriesManager.ts +++ b/src/azdo/repositoriesManager.ts @@ -177,7 +177,7 @@ export class RepositoriesManager implements vscode.Disposable { async authenticate(): Promise { // return !!(await this._credentialStore.login()); - await this._credentialStore.initialize(); + await this._credentialStore.reset(); if (this._credentialStore.getHub() !== undefined) { return true; } diff --git a/src/common/utils.ts b/src/common/utils.ts index 99fcadb856..5a3865d222 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -8,7 +8,7 @@ import { sep } from 'path'; import moment from 'moment'; import { Disposable, Event } from 'vscode'; -export function uniqBy(arr: T[], fn: (el: T) => string): T[] { +export function uniqBy(arr: (T[] | readonly T[]), fn: (el: T) => string): T[] { const seen = Object.create(null); return arr.filter(el => { diff --git a/src/env/browser/fs.ts b/src/env/browser/fs.ts new file mode 100644 index 0000000000..5072061343 --- /dev/null +++ b/src/env/browser/fs.ts @@ -0,0 +1,3 @@ +exports.existsSync = function (path) { + return false; +}; diff --git a/src/env/browser/ssh.ts b/src/env/browser/ssh.ts index 6a20a70be1..cf472e604c 100644 --- a/src/env/browser/ssh.ts +++ b/src/env/browser/ssh.ts @@ -2,5 +2,107 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { parse as parseConfig } from 'ssh-config'; -export const resolve = (url: string) => undefined; +const SSH_URL_RE = /^(?:([^@:]+)@)?([^:/]+):?(.+)$/; +const URL_SCHEME_RE = /^([a-z-]+):\/\//; + +export const sshParse = (url: string): Config | undefined => { + const urlMatch = URL_SCHEME_RE.exec(url); + if (urlMatch) { + const [fullSchemePrefix, scheme] = urlMatch; + if (scheme === 'ssh') { + url = url.slice(fullSchemePrefix.length); + } else { + return; + } + } + const match = SSH_URL_RE.exec(url); + if (!match) { + return; + } + const [, User, Host, path] = match; + return { User, Host, path }; +}; + +/** + * Parse and resolve an SSH url. Resolves host aliases using the configuration + * specified by ~/.ssh/config, if present. + * + * Examples: + * + * resolve("git@github.com:Microsoft/vscode") + * { + * Host: 'github.com', + * HostName: 'github.com', + * User: 'git', + * path: 'Microsoft/vscode', + * } + * + * resolve("hub:queerviolet/vscode", resolverFromConfig("Host hub\n HostName github.com\n User git\n")) + * { + * Host: 'hub', + * HostName: 'github.com', + * User: 'git', + * path: 'queerviolet/vscode', + * } + * + * @param {string} url the url to parse + * @param {ConfigResolver?} resolveConfig ssh config resolver (default: from ~/.ssh/config) + * @returns {Config} + */ + export const resolve = (url: string, resolveConfig = Resolvers.current) => { + const config = sshParse(url); + return config && resolveConfig(config); +}; + +export function baseResolver(config: Config) { + return { + ...config, + Hostname: config.Host, + }; +} + +/** + * SSH Config interface + * + * Note that this interface atypically capitalizes field names. This is for consistency + * with SSH config files. + */ +export interface Config { + Host: string; + [param: string]: string; +} + +/** + * ConfigResolvers take a config, resolve some additional data (perhaps using + * a config file), and return a new Config. + */ +export type ConfigResolver = (config: Config) => Config; + +export function chainResolvers(...chain: (ConfigResolver | undefined)[]): ConfigResolver { + const resolvers = chain.filter(x => !!x) as ConfigResolver[]; + return (config: Config) => + resolvers.reduce( + (resolved, next) => ({ + ...resolved, + ...next(resolved), + }), + config, + ); +} + +export function resolverFromConfig(text: string): ConfigResolver { + const config = parseConfig(text); + return h => config.compute(h.Host); +} + +export class Resolvers { + static default = baseResolver; + + static fromConfig(conf: string) { + return chainResolvers(baseResolver, resolverFromConfig(conf)); + } + + static current = Resolvers.default; +} \ No newline at end of file diff --git a/src/env/node/ssh.ts b/src/env/node/ssh.ts index ce1846056c..c242e69041 100644 --- a/src/env/node/ssh.ts +++ b/src/env/node/ssh.ts @@ -1,28 +1,18 @@ -import { parse as parseConfig } from 'ssh-config'; import { readFileSync } from 'fs'; -import { join } from 'path'; import { homedir } from 'os'; +import { join } from 'path'; import Logger from '../../common/logger'; +import { baseResolver, chainResolvers, ConfigResolver, resolverFromConfig, sshParse } from '../browser/ssh'; -const SSH_URL_RE = /^(?:([^@:]+)@)?([^:/]+):?(.+)$/; -const URL_SCHEME_RE = /^([a-z-]+):\/\//; +export class Resolvers { + static default = chainResolvers(baseResolver, resolverFromConfigFile()); -/** - * SSH Config interface - * - * Note that this interface atypically capitalizes field names. This is for consistency - * with SSH config files. - */ -export interface Config { - Host: string; - [param: string]: string; -} + static fromConfig(conf: string) { + return chainResolvers(baseResolver, resolverFromConfig(conf)); + } -/** - * ConfigResolvers take a config, resolve some additional data (perhaps using - * a config file), and return a new Config. - */ -export type ConfigResolver = (config: Config) => Config; + static current = Resolvers.default; +} /** * Parse and resolve an SSH url. Resolves host aliases using the configuration @@ -51,45 +41,10 @@ export type ConfigResolver = (config: Config) => Config; * @returns {Config} */ export const resolve = (url: string, resolveConfig = Resolvers.current) => { - const config = parse(url); + const config = sshParse(url); return config && resolveConfig(config); }; -export class Resolvers { - static default = chainResolvers(baseResolver, resolverFromConfigFile()); - - static fromConfig(conf: string) { - return chainResolvers(baseResolver, resolverFromConfig(conf)); - } - - static current = Resolvers.default; -} - -const parse = (url: string): Config | undefined => { - const urlMatch = URL_SCHEME_RE.exec(url); - if (urlMatch) { - const [fullSchemePrefix, scheme] = urlMatch; - if (scheme === 'ssh') { - url = url.slice(fullSchemePrefix.length); - } else { - return; - } - } - const match = SSH_URL_RE.exec(url); - if (!match) { - return; - } - const [, User, Host, path] = match; - return { User, Host, path }; -}; - -function baseResolver(config: Config) { - return { - ...config, - Hostname: config.Host, - }; -} - function resolverFromConfigFile(configPath = join(homedir(), '.ssh', 'config')): ConfigResolver | undefined { try { const config = readFileSync(configPath).toString(); @@ -98,20 +53,3 @@ function resolverFromConfigFile(configPath = join(homedir(), '.ssh', 'config')): Logger.appendLine(`${configPath}: ${error.message}`); } } - -export function resolverFromConfig(text: string): ConfigResolver { - const config = parseConfig(text); - return h => config.compute(h.Host); -} - -function chainResolvers(...chain: (ConfigResolver | undefined)[]): ConfigResolver { - const resolvers = chain.filter(x => !!x) as ConfigResolver[]; - return (config: Config) => - resolvers.reduce( - (resolved, next) => ({ - ...resolved, - ...next(resolved), - }), - config, - ); -} diff --git a/src/extension.ts b/src/extension.ts index ec47c201d5..01ff0cca44 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -25,6 +25,7 @@ import { handler as uriHandler } from './common/uri'; import { onceEvent } from './common/utils'; import { EXTENSION_ID, SETTINGS_NAMESPACE } from './constants'; import { registerBuiltinGitProvider, registerLiveShareGitProvider } from './gitProviders/api'; +import { MockGitProvider } from './gitProviders/mockGitProvider'; import { FileTypeDecorationProvider } from './view/fileTypeDecorationProvider'; import { PullRequestChangesTreeDataProvider } from './view/prChangesTreeDataProvider'; import { PullRequestsTreeDataProvider } from './view/prsTreeDataProvider'; @@ -64,8 +65,8 @@ async function init( const localStorageService = new LocalStorageService(context.workspaceState); const fileReviewedStatusService = new FileReviewedStatusService(localStorageService); - context.secrets.onDidChange(async e => { - if (e.key === credentialStore.getTokenKey()) { + vscode.authentication.onDidChangeSessions(async (e) => { + if (e.provider.id === 'microsoft') { await reposManager.clearCredentialCache(); if (reviewManagers) { reviewManagers.forEach(reviewManager => reviewManager.updateState()); @@ -191,6 +192,8 @@ export async function activate(context: vscode.ExtensionContext): Promise = this._onDidCloseRepository.event; private _onDidChangeState = new vscode.EventEmitter(); readonly onDidChangeState: vscode.Event = this._onDidChangeState.event; + private _onDidPublish = new vscode.EventEmitter(); + readonly onDidPublish: vscode.Event = this._onDidPublish.event; private _gitAPI: GitAPI; private _disposables: vscode.Disposable[]; private constructor(extension: vscode.Extension) { const gitExtension = extension.exports; - this._gitAPI = gitExtension.getAPI(1); + try { + this._gitAPI = gitExtension.getAPI(1); + } catch (e) { + // The git extension will throw if a git model cannot be found, i.e. if git is not installed. + vscode.window.showErrorMessage( + 'Activating the AzDO Pull Requests extension failed. Please make sure you have git installed.', + ); + throw e; + } this._disposables = []; this._disposables.push(this._gitAPI.onDidCloseRepository(e => this._onDidCloseRepository.fire(e as any))); this._disposables.push(this._gitAPI.onDidOpenRepository(e => this._onDidOpenRepository.fire(e as any))); this._disposables.push(this._gitAPI.onDidChangeState(e => this._onDidChangeState.fire(e))); + this._disposables.push(this._gitAPI.onDidPublish(e => this._onDidPublish.fire(e))); } static async createProvider(): Promise { diff --git a/src/gitProviders/mockGitProvider.ts b/src/gitProviders/mockGitProvider.ts new file mode 100644 index 0000000000..fb313616ae --- /dev/null +++ b/src/gitProviders/mockGitProvider.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { APIState, GitAPI, GitExtension, PublishEvent } from '../@types/git'; +import { IGit, Repository } from '../api/api'; +import { MockRepository } from './mockRepository'; + +export class MockGitProvider implements IGit, vscode.Disposable { + private _mockRepository: MockRepository; + get repositories(): Repository[] { + return [this._mockRepository]; + } + + get state(): APIState { + return 'initialized'; + } + + private _onDidOpenRepository = new vscode.EventEmitter(); + readonly onDidOpenRepository: vscode.Event = this._onDidOpenRepository.event; + private _onDidCloseRepository = new vscode.EventEmitter(); + readonly onDidCloseRepository: vscode.Event = this._onDidCloseRepository.event; + private _onDidChangeState = new vscode.EventEmitter(); + readonly onDidChangeState: vscode.Event = this._onDidChangeState.event; + private _onDidPublish = new vscode.EventEmitter(); + readonly onDidPublish: vscode.Event = this._onDidPublish.event; + + private _disposables: vscode.Disposable[]; + + public constructor() { + this._disposables = []; + this._mockRepository = new MockRepository(); + this._mockRepository.addRemote('origin', 'https://anksinha@dev.azure.com/anksinha/test/_git/test'); + this._onDidCloseRepository.fire(this._mockRepository); + this._onDidOpenRepository.fire(this._mockRepository); + } + + dispose() { + this._disposables.forEach(disposable => disposable.dispose()); + } +} diff --git a/src/gitProviders/mockRepository.ts b/src/gitProviders/mockRepository.ts new file mode 100644 index 0000000000..524bd04ca3 --- /dev/null +++ b/src/gitProviders/mockRepository.ts @@ -0,0 +1,305 @@ +import { Uri } from 'vscode'; +import type { + Branch, + BranchQuery, + Change, + Commit, + CommitOptions, + InputBox, + Ref, + Repository, + RepositoryState, + RepositoryUIState, +} from '../api/api'; +import { RefType } from '../api/api1'; + +type Mutable = { + -readonly [P in keyof T]: T[P]; +}; + +export class MockRepository implements Repository { + commit(message: string, opts?: CommitOptions): Promise { + return Promise.reject(new Error(`Unexpected commit(${message}, ${opts})`)); + } + renameRemote(name: string, newName: string): Promise { + return Promise.reject(new Error(`Unexpected renameRemote (${name}, ${newName})`)); + } + getGlobalConfig(key: string): Promise { + return Promise.reject(new Error(`Unexpected getGlobalConfig(${key})`)); + } + detectObjectType(object: string): Promise<{ mimetype: string; encoding?: string | undefined }> { + return Promise.reject(new Error(`Unexpected detectObjectType(${object})`)); + } + buffer(ref: string, path: string): Promise { + return Promise.reject(new Error(`Unexpected buffer(${ref}, ${path})`)); + } + clean(paths: string[]): Promise { + return Promise.reject(new Error(`Unexpected clean(${paths})`)); + } + diffWithHEAD(path?: any): any { + return Promise.reject(new Error(`Unexpected diffWithHEAD(${path})`)); + } + diffIndexWithHEAD(path?: any): any { + return Promise.reject(new Error(`Unexpected diffIndexWithHEAD(${path})`)); + } + diffIndexWith(ref: any, path?: any): any { + return Promise.reject(new Error(`Unexpected diffIndexWith(${ref}, ${path})`)); + } + getMergeBase(ref1: string, ref2: string): Promise { + return Promise.reject(new Error(`Unexpected getMergeBase(${ref1}, ${ref2})`)); + } + log(options?: any): Promise { + return Promise.reject(new Error(`Unexpected log(${options})`)); + } + + private _state: Mutable = { + HEAD: undefined, + refs: [], + remotes: [], + submodules: [], + rebaseCommit: undefined, + mergeChanges: [], + indexChanges: [], + workingTreeChanges: [], + onDidChange: () => ({ dispose() {} }), + }; + private _config: Map = new Map(); + private _branches: Branch[] = []; + private _expectedFetches: { remoteName?: string; ref?: string; depth?: number }[] = []; + private _expectedPulls: { unshallow?: boolean }[] = []; + private _expectedPushes: { remoteName?: string; branchName?: string; setUpstream?: boolean }[] = []; + + inputBox: InputBox = { value: '' }; + + rootUri = Uri.file('/root'); + + state: RepositoryState = this._state; + + ui: RepositoryUIState = { + selected: true, + onDidChange: () => ({ dispose() {} }), + }; + + async getConfigs(): Promise<{ key: string; value: string }[]> { + return Array.from(this._config, ([k, v]) => ({ key: k, value: v })); + } + + async getConfig(key: string): Promise { + return this._config.get(key) || ''; + } + + async setConfig(key: string, value: string): Promise { + const oldValue = this._config.get(key) || ''; + this._config.set(key, value); + return oldValue; + } + + getObjectDetails(treeish: string, treePath: string): Promise<{ mode: string; object: string; size: number }> { + return Promise.reject(new Error(`Unexpected getObjectDetails(${treeish}, ${treePath})`)); + } + + show(ref: string, treePath: string): Promise { + return Promise.reject(new Error(`Unexpected show(${ref}, ${treePath})`)); + } + + getCommit(ref: string): Promise { + return Promise.reject(new Error(`Unexpected getCommit(${ref})`)); + } + + apply(patch: string, reverse?: boolean | undefined): Promise { + return Promise.reject(new Error(`Unexpected apply(..., ${reverse})`)); + } + + diff(cached?: boolean | undefined): Promise { + return Promise.reject(new Error(`Unexpected diff(${cached})`)); + } + + diffWith(ref: string): Promise; + diffWith(ref: string, treePath: string): Promise; + diffWith(ref: string, treePath?: string) { + return Promise.reject(new Error(`Unexpected diffWith(${ref}, ${treePath})`)); + } + + diffBlobs(object1: string, object2: string): Promise { + return Promise.reject(new Error(`Unexpected diffBlobs(${object1}, ${object2})`)); + } + + diffBetween(ref1: string, ref2: string): Promise; + diffBetween(ref1: string, ref2: string, treePath: string): Promise; + diffBetween(ref1: string, ref2: string, treePath?: string) { + return Promise.reject(new Error(`Unexpected diffBlobs(${ref1}, ${ref2}, ${treePath})`)); + } + + hashObject(data: string): Promise { + return Promise.reject(new Error('Unexpected hashObject(...)')); + } + + async createBranch(name: string, checkout: boolean, ref?: string | undefined): Promise { + if (this._branches.some(b => b.name === name)) { + throw new Error(`A branch named ${name} already exists`); + } + + const branch = { + type: RefType.Head, + name, + commit: ref, + }; + + if (checkout) { + this._state.HEAD = branch; + } + + this._state.refs.push(branch); + this._branches.push(branch); + } + + async deleteBranch(name: string, force?: boolean | undefined): Promise { + const index = this._branches.findIndex(b => b.name === name); + if (index === -1) { + throw new Error(`Attempt to delete nonexistent branch ${name}`); + } + this._branches.splice(index, 1); + } + + async getBranch(name: string): Promise { + const branch = this._branches.find(b => b.name === name); + if (!branch) { + throw new Error(`getBranch called with unrecognized name "${name}"`); + } + return branch; + } + + async getBranches(_query: BranchQuery): Promise { + return []; + } + + async setBranchUpstream(name: string, upstream: string): Promise { + const index = this._branches.findIndex(b => b.name === name); + if (index === -1) { + throw new Error(`setBranchUpstream called with unrecognized branch name ${name})`); + } + + const match = /^refs\/remotes\/([^\/]+)\/(.+)$/.exec(upstream); + if (!match) { + throw new Error( + `upstream ${upstream} provided to setBranchUpstream did match pattern refs/remotes//`, + ); + } + const [, remoteName, remoteRef] = match; + + const existing = this._branches[index]; + const replacement = { + ...existing, + upstream: { + remote: remoteName, + name: remoteRef, + }, + }; + this._branches.splice(index, 1, replacement); + + if (this._state.HEAD === existing) { + this._state.HEAD = replacement; + } + } + + status(): Promise { + return Promise.reject(new Error('Unexpected status()')); + } + + async checkout(treeish: string): Promise { + const branch = this._branches.find(b => b.name === treeish); + + // Also: tags + + if (!branch) { + throw new Error(`checked called with unrecognized ref ${treeish}`); + } + + this._state.HEAD = branch; + } + + async addRemote(name: string, url: string): Promise { + if (this._state.remotes.some(r => r.name === name)) { + throw new Error(`A remote named ${name} already exists.`); + } + + this._state.remotes.push({ + name, + fetchUrl: url, + pushUrl: url, + isReadOnly: false, + }); + } + + async removeRemote(name: string): Promise { + const index = this._state.remotes.findIndex(r => r.name === name); + if (index === -1) { + throw new Error(`No remote named ${name} exists.`); + } + this._state.remotes.splice(index, 1); + } + + async fetch(arg0?: string | undefined | any, ref?: string | undefined, depth?: number | undefined): Promise { + let remoteName: string | undefined; + if (typeof arg0 === 'object') { + remoteName = arg0.remote; + ref = arg0.ref; + depth = arg0.depth; + } else { + remoteName = arg0; + } + + const index = this._expectedFetches.findIndex(f => f.remoteName === remoteName && f.ref === ref && f.depth === depth); + if (index === -1) { + throw new Error(`Unexpected fetch(${remoteName}, ${ref}, ${depth})`); + } + + if (ref) { + const match = /^(?:\+?[^:]+\:)?(.*)$/.exec(ref); + if (match) { + const [, localRef] = match; + await this.createBranch(localRef, false); + } + } + + this._expectedFetches.splice(index, 1); + } + + async pull(unshallow?: boolean | undefined): Promise { + const index = this._expectedPulls.findIndex(f => f.unshallow === unshallow); + if (index === -1) { + throw new Error(`Unexpected pull(${unshallow})`); + } + this._expectedPulls.splice(index, 1); + } + + async push( + remoteName?: string | undefined, + branchName?: string | undefined, + setUpstream?: boolean | undefined, + ): Promise { + const index = this._expectedPushes.findIndex( + f => f.remoteName === remoteName && f.branchName === branchName && f.setUpstream === setUpstream, + ); + if (index === -1) { + throw new Error(`Unexpected push(${remoteName}, ${branchName}, ${setUpstream})`); + } + this._expectedPushes.splice(index, 1); + } + + blame(treePath: string): Promise { + return Promise.reject(new Error(`Unexpected blame(${treePath})`)); + } + + expectFetch(remoteName?: string, ref?: string, depth?: number) { + this._expectedFetches.push({ remoteName, ref, depth }); + } + + expectPull(unshallow?: boolean) { + this._expectedPulls.push({ unshallow }); + } + + expectPush(remoteName?: string, branchName?: string, setUpstream?: boolean) { + this._expectedPushes.push({ remoteName, branchName, setUpstream }); + } +} diff --git a/src/test/browser/index.ts b/src/test/browser/index.ts new file mode 100644 index 0000000000..7ccb1fa58f --- /dev/null +++ b/src/test/browser/index.ts @@ -0,0 +1,41 @@ +// This file is providing the test runner to use when running extension tests. +import * as vscode from 'vscode'; +require('mocha/mocha'); +import { mockWebviewEnvironment } from '../mocks/mockWebviewEnvironment'; +import { EXTENSION_ID } from '../../constants'; + +async function runAllExtensionTests(testsRoot: string, clb: (error: Error | null, failures?: number) => void): Promise { + // Ensure the dev-mode extension is activated + await vscode.extensions.getExtension(EXTENSION_ID)!.activate(); + + mockWebviewEnvironment.install(global); + + mocha.setup({ + ui: 'bdd', + reporter: undefined + }); + + try { + const importAll = (r: __WebpackModuleApi.RequireContext) => r.keys().forEach(r); + importAll(require.context('../', true, /\.test$/)); + } catch (e) { + console.log(e); + } + + if (process.env.TEST_JUNIT_XML_PATH) { + mocha.reporter('mocha-multi-reporters', { + reporterEnabled: 'mocha-junit-reporter, spec', + mochaJunitReporterReporterOptions: { + mochaFile: process.env.TEST_JUNIT_XML_PATH, + suiteTitleSeparatedBy: ' / ', + outputs: true, + }, + }); + } + + return mocha.run(failures => clb(null, failures)); +} + +export function run(testsRoot: string, clb: (error: Error | null, failures?: number) => void): void { + runAllExtensionTests(testsRoot, clb); +} \ No newline at end of file diff --git a/src/test/browser/runTests.ts b/src/test/browser/runTests.ts new file mode 100644 index 0000000000..80f4243c52 --- /dev/null +++ b/src/test/browser/runTests.ts @@ -0,0 +1,28 @@ +import * as path from 'path'; +import { BrowserType, runTests } from '@vscode/test-web'; + +async function go() { + try { + const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); + const extensionTestsPath = path.resolve(__dirname, './index'); + console.log(extensionDevelopmentPath, extensionTestsPath); + const attachArgName = '--waitForDebugger='; + const waitForDebugger = process.argv.find(arg => arg.startsWith(attachArgName)); + const browserTypeName = '--browserType='; + const browserType = process.argv.find(arg => arg.startsWith(browserTypeName)); + + /** + * Basic usage + */ + await runTests({ + browserType: browserType ? browserType.slice(browserTypeName.length) : 'chromium', + extensionDevelopmentPath, + extensionTestsPath, + waitForDebugger: waitForDebugger ? Number(waitForDebugger.slice(attachArgName.length)) : undefined, + }); + } catch (e) { + console.log(e); + } +} + +go(); \ No newline at end of file diff --git a/src/view/pullRequestCommentController.ts b/src/view/pullRequestCommentController.ts index 63e5d0d2d9..4864d71716 100644 --- a/src/view/pullRequestCommentController.ts +++ b/src/view/pullRequestCommentController.ts @@ -91,7 +91,7 @@ export class PullRequestCommentController implements CommentHandler, CommentReac this.setContextKey(this.pullRequestModel.hasPendingReview); } - private getPREditors(editors: vscode.TextEditor[]): vscode.TextEditor[] { + private getPREditors(editors: readonly vscode.TextEditor[]): vscode.TextEditor[] { return editors.filter(editor => { if (editor.document.uri.scheme !== URI_SCHEME_PR) { return false; @@ -159,7 +159,7 @@ export class PullRequestCommentController implements CommentHandler, CommentReac this.addThreadsForEditors(prEditors); } - private onDidChangeOpenEditors(editors: vscode.TextEditor[]): void { + private onDidChangeOpenEditors(editors: readonly vscode.TextEditor[]): void { const prEditors = this.getPREditors(editors); const removed = this._openPREditors.filter(x => !prEditors.includes(x)); const added = prEditors.filter(x => !this._openPREditors.includes(x)); diff --git a/src/view/reviewCommentController.ts b/src/view/reviewCommentController.ts index 9d3e1ed39e..c24778a3d1 100644 --- a/src/view/reviewCommentController.ts +++ b/src/view/reviewCommentController.ts @@ -335,7 +335,7 @@ export class ReviewCommentController ); } - private visibleEditorsEqual(a: vscode.TextEditor[], b: vscode.TextEditor[]): boolean { + private visibleEditorsEqual(a: vscode.TextEditor[], b: readonly vscode.TextEditor[]): boolean { a = a.filter(ed => ed.document.uri.scheme !== 'comment'); b = b.filter(ed => ed.document.uri.scheme !== 'comment'); diff --git a/test_workspace/pr.http b/test_workspace/pr.http index 8a8aa60d96..a8a2ee0bb8 100644 --- a/test_workspace/pr.http +++ b/test_workspace/pr.http @@ -41,4 +41,12 @@ Authorization: Basic {{user}} {{$dotenv pat}} ### OPTIONS https://vsaex.dev.azure.com/anksinha/_apis/MemberEntitlementManagement +Authorization: Basic {{user}} {{$dotenv pat}} + +### +GET https://dev.azure.com/anksinha/_apis/projects/{{projectName}}/teams?$mine=True&api-version=6.1-preview.3 +Authorization: Basic {{user}} {{$dotenv pat}} + +### +GET https://dev.azure.com/anksinha/_apis/git/repositories/{{reposiory}}/pullrequests?searchCriteria.reviewerId=63f938a9-93f3-4991-aef2-11b73f5ceda4&api-version=6.1-preview.1 Authorization: Basic {{user}} {{$dotenv pat}} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index a0c06361f3..335d66b10d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,6 +16,7 @@ const { ESBuildMinifyPlugin } = require('esbuild-loader'); const ForkTsCheckerPlugin = require('fork-ts-checker-webpack-plugin'); const JSON5 = require('json5'); const TerserPlugin = require('terser-webpack-plugin'); +const webpack = require('webpack'); async function resolveTSConfig(configFile) { const data = await new Promise((resolve, reject) => { @@ -172,11 +173,27 @@ async function getExtensionConfig(target, mode, env) { }), ]; + if (target === 'webworker') { + plugins.push(new webpack.ProvidePlugin({ + process: path.join( + __dirname, + 'node_modules', + 'process', + 'browser.js'), + Buffer: ['buffer', 'Buffer'], + })); + } + + const entry = { + extension: './src/extension.ts', + }; + if (target === 'webworker') { + entry['test/index'] = './src/test/browser/index.ts'; + } + return { name: `extension:${target}`, - entry: { - extension: './src/extension.ts', - }, + entry, mode: mode, target: target, devtool: mode !== 'production' ? 'source-map' : undefined, @@ -286,6 +303,7 @@ async function getExtensionConfig(target, mode, env) { ), '../env/node/net': path.resolve(__dirname, 'src', 'env', 'browser', 'net'), '../env/node/ssh': path.resolve(__dirname, 'src', 'env', 'browser', 'ssh'), + '../../env/node/ssh': path.resolve(__dirname, 'src', 'env', 'browser', 'ssh'), './env/node/gitProviders/api': path.resolve( __dirname, 'src', @@ -303,24 +321,32 @@ async function getExtensionConfig(target, mode, env) { target === 'webworker' ? { path: require.resolve('path-browserify'), - url: false, - // stream: require.resolve("stream-browserify"), + url: require.resolve('url'), + stream: require.resolve("stream-browserify"), // zlib: require.resolve("browserify-zlib"), // crypto: require.resolve("crypto-browserify"), - // http: require.resolve("stream-http"), - // https: require.resolve("https-browserify"), + http: require.resolve("stream-http"), + https: require.resolve("https-browserify"), // util: require.resolve("util/"), - // buffer: require.resolve("buffer/"), + buffer: require.resolve("buffer/"), // assert: require.resolve("assert/"), - stream:false, + // stream:false, zlib: false, crypto:false, - http: false, - https:false, + // http: false, + //https:false, util: false, - buffer:false, - assert:false, - fs: false, + // buffer:false, + 'assert': require.resolve('assert'), + 'os': require.resolve('os-browserify/browser'), + "constants": require.resolve("constants-browserify"), + fs: path.resolve( + __dirname, + 'src', + 'env', + 'browser', + 'fs', + ), net: false, tls: false diff --git a/yarn.lock b/yarn.lock index 58bed34ef4..f2ec6df7bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -93,6 +93,17 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" +"@koa/router@^10.0.0": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-10.1.1.tgz#8e5a85c9b243e0bc776802c0de564561e57a5f78" + integrity sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw== + dependencies: + debug "^4.1.1" + http-errors "^1.7.3" + koa-compose "^4.1.0" + methods "^1.1.2" + path-to-regexp "^6.1.0" + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -459,6 +470,16 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== +"@types/vscode@1.79.0": + version "1.79.0" + resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.79.0.tgz#e2aed1bb3946ae2bebbc3b88020d0efe18f941a9" + integrity sha512-Tfowu2rSW8hVGbqzQLSPlOEiIOYYryTkgJ+chMecpYiJcnw9n0essvSiclnK+Qh/TcSVJHgaK4EMrQDZjZJ/Sw== + +"@types/webpack-env@^1.16.0": + version "1.16.2" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.2.tgz#8db514b059c1b2ae14ce9d7bb325296de6a9a0fa" + integrity sha512-vKx7WNQNZDyJveYcHAm9ZxhqSGLYwoyLhrHjLBOkw3a7cT76sTdjgtwyijhk1MaHyRIuSztcVwrUOO/NEu68Dw== + "@types/yargs-parser@*": version "15.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" @@ -471,6 +492,13 @@ dependencies: "@types/yargs-parser" "*" +"@types/yauzl@^2.9.1": + version "2.9.2" + resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.9.2.tgz#c48e5d56aff1444409e39fa164b0b4d4552a7b7a" + integrity sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA== + dependencies: + "@types/node" "*" + "@types/zen-observable@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" @@ -546,6 +574,34 @@ "@typescript-eslint/types" "4.18.0" eslint-visitor-keys "^2.0.0" +"@vscode/test-electron@^1.6.1": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-1.6.2.tgz#f639cab19a0013949015079dcfd2ff0c1aa88a1b" + integrity sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ== + dependencies: + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + rimraf "^3.0.2" + unzipper "^0.10.11" + +"@vscode/test-web@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@vscode/test-web/-/test-web-0.0.8.tgz#a7a5b15bcb23c2c0203a5b9ac09b04c6e93ca4ac" + integrity sha512-8VEKJ1s8Fo0oRFV/yLrgMv1bFuhS4PGodMR73FnTn6dzlNrV9g7mFrUsm+YyqqzdTUdo+7fahWS/qw0l/64e+w== + dependencies: + "@koa/router" "^10.0.0" + decompress "^4.2.1" + decompress-targz "^4.1.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + koa "^2.13.1" + koa-morgan "^1.0.1" + koa-mount "^4.0.0" + koa-static "^5.0.0" + minimist "^1.2.5" + playwright "^1.12.2" + vscode-uri "^3.0.2" + "@webassemblyjs/ast@1.11.0": version "1.11.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" @@ -694,6 +750,14 @@ abab@^2.0.3: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== +accepts@^1.3.5: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -1106,6 +1170,13 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +basic-auth@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" + integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== + dependencies: + safe-buffer "5.1.2" + bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -1146,6 +1217,14 @@ binary@~0.3.0: buffers "~0.1.1" chainsaw "~0.1.0" +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + bluebird@~3.4.1: version "3.4.7" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" @@ -1268,11 +1347,29 @@ browserslist@^4.14.5: escalade "^3.1.1" node-releases "^1.1.70" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1288,7 +1385,15 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= -buffer@6.0.3: +buffer@^5.2.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== @@ -1306,6 +1411,14 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +cache-content-type@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" + integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA== + dependencies: + mime-types "^2.1.18" + ylru "^1.2.0" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1506,6 +1619,11 @@ cls-hooked@^4.2.2: emitter-listener "^1.0.1" semver "^5.4.1" +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + color-convert@^1.9.0: version "1.9.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" @@ -1598,6 +1716,11 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.8.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@^6.1.0, commander@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" @@ -1608,11 +1731,28 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= +content-disposition@~0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + continuation-local-storage@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz#11f613f74e914fe9b34c92ad2d28fe6ae1db7ffb" @@ -1621,6 +1761,14 @@ continuation-local-storage@^3.2.1: async-listener "^0.6.0" emitter-listener "^1.1.1" +cookies@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" + integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -1802,6 +1950,13 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" +debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" @@ -1816,12 +1971,12 @@ debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.1: dependencies: ms "2.1.2" -debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== +debug@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== dependencies: - ms "2.0.0" + ms "2.1.2" decamelize@^1.2.0: version "1.2.0" @@ -1838,6 +1993,59 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0, decompress-targz@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" + integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -1845,6 +2053,11 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" +deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + deep-extend@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -1877,11 +2090,26 @@ delegate@^3.1.2: resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + denodeify@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= +depd@^2.0.0, depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + deprecation@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.0.0.tgz#dd0427cd920c78bc575ec39dab2f22e7c304fb9d" @@ -1900,6 +2128,11 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" +destroy@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + diagnostic-channel-publishers@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.3.3.tgz#376b7798f4fa90f37eb4f94d2caca611b0e9c330" @@ -2048,6 +2281,11 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + electron-to-chromium@^1.3.649: version "1.3.708" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.708.tgz#127970d2fc665ab356be59e668f2914856419176" @@ -2098,6 +2336,18 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== +encodeurl@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.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" + end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -2248,11 +2498,21 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-html@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -2481,6 +2741,17 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +extract-zip@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" + integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== + dependencies: + debug "^4.1.1" + get-stream "^5.1.0" + yauzl "^2.10.0" + optionalDependencies: + "@types/yauzl" "^2.9.1" + extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -2561,6 +2832,21 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= + +file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha1-LdvqfHP/42No365J3DOMBYwritY= + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -2657,6 +2943,16 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +fresh@~0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fs-extra@^9.0.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" @@ -2733,12 +3029,20 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= -get-stream@^5.0.0: +get-stream@^5.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== @@ -2847,6 +3151,11 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" +graceful-fs@^4.1.10: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -3020,6 +3329,35 @@ htmlparser2@^6.0.0: domutils "^2.4.4" entities "^2.0.0" +http-assert@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.5.0.tgz#c389ccd87ac16ed2dfa6246fd73b926aa00e6b8f" + integrity sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w== + dependencies: + deep-equal "~1.0.1" + http-errors "~1.8.0" + +http-errors@^1.6.3, http-errors@^1.7.3, http-errors@~1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507" + integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" @@ -3038,7 +3376,7 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-browserify@1.0.0: +https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= @@ -3068,7 +3406,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -3122,11 +3460,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -3275,6 +3618,11 @@ is-nan@^1.2.1: call-bind "^1.0.0" define-properties "^1.1.3" +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= + is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -3404,6 +3752,11 @@ joycon@^2.2.5: resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== +jpeg-js@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" + integrity sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q== + js-base64@^2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" @@ -3549,6 +3902,87 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc" integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw== +keygrip@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" + integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== + dependencies: + tsscmp "1.0.6" + +koa-compose@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" + integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw== + +koa-convert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-2.0.0.tgz#86a0c44d81d40551bae22fee6709904573eea4f5" + integrity sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA== + dependencies: + co "^4.6.0" + koa-compose "^4.1.0" + +koa-morgan@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/koa-morgan/-/koa-morgan-1.0.1.tgz#08052e0ce0d839d3c43178b90a5bb3424bef1f99" + integrity sha1-CAUuDODYOdPEMXi5CluzQkvvH5k= + dependencies: + morgan "^1.6.1" + +koa-mount@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/koa-mount/-/koa-mount-4.0.0.tgz#e0265e58198e1a14ef889514c607254ff386329c" + integrity sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ== + dependencies: + debug "^4.0.1" + koa-compose "^4.1.0" + +koa-send@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-5.0.1.tgz#39dceebfafb395d0d60beaffba3a70b4f543fe79" + integrity sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ== + dependencies: + debug "^4.1.1" + http-errors "^1.7.3" + resolve-path "^1.4.0" + +koa-static@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/koa-static/-/koa-static-5.0.0.tgz#5e92fc96b537ad5219f425319c95b64772776943" + integrity sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ== + dependencies: + debug "^3.1.0" + koa-send "^5.0.0" + +koa@^2.13.1: + version "2.13.3" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.3.tgz#a62641ba753ec54bee2c6da1a4f294c5fac35407" + integrity sha512-XhXIoR+ylAwqG3HhXwnMPQAM/4xfywz52OvxZNmxmTWGGHsvmBv4NSIhURha6yMuvEex1WdtplUTHnxnKpQiGw== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.8.0" + debug "^4.3.2" + delegates "^1.0.0" + depd "^2.0.0" + destroy "^1.0.4" + encodeurl "^1.0.2" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^2.0.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + kuler@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" @@ -3758,6 +4192,13 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + markdown-it@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" @@ -3890,6 +4331,11 @@ mdurl@^1.0.1: resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + memfs@^3.1.2: version "3.2.2" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.2.2.tgz#5de461389d596e3f23d48bb7c2afb6161f4df40e" @@ -3922,6 +4368,11 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +methods@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + micromark-extension-gfm-autolink-literal@~0.5.0: version "0.5.6" resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.6.tgz#406a58914d7a9cc6fb4cfafccc61a8ca36d7a12a" @@ -3996,6 +4447,11 @@ mime-db@1.47.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== +mime-db@1.50.0: + version "1.50.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" + integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== + mime-db@~1.35.0: version "1.35.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" @@ -4008,6 +4464,13 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "~1.35.0" +mime-types@^2.1.18, mime-types@~2.1.24: + version "2.1.33" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" + integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== + dependencies: + mime-db "1.50.0" + mime-types@^2.1.27: version "2.1.30" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" @@ -4020,6 +4483,11 @@ mime@^1.3.4: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^2.4.6: + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -4153,6 +4621,17 @@ moment@^2.22.1: resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y= +morgan@^1.6.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" + integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + dependencies: + basic-auth "~2.0.1" + debug "2.6.9" + depd "~2.0.0" + on-finished "~2.3.0" + on-headers "~1.0.2" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -4183,6 +4662,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -4345,6 +4829,18 @@ object.values@^1.1.1: es-abstract "^1.18.0-next.2" has "^1.0.3" +on-finished@^2.3.0, on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -4366,6 +4862,11 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +only@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" + integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= + optimism@^0.6.6: version "0.6.8" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.8.tgz#0780b546da8cd0a72e5207e0c3706c990c8673a6" @@ -4397,6 +4898,11 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -4560,6 +5066,11 @@ parse5@^6.0.0, parse5@^6.0.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parseurl@^1.3.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + path-browserify@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -4575,7 +5086,7 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0: +path-is-absolute@1.0.1, path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -4602,6 +5113,11 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" +path-to-regexp@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38" + integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg== + path-type@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" @@ -4655,11 +5171,28 @@ picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -pify@^2.0.0: +pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -4674,6 +5207,31 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +playwright@^1.12.2: + version "1.15.2" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.15.2.tgz#b350056d1fffbe5de5b1bdaca6ab73e35758baad" + integrity sha512-+Z+7ckihyxR6rK5q8DWC6eUbKARfXpyxpjNcoJfgwSr64lAOzjhyFQiPC/JkdIqhsLgZjxpWfl1S7fLb+wPkgA== + dependencies: + commander "^6.1.0" + debug "^4.1.1" + extract-zip "^2.0.1" + https-proxy-agent "^5.0.0" + jpeg-js "^0.4.2" + mime "^2.4.6" + pngjs "^5.0.0" + progress "^2.0.3" + proper-lockfile "^4.1.1" + proxy-from-env "^1.1.0" + rimraf "^3.0.2" + stack-utils "^2.0.3" + ws "^7.4.6" + yazl "^2.5.1" + +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== + postcss-modules-extract-imports@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" @@ -4772,7 +5330,12 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== -progress@^2.0.0: +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -4786,6 +5349,15 @@ prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +proper-lockfile@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" + integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== + dependencies: + graceful-fs "^4.2.4" + retry "^0.12.0" + signal-exit "^3.0.2" + property-information@^5.0.0: version "5.6.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" @@ -4793,6 +5365,11 @@ property-information@^5.0.0: dependencies: xtend "^4.0.0" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -4828,6 +5405,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -4851,6 +5433,11 @@ query-string@^6.2.0: decode-uri-component "^0.2.0" strict-uri-encode "^2.0.0" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -4990,7 +5577,7 @@ readable-stream@^2.0.1, readable-stream@^2.0.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^2.3.7, readable-stream@~2.3.6: +readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.7, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -5156,6 +5743,14 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-path@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" + integrity sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc= + dependencies: + http-errors "~1.6.2" + path-is-absolute "1.0.1" + resolve@>=1.9.0: version "1.19.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" @@ -5172,6 +5767,11 @@ resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.3, resolve@^1.9. is-core-module "^2.2.0" path-parse "^1.0.6" +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -5213,7 +5813,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -5261,6 +5861,13 @@ schema-utils@^3.0.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +seek-bzip@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" + integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== + dependencies: + commander "^2.8.1" + select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" @@ -5305,6 +5912,16 @@ setimmediate@~1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -5486,6 +6103,18 @@ stack-trace@0.0.x: resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= +stack-utils@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -5499,10 +6128,10 @@ stream-browserify@^3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" -stream-http@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" - integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== +stream-http@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" + integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== dependencies: builtin-status-codes "^3.0.0" inherits "^2.0.4" @@ -5612,6 +6241,13 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -5722,6 +6358,19 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b" integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw== +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + tar@^4.4.2: version "4.4.10" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" @@ -5774,6 +6423,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + tiny-emitter@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" @@ -5786,6 +6440,11 @@ tmp@0.0.29: dependencies: os-tmpdir "~1.0.1" +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + 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" @@ -5793,6 +6452,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -5872,6 +6536,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" integrity sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw== +tsscmp@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + tsutils@^3.17.1: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -5947,6 +6616,14 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-is@^1.6.16: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + typed-rest-client@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/typed-rest-client/-/typed-rest-client-1.2.0.tgz#723085d203f38d7d147271e5ed3a75488eb44a02" @@ -5989,6 +6666,14 @@ unbox-primitive@^1.0.0: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unbzip2-stream@^1.0.9: + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== + dependencies: + buffer "^5.2.1" + through "^2.3.8" + underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" @@ -6083,6 +6768,14 @@ url-join@^1.1.0: resolved "https://registry.yarnpkg.com/url-join/-/url-join-1.1.0.tgz#741c6c2f4596c4830d6718460920d0c92202dc78" integrity sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg= +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -6123,6 +6816,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +vary@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -6193,6 +6891,11 @@ vscode-test@^1.5.1: rimraf "^3.0.2" unzipper "^0.10.11" +vscode-uri@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.2.tgz#ecfd1d066cb8ef4c3a208decdbab9a8c23d055d0" + integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA== + vsls@^0.3.967: version "0.3.967" resolved "https://registry.yarnpkg.com/vsls/-/vsls-0.3.967.tgz#d762f1b10287c2a4ca8a54edb2f6b0f074a52583" @@ -6429,6 +7132,11 @@ ws@^7.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59" integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw== +ws@^7.4.6: + version "7.5.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" + integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -6517,7 +7225,7 @@ yargs@13.3.0, yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" -yauzl@^2.3.1: +yauzl@^2.10.0, yauzl@^2.3.1, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= @@ -6525,13 +7233,18 @@ yauzl@^2.3.1: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yazl@^2.2.2: +yazl@^2.2.2, yazl@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== dependencies: buffer-crc32 "~0.2.3" +ylru@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" + integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"