diff --git a/.drone.yml b/.drone.yml index 2d302c89..82693edd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,6 +6,11 @@ platform: arch: amd64 steps: +- name: submodules + image: alpine/git + commands: + - git submodule update --init + - name: cache:restore image: node:12 commands: @@ -69,7 +74,7 @@ steps: - name: publish:gcs image: plugins/gcs settings: - source: gcs_bucket + source: binary-upload target: codesrv-ci.cdr.sh/ token: from_secret: gcs-token @@ -85,6 +90,11 @@ platform: arch: amd64 steps: +- name: submodules + image: alpine/git + commands: + - git submodule update --init + - name: cache:restore image: node:12-alpine commands: @@ -133,7 +143,7 @@ steps: - name: publish:gcs image: plugins/gcs settings: - source: gcs_bucket + source: binary-upload target: codesrv-ci.cdr.sh/ token: from_secret: gcs-token @@ -149,6 +159,12 @@ platform: arch: arm64 steps: +- name: submodules + image: alpine + commands: + - apk add git + - git submodule update --init + - name: cache:restore image: node:12 commands: @@ -211,7 +227,7 @@ steps: - name: publish:gcs image: plugins/gcs settings: - source: gcs_bucket + source: binary-upload target: codesrv-ci.cdr.sh/ token: from_secret: gcs-token @@ -227,6 +243,12 @@ platform: arch: arm64 steps: +- name: submodules + image: alpine + commands: + - apk add git + - git submodule update --init + - name: cache:restore image: node:12-alpine commands: @@ -275,7 +297,7 @@ steps: - name: publish:gcs image: plugins/gcs settings: - source: gcs_bucket + source: binary-upload target: codesrv-ci.cdr.sh/ token: from_secret: gcs-token @@ -291,6 +313,12 @@ platform: arch: arm steps: +- name: submodules + image: alpine + commands: + - apk add git + - git submodule update --init + - name: cache:restore image: node:12 commands: @@ -360,6 +388,12 @@ platform: arch: arm steps: +- name: submodules + image: alpine + commands: + - apk add git + - git submodule update --init + - name: cache:restore image: node:12-alpine commands: diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..65705d95 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*] +indent_style = space +trim_trailing_whitespace = true +indent_size = 2 diff --git a/.eslintrc.yaml b/.eslintrc.yaml new file mode 100644 index 00000000..fbd92b97 --- /dev/null +++ b/.eslintrc.yaml @@ -0,0 +1,39 @@ +parser: "@typescript-eslint/parser" +env: + browser: true + es6: true # Map, etc. + mocha: true + node: true + +parserOptions: + ecmaVersion: 2018 + sourceType: module + ecmaFeatures: + jsx: true + +extends: + - eslint:recommended + - plugin:@typescript-eslint/recommended + - plugin:import/recommended + - plugin:import/typescript + - plugin:react/recommended + - plugin:prettier/recommended + - prettier # Removes eslint rules that conflict with prettier. + - prettier/@typescript-eslint # Remove conflicts again. + +plugins: + - react-hooks + +# Need to set this explicitly for the eslint-plugin-react. +settings: + react: + version: detect + +rules: + # For overloads. + no-dupe-class-members: off + + # https://www.npmjs.com/package/eslint-plugin-react-hooks + react-hooks/rules-of-hooks: error + + react/prop-types: off # We use Typescript to verify prop types. diff --git a/.gitignore b/.gitignore index 0a7a0e8f..a951666c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,14 @@ +*.tsbuildinfo +.cache +binaries +binary-upload +build +cache-upload +dist +dist-build node_modules -/build -/release -/binaries -/lib +out +out-build +release +source +yarn-cache diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..9854a1b1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/vscode"] + path = lib/vscode + url = https://github.com/microsoft/vscode diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000..aaaa29c7 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,7 @@ +printWidth: 120 +semi: false +tabWidth: 2 +singleQuote: false +trailingComma: es5 +useTabs: false +arrowParens: always diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml new file mode 100644 index 00000000..9cc924cb --- /dev/null +++ b/.stylelintrc.yaml @@ -0,0 +1,2 @@ +extends: + - stylelint-config-standard diff --git a/Dockerfile b/Dockerfile index 03026566..08005dbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,40 +4,40 @@ ARG githubToken # Install VS Code's deps. These are the only two it seems we need. RUN apt-get update && apt-get install -y \ - libxkbfile-dev \ - libsecret-1-dev + libxkbfile-dev \ + libsecret-1-dev WORKDIR /src COPY . . RUN yarn \ - && DRONE_TAG="$tag" MINIFY=true BINARY=true GITHUB_TOKEN="$githubToken" ./scripts/ci.bash \ - && rm -r /src/build \ - && rm -r /src/source + && DRONE_TAG="$tag" MINIFY=true STRIP_BIN_TARGET=true GITHUB_TOKEN="$githubToken" ./scripts/ci.bash \ + && rm -r /src/build \ + && rm -r /src/source # We deploy with Ubuntu so that devs have a familiar environment. FROM ubuntu:18.04 RUN apt-get update && apt-get install -y \ - openssl \ - net-tools \ - git \ - locales \ - sudo \ - dumb-init \ - vim \ - curl \ - wget \ - && rm -rf /var/lib/apt/lists/* + openssl \ + net-tools \ + git \ + locales \ + sudo \ + dumb-init \ + vim \ + curl \ + wget \ + && rm -rf /var/lib/apt/lists/* RUN locale-gen en_US.UTF-8 # We cannot use update-locale because docker will not use the env variables # configured in /etc/default/locale so we need to set it manually. ENV LC_ALL=en_US.UTF-8 \ - SHELL=/bin/bash + SHELL=/bin/bash RUN adduser --gecos '' --disabled-password coder && \ - echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd + echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd USER coder # Create first so these directories will be owned by coder instead of root diff --git a/README.md b/README.md index 095c7a44..b2a396a5 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,19 @@ docker run -it -p 127.0.0.1:8080:8080 -v "$PWD:/home/coder/project" codercom/cod ``` - **Consistent environment:** Code on your Chromebook, tablet, and laptop with a - consistent dev environment. develop more easily for Linux if you have a - Windows or Mac, and pick up where you left off when switching workstations. + consistent dev environment. Develop more easily for Linux if you have a + Windows or Mac and pick up where you left off when switching workstations. - **Server-powered:** Take advantage of large cloud servers to speed up tests, compilations, downloads, and more. Preserve battery life when you're on the go since all intensive computation runs on your server. ![Screenshot](/doc/assets/ide.gif) +## VS Code + +- See [our VS Code readme](./src/vscode) for more information about how + code-server and VS Code work together. + ## Getting Started ### Requirements @@ -25,7 +30,8 @@ docker run -it -p 127.0.0.1:8080:8080 -v "$PWD:/home/coder/project" codercom/cod - 64-bit host. - At least 1GB of RAM. - 2 cores or more are recommended (1 core works but not optimally). -- Secure connection over HTTPS or localhost (required for service workers). +- Secure connection over HTTPS or localhost (required for service workers and + clipboard support). - For Linux: GLIBC 2.17 or later and GLIBCXX 3.4.15 or later. - Docker (for Docker versions of `code-server`). @@ -37,12 +43,6 @@ Use [sshcode](https://github.com/codercom/sshcode) for a simple setup. See the Docker one-liner mentioned above. Dockerfile is at [/Dockerfile](/Dockerfile). -To debug Golang using the -[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go), -you need to add `--security-opt seccomp=unconfined` to your `docker run` -arguments when launching code-server with Docker. See -[#725](https://github.com/cdr/code-server/issues/725) for details. - ### Digital Ocean [![Create a Droplet](./doc/assets/droplet.svg)](https://marketplace.digitalocean.com/apps/code-server?action=deploy) @@ -59,18 +59,18 @@ arguments when launching code-server with Docker. See ### Build -See -[VS Code's prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) -before building. +- [VS Code prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) ```shell -export OUT=/path/to/output/build # Optional if only building. Required if also developing. -yarn build $vscodeVersion $codeServerVersion # See scripts/ci.bash for the VS Code version to use. - # The code-server version can be anything you want. -node /path/to/output/build/out/vs/server/main.js # You can run the built JavaScript with Node. -yarn binary $vscodeVersion $codeServerVersion # Or you can package it into a binary. +yarn +yarn build +node build/out/entry.js # You can run the built JavaScript with Node. +yarn binary # Or you can package it into a binary. ``` +If changes are made to the patch and you've built previously you must manually +reset VS Code then run `yarn patch:apply`. + ## Security ### Authentication @@ -98,32 +98,11 @@ for free. Do not expose `code-server` to the open internet without SSL, whether built-in or through a proxy. -## Known Issues - -- Creating custom VS Code extensions and debugging them doesn't work. -- Extension profiling and tips are currently disabled. - ## Future -- **Stay up to date!** Get notified about new releases of code-server. +- **Stay up to date!** Get notified about new releases of `code-server`. ![Screenshot](/doc/assets/release.gif) -- Windows support. - Electron and Chrome OS applications to bridge the gap between local<->remote. -- Run VS Code unit tests against our builds to ensure features work as expected. - -## Extensions - -code-server does not provide access to the official -[Visual Studio Marketplace](https://marketplace.visualstudio.com/vscode). Instead, -Coder has created a custom extension marketplace that we manage for open-source -extensions. If you want to use an extension with code-server that we do not have -in our marketplace please look for a release in the extension’s repository, -contact us to see if we have one in the works or, if you build an extension -locally from open source, you can copy it to the `extensions` folder. If you -build one locally from open-source please contribute it to the project and let -us know so we can give you props! If you have your own custom marketplace, it is -possible to point code-server to it by setting the `SERVICE_URL` and `ITEM_URL` -environment variables. ## Telemetry @@ -134,51 +113,18 @@ data collected to improve code-server. ### Development -See -[VS Code's prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) -before developing. +- [VS Code prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) ```shell -git clone https://github.com/microsoft/vscode -cd vscode -git checkout ${vscodeVersion} # See scripts/ci.bash for the version to use. yarn -git clone https://github.com/cdr/code-server src/vs/server -cd src/vs/server -yarn -yarn patch:apply -yarn watch -# Wait for the initial compilation to complete (it will say "Finished compilation"). -# Run the next command in another shell. -yarn start -# Visit http://localhost:8080 +yarn watch # Visit http://localhost:8080 once completed. ``` If you run into issues about a different version of Node being used, try running `npm rebuild` in the VS Code directory. -### Upgrading VS Code - -We patch VS Code to provide and fix some functionality. As the web portion of VS -Code matures, we'll be able to shrink and maybe even entirely eliminate our -patch. In the meantime, however, upgrading the VS Code version requires ensuring -that the patch still applies and has the intended effects. - -To generate a new patch, **stage all the changes** you want to be included in -the patch in the VS Code source, then run `yarn patch:generate` in this -directory. - -Our changes include: - -- Allow multiple extension directories (both user and built-in). -- Modify the loader, websocket, webview, service worker, and asset requests to - use the URL of the page as a base (and TLS if necessary for the websocket). -- Send client-side telemetry through the server. -- Make changing the display language work. -- Make it possible for us to load code on the client. -- Make extensions work in the browser. -- Fix getting permanently disconnected when you sleep or hibernate for a while. -- Make it possible to automatically update the binary. +If changes are made to the patch and you've built previously you must manually +reset VS Code then run `yarn patch:apply`. ## License diff --git a/lib/vscode b/lib/vscode new file mode 160000 index 00000000..26076a4d --- /dev/null +++ b/lib/vscode @@ -0,0 +1 @@ +Subproject commit 26076a4de974ead31f97692a0d32f90d735645c0 diff --git a/main.js b/main.js deleted file mode 100644 index 360cd6ea..00000000 --- a/main.js +++ /dev/null @@ -1,7 +0,0 @@ -// Once our entry file is loaded we no longer need nbin to bypass normal Node -// execution. We can still shim the fs into the binary even when bypassing. This -// will ensure for example that a spawn like `${process.argv[0]} -e` will work -// while still allowing us to access files within the binary. -process.env.NBIN_BYPASS = true; - -require("../../bootstrap-amd").load("vs/server/src/node/cli"); diff --git a/package.json b/package.json index 12dcf927..43e79f7d 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,70 @@ { + "name": "code-server", "license": "MIT", + "version": "2.1.0", "scripts": { + "i": "yarn install --ignore-scripts", + "preinstall": "./scripts/preinstall.sh", + "postinstall": "./scripts/postinstall.sh", + "patch:generate": "cd ./lib/vscode && git diff HEAD > ../../scripts/vscode.patch", + "patch:apply": "cd ./lib/vscode && git apply ../../scripts/vscode.patch", + "test": "mocha -r ts-node/register ./test/*.test.ts", + "lint:js": "eslint {src,test,scripts} --ext .ts,.tsx", + "lint:css": "stylelint 'src/**/*.css'", + "lint": "./scripts/lint.sh", + "watch": "yarn runner watch", "runner": "cd ./scripts && node --max-old-space-size=32384 -r ts-node/register ./build.ts", - "start": "nodemon --watch ../../../out --verbose ../../../out/vs/server/main.js", - "test": "./scripts/test.sh", - "watch": "cd ../../../ && yarn watch", - "build": "yarn && yarn runner build", - "package": "yarn runner package", + "build": "yarn runner build", "binary": "yarn runner binary", - "patch:generate": "cd ../../../ && git diff --staged > ./src/vs/server/scripts/vscode.patch", - "patch:apply": "cd ../../../ && git apply ./src/vs/server/scripts/vscode.patch" + "package": "yarn runner package" }, "devDependencies": { "@coder/nbin": "^1.2.7", "@types/fs-extra": "^8.0.1", - "@types/node": "^10.12.12", + "@types/mocha": "^5.2.7", + "@types/node": "^12.12.7", + "@types/parcel-bundler": "^1.12.1", "@types/pem": "^1.9.5", + "@types/react": "^16.9.18", + "@types/react-dom": "^16.9.5", + "@types/react-router-dom": "^5.1.3", "@types/safe-compare": "^1.1.0", "@types/tar-fs": "^1.16.1", "@types/tar-stream": "^1.6.1", - "fs-extra": "^8.1.0", - "nodemon": "^1.19.1", + "@types/ws": "^6.0.4", + "@typescript-eslint/eslint-plugin": "^2.0.0", + "@typescript-eslint/parser": "^2.0.0", + "eslint": "^6.2.0", + "eslint-config-prettier": "^6.0.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-prettier": "^3.1.0", + "eslint-plugin-react": "^7.14.3", + "eslint-plugin-react-hooks": "^1.7.0", + "leaked-handles": "^5.2.0", + "mocha": "^6.2.0", + "parcel-bundler": "^1.12.4", + "prettier": "^1.18.2", + "stylelint": "^13.0.0", + "stylelint-config-standard": "^19.0.0", "ts-node": "^8.4.1", - "typescript": "3.6" + "typescript": "3.7.2" }, "resolutions": { - "@types/node": "^10.12.12", - "safe-buffer": "^5.1.1" + "@types/node": "^12.12.7", + "safe-buffer": "^5.1.1", + "vfile-message": "^2.0.2" }, "dependencies": { - "@coder/logger": "^1.1.12", - "@coder/node-browser": "^1.0.6", - "@coder/requirefs": "^1.0.6", + "@coder/logger": "1.1.11", + "fs-extra": "^8.1.0", "httpolyglot": "^0.1.2", "pem": "^1.14.2", + "react": "^16.12.0", + "react-dom": "^16.12.0", + "react-router-dom": "^5.1.2", "safe-compare": "^1.1.4", "tar-fs": "^2.0.0", "tar-stream": "^2.1.0", - "util": "^0.12.1" + "ws": "^7.2.0" } } diff --git a/scripts/build.ts b/scripts/build.ts index 945c9b22..617687fc 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -1,391 +1,451 @@ -import { Binary } from "@coder/nbin"; -import * as cp from "child_process"; -// import * as crypto from "crypto"; -import * as fs from "fs-extra"; -import * as os from "os"; -import * as path from "path"; -import * as util from "util"; +import { Binary } from "@coder/nbin" +import * as cp from "child_process" +import * as fs from "fs-extra" +import * as os from "os" +import Bundler from "parcel-bundler" +import * as path from "path" +import * as util from "util" enum Task { - /** - * Use before running anything that only works inside VS Code. - */ - EnsureInVscode = "ensure-in-vscode", - Binary = "binary", - Package = "package", - Build = "build", + Binary = "binary", + Package = "package", + Build = "build", + Watch = "watch", } class Builder { - private readonly rootPath = path.resolve(__dirname, ".."); - private readonly outPath = process.env.OUT || this.rootPath; - private _target?: "darwin" | "alpine" | "linux"; - private currentTask?: Task; + private readonly rootPath = path.resolve(__dirname, "..") + private readonly vscodeSourcePath = path.join(this.rootPath, "lib/vscode") + private readonly binariesPath = path.join(this.rootPath, "binaries") + private readonly buildPath = path.join(this.rootPath, "build") + private readonly codeServerVersion: string + private _target?: "darwin" | "alpine" | "linux" + private currentTask?: Task - public run(task: Task | undefined, args: string[]): void { - this.currentTask = task; - this.doRun(task, args).catch((error) => { - console.error(error.message); - process.exit(1); - }); - } + public constructor() { + this.ensureArgument("rootPath", this.rootPath) + this.codeServerVersion = this.ensureArgument( + "codeServerVersion", + process.env.VERSION || require(path.join(this.rootPath, "package.json")).version + ) + } - private async task(message: string, fn: () => Promise): Promise { - const time = Date.now(); - this.log(`${message}...`, true); - try { - const t = await fn(); - process.stdout.write(`took ${Date.now() - time}ms\n`); - return t; - } catch (error) { - process.stdout.write("failed\n"); - throw error; - } - } + public run(task: Task | undefined): void { + this.currentTask = task + this.doRun(task).catch((error) => { + console.error(error.message) + process.exit(1) + }) + } - /** - * Writes to stdout with an optional newline. - */ - private log(message: string, skipNewline: boolean = false): void { - process.stdout.write(`[${this.currentTask || "default"}] ${message}`); - if (!skipNewline) { - process.stdout.write("\n"); - } - } + private async task(message: string, fn: () => Promise): Promise { + const time = Date.now() + this.log(`${message}...`, true) + try { + const t = await fn() + process.stdout.write(`took ${Date.now() - time}ms\n`) + return t + } catch (error) { + process.stdout.write("failed\n") + throw error + } + } - private async doRun(task: Task | undefined, args: string[]): Promise { - if (!task) { - throw new Error("No task provided"); - } + /** + * Writes to stdout with an optional newline. + */ + private log(message: string, skipNewline = false): void { + process.stdout.write(`[${this.currentTask || "default"}] ${message}`) + if (!skipNewline) { + process.stdout.write("\n") + } + } - if (task === Task.EnsureInVscode) { - return process.exit(this.isInVscode(this.rootPath) ? 0 : 1); - } + private async doRun(task: Task | undefined): Promise { + if (!task) { + throw new Error("No task provided") + } - // If we're inside VS Code assume we want to develop. In that case we should - // set an OUT directory and not build in this directory, otherwise when you - // build/watch VS Code the build directory will be included. - if (this.isInVscode(this.outPath)) { - throw new Error("Should not build inside VS Code; set the OUT environment variable"); - } + const arch = this.ensureArgument("arch", os.arch().replace(/^x/, "x86_")) + const target = this.ensureArgument("target", await this.target()) + const binaryName = `code-server-${this.codeServerVersion}-${target}-${arch}` - this.ensureArgument("rootPath", this.rootPath); - this.ensureArgument("outPath", this.outPath); + switch (task) { + case Task.Watch: + return this.watch() + case Task.Binary: + return this.binary(binaryName) + case Task.Package: + return this.package(binaryName) + case Task.Build: + return this.build() + default: + throw new Error(`No task matching "${task}"`) + } + } - const arch = this.ensureArgument("arch", os.arch().replace(/^x/, "x86_")); - const target = this.ensureArgument("target", await this.target()); - const vscodeVersion = this.ensureArgument("vscodeVersion", args[0]); - const codeServerVersion = this.ensureArgument("codeServerVersion", args[1]); + /** + * Get the target of the system. + */ + private async target(): Promise<"darwin" | "alpine" | "linux"> { + if (!this._target) { + if (os.platform() === "darwin" || (process.env.OSTYPE && /^darwin/.test(process.env.OSTYPE))) { + this._target = "darwin" + } else { + // Alpine's ldd doesn't have a version flag but if you use an invalid flag + // (like --version) it outputs the version to stderr and exits with 1. + const result = await util + .promisify(cp.exec)("ldd --version") + .catch((error) => ({ stderr: error.message, stdout: "" })) + if (/musl/.test(result.stderr) || /musl/.test(result.stdout)) { + this._target = "alpine" + } else { + this._target = "linux" + } + } + } + return this._target + } - const vscodeSourcePath = path.join(this.outPath, "source", `vscode-${vscodeVersion}-source`); - const binariesPath = path.join(this.outPath, "binaries"); - const binaryName = `code-server${codeServerVersion}-vsc${vscodeVersion}-${target}-${arch}`; - const finalBuildPath = path.join(this.outPath, "build", `${binaryName}-built`); + /** + * Make sure the argument is set. Display the value if it is. + */ + private ensureArgument(name: string, arg?: string): string { + if (!arg) { + throw new Error(`${name} is missing`) + } + this.log(`${name} is "${arg}"`) + return arg + } - switch (task) { - case Task.Binary: - return this.binary(finalBuildPath, binariesPath, binaryName); - case Task.Package: - return this.package(vscodeSourcePath, binariesPath, binaryName); - case Task.Build: - return this.build(vscodeSourcePath, vscodeVersion, codeServerVersion, finalBuildPath); - default: - throw new Error(`No task matching "${task}"`); - } - } + /** + * Build VS Code and code-server. + */ + private async build(): Promise { + process.env.NODE_OPTIONS = "--max-old-space-size=32384 " + (process.env.NODE_OPTIONS || "") + process.env.NODE_ENV = "production" - /** - * Get the target of the system. - */ - private async target(): Promise<"darwin" | "alpine" | "linux"> { - if (!this._target) { - if (os.platform() === "darwin" || (process.env.OSTYPE && /^darwin/.test(process.env.OSTYPE))) { - this._target = "darwin"; - } else { - // Alpine's ldd doesn't have a version flag but if you use an invalid flag - // (like --version) it outputs the version to stderr and exits with 1. - const result = await util.promisify(cp.exec)("ldd --version") - .catch((error) => ({ stderr: error.message, stdout: "" })); - if (/musl/.test(result.stderr) || /musl/.test(result.stdout)) { - this._target = "alpine"; - } else { - this._target = "linux"; - } - } - } - return this._target; - } + await this.task("cleaning up old build", async () => { + if (!process.env.SKIP_VSCODE) { + return fs.remove(this.buildPath) + } + // If skipping VS Code, keep the existing build if any. + try { + const files = await fs.readdir(this.buildPath) + return Promise.all(files.filter((f) => f !== "lib").map((f) => fs.remove(path.join(this.buildPath, f)))) + } catch (error) { + if (error.code !== "ENOENT") { + throw error + } + } + }) - /** - * Make sure the argument is set. Display the value if it is. - */ - private ensureArgument(name: string, arg?: string): string { - if (!arg) { - this.log(`${name} is missing`); - throw new Error("Usage: "); - } - this.log(`${name} is "${arg}"`); - return arg; - } + const commit = require(path.join(this.vscodeSourcePath, "build/lib/util")).getVersion(this.rootPath) as string + if (!process.env.SKIP_VSCODE) { + await this.buildVscode(commit) + } else { + this.log("skipping vs code build") + } + await this.buildCodeServer(commit) - /** - * Return true if it looks like we're inside VS Code. This is used to prevent - * accidentally building inside VS Code while developing which causes issues - * because the watcher will try compiling those built files. - */ - private isInVscode(pathToCheck: string): boolean { - let inside = false; - const maybeVsCode = path.join(pathToCheck, "../../../"); - try { - // If it has a package.json with the right name it's probably VS Code. - inside = require(path.join(maybeVsCode, "package.json")).name === "code-oss-dev"; - } catch (error) {} - this.log( - inside - ? `Running inside VS Code ([${maybeVsCode}]${path.relative(maybeVsCode, pathToCheck)})` - : "Not running inside VS Code" - ); - return inside; - } + this.log(`final build: ${this.buildPath}`) + } - /** - * Build code-server within VS Code. - */ - private async build(vscodeSourcePath: string, vscodeVersion: string, codeServerVersion: string, finalBuildPath: string): Promise { - // Install dependencies (should be cached by CI). - await this.task("Installing code-server dependencies", async () => { - await util.promisify(cp.exec)("yarn", { cwd: this.rootPath }); - }); + private async buildCodeServer(commit: string): Promise { + await this.task("building code-server", async () => { + return util.promisify(cp.exec)("tsc --outDir ./out-build --tsBuildInfoFile ./.prod.tsbuildinfo", { + cwd: this.rootPath, + }) + }) - // Download and prepare VS Code if necessary (should be cached by CI). - if (fs.existsSync(vscodeSourcePath)) { - this.log("Using existing VS Code clone"); - } else { - await this.task("Cloning VS Code", () => { - return util.promisify(cp.exec)( - "git clone https://github.com/microsoft/vscode" - + ` --quiet --branch "${vscodeVersion}"` - + ` --single-branch --depth=1 "${vscodeSourcePath}"`); - }); - } + await this.task("bundling code-server", async () => { + return this.createBundler("dist-build", commit).bundle() + }) - await this.task("Installing VS Code dependencies", () => { - return util.promisify(cp.exec)("yarn", { cwd: vscodeSourcePath }); - }); + await this.task("copying code-server into build directory", async () => { + await fs.mkdirp(this.buildPath) + await Promise.all([ + fs.copy(path.join(this.rootPath, "out-build"), path.join(this.buildPath, "out")), + fs.copy(path.join(this.rootPath, "dist-build"), path.join(this.buildPath, "dist")), + // For source maps and images. + fs.copy(path.join(this.rootPath, "src"), path.join(this.buildPath, "src")), + ]) + }) - if (fs.existsSync(path.join(vscodeSourcePath, ".build/extensions"))) { - this.log("Using existing built-in-extensions"); - } else { - await this.task("Building default extensions", () => { - return util.promisify(cp.exec)( - "yarn gulp compile-extensions-build --max-old-space-size=32384", - { cwd: vscodeSourcePath }, - ); - }); - } + await this.copyDependencies("code-server", this.rootPath, this.buildPath) + } - // Clean before patching or it could fail if already patched. - await this.task("Patching VS Code", async () => { - await util.promisify(cp.exec)("git reset --hard", { cwd: vscodeSourcePath }); - await util.promisify(cp.exec)("git clean -fd", { cwd: vscodeSourcePath }); - await util.promisify(cp.exec)(`git apply ${this.rootPath}/scripts/vscode.patch`, { cwd: vscodeSourcePath }); - }); + private async buildVscode(commit: string): Promise { + await this.task("building vs code", () => { + return util.promisify(cp.exec)("yarn gulp compile-build", { cwd: this.vscodeSourcePath }) + }) - const serverPath = path.join(vscodeSourcePath, "src/vs/server"); - await this.task("Copying code-server into VS Code", async () => { - await fs.remove(serverPath); - await fs.mkdirp(serverPath); - await Promise.all(["main.js", "node_modules", "src", "typings"].map((fileName) => { - return fs.copy(path.join(this.rootPath, fileName), path.join(serverPath, fileName)); - })); - }); + await this.task("building builtin extensions", async () => { + const exists = await fs.pathExists(path.join(this.vscodeSourcePath, ".build/extensions")) + if (exists) { + process.stdout.write("already built, skipping...") + } else { + await util.promisify(cp.exec)("yarn gulp compile-extensions-build", { cwd: this.vscodeSourcePath }) + } + }) - await this.task("Building VS Code", () => { - return util.promisify(cp.exec)("yarn gulp compile-build --max-old-space-size=32384", { cwd: vscodeSourcePath }); - }); + await this.task("optimizing vs code", async () => { + return util.promisify(cp.exec)("yarn gulp optimize --gulpfile ./coder.js", { cwd: this.vscodeSourcePath }) + }) - await this.task("Optimizing VS Code", async () => { - await fs.copyFile(path.join(this.rootPath, "scripts/optimize.js"), path.join(vscodeSourcePath, "coder.js")); - await util.promisify(cp.exec)(`yarn gulp optimize --max-old-space-size=32384 --gulpfile ./coder.js`, { cwd: vscodeSourcePath }); - }); + if (process.env.MINIFY) { + await this.task("minifying vs code", () => { + return util.promisify(cp.exec)("yarn gulp minify --gulpfile ./coder.js", { cwd: this.vscodeSourcePath }) + }) + } - const { productJson, packageJson } = await this.task("Generating final package.json and product.json", async () => { - const merge = async (name: string, extraJson: { [key: string]: string } = {}): Promise<{ [key: string]: string }> => { - const [aJson, bJson] = (await Promise.all([ - fs.readFile(path.join(vscodeSourcePath, `${name}.json`), "utf8"), - fs.readFile(path.join(this.rootPath, `scripts/${name}.json`), "utf8"), - ])).map((raw) => { - const json = JSON.parse(raw); - delete json.scripts; - delete json.dependencies; - delete json.devDependencies; - delete json.optionalDependencies; - return json; - }); + const { productJson, packageJson } = await this.task("generating vs code product configuration", async () => { + const merge = async (name: string, json: { [key: string]: string } = {}): Promise<{ [key: string]: string }> => { + return { + ...JSON.parse(await fs.readFile(path.join(this.vscodeSourcePath, `${name}.json`), "utf8")), + ...json, + } + } - return { ...aJson, ...bJson, ...extraJson }; - }; + const date = new Date().toISOString() + const [packageJson, productJson] = await Promise.all([merge("package", {}), merge("product", { commit, date })]) - const date = new Date().toISOString(); - const commit = require(path.join(vscodeSourcePath, "build/lib/util")).getVersion(this.rootPath); + return { productJson, packageJson } + }) - const [productJson, packageJson] = await Promise.all([ - merge("product", { commit, date }), - merge("package", { codeServerVersion: `${codeServerVersion}-vsc${vscodeVersion}` }), - ]); + await this.task("inserting vs code product configuration", async () => { + const filePath = path.join(this.vscodeSourcePath, "out-build/vs/platform/product/common/product.js") + return fs.writeFile( + filePath, + (await fs.readFile(filePath, "utf8")).replace( + "{ /*BUILD->INSERT_PRODUCT_CONFIGURATION*/}", + JSON.stringify({ + version: packageJson.version, + ...productJson, + }) + ) + ) + }) - // We could do this before the optimization but then it'd be copied into - // three files and unused in two which seems like a waste of bytes. - const apiPath = path.join(vscodeSourcePath, "out-vscode/vs/workbench/workbench.web.api.js"); - await fs.writeFile(apiPath, (await fs.readFile(apiPath, "utf8")).replace('{ /*BUILD->INSERT_PRODUCT_CONFIGURATION*/}', JSON.stringify({ - version: packageJson.version, - codeServerVersion: packageJson.codeServerVersion, - ...productJson, - }))); + const vscodeBuildPath = path.join(this.buildPath, "lib/vscode") + await this.task("copying vs code into build directory", async () => { + await fs.mkdirp(vscodeBuildPath) + await Promise.all([ + (async (): Promise => { + await fs.move( + path.join(this.vscodeSourcePath, `out-vscode${process.env.MINIFY ? "-min" : ""}`), + path.join(vscodeBuildPath, "out") + ) + await fs.remove(path.join(vscodeBuildPath, "out/vs/server/browser/workbench.html")) + await fs.move( + path.join(vscodeBuildPath, "out/vs/server/browser/workbench-build.html"), + path.join(vscodeBuildPath, "out/vs/server/browser/workbench.html") + ) + })(), + await fs.copy(path.join(this.vscodeSourcePath, ".build/extensions"), path.join(vscodeBuildPath, "extensions")), + ]) + }) - return { productJson, packageJson }; - }); + await this.copyDependencies("vs code", this.vscodeSourcePath, vscodeBuildPath) - if (process.env.MINIFY) { - await this.task("Minifying VS Code", () => { - return util.promisify(cp.exec)("yarn gulp minify --max-old-space-size=32384 --gulpfile ./coder.js", { cwd: vscodeSourcePath }); - }); - } + await this.task("writing final vs code product.json", () => { + return fs.writeFile(path.join(vscodeBuildPath, "product.json"), JSON.stringify(productJson, null, 2)) + }) + } - const finalServerPath = path.join(finalBuildPath, "out/vs/server"); - await this.task("Copying into final build directory", async () => { - await fs.remove(finalBuildPath); - await fs.mkdirp(finalBuildPath); - await Promise.all([ - fs.copy(path.join(vscodeSourcePath, "remote/node_modules"), path.join(finalBuildPath, "node_modules")), - fs.copy(path.join(vscodeSourcePath, ".build/extensions"), path.join(finalBuildPath, "extensions")), - fs.copy(path.join(vscodeSourcePath, `out-vscode${process.env.MINIFY ? "-min" : ""}`), path.join(finalBuildPath, "out")).then(() => { - return Promise.all([ - fs.remove(path.join(finalServerPath, "node_modules")).then(() => { - return fs.copy(path.join(serverPath, "node_modules"), path.join(finalServerPath, "node_modules")); - }), - fs.copy(path.join(finalServerPath, "src/browser/workbench-build.html"), path.join(finalServerPath, "src/browser/workbench.html")), - ]); - }), - ]); - }); + private async copyDependencies(name: string, sourcePath: string, buildPath: string): Promise { + await this.task(`copying ${name} dependencies`, async () => { + return Promise.all( + ["node_modules", "package.json", "yarn.lock"].map((fileName) => { + return fs.copy(path.join(sourcePath, fileName), path.join(buildPath, fileName)) + }) + ) + }) - if (process.env.MINIFY) { - await this.task("Restricting to production dependencies", async () => { - await Promise.all(["package.json", "yarn.lock"].map((fileName) => { - Promise.all([ - fs.copy(path.join(this.rootPath, fileName), path.join(finalServerPath, fileName)), - fs.copy(path.join(path.join(vscodeSourcePath, "remote"), fileName), path.join(finalBuildPath, fileName)), - ]); - })); + if (process.env.MINIFY) { + await this.task(`restricting ${name} to production dependencies`, async () => { + return util.promisify(cp.exec)("yarn --production --ignore-scripts", { cwd: buildPath }) + }) + } + } - await Promise.all([finalServerPath, finalBuildPath].map((cwd) => { - return util.promisify(cp.exec)("yarn --production", { cwd }); - })); + /** + * Bundles the built code into a binary. + */ + private async binary(binaryName: string): Promise { + const bin = new Binary({ + mainFile: path.join(this.buildPath, "out/node/entry.js"), + target: await this.target(), + }) - await Promise.all(["package.json", "yarn.lock"].map((fileName) => { - return Promise.all([ - fs.remove(path.join(finalServerPath, fileName)), - fs.remove(path.join(finalBuildPath, fileName)), - ]); - })); - }); - } + bin.writeFiles(path.join(this.buildPath, "**")) - await this.task("Writing final package.json and product.json", () => { - return Promise.all([ - fs.writeFile(path.join(finalBuildPath, "package.json"), JSON.stringify(packageJson, null, 2)), - fs.writeFile(path.join(finalBuildPath, "product.json"), JSON.stringify(productJson, null, 2)), - ]); - }); + await fs.mkdirp(this.binariesPath) - // Prevent needless cache changes. - await this.task("Cleaning for smaller cache", () => { - return Promise.all([ - fs.remove(serverPath), - fs.remove(path.join(vscodeSourcePath, "out-vscode")), - fs.remove(path.join(vscodeSourcePath, "out-vscode-min")), - fs.remove(path.join(vscodeSourcePath, "out-build")), - util.promisify(cp.exec)("git reset --hard", { cwd: vscodeSourcePath }).then(() => { - return util.promisify(cp.exec)("git clean -fd", { cwd: vscodeSourcePath }); - }), - ]); - }); + const binaryPath = path.join(this.binariesPath, binaryName) + await fs.writeFile(binaryPath, await bin.build()) + await fs.chmod(binaryPath, "755") - // Prepend code to the target which enables finding files within the binary. - const prependLoader = async (relativeFilePath: string): Promise => { - const filePath = path.join(finalBuildPath, relativeFilePath); - const shim = ` - if (!global.NBIN_LOADED) { - try { - const nbin = require("nbin"); - nbin.shimNativeFs("${finalBuildPath}"); - global.NBIN_LOADED = true; - const path = require("path"); - const rg = require("vscode-ripgrep"); - rg.binaryRgPath = rg.rgPath; - rg.rgPath = path.join(require("os").tmpdir(), "code-server", path.basename(rg.binaryRgPath)); - } catch (error) { /* Not in the binary. */ } - } - `; - await fs.writeFile(filePath, shim + (await fs.readFile(filePath, "utf8"))); - }; + this.log(`binary: ${binaryPath}`) + } - await this.task("Prepending nbin loader", () => { - return Promise.all([ - prependLoader("out/vs/server/main.js"), - prependLoader("out/bootstrap-fork.js"), - prependLoader("extensions/node_modules/typescript/lib/tsserver.js"), - ]); - }); + /** + * Package the binary into a release archive. + */ + private async package(binaryName: string): Promise { + const releasePath = path.join(this.rootPath, "release") + const archivePath = path.join(releasePath, binaryName) - this.log(`Final build: ${finalBuildPath}`); - } + await fs.remove(archivePath) + await fs.mkdirp(archivePath) - /** - * Bundles the built code into a binary. - */ - private async binary(targetPath: string, binariesPath: string, binaryName: string): Promise { - const bin = new Binary({ - mainFile: path.join(targetPath, "out/vs/server/main.js"), - target: await this.target(), - }); + await fs.copyFile(path.join(this.binariesPath, binaryName), path.join(archivePath, "code-server")) + await fs.copyFile(path.join(this.rootPath, "README.md"), path.join(archivePath, "README.md")) + await fs.copyFile(path.join(this.vscodeSourcePath, "LICENSE.txt"), path.join(archivePath, "LICENSE.txt")) + await fs.copyFile( + path.join(this.vscodeSourcePath, "ThirdPartyNotices.txt"), + path.join(archivePath, "ThirdPartyNotices.txt") + ) - bin.writeFiles(path.join(targetPath, "**")); + if ((await this.target()) === "darwin") { + await util.promisify(cp.exec)(`zip -r "${binaryName}.zip" "${binaryName}"`, { cwd: releasePath }) + this.log(`archive: ${archivePath}.zip`) + } else { + await util.promisify(cp.exec)(`tar -czf "${binaryName}.tar.gz" "${binaryName}"`, { cwd: releasePath }) + this.log(`archive: ${archivePath}.tar.gz`) + } + } - await fs.mkdirp(binariesPath); + private async watch(): Promise { + let server: cp.ChildProcess | undefined + const restartServer = (): void => { + if (server) { + server.kill() + } + const s = cp.fork(path.join(this.rootPath, "out/node/entry.js")) + console.log(`[server] spawned process ${s.pid}`) + s.on("exit", () => console.log(`[server] process ${s.pid} exited`)) + server = s + } - const binaryPath = path.join(binariesPath, binaryName); - await fs.writeFile(binaryPath, await bin.build()); - await fs.chmod(binaryPath, "755"); + const vscode = cp.spawn("yarn", ["watch"], { cwd: this.vscodeSourcePath }) + const tsc = cp.spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath }) + const bundler = this.createBundler() - this.log(`Binary: ${binaryPath}`); - } + const cleanup = (code?: number | null): void => { + this.log("killing vs code watcher") + vscode.removeAllListeners() + vscode.kill() - /** - * Package the binary into a release archive. - */ - private async package(vscodeSourcePath: string, binariesPath: string, binaryName: string): Promise { - const releasePath = path.join(this.outPath, "release"); - const archivePath = path.join(releasePath, binaryName); + this.log("killing tsc") + tsc.removeAllListeners() + tsc.kill() - await fs.remove(archivePath); - await fs.mkdirp(archivePath); + if (server) { + this.log("killing server") + server.removeAllListeners() + server.kill() + } - await fs.copyFile(path.join(binariesPath, binaryName), path.join(archivePath, "code-server")); - await fs.copyFile(path.join(this.rootPath, "README.md"), path.join(archivePath, "README.md")); - await fs.copyFile(path.join(vscodeSourcePath, "LICENSE.txt"), path.join(archivePath, "LICENSE.txt")); - await fs.copyFile(path.join(vscodeSourcePath, "ThirdPartyNotices.txt"), path.join(archivePath, "ThirdPartyNotices.txt")); + this.log("killing bundler") + process.exit(code || 0) + } - if ((await this.target()) === "darwin") { - await util.promisify(cp.exec)(`zip -r "${binaryName}.zip" "${binaryName}"`, { cwd: releasePath }); - this.log(`Archive: ${archivePath}.zip`); - } else { - await util.promisify(cp.exec)(`tar -czf "${binaryName}.tar.gz" "${binaryName}"`, { cwd: releasePath }); - this.log(`Archive: ${archivePath}.tar.gz`); - } - } + process.on("SIGINT", () => cleanup()) + process.on("SIGTERM", () => cleanup()) + + vscode.on("exit", (code) => { + this.log("vs code watcher terminated unexpectedly") + cleanup(code) + }) + tsc.on("exit", (code) => { + this.log("tsc terminated unexpectedly") + cleanup(code) + }) + const bundle = bundler.bundle().catch(() => { + this.log("parcel watcher terminated unexpectedly") + cleanup(1) + }) + bundler.on("buildEnd", () => { + console.log("[parcel] bundled") + }) + + vscode.stderr.on("data", (d) => process.stderr.write(d)) + tsc.stderr.on("data", (d) => process.stderr.write(d)) + + // From https://github.com/chalk/ansi-regex + const pattern = [ + "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", + "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", + ].join("|") + const re = new RegExp(pattern, "g") + + /** + * Split stdout on newlines and strip ANSI codes. + */ + const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): void => { + let buffer = "" + if (!proc.stdout) { + throw new Error("no stdout") + } + proc.stdout.setEncoding("utf8") + proc.stdout.on("data", (d) => { + const data = buffer + d + const split = data.split("\n") + const last = split.length - 1 + + for (let i = 0; i < last; ++i) { + callback(split[i].replace(re, ""), split[i]) + } + + // The last item will either be an empty string (the data ended with a + // newline) or a partial line (did not end with a newline) and we must + // wait to parse it until we get a full line. + buffer = split[last] + }) + } + + let startingVscode = false + onLine(vscode, (line, original) => { + console.log("[vscode]", original) + // Wait for watch-client since "Finished compilation" will appear multiple + // times before the client starts building. + if (!startingVscode && line.includes("Starting watch-client")) { + startingVscode = true + } else if (startingVscode && line.includes("Finished compilation") && process.env.AUTO_PATCH) { + cp.exec("yarn patch:generate", { cwd: this.rootPath }, (error, _, stderr) => { + if (error || stderr) { + console.error(error ? error.message : stderr) + } + }) + } + }) + + onLine(tsc, (line, original) => { + // tsc outputs blank lines; skip them. + if (line !== "") { + console.log("[tsc]", original) + } + if (line.includes("Watching for file changes")) { + bundle.then(restartServer) + } + }) + } + + private createBundler(out = "dist", commit?: string): Bundler { + return new Bundler(path.join(this.rootPath, "src/browser/index.tsx"), { + cache: true, + cacheDir: path.join(this.rootPath, ".cache"), + detailedReport: true, + minify: !!process.env.MINIFY, + hmr: false, + logLevel: 1, + outDir: path.join(this.rootPath, out), + publicUrl: `/static-${commit}/dist`, + target: "browser", + }) + } } -const builder = new Builder(); -builder.run(process.argv[2] as Task, process.argv.slice(3)); +const builder = new Builder() +builder.run(process.argv[2] as Task) diff --git a/scripts/cacher.sh b/scripts/cacher.sh index 0ee1bc58..df076f1a 100755 --- a/scripts/cacher.sh +++ b/scripts/cacher.sh @@ -8,46 +8,48 @@ set -eu # Try restoring from each argument in turn until we get something. restore() { - for branch in "$@" ; do - if [ -n "$branch" ] ; then - cache_path="https://codesrv-ci.cdr.sh/cache/$branch/$tar.tar.gz" - if wget "$cache_path" ; then - tar xzvf "$tar.tar.gz" - break - fi - fi - done + for branch in "$@" ; do + if [ -n "$branch" ] ; then + cache_path="https://codesrv-ci.cdr.sh/cache/$branch/$tar.tar.gz" + if wget "$cache_path" ; then + tar xzvf "$tar.tar.gz" + break + fi + fi + done } # We need to cache the built-in extensions and Node modules. Everything inside # the cache-upload directory will be uploaded as-is to the code-server bucket. package() { - mkdir -p "cache-upload/cache/$1" - tar czfv "cache-upload/cache/$1/$tar.tar.gz" node_modules source yarn-cache + mkdir -p "cache-upload/cache/$1" + tar czfv "cache-upload/cache/$1/$tar.tar.gz" node_modules yarn-cache \ + lib/vscode/.build \ + lib/vscode/node_modules } main() { - cd "$(dirname "$0")/.." + cd "$(dirname "$0")/.." - # Get the branch for this build. - branch=${DRONE_BRANCH:-${DRONE_SOURCE_BRANCH:-${DRONE_TAG:-}}} + # Get the branch for this build. + branch=${DRONE_BRANCH:-${DRONE_SOURCE_BRANCH:-${DRONE_TAG:-}}} - # The cache will be named based on the arch, platform, and libc. - arch=$DRONE_STAGE_ARCH - platform=${PLATFORM:-linux} - case $DRONE_STAGE_NAME in - *alpine*) libc=musl ;; - * ) libc=glibc ;; - esac + # The cache will be named based on the arch, platform, and libc. + arch=$DRONE_STAGE_ARCH + platform=${PLATFORM:-linux} + case $DRONE_STAGE_NAME in + *alpine*) libc=musl ;; + * ) libc=glibc ;; + esac - tar="$platform-$arch-$libc" + tar="$platform-$arch-$libc" - # The action is determined by the name of the step. - case $DRONE_STEP_NAME in - *restore*) restore "$branch" "$DRONE_REPO_BRANCH" ;; - *rebuild*|*package*) package "$branch" ;; - *) exit 1 ;; - esac + # The action is determined by the name of the step. + case $DRONE_STEP_NAME in + *restore*) restore "$branch" "$DRONE_REPO_BRANCH" ;; + *rebuild*|*package*) package "$branch" ;; + *) exit 1 ;; + esac } main "$@" diff --git a/scripts/ci.bash b/scripts/ci.bash index e33a22c0..6ccada80 100755 --- a/scripts/ci.bash +++ b/scripts/ci.bash @@ -3,71 +3,62 @@ set -euo pipefail -function target() { - local os=$(uname | tr '[:upper:]' '[:lower:]') - if [[ "$os" == "linux" ]]; then - # Using the same strategy to detect Alpine as build.ts. - local ldd_output=$(ldd --version 2>&1 || true) - if echo "$ldd_output" | grep -iq musl; then - os="alpine" - fi - fi - - echo "${os}-$(uname -m)" -} - function main() { - cd "$(dirname "${0}")/.." + cd "$(dirname "${0}")/.." - # Get the version information. If a specific version wasn't set, generate it - # from the tag and VS Code version. - local vscode_version=${VSCODE_VERSION:-1.41.1} - local code_server_version=${VERSION:-${TRAVIS_TAG:-${DRONE_TAG:-daily}}} + local code_server_version=${VERSION:-${TRAVIS_TAG:-${DRONE_TAG:-}}} + if [[ -z $code_server_version ]] ; then + code_server_version=$(grep version ./package.json | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[:space:]') + fi + export VERSION=$code_server_version - # Remove everything that isn't the current VS Code source for caching - # (otherwise the cache will contain old versions). - if [[ -d "source/vscode-$vscode_version-source" ]] ; then - mv "source/vscode-$vscode_version-source" "vscode-$vscode_version-source" - fi - rm -rf source/vscode-*-source - if [[ -d "vscode-$vscode_version-source" ]] ; then - mv "vscode-$vscode_version-source" "source/vscode-$vscode_version-source" - fi + YARN_CACHE_FOLDER="$(pwd)/yarn-cache" + export YARN_CACHE_FOLDER - YARN_CACHE_FOLDER="$(pwd)/yarn-cache" - export YARN_CACHE_FOLDER + # Always minify and package on tags since that's when releases are pushed. + if [[ -n ${DRONE_TAG:-} || -n ${TRAVIS_TAG:-} ]] ; then + export MINIFY="true" + export PACKAGE="true" + fi - # Always minify and package on tags since that's when releases are pushed. - if [[ -n ${DRONE_TAG:-} || -n ${TRAVIS_TAG:-} ]] ; then - export MINIFY="true" - export PACKAGE="true" - fi + if [[ -z ${SKIP_YARN:-} ]] ; then + yarn + fi - function run-yarn() { - yarn "$1" "$vscode_version" "$code_server_version" - } + yarn build + yarn binary + if [[ -n ${PACKAGE:-} ]] ; then + yarn package + fi - run-yarn build - run-yarn binary - if [[ -n ${PACKAGE:-} ]] ; then - run-yarn package - fi + cd binaries - # In this case provide a plainly named "code-server" binary. - if [[ -n ${BINARY:-} ]] ; then - mv binaries/code-server*-vsc* binaries/code-server - fi + if [[ -n ${STRIP_BIN_TARGET:-} ]] ; then + # In this case provide plainly named binaries. + for binary in code-server* ; do + echo "Moving $binary to code-server" + mv "$binary" code-server + done + elif [[ -n ${DRONE_TAG:-} || -n ${TRAVIS_TAG:-} ]] ; then + # Prepare directory for uploading binaries on release. + for binary in code-server* ; do + mkdir -p "../binary-upload" - # Prepare GCS bucket directory on release. - if [[ -n ${DRONE_TAG:-} || -n ${TRAVIS_TAG:-} ]] ; then - local gcp_dir="gcs_bucket/releases/$code_server_version/$(target)" + local prefix="code-server-$code_server_version-" + local target="${binary#$prefix}" + if [[ $target == "linux-x86_64" ]] ; then + echo "Copying $binary to ../binary-upload/latest-linux" + cp "$binary" "../binary-upload/latest-linux" + fi - mkdir -p "$gcp_dir" - mv binaries/code-server*-vsc* "$gcp_dir" - if [[ "$(target)" == "linux-x86_64" ]] ; then - mv binaries/code-server*-vsc* "gcs_bucket/latest-linux" - fi - fi + local gcp_dir + gcp_dir="../binary-upload/releases/$code_server_version/$target" + mkdir -p "$gcp_dir" + + echo "Copying $binary to $gcp_dir/code-server" + cp "$binary" "$gcp_dir/code-server" + done + fi } main "$@" diff --git a/scripts/ci.dockerfile b/scripts/ci.dockerfile index dbb146c8..d32b51ea 100644 --- a/scripts/ci.dockerfile +++ b/scripts/ci.dockerfile @@ -2,24 +2,24 @@ FROM ubuntu:18.04 RUN apt-get update && apt-get install -y \ - openssl \ - net-tools \ - git \ - locales \ - sudo \ - dumb-init \ - vim \ - curl \ - wget + openssl \ + net-tools \ + git \ + locales \ + sudo \ + dumb-init \ + vim \ + curl \ + wget RUN locale-gen en_US.UTF-8 # We cannot use update-locale because docker will not use the env variables # configured in /etc/default/locale so we need to set it manually. ENV LC_ALL=en_US.UTF-8 \ - SHELL=/bin/bash + SHELL=/bin/bash RUN adduser --gecos '' --disabled-password coder && \ - echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd + echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd USER coder # Create first so these directories will be owned by coder instead of root diff --git a/scripts/lint.sh b/scripts/lint.sh new file mode 100755 index 00000000..de9b59ea --- /dev/null +++ b/scripts/lint.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +# lint.sh -- Lint CSS and JS files. + +set -eu + +main() { + yarn lint:css "$@" + yarn lint:js "$@" +} + +main "$@" diff --git a/scripts/optimize.js b/scripts/optimize.js deleted file mode 100644 index 5e4ab420..00000000 --- a/scripts/optimize.js +++ /dev/null @@ -1,71 +0,0 @@ -// This must be ran from VS Code's root. -const gulp = require("gulp"); -const path = require("path"); -const _ = require("underscore"); -const buildfile = require("./src/buildfile"); -const common = require("./build/lib/optimize"); -const util = require("./build/lib/util"); -const deps = require("./build/dependencies"); - -const vscodeEntryPoints = _.flatten([ - buildfile.entrypoint("vs/workbench/workbench.web.api"), - buildfile.entrypoint("vs/server/src/node/cli"), - buildfile.base, - buildfile.workbenchWeb, - buildfile.workerExtensionHost, - buildfile.keyboardMaps, - buildfile.entrypoint('vs/platform/files/node/watcher/unix/watcherApp', ["vs/css", "vs/nls"]), - buildfile.entrypoint('vs/platform/files/node/watcher/nsfw/watcherApp', ["vs/css", "vs/nls"]), - buildfile.entrypoint('vs/workbench/services/extensions/node/extensionHostProcess', ["vs/css", "vs/nls"]), -]); - -const vscodeResources = [ - "out-build/vs/server/main.js", - "out-build/vs/server/src/node/uriTransformer.js", - "!out-build/vs/server/doc/**", - "out-build/vs/server/src/media/*", - "out-build/vs/workbench/services/extensions/worker/extensionHostWorkerMain.js", - "out-build/bootstrap.js", - "out-build/bootstrap-fork.js", - "out-build/bootstrap-amd.js", - "out-build/paths.js", - 'out-build/vs/**/*.{svg,png,html}', - "!out-build/vs/code/browser/workbench/*.html", - '!out-build/vs/code/electron-browser/**', - "out-build/vs/base/common/performance.js", - "out-build/vs/base/node/languagePacks.js", - "out-build/vs/base/browser/ui/octiconLabel/octicons/**", - "out-build/vs/base/browser/ui/codiconLabel/codicon/**", - "out-build/vs/workbench/browser/media/*-theme.css", - "out-build/vs/workbench/contrib/debug/**/*.json", - "out-build/vs/workbench/contrib/externalTerminal/**/*.scpt", - "out-build/vs/workbench/contrib/webview/browser/pre/*.js", - "out-build/vs/**/markdown.css", - "out-build/vs/workbench/contrib/tasks/**/*.json", - "out-build/vs/platform/files/**/*.md", - "!**/test/**" -]; - -const rootPath = __dirname; -const nodeModules = ["electron", "original-fs"] - .concat(_.uniq(deps.getProductionDependencies(rootPath).map((d) => d.name))) - .concat(_.uniq(deps.getProductionDependencies(path.join(rootPath, "src/vs/server")).map((d) => d.name))) - .concat(Object.keys(process.binding("natives")).filter((n) => !/^_|\//.test(n))); - -gulp.task("optimize", gulp.series( - util.rimraf("out-vscode"), - common.optimizeTask({ - src: "out-build", - entryPoints: vscodeEntryPoints, - resources: vscodeResources, - loaderConfig: common.loaderConfig(nodeModules), - out: "out-vscode", - inlineAmdImages: true, - bundleInfo: undefined - }), -)); - -gulp.task("minify", gulp.series( - util.rimraf("out-vscode-min"), - common.minifyTask("out-vscode") -)); diff --git a/scripts/package.json b/scripts/package.json deleted file mode 100644 index 5085fa85..00000000 --- a/scripts/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "code-server", - "main": "out/vs/server/main", - "desktopName": "code-server-url-handler.desktop" -} diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh new file mode 100755 index 00000000..353f02e2 --- /dev/null +++ b/scripts/postinstall.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +# postinstall.sh - Does nothing at the moment. + +set -eu + +main() { + cd "$(dirname "${0}")/.." +} + +main "$@" diff --git a/scripts/preinstall.sh b/scripts/preinstall.sh new file mode 100755 index 00000000..127311fb --- /dev/null +++ b/scripts/preinstall.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env sh +# preinstall.sh -- Prepare VS Code. + +set -eu + +main() { + cd "$(dirname "${0}")/.." + +# Ensure submodules are cloned and up to date. + git submodule update --init + + # Try patching but don't worry too much if it fails. It's possible VS Code has + # already been patched. + yarn patch:apply || echo "Unable to patch; assuming already patched" + + # Install VS Code dependencies. + cd ./lib/vscode + yarn +} + +main "$@" diff --git a/scripts/product.json b/scripts/product.json deleted file mode 100644 index dabf03e8..00000000 --- a/scripts/product.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "nameShort": "code-server", - "nameLong": "code-server", - "applicationName": "code-server", - "dataFolderName": ".code-server", - "win32MutexName": "codeserver", - "win32DirName": "Code Server", - "win32NameVersion": "Code Server", - "win32RegValueName": "CodeServer", - "win32AppId": "", - "win32x64AppId": "", - "win32UserAppId": "", - "win32x64UserAppId": "", - "win32AppUserModelId": "CodeServer", - "win32ShellNameShort": "C&ode Server", - "darwinBundleIdentifier": "com.code.server", - "linuxIconName": "com.code.server", - "urlProtocol": "code-server", - "updateUrl": "https://api.github.com/repos/cdr/code-server/releases", - "quality": "latest" -} diff --git a/scripts/test.sh b/scripts/test.sh deleted file mode 100755 index b8496130..00000000 --- a/scripts/test.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env sh -# test.sh -- Simple test for CI. -# We'll have more involved tests eventually. This just ensures the binary has -# been built and runs. - -set -eu - -main() { - cd "$(dirname "$0")/.." - - version=$(./binaries/code-server* --version | head -1) - echo "Got '$version' for the version" - case $version in - *-vsc1.41.1) exit 0 ;; - *) exit 1 ;; - esac -} - -main "$@" diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 149a7f36..93e81846 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -1,17 +1,21 @@ { - "compilerOptions": { - "module": "commonjs", - "moduleResolution": "node", - "noImplicitAny": true, - "experimentalDecorators": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noImplicitThis": true, - "alwaysStrict": true, - "strictBindCallApply": true, - "strictNullChecks": true, - "forceConsistentCasingInFileNames": true, - "baseUrl": ".", - "target": "esnext" - } + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./out", + "declaration": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "sourceMap": true + }, + "include": [ + "./**/*.ts" + ] } diff --git a/scripts/vscode.patch b/scripts/vscode.patch index cafd87c9..a139bd68 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -1,3 +1,137 @@ +diff --git a/.gitignore b/.gitignore +index 160c42ed74..0d544c495c 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -23,7 +23,6 @@ out-vscode-reh-web-min/ + out-vscode-reh-web-pkg/ + out-vscode-web/ + out-vscode-web-min/ +-src/vs/server + resources/server + build/node_modules + coverage/ +diff --git a/coder.js b/coder.js +new file mode 100644 +index 0000000000..fc18355f89 +--- /dev/null ++++ b/coder.js +@@ -0,0 +1,70 @@ ++// This must be ran from VS Code's root. ++const gulp = require("gulp"); ++const path = require("path"); ++const _ = require("underscore"); ++const buildfile = require("./src/buildfile"); ++const common = require("./build/lib/optimize"); ++const util = require("./build/lib/util"); ++const deps = require("./build/dependencies"); ++ ++const vscodeEntryPoints = _.flatten([ ++ buildfile.entrypoint("vs/workbench/workbench.web.api"), ++ buildfile.entrypoint("vs/server/entry"), ++ buildfile.base, ++ buildfile.workbenchWeb, ++ buildfile.workerExtensionHost, ++ buildfile.keyboardMaps, ++ buildfile.entrypoint('vs/platform/files/node/watcher/unix/watcherApp', ["vs/css", "vs/nls"]), ++ buildfile.entrypoint('vs/platform/files/node/watcher/nsfw/watcherApp', ["vs/css", "vs/nls"]), ++ buildfile.entrypoint('vs/workbench/services/extensions/node/extensionHostProcess', ["vs/css", "vs/nls"]), ++]); ++ ++const vscodeResources = [ ++ "out-build/vs/server/fork.js", ++ "out-build/vs/server/node/uriTransformer.js", ++ "!out-build/vs/server/doc/**", ++ "out-build/vs/workbench/services/extensions/worker/extensionHostWorkerMain.js", ++ "out-build/bootstrap.js", ++ "out-build/bootstrap-fork.js", ++ "out-build/bootstrap-amd.js", ++ "out-build/paths.js", ++ 'out-build/vs/**/*.{svg,png,html}', ++ "!out-build/vs/code/browser/workbench/*.html", ++ '!out-build/vs/code/electron-browser/**', ++ "out-build/vs/base/common/performance.js", ++ "out-build/vs/base/node/languagePacks.js", ++ "out-build/vs/base/browser/ui/octiconLabel/octicons/**", ++ "out-build/vs/base/browser/ui/codiconLabel/codicon/**", ++ "out-build/vs/workbench/browser/media/*-theme.css", ++ "out-build/vs/workbench/contrib/debug/**/*.json", ++ "out-build/vs/workbench/contrib/externalTerminal/**/*.scpt", ++ "out-build/vs/workbench/contrib/webview/browser/pre/*.js", ++ "out-build/vs/**/markdown.css", ++ "out-build/vs/workbench/contrib/tasks/**/*.json", ++ "out-build/vs/platform/files/**/*.md", ++ "!**/test/**" ++]; ++ ++const rootPath = __dirname; ++const nodeModules = ["electron", "original-fs"] ++ .concat(_.uniq(deps.getProductionDependencies(rootPath).map((d) => d.name))) ++ .concat(_.uniq(deps.getProductionDependencies(path.join(rootPath, "src/vs/server")).map((d) => d.name))) ++ .concat(Object.keys(process.binding("natives")).filter((n) => !/^_|\//.test(n))); ++ ++gulp.task("optimize", gulp.series( ++ util.rimraf("out-vscode"), ++ common.optimizeTask({ ++ src: "out-build", ++ entryPoints: vscodeEntryPoints, ++ resources: vscodeResources, ++ loaderConfig: common.loaderConfig(nodeModules), ++ out: "out-vscode", ++ inlineAmdImages: true, ++ bundleInfo: undefined ++ }), ++)); ++ ++gulp.task("minify", gulp.series( ++ util.rimraf("out-vscode-min"), ++ common.minifyTask("out-vscode") ++)); +diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json +index 8ac6b2806c..60b1255e2c 100644 +--- a/extensions/vscode-api-tests/package.json ++++ b/extensions/vscode-api-tests/package.json +@@ -121,7 +121,7 @@ + "@types/node": "^12.11.7", + "mocha-junit-reporter": "^1.17.0", + "mocha-multi-reporters": "^1.1.7", +- "typescript": "^1.6.2", ++ "typescript": "3.7.2", + "vscode": "1.1.5" + } + } +diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock +index 2d8b725ff2..a8d93a17ca 100644 +--- a/extensions/vscode-api-tests/yarn.lock ++++ b/extensions/vscode-api-tests/yarn.lock +@@ -1855,10 +1855,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +-typescript@^1.6.2: +- version "1.8.10" +- resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e" +- integrity sha1-tHXW4N/wv1DyluXKbvn7tccyDx4= ++typescript@3.7.2: ++ version "3.7.2" ++ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" ++ integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + + unique-stream@^2.0.2: + version "2.2.1" +diff --git a/package.json b/package.json +index ade5fcdaf0..73d661eb57 100644 +--- a/package.json ++++ b/package.json +@@ -30,6 +30,9 @@ + "web": "node scripts/code-web.js" + }, + "dependencies": { ++ "@coder/logger": "^1.1.11", ++ "@coder/node-browser": "^1.0.8", ++ "@coder/requirefs": "^1.0.6", + "applicationinsights": "1.0.8", + "chokidar": "3.2.3", + "graceful-fs": "4.1.11", diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index 231180d513..5b98e191c1 100644 --- a/src/vs/base/common/network.ts @@ -24,14 +158,14 @@ index 231180d513..5b98e191c1 100644 }); } diff --git a/src/vs/base/common/platform.ts b/src/vs/base/common/platform.ts -index 5a631e0b39..8a2b1518d6 100644 +index 5a631e0b39..4114bd9287 100644 --- a/src/vs/base/common/platform.ts +++ b/src/vs/base/common/platform.ts @@ -59,6 +59,17 @@ if (typeof navigator === 'object' && !isElectronRenderer) { _isWeb = true; _locale = navigator.language; _language = _locale; -+ // NOTE@coder: make languages work. ++ // NOTE@coder: Make languages work. + const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration'); + const rawNlsConfig = el && el.getAttribute('data-settings'); + if (rawNlsConfig) { @@ -46,17 +180,16 @@ index 5a631e0b39..8a2b1518d6 100644 _isWindows = (process.platform === 'win32'); _isMacintosh = (process.platform === 'darwin'); diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts -index c52f7b3774..5a7e7f579e 100644 +index c52f7b3774..4c9a0c4bab 100644 --- a/src/vs/base/common/processes.ts +++ b/src/vs/base/common/processes.ts -@@ -110,7 +110,10 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve +@@ -110,7 +110,9 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve /^ELECTRON_.+$/, /^GOOGLE_API_KEY$/, /^VSCODE_.+$/, - /^SNAP(|_.*)$/ + /^SNAP(|_.*)$/, -+ // NOTE@coder: add our own environment variables. -+ /^NBIN_BYPASS$/, ++ // NOTE@coder: Add our variables. + /^LAUNCH_VSCODE$/ ]; const envKeys = Object.keys(env); @@ -209,10 +342,10 @@ index 5bfc2bb66c..49a6ce8540 100644 const toRemove: ILocalExtension[] = []; diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts -index 804d113856..4b651e5c77 100644 +index 804d113856..30a349f69f 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts -@@ -22,11 +22,19 @@ if (isWeb) { +@@ -22,11 +22,18 @@ if (isWeb) { if (Object.keys(product).length === 0) { assign(product, { version: '1.41.0-dev', @@ -222,8 +355,7 @@ index 804d113856..4b651e5c77 100644 urlProtocol: 'code-oss' }); } -+ -+ // NOTE@coder: enable injecting settings from the server. ++ // NOTE@coder: Add the ability to inject settings from the server. + const el = document.getElementById('vscode-remote-product-configuration'); + const rawProductConfiguration = el && el.getAttribute('data-settings'); + if (rawProductConfiguration) { @@ -232,7 +364,7 @@ index 804d113856..4b651e5c77 100644 } // Node: AMD loader -@@ -36,7 +44,7 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === ' +@@ -36,7 +43,7 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === ' const rootPath = path.dirname(getPathFromAmdModule(require, '')); product = assign({}, require.__$__nodeRequire(path.join(rootPath, 'product.json')) as IProductConfiguration); @@ -241,7 +373,7 @@ index 804d113856..4b651e5c77 100644 // Running out of sources if (env['VSCODE_DEV']) { -@@ -48,7 +56,8 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === ' +@@ -48,7 +55,8 @@ else if (typeof require !== 'undefined' && typeof require.__$__nodeRequire === ' } assign(product, { @@ -284,117 +416,2311 @@ index d0f6e6b18a..1966fd297d 100644 - - - -diff --git a/src/vs/platform/request/common/request.ts b/src/vs/platform/request/common/request.ts -index 81ec255e65..c94829fc6a 100644 ---- a/src/vs/platform/request/common/request.ts -+++ b/src/vs/platform/request/common/request.ts -@@ -16,7 +16,7 @@ export const IRequestService = createDecorator('requestService' - export interface IRequestService { - _serviceBrand: undefined; - -- request(options: IRequestOptions, token: CancellationToken): Promise; -+ request(options: IRequestOptions, token: CancellationToken, gzip?: boolean): Promise; - - resolveProxy(url: string): Promise; - } -diff --git a/src/vs/platform/request/node/requestService.ts b/src/vs/platform/request/node/requestService.ts -index ad44dcbc33..7a7b5261ff 100644 ---- a/src/vs/platform/request/node/requestService.ts -+++ b/src/vs/platform/request/node/requestService.ts -@@ -57,7 +57,7 @@ export class RequestService extends Disposable implements IRequestService { - this.authorization = config.http && config.http.proxyAuthorization; - } - -- async request(options: NodeRequestOptions, token: CancellationToken): Promise { -+ async request(options: NodeRequestOptions, token: CancellationToken, gzip?: boolean): Promise { - this.logService.trace('RequestService#request', options.url); - - const { proxyUrl, strictSSL } = this; -@@ -70,7 +70,7 @@ export class RequestService extends Disposable implements IRequestService { - options.headers = assign(options.headers || {}, { 'Proxy-Authorization': this.authorization }); - } - -- return this._request(options, token); -+ return this._request(options, token, gzip); - } - - private async getNodeRequest(options: IRequestOptions): Promise { -@@ -79,7 +79,7 @@ export class RequestService extends Disposable implements IRequestService { - return module.request; - } - -- private _request(options: NodeRequestOptions, token: CancellationToken): Promise { -+ private _request(options: NodeRequestOptions, token: CancellationToken, gzip?: boolean): Promise { - - return new Promise(async (c, e) => { - let req: http.ClientRequest; -@@ -114,7 +114,7 @@ export class RequestService extends Disposable implements IRequestService { - } else { - let stream: streams.ReadableStream = res; - -- if (res.headers['content-encoding'] === 'gzip') { -+ if (gzip || res.headers['content-encoding'] === 'gzip') { - stream = res.pipe(createGunzip()); - } - -diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts -index 8a1c95d37b..8225a85d47 100644 ---- a/src/vs/platform/update/electron-main/abstractUpdateService.ts -+++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts -@@ -6,7 +6,6 @@ - import { Event, Emitter } from 'vs/base/common/event'; - import { timeout } from 'vs/base/common/async'; - import { IConfigurationService, getMigratedSettingValue } from 'vs/platform/configuration/common/configuration'; --import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; - import product from 'vs/platform/product/common/product'; - import { IUpdateService, State, StateType, AvailableForDownload, UpdateType } from 'vs/platform/update/common/update'; - import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -@@ -44,7 +43,7 @@ export abstract class AbstractUpdateService implements IUpdateService { - } - - constructor( -- @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, -+ _: any, // NOTE@coder: This depends on Electron so we skip it. - @IConfigurationService protected configurationService: IConfigurationService, - @IEnvironmentService private readonly environmentService: IEnvironmentService, - @IRequestService protected requestService: IRequestService, -@@ -152,15 +151,8 @@ export abstract class AbstractUpdateService implements IUpdateService { - - this.logService.trace('update#quitAndInstall(): before lifecycle quit()'); - -- this.lifecycleMainService.quit(true /* from update */).then(vetod => { -- this.logService.trace(`update#quitAndInstall(): after lifecycle quit() with veto: ${vetod}`); -- if (vetod) { -- return; -- } -- - this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); - this.doQuitAndInstall(); -- }); - - return Promise.resolve(undefined); - } +diff --git a/src/vs/server/browser/client.ts b/src/vs/server/browser/client.ts +new file mode 100644 +index 0000000000..8e7c5af184 +--- /dev/null ++++ b/src/vs/server/browser/client.ts +@@ -0,0 +1,162 @@ ++import { Emitter } from 'vs/base/common/event'; ++import { URI } from 'vs/base/common/uri'; ++import { localize } from 'vs/nls'; ++import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; ++import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; ++import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; ++import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; ++import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; ++import { Registry } from 'vs/platform/registry/common/platform'; ++import { PersistentConnectionEventType } from 'vs/platform/remote/common/remoteAgentConnection'; ++import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; ++import { INodeProxyService, NodeProxyChannelClient } from 'vs/server/common/nodeProxy'; ++import { TelemetryChannelClient } from 'vs/server/common/telemetry'; ++import 'vs/workbench/contrib/localizations/browser/localizations.contribution'; ++import { LocalizationsService } from 'vs/workbench/services/localizations/electron-browser/localizationsService'; ++import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; ++ ++class TelemetryService extends TelemetryChannelClient { ++ public constructor( ++ @IRemoteAgentService remoteAgentService: IRemoteAgentService, ++ ) { ++ super(remoteAgentService.getConnection()!.getChannel('telemetry')); ++ } ++} ++ ++const TELEMETRY_SECTION_ID = 'telemetry'; ++ ++Registry.as(Extensions.Configuration).registerConfiguration({ ++ 'id': TELEMETRY_SECTION_ID, ++ 'order': 110, ++ 'type': 'object', ++ 'title': localize('telemetryConfigurationTitle', 'Telemetry'), ++ 'properties': { ++ 'telemetry.enableTelemetry': { ++ 'type': 'boolean', ++ 'description': localize('telemetry.enableTelemetry', 'Enable usage data and errors to be sent to a Microsoft online service.'), ++ 'default': true, ++ 'tags': ['usesOnlineServices'] ++ } ++ } ++}); ++ ++class NodeProxyService extends NodeProxyChannelClient implements INodeProxyService { ++ private readonly _onClose = new Emitter(); ++ public readonly onClose = this._onClose.event; ++ private readonly _onDown = new Emitter(); ++ public readonly onDown = this._onDown.event; ++ private readonly _onUp = new Emitter(); ++ public readonly onUp = this._onUp.event; ++ ++ public constructor( ++ @IRemoteAgentService remoteAgentService: IRemoteAgentService, ++ ) { ++ super(remoteAgentService.getConnection()!.getChannel('nodeProxy')); ++ remoteAgentService.getConnection()!.onDidStateChange((state) => { ++ switch (state.type) { ++ case PersistentConnectionEventType.ConnectionGain: ++ return this._onUp.fire(); ++ case PersistentConnectionEventType.ConnectionLost: ++ return this._onDown.fire(); ++ case PersistentConnectionEventType.ReconnectionPermanentFailure: ++ return this._onClose.fire(); ++ } ++ }); ++ } ++} ++ ++registerSingleton(ILocalizationsService, LocalizationsService); ++registerSingleton(INodeProxyService, NodeProxyService); ++registerSingleton(ITelemetryService, TelemetryService); ++ ++/** ++ * This is called by vs/workbench/browser/web.main.ts after the workbench has ++ * been initialized so we can initialize our own client-side code. ++ */ ++export const initialize = async (services: ServiceCollection): Promise => { ++ const event = new CustomEvent('ide-ready'); ++ window.dispatchEvent(event); ++ ++ if (parent) { ++ // Tell the parent loading has completed. ++ parent.postMessage({ event: 'loaded' }, window.location.origin); ++ ++ // Proxy or stop proxing events as requested by the parent. ++ const listeners = new Map void>(); ++ window.addEventListener('message', (parentEvent) => { ++ const eventName = parentEvent.data.bind || parentEvent.data.unbind; ++ if (eventName) { ++ const oldListener = listeners.get(eventName); ++ if (oldListener) { ++ document.removeEventListener(eventName, oldListener); ++ } ++ } ++ ++ if (parentEvent.data.bind && parentEvent.data.prop) { ++ const listener = (event: Event) => { ++ parent.postMessage({ ++ event: parentEvent.data.event, ++ [parentEvent.data.prop]: event[parentEvent.data.prop as keyof Event] ++ }, window.location.origin); ++ }; ++ listeners.set(parentEvent.data.bind, listener); ++ document.addEventListener(parentEvent.data.bind, listener); ++ } ++ }); ++ } ++ ++ if (!window.isSecureContext) { ++ (services.get(INotificationService) as INotificationService).notify({ ++ severity: Severity.Warning, ++ message: "code-server is being accessed over an insecure domain. Some functionality may not work as expected.", ++ actions: { ++ primary: [{ ++ id: "understand", ++ label: "I understand", ++ tooltip: "", ++ class: undefined, ++ enabled: true, ++ checked: true, ++ dispose: () => undefined, ++ run: () => { ++ return Promise.resolve(); ++ } ++ }], ++ } ++ }); ++ } ++}; ++ ++export interface Query { ++ [key: string]: string | undefined; ++} ++ ++/** ++ * Split a string up to the delimiter. If the delimiter doesn't exist the first ++ * item will have all the text and the second item will be an empty string. ++ */ ++export const split = (str: string, delimiter: string): [string, string] => { ++ const index = str.indexOf(delimiter); ++ return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, '']; ++}; ++ ++/** ++ * Return the URL modified with the specified query variables. It's pretty ++ * stupid so it probably doesn't cover any edge cases. Undefined values will ++ * unset existing values. Doesn't allow duplicates. ++ */ ++export const withQuery = (url: string, replace: Query): string => { ++ const uri = URI.parse(url); ++ const query = { ...replace }; ++ uri.query.split('&').forEach((kv) => { ++ const [key, value] = split(kv, '='); ++ if (!(key in query)) { ++ query[key] = value; ++ } ++ }); ++ return uri.with({ ++ query: Object.keys(query) ++ .filter((k) => typeof query[k] !== 'undefined') ++ .map((k) => `${k}=${query[k]}`).join('&'), ++ }).toString(true); ++}; +diff --git a/src/vs/server/browser/extHostNodeProxy.ts b/src/vs/server/browser/extHostNodeProxy.ts +new file mode 100644 +index 0000000000..ed7c078077 +--- /dev/null ++++ b/src/vs/server/browser/extHostNodeProxy.ts +@@ -0,0 +1,46 @@ ++import { Emitter } from 'vs/base/common/event'; ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++import { ExtHostNodeProxyShape, MainContext, MainThreadNodeProxyShape } from 'vs/workbench/api/common/extHost.protocol'; ++import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; ++ ++export class ExtHostNodeProxy implements ExtHostNodeProxyShape { ++ _serviceBrand: any; ++ ++ private readonly _onMessage = new Emitter(); ++ public readonly onMessage = this._onMessage.event; ++ private readonly _onClose = new Emitter(); ++ public readonly onClose = this._onClose.event; ++ private readonly _onDown = new Emitter(); ++ public readonly onDown = this._onDown.event; ++ private readonly _onUp = new Emitter(); ++ public readonly onUp = this._onUp.event; ++ ++ private readonly proxy: MainThreadNodeProxyShape; ++ ++ constructor(@IExtHostRpcService rpc: IExtHostRpcService) { ++ this.proxy = rpc.getProxy(MainContext.MainThreadNodeProxy); ++ } ++ ++ public $onMessage(message: string): void { ++ this._onMessage.fire(message); ++ } ++ ++ public $onClose(): void { ++ this._onClose.fire(); ++ } ++ ++ public $onUp(): void { ++ this._onUp.fire(); ++ } ++ ++ public $onDown(): void { ++ this._onDown.fire(); ++ } ++ ++ public send(message: string): void { ++ this.proxy.$send(message); ++ } ++} ++ ++export interface IExtHostNodeProxy extends ExtHostNodeProxy { } ++export const IExtHostNodeProxy = createDecorator('IExtHostNodeProxy'); +diff --git a/src/vs/server/browser/mainThreadNodeProxy.ts b/src/vs/server/browser/mainThreadNodeProxy.ts +new file mode 100644 +index 0000000000..0d2e93edae +--- /dev/null ++++ b/src/vs/server/browser/mainThreadNodeProxy.ts +@@ -0,0 +1,37 @@ ++import { IDisposable } from 'vs/base/common/lifecycle'; ++import { INodeProxyService } from 'vs/server/common/nodeProxy'; ++import { ExtHostContext, IExtHostContext, MainContext, MainThreadNodeProxyShape } from 'vs/workbench/api/common/extHost.protocol'; ++import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; ++ ++@extHostNamedCustomer(MainContext.MainThreadNodeProxy) ++export class MainThreadNodeProxy implements MainThreadNodeProxyShape { ++ private disposed = false; ++ private disposables = []; ++ ++ constructor( ++ extHostContext: IExtHostContext, ++ @INodeProxyService private readonly proxyService: INodeProxyService, ++ ) { ++ if (!extHostContext.remoteAuthority) { // HACK: A terrible way to detect if running in the worker. ++ const proxy = extHostContext.getProxy(ExtHostContext.ExtHostNodeProxy); ++ this.disposables = [ ++ this.proxyService.onMessage((message: string) => proxy.$onMessage(message)), ++ this.proxyService.onClose(() => proxy.$onClose()), ++ this.proxyService.onDown(() => proxy.$onDown()), ++ this.proxyService.onUp(() => proxy.$onUp()), ++ ]; ++ } ++ } ++ ++ $send(message: string): void { ++ if (!this.disposed) { ++ this.proxyService.send(message); ++ } ++ } ++ ++ dispose(): void { ++ this.disposables.forEach((d) => d.dispose()); ++ this.disposables = []; ++ this.disposed = true; ++ } ++} +diff --git a/src/vs/server/browser/workbench-build.html b/src/vs/server/browser/workbench-build.html +new file mode 100644 +index 0000000000..50f48cd74c +--- /dev/null ++++ b/src/vs/server/browser/workbench-build.html +@@ -0,0 +1,92 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/vs/server/browser/workbench.html b/src/vs/server/browser/workbench.html +new file mode 100644 +index 0000000000..47d76f388b +--- /dev/null ++++ b/src/vs/server/browser/workbench.html +@@ -0,0 +1,55 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/vs/server/browser/worker.ts b/src/vs/server/browser/worker.ts +new file mode 100644 +index 0000000000..0ba93cc070 +--- /dev/null ++++ b/src/vs/server/browser/worker.ts +@@ -0,0 +1,57 @@ ++import { Client } from '@coder/node-browser'; ++import { fromTar } from '@coder/requirefs'; ++import { URI } from 'vs/base/common/uri'; ++import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; ++import { ILogService } from 'vs/platform/log/common/log'; ++import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator'; ++import { IExtHostNodeProxy } from './extHostNodeProxy'; ++ ++export const loadCommonJSModule = async ( ++ module: IExtensionDescription, ++ activationTimesBuilder: ExtensionActivationTimesBuilder, ++ nodeProxy: IExtHostNodeProxy, ++ logService: ILogService, ++ vscode: any, ++): Promise => { ++ const fetchUri = URI.from({ ++ scheme: self.location.protocol.replace(':', ''), ++ authority: self.location.host, ++ path: `${self.location.pathname.replace(/\/static.*\/out\/vs\/workbench\/services\/extensions\/worker\/extensionHostWorkerMain.js$/, '')}/tar`, ++ query: `path=${encodeURIComponent(module.extensionLocation.path)}`, ++ }); ++ const response = await fetch(fetchUri.toString(true)); ++ if (response.status !== 200) { ++ throw new Error(`Failed to download extension "${module.extensionLocation.path}"`); ++ } ++ const client = new Client(nodeProxy, { logger: logService }); ++ const init = await client.handshake(); ++ const buffer = new Uint8Array(await response.arrayBuffer()); ++ const rfs = fromTar(buffer); ++ (self).global = self; ++ rfs.provide('vscode', vscode); ++ Object.keys(client.modules).forEach((key) => { ++ const mod = (client.modules as any)[key]; ++ if (key === 'process') { ++ (self).process = mod; ++ (self).process.env = init.env; ++ return; ++ } ++ ++ rfs.provide(key, mod); ++ switch (key) { ++ case 'buffer': ++ (self).Buffer = mod.Buffer; ++ break; ++ case 'timers': ++ (self).setImmediate = mod.setImmediate; ++ break; ++ } ++ }); ++ ++ try { ++ activationTimesBuilder.codeLoadingStart(); ++ return rfs.require('.'); ++ } finally { ++ activationTimesBuilder.codeLoadingStop(); ++ } ++}; +diff --git a/src/vs/server/common/nodeProxy.ts b/src/vs/server/common/nodeProxy.ts +new file mode 100644 +index 0000000000..14b9de879c +--- /dev/null ++++ b/src/vs/server/common/nodeProxy.ts +@@ -0,0 +1,47 @@ ++import { ReadWriteConnection } from '@coder/node-browser'; ++import { Event } from 'vs/base/common/event'; ++import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; ++import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; ++ ++export const INodeProxyService = createDecorator('nodeProxyService'); ++ ++export interface INodeProxyService extends ReadWriteConnection { ++ _serviceBrand: any; ++ send(message: string): void; ++ onMessage: Event; ++ onUp: Event; ++ onClose: Event; ++ onDown: Event; ++} ++ ++export class NodeProxyChannel implements IServerChannel { ++ constructor(private service: INodeProxyService) {} ++ ++ listen(_: unknown, event: string): Event { ++ switch (event) { ++ case 'onMessage': return this.service.onMessage; ++ } ++ throw new Error(`Invalid listen ${event}`); ++ } ++ ++ async call(_: unknown, command: string, args?: any): Promise { ++ switch (command) { ++ case 'send': return this.service.send(args[0]); ++ } ++ throw new Error(`Invalid call ${command}`); ++ } ++} ++ ++export class NodeProxyChannelClient { ++ _serviceBrand: any; ++ ++ public readonly onMessage: Event; ++ ++ constructor(private readonly channel: IChannel) { ++ this.onMessage = this.channel.listen('onMessage'); ++ } ++ ++ public send(data: string): void { ++ this.channel.call('send', [data]); ++ } ++} +diff --git a/src/vs/server/common/telemetry.ts b/src/vs/server/common/telemetry.ts +new file mode 100644 +index 0000000000..eb62b87798 +--- /dev/null ++++ b/src/vs/server/common/telemetry.ts +@@ -0,0 +1,49 @@ ++import { ITelemetryData } from 'vs/base/common/actions'; ++import { Event } from 'vs/base/common/event'; ++import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; ++import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings'; ++import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; ++ ++export class TelemetryChannel implements IServerChannel { ++ constructor(private service: ITelemetryService) {} ++ ++ listen(_: unknown, event: string): Event { ++ throw new Error(`Invalid listen ${event}`); ++ } ++ ++ call(_: unknown, command: string, args?: any): Promise { ++ switch (command) { ++ case 'publicLog': return this.service.publicLog(args[0], args[1], args[2]); ++ case 'publicLog2': return this.service.publicLog2(args[0], args[1], args[2]); ++ case 'setEnabled': return Promise.resolve(this.service.setEnabled(args[0])); ++ case 'getTelemetryInfo': return this.service.getTelemetryInfo(); ++ } ++ throw new Error(`Invalid call ${command}`); ++ } ++} ++ ++export class TelemetryChannelClient implements ITelemetryService { ++ _serviceBrand: any; ++ ++ constructor(private readonly channel: IChannel) {} ++ ++ public publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise { ++ return this.channel.call('publicLog', [eventName, data, anonymizeFilePaths]); ++ } ++ ++ public publicLog2 = never, T extends GDPRClassification = never>(eventName: string, data?: StrictPropertyCheck, anonymizeFilePaths?: boolean): Promise { ++ return this.channel.call('publicLog2', [eventName, data, anonymizeFilePaths]); ++ } ++ ++ public setEnabled(value: boolean): void { ++ this.channel.call('setEnable', [value]); ++ } ++ ++ public getTelemetryInfo(): Promise { ++ return this.channel.call('getTelemetryInfo'); ++ } ++ ++ public get isOptedIn(): boolean { ++ return true; ++ } ++} +diff --git a/src/vs/server/entry.ts b/src/vs/server/entry.ts +new file mode 100644 +index 0000000000..cb606e6a68 +--- /dev/null ++++ b/src/vs/server/entry.ts +@@ -0,0 +1,67 @@ ++import { field } from '@coder/logger'; ++import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; ++import { CodeServerMessage, VscodeMessage } from 'vs/server/ipc'; ++import { logger } from 'vs/server/node/logger'; ++import { enableCustomMarketplace } from 'vs/server/node/marketplace'; ++import { Vscode } from 'vs/server/node/server'; ++ ++setUnexpectedErrorHandler((error) => logger.warn(error.message)); ++enableCustomMarketplace(); ++ ++/** ++ * Ensure we control when the process exits. ++ */ ++const exit = process.exit; ++process.exit = function(code?: number) { ++ logger.warn(`process.exit() was prevented: ${code || 'unknown code'}.`); ++} as (code?: number) => never; ++ ++// Kill VS Code if the parent process dies. ++if (typeof process.env.CODE_SERVER_PARENT_PID !== 'undefined') { ++ const parentPid = parseInt(process.env.CODE_SERVER_PARENT_PID, 10); ++ setInterval(() => { ++ try { ++ process.kill(parentPid, 0); // Throws an exception if the process doesn't exist anymore. ++ } catch (e) { ++ exit(); ++ } ++ }, 5000); ++} else { ++ logger.error('no parent process'); ++ exit(1); ++} ++ ++const vscode = new Vscode(); ++const send = (message: VscodeMessage): void => { ++ if (!process.send) { ++ throw new Error('not spawned with IPC'); ++ } ++ process.send(message); ++}; ++ ++// Wait for the init message then start up VS Code. Future messages will return ++// new workbench options without starting a new instance. ++process.on('message', async (message: CodeServerMessage, socket) => { ++ logger.debug('got message from code-server', field('message', message)); ++ switch (message.type) { ++ case 'init': ++ try { ++ const options = await vscode.initialize(message.options); ++ send({ type: 'options', id: message.id, options }); ++ } catch (error) { ++ logger.error(error.message); ++ exit(1); ++ } ++ break; ++ case 'socket': ++ vscode.handleWebSocket(socket, message.query); ++ break; ++ } ++}); ++if (!process.send) { ++ logger.error('not spawned with IPC'); ++ exit(1); ++} else { ++ // This lets the parent know the child is ready to receive messages. ++ send({ type: 'ready' }); ++} +diff --git a/src/vs/server/fork.js b/src/vs/server/fork.js +new file mode 100644 +index 0000000000..56331ff1fc +--- /dev/null ++++ b/src/vs/server/fork.js +@@ -0,0 +1,3 @@ ++// This must be a JS file otherwise when it gets compiled it turns into AMD ++// syntax which will not work without the right loader. ++require('../../bootstrap-amd').load('vs/server/entry'); +diff --git a/src/vs/server/ipc.d.ts b/src/vs/server/ipc.d.ts +new file mode 100644 +index 0000000000..218faa34d2 +--- /dev/null ++++ b/src/vs/server/ipc.d.ts +@@ -0,0 +1,93 @@ ++/** ++ * External interfaces for integration into code-server over IPC. No vs imports ++ * should be made in this file. ++ */ ++ ++export interface InitMessage { ++ type: 'init'; ++ id: string; ++ options: VscodeOptions; ++} ++ ++export type Query = { [key: string]: string | string[] | undefined }; ++ ++export interface SocketMessage { ++ type: 'socket'; ++ query: Query; ++} ++ ++export type CodeServerMessage = InitMessage | SocketMessage; ++ ++export interface ReadyMessage { ++ type: 'ready'; ++} ++ ++export interface OptionsMessage { ++ id: string; ++ type: 'options'; ++ options: WorkbenchOptions; ++} ++ ++export type VscodeMessage = ReadyMessage | OptionsMessage; ++ ++export interface StartPath { ++ path?: string[] | string; ++ workspace?: boolean; ++} ++ ++export interface Settings { ++ lastVisited?: StartPath; ++} ++ ++export interface VscodeOptions { ++ readonly remoteAuthority: string; ++ readonly query: Query; ++ readonly args?: string[]; ++ readonly settings: Settings; ++} ++ ++export interface VscodeOptionsMessage extends VscodeOptions { ++ readonly id: string; ++} ++ ++export interface UriComponents { ++ readonly scheme: string; ++ readonly authority: string; ++ readonly path: string; ++ readonly query: string; ++ readonly fragment: string; ++} ++ ++export interface NLSConfiguration { ++ locale: string; ++ availableLanguages: { ++ [key: string]: string; ++ }; ++ pseudo?: boolean; ++ _languagePackSupport?: boolean; ++} ++ ++export interface WorkbenchOptions { ++ readonly startPath?: StartPath; ++ readonly workbenchWebConfiguration: { ++ readonly remoteAuthority?: string; ++ readonly folderUri?: UriComponents; ++ readonly workspaceUri?: UriComponents; ++ readonly logLevel?: number; ++ }; ++ readonly remoteUserDataUri: UriComponents; ++ readonly productConfiguration: { ++ readonly extensionsGallery?: { ++ readonly serviceUrl: string; ++ readonly itemUrl: string; ++ readonly controlUrl: string; ++ readonly recommendationsUrl: string; ++ }; ++ }; ++ readonly nlsConfiguration: NLSConfiguration; ++ readonly commit: string; ++} ++ ++export interface WorkbenchOptionsMessage { ++ id: string; ++} +diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts +new file mode 100644 +index 0000000000..9c240b992d +--- /dev/null ++++ b/src/vs/server/node/channel.ts +@@ -0,0 +1,343 @@ ++import { Server } from '@coder/node-browser'; ++import * as path from 'path'; ++import { VSBuffer, VSBufferReadableStream } from 'vs/base/common/buffer'; ++import { Emitter, Event } from 'vs/base/common/event'; ++import { IDisposable } from 'vs/base/common/lifecycle'; ++import { OS } from 'vs/base/common/platform'; ++import { ReadableStreamEventPayload } from 'vs/base/common/stream'; ++import { URI, UriComponents } from 'vs/base/common/uri'; ++import { transformOutgoingURIs } from 'vs/base/common/uriIpc'; ++import { IServerChannel } from 'vs/base/parts/ipc/common/ipc'; ++import { IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; ++import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileReadStreamOptions, FileType, FileWriteOptions, IStat, IWatchOptions } from 'vs/platform/files/common/files'; ++import { createReadStream } from 'vs/platform/files/common/io'; ++import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; ++import { ILogService } from 'vs/platform/log/common/log'; ++import product from 'vs/platform/product/common/product'; ++import { IRemoteAgentEnvironment, RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment'; ++import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; ++import { INodeProxyService } from 'vs/server/common/nodeProxy'; ++import { getTranslations } from 'vs/server/node/nls'; ++import { getUriTransformer } from 'vs/server/node/util'; ++import { IFileChangeDto } from 'vs/workbench/api/common/extHost.protocol'; ++import { ExtensionScanner, ExtensionScannerInput } from 'vs/workbench/services/extensions/node/extensionPoints'; ++ ++/** ++ * Extend the file provider to allow unwatching. ++ */ ++class Watcher extends DiskFileSystemProvider { ++ public readonly watches = new Map(); ++ ++ public dispose(): void { ++ this.watches.forEach((w) => w.dispose()); ++ this.watches.clear(); ++ super.dispose(); ++ } ++ ++ public _watch(req: number, resource: URI, opts: IWatchOptions): void { ++ this.watches.set(req, this.watch(resource, opts)); ++ } ++ ++ public unwatch(req: number): void { ++ this.watches.get(req)!.dispose(); ++ this.watches.delete(req); ++ } ++} ++ ++export class FileProviderChannel implements IServerChannel, IDisposable { ++ private readonly provider: DiskFileSystemProvider; ++ private readonly watchers = new Map(); ++ ++ public constructor( ++ private readonly environmentService: IEnvironmentService, ++ private readonly logService: ILogService, ++ ) { ++ this.provider = new DiskFileSystemProvider(this.logService); ++ } ++ ++ public listen(context: RemoteAgentConnectionContext, event: string, args?: any): Event { ++ switch (event) { ++ case 'filechange': return this.filechange(context, args[0]); ++ case 'readFileStream': return this.readFileStream(args[0], args[1]); ++ } ++ ++ throw new Error(`Invalid listen '${event}'`); ++ } ++ ++ private filechange(context: RemoteAgentConnectionContext, session: string): Event { ++ const emitter = new Emitter({ ++ onFirstListenerAdd: () => { ++ const provider = new Watcher(this.logService); ++ this.watchers.set(session, provider); ++ const transformer = getUriTransformer(context.remoteAuthority); ++ provider.onDidChangeFile((events) => { ++ emitter.fire(events.map((event) => ({ ++ ...event, ++ resource: transformer.transformOutgoing(event.resource), ++ }))); ++ }); ++ provider.onDidErrorOccur((event) => this.logService.error(event)); ++ }, ++ onLastListenerRemove: () => { ++ this.watchers.get(session)!.dispose(); ++ this.watchers.delete(session); ++ }, ++ }); ++ ++ return emitter.event; ++ } ++ ++ private readFileStream(resource: UriComponents, opts: FileReadStreamOptions): Event> { ++ let fileStream: VSBufferReadableStream | undefined; ++ const emitter = new Emitter>({ ++ onFirstListenerAdd: () => { ++ if (!fileStream) { ++ fileStream = createReadStream(this.provider, this.transform(resource), { ++ ...opts, ++ bufferSize: 64 * 1024, // From DiskFileSystemProvider ++ }); ++ fileStream.on('data', (data) => emitter.fire(data)); ++ fileStream.on('error', (error) => emitter.fire(error)); ++ fileStream.on('end', () => emitter.fire('end')); ++ } ++ }, ++ onLastListenerRemove: () => fileStream && fileStream.destroy(), ++ }); ++ ++ return emitter.event; ++ } ++ ++ public call(_: unknown, command: string, args?: any): Promise { ++ switch (command) { ++ case 'stat': return this.stat(args[0]); ++ case 'open': return this.open(args[0], args[1]); ++ case 'close': return this.close(args[0]); ++ case 'read': return this.read(args[0], args[1], args[2]); ++ case 'readFile': return this.readFile(args[0]); ++ case 'write': return this.write(args[0], args[1], args[2], args[3], args[4]); ++ case 'writeFile': return this.writeFile(args[0], args[1], args[2]); ++ case 'delete': return this.delete(args[0], args[1]); ++ case 'mkdir': return this.mkdir(args[0]); ++ case 'readdir': return this.readdir(args[0]); ++ case 'rename': return this.rename(args[0], args[1], args[2]); ++ case 'copy': return this.copy(args[0], args[1], args[2]); ++ case 'watch': return this.watch(args[0], args[1], args[2], args[3]); ++ case 'unwatch': return this.unwatch(args[0], args[1]); ++ } ++ ++ throw new Error(`Invalid call '${command}'`); ++ } ++ ++ public dispose(): void { ++ this.watchers.forEach((w) => w.dispose()); ++ this.watchers.clear(); ++ } ++ ++ private async stat(resource: UriComponents): Promise { ++ return this.provider.stat(this.transform(resource)); ++ } ++ ++ private async open(resource: UriComponents, opts: FileOpenOptions): Promise { ++ return this.provider.open(this.transform(resource), opts); ++ } ++ ++ private async close(fd: number): Promise { ++ return this.provider.close(fd); ++ } ++ ++ private async read(fd: number, pos: number, length: number): Promise<[VSBuffer, number]> { ++ const buffer = VSBuffer.alloc(length); ++ const bytesRead = await this.provider.read(fd, pos, buffer.buffer, 0, length); ++ return [buffer, bytesRead]; ++ } ++ ++ private async readFile(resource: UriComponents): Promise { ++ return VSBuffer.wrap(await this.provider.readFile(this.transform(resource))); ++ } ++ ++ private write(fd: number, pos: number, buffer: VSBuffer, offset: number, length: number): Promise { ++ return this.provider.write(fd, pos, buffer.buffer, offset, length); ++ } ++ ++ private writeFile(resource: UriComponents, buffer: VSBuffer, opts: FileWriteOptions): Promise { ++ return this.provider.writeFile(this.transform(resource), buffer.buffer, opts); ++ } ++ ++ private async delete(resource: UriComponents, opts: FileDeleteOptions): Promise { ++ return this.provider.delete(this.transform(resource), opts); ++ } ++ ++ private async mkdir(resource: UriComponents): Promise { ++ return this.provider.mkdir(this.transform(resource)); ++ } ++ ++ private async readdir(resource: UriComponents): Promise<[string, FileType][]> { ++ return this.provider.readdir(this.transform(resource)); ++ } ++ ++ private async rename(resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise { ++ return this.provider.rename(this.transform(resource), URI.from(target), opts); ++ } ++ ++ private copy(resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise { ++ return this.provider.copy(this.transform(resource), URI.from(target), opts); ++ } ++ ++ private async watch(session: string, req: number, resource: UriComponents, opts: IWatchOptions): Promise { ++ this.watchers.get(session)!._watch(req, this.transform(resource), opts); ++ } ++ ++ private async unwatch(session: string, req: number): Promise { ++ this.watchers.get(session)!.unwatch(req); ++ } ++ ++ private transform(resource: UriComponents): URI { ++ // Used for walkthrough content. ++ if (/^\/static[^/]*\//.test(resource.path)) { ++ return URI.file(this.environmentService.appRoot + resource.path.replace(/^\/static[^/]*\//, '/')); ++ // Used by the webview service worker to load resources. ++ } else if (resource.path === '/vscode-resource' && resource.query) { ++ try { ++ const query = JSON.parse(resource.query); ++ if (query.requestResourcePath) { ++ return URI.file(query.requestResourcePath); ++ } ++ } catch (error) { /* Carry on. */ } ++ } ++ return URI.from(resource); ++ } ++} ++ ++export class ExtensionEnvironmentChannel implements IServerChannel { ++ public constructor( ++ private readonly environment: IEnvironmentService, ++ private readonly log: ILogService, ++ private readonly telemetry: ITelemetryService, ++ private readonly connectionToken: string, ++ ) {} ++ ++ public listen(_: unknown, event: string): Event { ++ throw new Error(`Invalid listen '${event}'`); ++ } ++ ++ public async call(context: any, command: string, args?: any): Promise { ++ switch (command) { ++ case 'getEnvironmentData': ++ return transformOutgoingURIs( ++ await this.getEnvironmentData(args.language), ++ getUriTransformer(context.remoteAuthority), ++ ); ++ case 'getDiagnosticInfo': return this.getDiagnosticInfo(); ++ case 'disableTelemetry': return this.disableTelemetry(); ++ } ++ throw new Error(`Invalid call '${command}'`); ++ } ++ ++ private async getEnvironmentData(locale: string): Promise { ++ return { ++ pid: process.pid, ++ connectionToken: this.connectionToken, ++ appRoot: URI.file(this.environment.appRoot), ++ appSettingsHome: this.environment.appSettingsHome, ++ settingsPath: this.environment.machineSettingsHome, ++ logsPath: URI.file(this.environment.logsPath), ++ extensionsPath: URI.file(this.environment.extensionsPath!), ++ extensionHostLogsPath: URI.file(path.join(this.environment.logsPath, 'extension-host')), ++ globalStorageHome: URI.file(this.environment.globalStorageHome), ++ userHome: URI.file(this.environment.userHome), ++ extensions: await this.scanExtensions(locale), ++ os: OS, ++ }; ++ } ++ ++ private async scanExtensions(locale: string): Promise { ++ const translations = await getTranslations(locale, this.environment.userDataPath); ++ ++ const scanMultiple = (isBuiltin: boolean, isUnderDevelopment: boolean, paths: string[]): Promise => { ++ return Promise.all(paths.map((path) => { ++ return ExtensionScanner.scanExtensions(new ExtensionScannerInput( ++ product.version, ++ product.commit, ++ locale, ++ !!process.env.VSCODE_DEV, ++ path, ++ isBuiltin, ++ isUnderDevelopment, ++ translations, ++ ), this.log); ++ })); ++ }; ++ ++ const scanBuiltin = async (): Promise => { ++ return scanMultiple(true, false, [this.environment.builtinExtensionsPath, ...this.environment.extraBuiltinExtensionPaths]); ++ }; ++ ++ const scanInstalled = async (): Promise => { ++ return scanMultiple(false, true, [this.environment.extensionsPath!, ...this.environment.extraExtensionPaths]); ++ }; ++ ++ return Promise.all([scanBuiltin(), scanInstalled()]).then((allExtensions) => { ++ const uniqueExtensions = new Map(); ++ allExtensions.forEach((multipleExtensions) => { ++ multipleExtensions.forEach((extensions) => { ++ extensions.forEach((extension) => { ++ const id = ExtensionIdentifier.toKey(extension.identifier); ++ if (uniqueExtensions.has(id)) { ++ const oldPath = uniqueExtensions.get(id)!.extensionLocation.fsPath; ++ const newPath = extension.extensionLocation.fsPath; ++ this.log.warn(`${oldPath} has been overridden ${newPath}`); ++ } ++ uniqueExtensions.set(id, extension); ++ }); ++ }); ++ }); ++ return Array.from(uniqueExtensions.values()); ++ }); ++ } ++ ++ private getDiagnosticInfo(): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async disableTelemetry(): Promise { ++ this.telemetry.setEnabled(false); ++ } ++} ++ ++export class NodeProxyService implements INodeProxyService { ++ public _serviceBrand = undefined; ++ ++ public readonly server: Server; ++ ++ private readonly _onMessage = new Emitter(); ++ public readonly onMessage = this._onMessage.event; ++ private readonly _$onMessage = new Emitter(); ++ public readonly $onMessage = this._$onMessage.event; ++ public readonly _onDown = new Emitter(); ++ public readonly onDown = this._onDown.event; ++ public readonly _onUp = new Emitter(); ++ public readonly onUp = this._onUp.event; ++ ++ // Unused because the server connection will never permanently close. ++ private readonly _onClose = new Emitter(); ++ public readonly onClose = this._onClose.event; ++ ++ public constructor() { ++ // TODO: down/up ++ this.server = new Server({ ++ onMessage: this.$onMessage, ++ onClose: this.onClose, ++ onDown: this.onDown, ++ onUp: this.onUp, ++ send: (message: string): void => { ++ this._onMessage.fire(message); ++ } ++ }); ++ } ++ ++ public send(message: string): void { ++ this._$onMessage.fire(message); ++ } ++} +diff --git a/src/vs/server/node/cli.ts b/src/vs/server/node/cli.ts +new file mode 100644 +index 0000000000..117cc4900a +--- /dev/null ++++ b/src/vs/server/node/cli.ts +@@ -0,0 +1,75 @@ ++import * as os from 'os'; ++import * as path from 'path'; ++import { main as vsCli } from 'vs/code/node/cliProcessMain'; ++import { validatePaths } from 'vs/code/node/paths'; ++import { ParsedArgs } from 'vs/platform/environment/common/environment'; ++import { buildHelpMessage, buildVersionMessage, OPTIONS } from 'vs/platform/environment/node/argv'; ++import { parseMainProcessArgv } from 'vs/platform/environment/node/argvHelper'; ++import product from 'vs/platform/product/common/product'; ++import { logger } from 'vs/server/node/logger'; ++import { xdgLocalDir } from 'vs/server/node/util'; ++ ++export const parseArgs = (rawArgs: string[]): ParsedArgs => { ++ // Remove options that won't work or don't make sense. ++ for (let key in OPTIONS) { ++ switch (key) { ++ case 'add': ++ case 'diff': ++ case 'file-uri': ++ case 'folder-uri': ++ case 'goto': ++ case 'new-window': ++ case 'reuse-window': ++ case 'wait': ++ case 'disable-gpu': ++ // TODO: pretty sure these don't work but not 100%. ++ case 'prof-startup': ++ case 'inspect-extensions': ++ case 'inspect-brk-extensions': ++ delete OPTIONS[key]; ++ break; ++ } ++ } ++ ++ const args = parseMainProcessArgv(rawArgs); ++ if (!args['user-data-dir']) { ++ args['user-data-dir'] = xdgLocalDir; ++ } ++ if (!args['extensions-dir']) { ++ args['extensions-dir'] = path.join(args['user-data-dir'], 'extensions'); ++ } ++ ++ if (!args.verbose && !args.log && process.env.LOG_LEVEL) { ++ args.log = process.env.LOG_LEVEL; ++ } ++ ++ return validatePaths(args); ++}; ++ ++export const startCli = (args: ParsedArgs): boolean | Promise => { ++ if (args.help) { ++ const executable = `${product.applicationName}${os.platform() === 'win32' ? '.exe' : ''}`; ++ console.log(buildHelpMessage(product.nameLong, executable, product.version, OPTIONS, false)); ++ return true; ++ } ++ ++ if (args.version) { ++ buildVersionMessage(product.version, product.commit).split('\n').map((line) => logger.info(line)); ++ return true; ++ } ++ ++ const shouldSpawnCliProcess = (): boolean => { ++ return !!args['install-source'] ++ || !!args['list-extensions'] ++ || !!args['install-extension'] ++ || !!args['uninstall-extension'] ++ || !!args['locate-extension'] ++ || !!args['telemetry']; ++ }; ++ ++ if (shouldSpawnCliProcess()) { ++ return vsCli(args); ++ } ++ ++ return false; ++}; +diff --git a/src/vs/server/node/connection.ts b/src/vs/server/node/connection.ts +new file mode 100644 +index 0000000000..3b42933419 +--- /dev/null ++++ b/src/vs/server/node/connection.ts +@@ -0,0 +1,156 @@ ++import * as cp from 'child_process'; ++import { getPathFromAmdModule } from 'vs/base/common/amd'; ++import { VSBuffer } from 'vs/base/common/buffer'; ++import { Emitter } from 'vs/base/common/event'; ++import { ISocket } from 'vs/base/parts/ipc/common/ipc.net'; ++import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; ++import { IEnvironmentService } from 'vs/platform/environment/common/environment'; ++import { ILogService } from 'vs/platform/log/common/log'; ++import { getNlsConfiguration } from 'vs/server/node/nls'; ++import { Protocol } from 'vs/server/node/protocol'; ++import { uriTransformerPath } from 'vs/server/node/util'; ++import { IExtHostReadyMessage } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; ++ ++export abstract class Connection { ++ private readonly _onClose = new Emitter(); ++ public readonly onClose = this._onClose.event; ++ private disposed = false; ++ private _offline: number | undefined; ++ ++ public constructor(protected protocol: Protocol, public readonly token: string) {} ++ ++ public get offline(): number | undefined { ++ return this._offline; ++ } ++ ++ public reconnect(socket: ISocket, buffer: VSBuffer): void { ++ this._offline = undefined; ++ this.doReconnect(socket, buffer); ++ } ++ ++ public dispose(): void { ++ if (!this.disposed) { ++ this.disposed = true; ++ this.doDispose(); ++ this._onClose.fire(); ++ } ++ } ++ ++ protected setOffline(): void { ++ if (!this._offline) { ++ this._offline = Date.now(); ++ } ++ } ++ ++ /** ++ * Set up the connection on a new socket. ++ */ ++ protected abstract doReconnect(socket: ISocket, buffer: VSBuffer): void; ++ protected abstract doDispose(): void; ++} ++ ++/** ++ * Used for all the IPC channels. ++ */ ++export class ManagementConnection extends Connection { ++ public constructor(protected protocol: Protocol, token: string) { ++ super(protocol, token); ++ protocol.onClose(() => this.dispose()); // Explicit close. ++ protocol.onSocketClose(() => this.setOffline()); // Might reconnect. ++ } ++ ++ protected doDispose(): void { ++ this.protocol.sendDisconnect(); ++ this.protocol.dispose(); ++ this.protocol.getSocket().end(); ++ } ++ ++ protected doReconnect(socket: ISocket, buffer: VSBuffer): void { ++ this.protocol.beginAcceptReconnection(socket, buffer); ++ this.protocol.endAcceptReconnection(); ++ } ++} ++ ++export class ExtensionHostConnection extends Connection { ++ private process?: cp.ChildProcess; ++ ++ public constructor( ++ locale:string, protocol: Protocol, buffer: VSBuffer, token: string, ++ private readonly log: ILogService, ++ private readonly environment: IEnvironmentService, ++ ) { ++ super(protocol, token); ++ this.protocol.dispose(); ++ this.spawn(locale, buffer).then((p) => this.process = p); ++ this.protocol.getUnderlyingSocket().pause(); ++ } ++ ++ protected doDispose(): void { ++ if (this.process) { ++ this.process.kill(); ++ } ++ this.protocol.getSocket().end(); ++ } ++ ++ protected doReconnect(socket: ISocket, buffer: VSBuffer): void { ++ // This is just to set the new socket. ++ this.protocol.beginAcceptReconnection(socket, null); ++ this.protocol.dispose(); ++ this.sendInitMessage(buffer); ++ } ++ ++ private sendInitMessage(buffer: VSBuffer): void { ++ const socket = this.protocol.getUnderlyingSocket(); ++ socket.pause(); ++ this.process!.send({ // Process must be set at this point. ++ type: 'VSCODE_EXTHOST_IPC_SOCKET', ++ initialDataChunk: (buffer.buffer as Buffer).toString('base64'), ++ skipWebSocketFrames: this.protocol.getSocket() instanceof NodeSocket, ++ }, socket); ++ } ++ ++ private async spawn(locale: string, buffer: VSBuffer): Promise { ++ const config = await getNlsConfiguration(locale, this.environment.userDataPath); ++ const proc = cp.fork( ++ getPathFromAmdModule(require, 'bootstrap-fork'), ++ [ '--type=extensionHost', `--uriTransformerPath=${uriTransformerPath}` ], ++ { ++ env: { ++ ...process.env, ++ AMD_ENTRYPOINT: 'vs/workbench/services/extensions/node/extensionHostProcess', ++ PIPE_LOGGING: 'true', ++ VERBOSE_LOGGING: 'true', ++ VSCODE_EXTHOST_WILL_SEND_SOCKET: 'true', ++ VSCODE_HANDLES_UNCAUGHT_ERRORS: 'true', ++ VSCODE_LOG_STACK: 'false', ++ VSCODE_LOG_LEVEL: this.environment.verbose ? 'trace' : this.environment.log, ++ VSCODE_NLS_CONFIG: JSON.stringify(config), ++ }, ++ silent: true, ++ }, ++ ); ++ ++ proc.on('error', () => this.dispose()); ++ proc.on('exit', () => this.dispose()); ++ proc.stdout.setEncoding('utf8').on('data', (d) => this.log.info('Extension host stdout', d)); ++ proc.stderr.setEncoding('utf8').on('data', (d) => this.log.error('Extension host stderr', d)); ++ proc.on('message', (event) => { ++ if (event && event.type === '__$console') { ++ const severity = (this.log)[event.severity] ? event.severity : 'info'; ++ (this.log)[severity]('Extension host', event.arguments); ++ } ++ if (event && event.type === 'VSCODE_EXTHOST_DISCONNECTED') { ++ this.setOffline(); ++ } ++ }); ++ ++ const listen = (message: IExtHostReadyMessage) => { ++ if (message.type === 'VSCODE_EXTHOST_IPC_READY') { ++ proc.removeListener('message', listen); ++ this.sendInitMessage(buffer); ++ } ++ }; ++ ++ return proc.on('message', listen); ++ } ++} +diff --git a/src/vs/server/node/insights.ts b/src/vs/server/node/insights.ts +new file mode 100644 +index 0000000000..a0ece345f2 +--- /dev/null ++++ b/src/vs/server/node/insights.ts +@@ -0,0 +1,124 @@ ++import * as appInsights from 'applicationinsights'; ++import * as https from 'https'; ++import * as http from 'http'; ++import * as os from 'os'; ++ ++class Channel { ++ public get _sender() { ++ throw new Error('unimplemented'); ++ } ++ public get _buffer() { ++ throw new Error('unimplemented'); ++ } ++ ++ public setUseDiskRetryCaching(): void { ++ throw new Error('unimplemented'); ++ } ++ public send(): void { ++ throw new Error('unimplemented'); ++ } ++ public triggerSend(): void { ++ throw new Error('unimplemented'); ++ } ++} ++ ++export class TelemetryClient { ++ public context: any = undefined; ++ public commonProperties: any = undefined; ++ public config: any = {}; ++ ++ public channel: any = new Channel(); ++ ++ public addTelemetryProcessor(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public clearTelemetryProcessors(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public runTelemetryProcessors(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackTrace(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackMetric(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackException(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackRequest(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackDependency(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public track(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpRequestSync(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpRequest(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackNodeHttpDependency(): void { ++ throw new Error('unimplemented'); ++ } ++ ++ public trackEvent(options: appInsights.Contracts.EventTelemetry): void { ++ if (!options.properties) { ++ options.properties = {}; ++ } ++ if (!options.measurements) { ++ options.measurements = {}; ++ } ++ ++ try { ++ const cpus = os.cpus(); ++ options.measurements.cores = cpus.length; ++ options.properties['common.cpuModel'] = cpus[0].model; ++ } catch (error) {} ++ ++ try { ++ options.measurements.memoryFree = os.freemem(); ++ options.measurements.memoryTotal = os.totalmem(); ++ } catch (error) {} ++ ++ try { ++ options.properties['common.shell'] = os.userInfo().shell; ++ options.properties['common.release'] = os.release(); ++ options.properties['common.arch'] = os.arch(); ++ } catch (error) {} ++ ++ try { ++ const url = process.env.TELEMETRY_URL || 'https://v1.telemetry.coder.com/track'; ++ const request = (/^http:/.test(url) ? http : https).request(url, { ++ method: 'POST', ++ headers: { ++ 'Content-Type': 'application/json', ++ }, ++ }); ++ request.on('error', () => { /* We don't care. */ }); ++ request.write(JSON.stringify(options)); ++ request.end(); ++ } catch (error) {} ++ } ++ ++ public flush(options: { callback: (v: string) => void }): void { ++ if (options.callback) { ++ options.callback(''); ++ } ++ } ++} +diff --git a/src/vs/server/node/ipc.ts b/src/vs/server/node/ipc.ts +new file mode 100644 +index 0000000000..5e560eb46e +--- /dev/null ++++ b/src/vs/server/node/ipc.ts +@@ -0,0 +1,61 @@ ++import * as cp from 'child_process'; ++import { Emitter } from 'vs/base/common/event'; ++ ++enum ControlMessage { ++ okToChild = 'ok>', ++ okFromChild = 'ok<', ++} ++ ++interface RelaunchMessage { ++ type: 'relaunch'; ++ version: string; ++} ++ ++export type Message = RelaunchMessage; ++ ++class IpcMain { ++ protected readonly _onMessage = new Emitter(); ++ public readonly onMessage = this._onMessage.event; ++ ++ public handshake(child?: cp.ChildProcess): Promise { ++ return new Promise((resolve, reject) => { ++ const target = child || process; ++ if (!target.send) { ++ throw new Error('Not spawned with IPC enabled'); ++ } ++ target.on('message', (message) => { ++ if (message === child ? ControlMessage.okFromChild : ControlMessage.okToChild) { ++ target.removeAllListeners(); ++ target.on('message', (msg) => this._onMessage.fire(msg)); ++ if (child) { ++ target.send!(ControlMessage.okToChild); ++ } ++ resolve(); ++ } ++ }); ++ if (child) { ++ child.once('error', reject); ++ child.once('exit', (code) => { ++ const error = new Error(`Unexpected exit with code ${code}`); ++ (error as any).code = code; ++ reject(error); ++ }); ++ } else { ++ target.send(ControlMessage.okFromChild); ++ } ++ }); ++ } ++ ++ public relaunch(version: string): void { ++ this.send({ type: 'relaunch', version }); ++ } ++ ++ private send(message: Message): void { ++ if (!process.send) { ++ throw new Error('Not a child process with IPC enabled'); ++ } ++ process.send(message); ++ } ++} ++ ++export const ipcMain = new IpcMain(); +diff --git a/src/vs/server/node/logger.ts b/src/vs/server/node/logger.ts +new file mode 100644 +index 0000000000..2a39c524aa +--- /dev/null ++++ b/src/vs/server/node/logger.ts +@@ -0,0 +1,2 @@ ++import { logger as baseLogger } from '@coder/logger'; ++export const logger = baseLogger.named('vscode'); +diff --git a/src/vs/server/node/marketplace.ts b/src/vs/server/node/marketplace.ts +new file mode 100644 +index 0000000000..9960ccfd07 +--- /dev/null ++++ b/src/vs/server/node/marketplace.ts +@@ -0,0 +1,174 @@ ++import * as fs from 'fs'; ++import * as path from 'path'; ++import * as tarStream from 'tar-stream'; ++import * as util from 'util'; ++import { CancellationToken } from 'vs/base/common/cancellation'; ++import { mkdirp } from 'vs/base/node/pfs'; ++import * as vszip from 'vs/base/node/zip'; ++import * as nls from 'vs/nls'; ++import product from 'vs/platform/product/common/product'; ++ ++// We will be overriding these, so keep a reference to the original. ++const vszipExtract = vszip.extract; ++const vszipBuffer = vszip.buffer; ++ ++export interface IExtractOptions { ++ overwrite?: boolean; ++ /** ++ * Source path within the TAR/ZIP archive. Only the files ++ * contained in this path will be extracted. ++ */ ++ sourcePath?: string; ++} ++ ++export interface IFile { ++ path: string; ++ contents?: Buffer | string; ++ localPath?: string; ++} ++ ++export const tar = async (tarPath: string, files: IFile[]): Promise => { ++ const pack = tarStream.pack(); ++ const chunks: Buffer[] = []; ++ const ended = new Promise((resolve) => { ++ pack.on('end', () => resolve(Buffer.concat(chunks))); ++ }); ++ pack.on('data', (chunk: Buffer) => chunks.push(chunk)); ++ for (let i = 0; i < files.length; i++) { ++ const file = files[i]; ++ pack.entry({ name: file.path }, file.contents); ++ } ++ pack.finalize(); ++ await util.promisify(fs.writeFile)(tarPath, await ended); ++ return tarPath; ++}; ++ ++export const extract = async (archivePath: string, extractPath: string, options: IExtractOptions = {}, token: CancellationToken): Promise => { ++ try { ++ await extractTar(archivePath, extractPath, options, token); ++ } catch (error) { ++ if (error.toString().includes('Invalid tar header')) { ++ await vszipExtract(archivePath, extractPath, options, token); ++ } ++ } ++}; ++ ++export const buffer = (targetPath: string, filePath: string): Promise => { ++ return new Promise(async (resolve, reject) => { ++ try { ++ let done: boolean = false; ++ await extractAssets(targetPath, new RegExp(filePath), (assetPath: string, data: Buffer) => { ++ if (path.normalize(assetPath) === path.normalize(filePath)) { ++ done = true; ++ resolve(data); ++ } ++ }); ++ if (!done) { ++ throw new Error('couldn\'t find asset ' + filePath); ++ } ++ } catch (error) { ++ if (error.toString().includes('Invalid tar header')) { ++ vszipBuffer(targetPath, filePath).then(resolve).catch(reject); ++ } else { ++ reject(error); ++ } ++ } ++ }); ++}; ++ ++const extractAssets = async (tarPath: string, match: RegExp, callback: (path: string, data: Buffer) => void): Promise => { ++ return new Promise((resolve, reject): void => { ++ const extractor = tarStream.extract(); ++ const fail = (error: Error) => { ++ extractor.destroy(); ++ reject(error); ++ }; ++ extractor.once('error', fail); ++ extractor.on('entry', async (header, stream, next) => { ++ const name = header.name; ++ if (match.test(name)) { ++ extractData(stream).then((data) => { ++ callback(name, data); ++ next(); ++ }).catch(fail); ++ } else { ++ stream.on('end', () => next()); ++ stream.resume(); // Just drain it. ++ } ++ }); ++ extractor.on('finish', resolve); ++ fs.createReadStream(tarPath).pipe(extractor); ++ }); ++}; ++ ++const extractData = (stream: NodeJS.ReadableStream): Promise => { ++ return new Promise((resolve, reject): void => { ++ const fileData: Buffer[] = []; ++ stream.on('error', reject); ++ stream.on('end', () => resolve(Buffer.concat(fileData))); ++ stream.on('data', (data) => fileData.push(data)); ++ }); ++}; ++ ++const extractTar = async (tarPath: string, targetPath: string, options: IExtractOptions = {}, token: CancellationToken): Promise => { ++ return new Promise((resolve, reject): void => { ++ const sourcePathRegex = new RegExp(options.sourcePath ? `^${options.sourcePath}` : ''); ++ const extractor = tarStream.extract(); ++ const fail = (error: Error) => { ++ extractor.destroy(); ++ reject(error); ++ }; ++ extractor.once('error', fail); ++ extractor.on('entry', async (header, stream, next) => { ++ const nextEntry = (): void => { ++ stream.on('end', () => next()); ++ stream.resume(); ++ }; ++ ++ const rawName = path.normalize(header.name); ++ if (token.isCancellationRequested || !sourcePathRegex.test(rawName)) { ++ return nextEntry(); ++ } ++ ++ const fileName = rawName.replace(sourcePathRegex, ''); ++ const targetFileName = path.join(targetPath, fileName); ++ if (/\/$/.test(fileName)) { ++ return mkdirp(targetFileName).then(nextEntry); ++ } ++ ++ const dirName = path.dirname(fileName); ++ const targetDirName = path.join(targetPath, dirName); ++ if (targetDirName.indexOf(targetPath) !== 0) { ++ return fail(new Error(nls.localize('invalid file', 'Error extracting {0}. Invalid file.', fileName))); ++ } ++ ++ await mkdirp(targetDirName, undefined); ++ ++ const fstream = fs.createWriteStream(targetFileName, { mode: header.mode }); ++ fstream.once('close', () => next()); ++ fstream.once('error', fail); ++ stream.pipe(fstream); ++ }); ++ extractor.once('finish', resolve); ++ fs.createReadStream(tarPath).pipe(extractor); ++ }); ++}; ++ ++/** ++ * Override original functionality so we can use a custom marketplace with ++ * either tars or zips. ++ */ ++export const enableCustomMarketplace = (): void => { ++ (product).extensionsGallery = { // Use `any` to override readonly. ++ serviceUrl: process.env.SERVICE_URL || 'https://v1.extapi.coder.com', ++ itemUrl: process.env.ITEM_URL || '', ++ controlUrl: '', ++ recommendationsUrl: '', ++ ...(product.extensionsGallery || {}), ++ }; ++ ++ const target = vszip as typeof vszip; ++ target.zip = tar; ++ target.extract = extract; ++ target.buffer = buffer; ++}; +diff --git a/src/vs/server/node/nls.ts b/src/vs/server/node/nls.ts +new file mode 100644 +index 0000000000..61c79d0d80 +--- /dev/null ++++ b/src/vs/server/node/nls.ts +@@ -0,0 +1,86 @@ ++import * as fs from 'fs'; ++import * as path from 'path'; ++import * as util from 'util'; ++import { getPathFromAmdModule } from 'vs/base/common/amd'; ++import * as lp from 'vs/base/node/languagePacks'; ++import product from 'vs/platform/product/common/product'; ++import { Translations } from 'vs/workbench/services/extensions/common/extensionPoints'; ++ ++const configurations = new Map>(); ++const metadataPath = path.join(getPathFromAmdModule(require, ''), 'nls.metadata.json'); ++ ++export const isInternalConfiguration = (config: lp.NLSConfiguration): config is lp.InternalNLSConfiguration => { ++ return config && !!(config)._languagePackId; ++}; ++ ++const DefaultConfiguration = { ++ locale: 'en', ++ availableLanguages: {}, ++}; ++ ++export const getNlsConfiguration = async (locale: string, userDataPath: string): Promise => { ++ const id = `${locale}: ${userDataPath}`; ++ if (!configurations.has(id)) { ++ configurations.set(id, new Promise(async (resolve) => { ++ const config = product.commit && await util.promisify(fs.exists)(metadataPath) ++ ? await lp.getNLSConfiguration(product.commit, userDataPath, metadataPath, locale) ++ : DefaultConfiguration; ++ if (isInternalConfiguration(config)) { ++ config._languagePackSupport = true; ++ } ++ // If the configuration has no results keep trying since code-server ++ // doesn't restart when a language is installed so this result would ++ // persist (the plugin might not be installed yet or something). ++ if (config.locale !== 'en' && config.locale !== 'en-us' && Object.keys(config.availableLanguages).length === 0) { ++ configurations.delete(id); ++ } ++ resolve(config); ++ })); ++ } ++ return configurations.get(id)!; ++}; ++ ++export const getTranslations = async (locale: string, userDataPath: string): Promise => { ++ const config = await getNlsConfiguration(locale, userDataPath); ++ if (isInternalConfiguration(config)) { ++ try { ++ return JSON.parse(await util.promisify(fs.readFile)(config._translationsConfigFile, 'utf8')); ++ } catch (error) { /* Nothing yet. */} ++ } ++ return {}; ++}; ++ ++export const getLocaleFromConfig = async (userDataPath: string): Promise => { ++ let locale = 'en'; ++ try { ++ const localeConfigUri = path.join(userDataPath, 'User/locale.json'); ++ const content = stripComments(await util.promisify(fs.readFile)(localeConfigUri, 'utf8')); ++ locale = JSON.parse(content).locale; ++ } catch (error) { /* Ignore. */ } ++ return locale; ++}; ++ ++// Taken from src/main.js in the main VS Code source. ++const stripComments = (content: string): string => { ++ const regexp = /('(?:[^\\']*(?:\\.)?)*')|('(?:[^\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; ++ ++ return content.replace(regexp, (match, _m1, _m2, m3, m4) => { ++ // Only one of m1, m2, m3, m4 matches ++ if (m3) { ++ // A block comment. Replace with nothing ++ return ''; ++ } else if (m4) { ++ // A line comment. If it ends in \r?\n then keep it. ++ const length_1 = m4.length; ++ if (length_1 > 2 && m4[length_1 - 1] === '\n') { ++ return m4[length_1 - 2] === '\r' ? '\r\n' : '\n'; ++ } ++ else { ++ return ''; ++ } ++ } else { ++ // We match a string ++ return match; ++ } ++ }); ++}; +diff --git a/src/vs/server/node/protocol.ts b/src/vs/server/node/protocol.ts +new file mode 100644 +index 0000000000..3c74512192 +--- /dev/null ++++ b/src/vs/server/node/protocol.ts +@@ -0,0 +1,73 @@ ++import * as net from 'net'; ++import { VSBuffer } from 'vs/base/common/buffer'; ++import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net'; ++import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net'; ++import { AuthRequest, ConnectionTypeRequest, HandshakeMessage } from 'vs/platform/remote/common/remoteAgentConnection'; ++ ++export interface SocketOptions { ++ readonly reconnectionToken: string; ++ readonly reconnection: boolean; ++ readonly skipWebSocketFrames: boolean; ++} ++ ++export class Protocol extends PersistentProtocol { ++ public constructor(socket: net.Socket, public readonly options: SocketOptions) { ++ super( ++ options.skipWebSocketFrames ++ ? new NodeSocket(socket) ++ : new WebSocketNodeSocket(new NodeSocket(socket)), ++ ); ++ } ++ ++ public getUnderlyingSocket(): net.Socket { ++ const socket = this.getSocket(); ++ return socket instanceof NodeSocket ++ ? socket.socket ++ : (socket as WebSocketNodeSocket).socket.socket; ++ } ++ ++ /** ++ * Perform a handshake to get a connection request. ++ */ ++ public handshake(): Promise { ++ return new Promise((resolve, reject) => { ++ const handler = this.onControlMessage((rawMessage) => { ++ try { ++ const message = JSON.parse(rawMessage.toString()); ++ switch (message.type) { ++ case 'auth': return this.authenticate(message); ++ case 'connectionType': ++ handler.dispose(); ++ return resolve(message); ++ default: throw new Error('Unrecognized message type'); ++ } ++ } catch (error) { ++ handler.dispose(); ++ reject(error); ++ } ++ }); ++ }); ++ } ++ ++ /** ++ * TODO: This ignores the authentication process entirely for now. ++ */ ++ private authenticate(_message: AuthRequest): void { ++ this.sendMessage({ type: 'sign', data: '' }); ++ } ++ ++ /** ++ * TODO: implement. ++ */ ++ public tunnel(): void { ++ throw new Error('Tunnel is not implemented yet'); ++ } ++ ++ /** ++ * Send a handshake message. In the case of the extension host, it just sends ++ * back a debug port. ++ */ ++ public sendMessage(message: HandshakeMessage | { debugPort?: number } ): void { ++ this.sendControl(VSBuffer.fromString(JSON.stringify(message))); ++ } ++} +diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts +new file mode 100644 +index 0000000000..5207c90081 +--- /dev/null ++++ b/src/vs/server/node/server.ts +@@ -0,0 +1,293 @@ ++import * as fs from 'fs-extra'; ++import * as net from 'net'; ++import * as path from 'path'; ++import { Emitter } from 'vs/base/common/event'; ++import { sanitizeFilePath } from 'vs/base/common/extpath'; ++import { Schemas } from 'vs/base/common/network'; ++import { URI } from 'vs/base/common/uri'; ++import { getMachineId } from 'vs/base/node/id'; ++import { ClientConnectionEvent, IPCServer, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; ++import { createChannelReceiver } from 'vs/base/parts/ipc/node/ipc'; ++import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; ++import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; ++import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; ++import { ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; ++import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; ++import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; ++import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; ++import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; ++import { ExtensionManagementChannel } from 'vs/platform/extensionManagement/common/extensionManagementIpc'; ++import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; ++import { IFileService } from 'vs/platform/files/common/files'; ++import { FileService } from 'vs/platform/files/common/fileService'; ++import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; ++import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; ++import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; ++import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; ++import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; ++import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; ++import { getLogLevel, ILogService } from 'vs/platform/log/common/log'; ++import { LoggerChannel } from 'vs/platform/log/common/logIpc'; ++import { SpdLogService } from 'vs/platform/log/node/spdlogService'; ++import product from 'vs/platform/product/common/product'; ++import { IProductService } from 'vs/platform/product/common/productService'; ++import { ConnectionType, ConnectionTypeRequest } from 'vs/platform/remote/common/remoteAgentConnection'; ++import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment'; ++import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/platform/remote/common/remoteAgentFileSystemChannel'; ++import { IRequestService } from 'vs/platform/request/common/request'; ++import { RequestChannel } from 'vs/platform/request/common/requestIpc'; ++import { RequestService } from 'vs/platform/request/node/requestService'; ++import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; ++import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; ++import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; ++import { combinedAppender, LogAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; ++import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; ++import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; ++import { INodeProxyService, NodeProxyChannel } from 'vs/server/common/nodeProxy'; ++import { TelemetryChannel } from 'vs/server/common/telemetry'; ++import { Query, StartPath, VscodeOptions, WorkbenchOptions } from 'vs/server/ipc'; ++import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService } from 'vs/server/node/channel'; ++import { parseArgs } from 'vs/server/node/cli'; ++import { Connection, ExtensionHostConnection, ManagementConnection } from 'vs/server/node/connection'; ++import { TelemetryClient } from 'vs/server/node/insights'; ++import { logger } from 'vs/server/node/logger'; ++import { getLocaleFromConfig, getNlsConfiguration } from 'vs/server/node/nls'; ++import { Protocol } from 'vs/server/node/protocol'; ++import { getUriTransformer } from 'vs/server/node/util'; ++import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService'; ++ ++export class Vscode { ++ public readonly _onDidClientConnect = new Emitter(); ++ public readonly onDidClientConnect = this._onDidClientConnect.event; ++ private readonly ipc = new IPCServer(this.onDidClientConnect); ++ ++ private readonly maxExtraOfflineConnections = 0; ++ private readonly connections = new Map>(); ++ ++ private readonly services = new ServiceCollection(); ++ private servicesPromise?: Promise; ++ private args?: ParsedArgs; ++ ++ public async initialize(options: VscodeOptions): Promise { ++ if (!this.args) { ++ this.args = parseArgs(options.args || []); ++ } ++ const transformer = getUriTransformer(options.remoteAuthority); ++ const startPath = await this.getFirstValidPath([ ++ options.settings.lastVisited, ++ { path: this.args._[0] }, ++ ]); ++ if (!this.servicesPromise) { ++ this.servicesPromise = this.initializeServices(this.args); ++ } ++ await this.servicesPromise; ++ const environment = this.services.get(IEnvironmentService) as IEnvironmentService; ++ return { ++ startPath, ++ workbenchWebConfiguration: { ++ workspaceUri: startPath && startPath.workspace ? transformer.transformOutgoing(URI.file(startPath.path)) : undefined, ++ folderUri: startPath && !startPath.workspace ? transformer.transformOutgoing(URI.file(startPath.path)) : undefined, ++ remoteAuthority: options.remoteAuthority, ++ logLevel: getLogLevel(environment), ++ }, ++ remoteUserDataUri: transformer.transformOutgoing(URI.file(environment.userDataPath)), ++ productConfiguration: { ++ extensionsGallery: product.extensionsGallery, ++ }, ++ nlsConfiguration: await getNlsConfiguration(environment.args.locale || await getLocaleFromConfig(environment.userDataPath), environment.userDataPath), ++ commit: product.commit || '', ++ }; ++ } ++ ++ public async handleWebSocket(socket: net.Socket, query: Query): Promise { ++ if (!query.reconnectionToken) { ++ throw new Error('Reconnection token is missing from query parameters'); ++ } ++ const protocol = new Protocol(socket, { ++ reconnectionToken: query.reconnectionToken, ++ reconnection: query.reconnection === 'true', ++ skipWebSocketFrames: query.skipWebSocketFrames === 'true', ++ }); ++ try { ++ await this.connect(await protocol.handshake(), protocol); ++ } catch (error) { ++ protocol.sendMessage({ type: 'error', reason: error.message }); ++ protocol.dispose(); ++ protocol.getSocket().dispose(); ++ } ++ return true; ++ } ++ ++ /** ++ * Choose the first valid path. If `workspace` is undefined then either a ++ * workspace or a directory are acceptable. Otherwise it must be a file if a ++ * workspace or a directory otherwise. ++ */ ++ private async getFirstValidPath(startPaths: Array): Promise<{ path: string, workspace?: boolean} | undefined> { ++ const cwd = process.env.VSCODE_CWD || process.cwd(); ++ for (let i = 0; i < startPaths.length; ++i) { ++ const startPath = startPaths[i]; ++ if (!startPath) { ++ continue; ++ } ++ const paths = typeof startPath.path === 'string' ? [startPath.path] : (startPath.path || []); ++ for (let j = 0; j < paths.length; ++j) { ++ const p = sanitizeFilePath(paths[j], cwd); ++ try { ++ const stat = await fs.stat(p); ++ if (typeof startPath.workspace === 'undefined' || startPath.workspace !== stat.isDirectory()) { ++ return { path: p, workspace: !stat.isDirectory() }; ++ } ++ } catch (error) { ++ logger.warn(error.message); ++ } ++ } ++ } ++ return undefined; ++ } ++ ++ private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise { ++ if (product.commit && message.commit !== product.commit) { ++ throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`); ++ } ++ ++ switch (message.desiredConnectionType) { ++ case ConnectionType.ExtensionHost: ++ case ConnectionType.Management: ++ if (!this.connections.has(message.desiredConnectionType)) { ++ this.connections.set(message.desiredConnectionType, new Map()); ++ } ++ const connections = this.connections.get(message.desiredConnectionType)!; ++ ++ const ok = async () => { ++ return message.desiredConnectionType === ConnectionType.ExtensionHost ++ ? { debugPort: await this.getDebugPort() } ++ : { type: 'ok' }; ++ }; ++ ++ const token = protocol.options.reconnectionToken; ++ if (protocol.options.reconnection && connections.has(token)) { ++ protocol.sendMessage(await ok()); ++ const buffer = protocol.readEntireBuffer(); ++ protocol.dispose(); ++ return connections.get(token)!.reconnect(protocol.getSocket(), buffer); ++ } else if (protocol.options.reconnection || connections.has(token)) { ++ throw new Error(protocol.options.reconnection ++ ? 'Unrecognized reconnection token' ++ : 'Duplicate reconnection token' ++ ); ++ } ++ ++ protocol.sendMessage(await ok()); ++ ++ let connection: Connection; ++ if (message.desiredConnectionType === ConnectionType.Management) { ++ connection = new ManagementConnection(protocol, token); ++ this._onDidClientConnect.fire({ ++ protocol, onDidClientDisconnect: connection.onClose, ++ }); ++ // TODO: Need a way to match clients with a connection. For now ++ // dispose everything which only works because no extensions currently ++ // utilize long-running proxies. ++ (this.services.get(INodeProxyService) as NodeProxyService)._onUp.fire(); ++ connection.onClose(() => (this.services.get(INodeProxyService) as NodeProxyService)._onDown.fire()); ++ } else { ++ const buffer = protocol.readEntireBuffer(); ++ connection = new ExtensionHostConnection( ++ message.args ? message.args.language : 'en', ++ protocol, buffer, token, ++ this.services.get(ILogService) as ILogService, ++ this.services.get(IEnvironmentService) as IEnvironmentService, ++ ); ++ } ++ connections.set(token, connection); ++ connection.onClose(() => connections.delete(token)); ++ this.disposeOldOfflineConnections(connections); ++ break; ++ case ConnectionType.Tunnel: return protocol.tunnel(); ++ default: throw new Error('Unrecognized connection type'); ++ } ++ } ++ ++ private disposeOldOfflineConnections(connections: Map): void { ++ const offline = Array.from(connections.values()) ++ .filter((connection) => typeof connection.offline !== 'undefined'); ++ for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) { ++ offline[i].dispose(); ++ } ++ } ++ ++ private async initializeServices(args: ParsedArgs): Promise { ++ const environmentService = new EnvironmentService(args, process.execPath); ++ const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService)); ++ const fileService = new FileService(logService); ++ fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(logService)); ++ ++ const piiPaths = [ ++ path.join(environmentService.userDataPath, 'clp'), // Language packs. ++ environmentService.extensionsPath, ++ environmentService.builtinExtensionsPath, ++ ...environmentService.extraExtensionPaths, ++ ...environmentService.extraBuiltinExtensionPaths, ++ ]; ++ ++ this.ipc.registerChannel('logger', new LoggerChannel(logService)); ++ this.ipc.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ExtensionHostDebugBroadcastChannel()); ++ ++ this.services.set(ILogService, logService); ++ this.services.set(IEnvironmentService, environmentService); ++ this.services.set(IConfigurationService, new SyncDescriptor(ConfigurationService, [environmentService.machineSettingsResource])); ++ this.services.set(IRequestService, new SyncDescriptor(RequestService)); ++ this.services.set(IFileService, fileService); ++ this.services.set(IProductService, { _serviceBrand: undefined, ...product }); ++ this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); ++ this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); ++ ++ if (!environmentService.args['disable-telemetry']) { ++ this.services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [{ ++ appender: combinedAppender( ++ new AppInsightsAppender('code-server', null, () => new TelemetryClient() as any, logService), ++ new LogAppender(logService), ++ ), ++ commonProperties: resolveCommonProperties( ++ product.commit, product.version, await getMachineId(), ++ [], environmentService.installSourcePath, 'code-server', ++ ), ++ piiPaths, ++ } as ITelemetryServiceConfig])); ++ } else { ++ this.services.set(ITelemetryService, NullTelemetryService); ++ } ++ ++ await new Promise((resolve) => { ++ const instantiationService = new InstantiationService(this.services); ++ this.services.set(ILocalizationsService, instantiationService.createInstance(LocalizationsService)); ++ this.services.set(INodeProxyService, instantiationService.createInstance(NodeProxyService)); ++ ++ instantiationService.invokeFunction(() => { ++ instantiationService.createInstance(LogsDataCleaner); ++ const telemetryService = this.services.get(ITelemetryService) as ITelemetryService; ++ this.ipc.registerChannel('extensions', new ExtensionManagementChannel( ++ this.services.get(IExtensionManagementService) as IExtensionManagementService, ++ (context) => getUriTransformer(context.remoteAuthority), ++ )); ++ this.ipc.registerChannel('remoteextensionsenvironment', new ExtensionEnvironmentChannel( ++ environmentService, logService, telemetryService, '', ++ )); ++ this.ipc.registerChannel('request', new RequestChannel(this.services.get(IRequestService) as IRequestService)); ++ this.ipc.registerChannel('telemetry', new TelemetryChannel(telemetryService)); ++ this.ipc.registerChannel('nodeProxy', new NodeProxyChannel(this.services.get(INodeProxyService) as INodeProxyService)); ++ this.ipc.registerChannel('localizations', >createChannelReceiver(this.services.get(ILocalizationsService) as ILocalizationsService)); ++ this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); ++ resolve(new ErrorTelemetry(telemetryService)); ++ }); ++ }); ++ } ++ ++ /** ++ * TODO: implement. ++ */ ++ private async getDebugPort(): Promise { ++ return undefined; ++ } ++} +diff --git a/src/vs/server/node/uriTransformer.js b/src/vs/server/node/uriTransformer.js +new file mode 100644 +index 0000000000..fc69441cf0 +--- /dev/null ++++ b/src/vs/server/node/uriTransformer.js +@@ -0,0 +1,24 @@ ++// This file is included via a regular Node require. I'm not sure how (or if) ++// we can write this in Typescript and have it compile to non-AMD syntax. ++module.exports = (remoteAuthority) => { ++ return { ++ transformIncoming: (uri) => { ++ switch (uri.scheme) { ++ case "vscode-remote": return { scheme: "file", path: uri.path }; ++ default: return uri; ++ } ++ }, ++ transformOutgoing: (uri) => { ++ switch (uri.scheme) { ++ case "file": return { scheme: "vscode-remote", authority: remoteAuthority, path: uri.path }; ++ default: return uri; ++ } ++ }, ++ transformOutgoingScheme: (scheme) => { ++ switch (scheme) { ++ case "file": return "vscode-remote"; ++ default: return scheme; ++ } ++ }, ++ }; ++}; +diff --git a/src/vs/server/node/util.ts b/src/vs/server/node/util.ts +new file mode 100644 +index 0000000000..ac950994b9 +--- /dev/null ++++ b/src/vs/server/node/util.ts +@@ -0,0 +1,27 @@ ++import * as path from 'path'; ++import * as os from 'os'; ++import { getPathFromAmdModule } from 'vs/base/common/amd'; ++import { URITransformer, IRawURITransformer } from 'vs/base/common/uriIpc'; ++ ++export const uriTransformerPath = getPathFromAmdModule(require, 'vs/server/node/uriTransformer'); ++export const getUriTransformer = (remoteAuthority: string): URITransformer => { ++ const rawURITransformerFactory = require.__$__nodeRequire(uriTransformerPath); ++ const rawURITransformer = rawURITransformerFactory(remoteAuthority); ++ return new URITransformer(rawURITransformer); ++}; ++ ++const getXdgDataDir = (): string => { ++ switch (process.platform) { ++ case 'win32': ++ return path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), 'AppData/Local'), 'code-server/Data'); ++ case 'darwin': ++ return path.join( ++ process.env.XDG_DATA_HOME || path.join(os.homedir(), 'Library/Application Support'), ++ 'code-server' ++ ); ++ default: ++ return path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local/share'), 'code-server'); ++ } ++}; ++ ++export const xdgLocalDir = getXdgDataDir(); diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts -index 2905c52411..303ddf211f 100644 +index 2905c52411..6ecfae2634 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -57,6 +57,7 @@ import './mainThreadComments'; import './mainThreadTask'; import './mainThreadLabelService'; import 'vs/workbench/api/common/apiCommands'; -+import 'vs/server/src/browser/mainThreadNodeProxy'; ++import 'vs/server/browser/mainThreadNodeProxy'; export class ExtensionPoints implements IWorkbenchContribution { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts -index ea5ad7991f..8d8e99339e 100644 +index ea5ad7991f..e5e0ec0fce 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -67,6 +67,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; -+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy'; ++import { IExtHostNodeProxy } from 'vs/server/browser/extHostNodeProxy'; export interface IExtensionApiFactory { (extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode; @@ -462,7 +2788,7 @@ index 3dab81c9c5..73fc57118a 100644 + ExtHostNodeProxy: createMainId('ExtHostNodeProxy') }; diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts -index a3b5ed0057..f47a97336d 100644 +index a3b5ed0057..679be7f377 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -5,7 +5,7 @@ @@ -478,7 +2804,7 @@ index a3b5ed0057..f47a97336d 100644 import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy'; ++import { IExtHostNodeProxy } from 'vs/server/browser/extHostNodeProxy'; interface ITestRunner { /** Old test runner API, as exported from `vscode/lib/testrunner` */ @@ -490,7 +2816,7 @@ index a3b5ed0057..f47a97336d 100644 protected readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape; protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape; -@@ -104,7 +106,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio +@@ -104,15 +106,18 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio @IExtHostConfiguration extHostConfiguration: IExtHostConfiguration, @ILogService logService: ILogService, @IExtHostInitDataService initData: IExtHostInitDataService, @@ -500,7 +2826,9 @@ index a3b5ed0057..f47a97336d 100644 ) { this._hostUtils = hostUtils; this._extHostContext = extHostContext; -@@ -113,6 +116,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio + this._initData = initData; ++ this._nodeProxy = nodeProxy; + this._extHostWorkspace = extHostWorkspace; this._extHostConfiguration = extHostConfiguration; this._logService = logService; @@ -508,7 +2836,7 @@ index a3b5ed0057..f47a97336d 100644 this._disposables = new DisposableStore(); this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace); -@@ -337,14 +341,14 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio +@@ -337,14 +342,14 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup); return Promise.all([ @@ -526,7 +2854,7 @@ index a3b5ed0057..f47a97336d 100644 private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise { diff --git a/src/vs/workbench/api/node/extHost.services.ts b/src/vs/workbench/api/node/extHost.services.ts -index 9ae085f536..4e3ccca3d3 100644 +index 9ae085f536..2510c86617 100644 --- a/src/vs/workbench/api/node/extHost.services.ts +++ b/src/vs/workbench/api/node/extHost.services.ts @@ -26,6 +26,8 @@ import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionS @@ -534,7 +2862,7 @@ index 9ae085f536..4e3ccca3d3 100644 import { ILogService } from 'vs/platform/log/common/log'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; +import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -+import { IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy'; ++import { IExtHostNodeProxy } from 'vs/server/browser/extHostNodeProxy'; // register singleton services registerSingleton(ILogService, ExtHostLogService); @@ -584,7 +2912,7 @@ index a1c3e50ffd..910627aaf9 100644 throw new Error(`Cannot load URI: '${module}', must be of file-scheme`); } diff --git a/src/vs/workbench/api/node/extHostStoragePaths.ts b/src/vs/workbench/api/node/extHostStoragePaths.ts -index afdd6bf398..ac91318ce3 100644 +index afdd6bf398..604fdd255c 100644 --- a/src/vs/workbench/api/node/extHostStoragePaths.ts +++ b/src/vs/workbench/api/node/extHostStoragePaths.ts @@ -5,13 +5,14 @@ @@ -620,7 +2948,7 @@ index afdd6bf398..ac91318ce3 100644 + // NOTE@coder: Use the file system proxy so this will work in the browser. + // writeFile performs a mkdirp so we don't need to bother ourselves. + const fileSystem = this._extHostRpc.getProxy(MainContext.MainThreadFileSystem); -+ const exists = fileSystem.$stat(URI.file(storagePath)) ++ const exists = fileSystem.$stat(URI.file(storagePath)); if (exists) { return storagePath; @@ -648,7 +2976,7 @@ index afdd6bf398..ac91318ce3 100644 return storagePath; diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts -index 4781f22676..25143a97c0 100644 +index 4781f22676..86c9246f51 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts @@ -9,6 +9,9 @@ import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHost @@ -657,7 +2985,7 @@ index 4781f22676..25143a97c0 100644 import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; +import { joinPath } from 'vs/base/common/resources'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; -+import { loadCommonJSModule } from 'vs/server/src/browser/worker'; ++import { loadCommonJSModule } from 'vs/server/browser/worker'; class WorkerRequireInterceptor extends RequireInterceptor { @@ -687,14 +3015,14 @@ index 4781f22676..25143a97c0 100644 throw new Error(`Cannot load module '${request}'`); } diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts -index 807ac56d8f..a22bd92a82 100644 +index 807ac56d8f..7482c92fd4 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -50,6 +50,7 @@ import { IndexedDBLogProvider } from 'vs/workbench/services/log/browser/indexedD import { InMemoryLogProvider } from 'vs/workbench/services/log/common/inMemoryLogProvider'; import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows'; import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces'; -+import { initialize } from 'vs/server/src/browser/client'; ++import { initialize } from 'vs/server/browser/client'; class BrowserMain extends Disposable { @@ -715,7 +3043,7 @@ index 807ac56d8f..a22bd92a82 100644 if (!this.configuration.userDataProvider) { const remoteUserDataUri = this.getRemoteUserDataUri(); diff --git a/src/vs/workbench/common/resources.ts b/src/vs/workbench/common/resources.ts -index c509716fc4..e416413084 100644 +index c509716fc4..2b4c847d1e 100644 --- a/src/vs/workbench/common/resources.ts +++ b/src/vs/workbench/common/resources.ts @@ -15,6 +15,7 @@ import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob'; @@ -731,7 +3059,7 @@ index c509716fc4..e416413084 100644 if (!ResourceContextKey._uriEquals(this._resourceKey.get(), value)) { this._resourceKey.set(value); - this._schemeKey.set(value ? value.scheme : null); -+ // NOTE@coder: fixes extensions matching against file schemas. ++ // NOTE@coder: Fixes extensions matching against file schemas. + this._schemeKey.set(value ? (value.scheme === Schemas.vscodeRemote ? Schemas.file : value.scheme) : null); this._filenameKey.set(value ? basename(value) : null); this._langIdKey.set(value ? this._modeService.getModeIdByFilepathOrFirstLine(value) : null); @@ -770,7 +3098,7 @@ index f67f9aa064..add754cd5a 100644 const { choice } = await this.show(Severity.Info, this.productService.nameLong, [nls.localize('copy', "Copy"), nls.localize('ok', "OK")], { detail, cancelId: 1 }); diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts -index d54e68fa70..b2c4ea5f6a 100644 +index d54e68fa70..d1cd9c4c1b 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -189,8 +189,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment @@ -784,15 +3112,15 @@ index d54e68fa70..b2c4ea5f6a 100644 } @memoize -@@ -267,6 +267,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment - //#region TODO ENABLE IN WEB +@@ -245,6 +245,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment + installSourcePath!: string; - galleryMachineIdResource?: URI; + builtinExtensionsPath!: string; + extraExtensionPaths!: string[]; + extraBuiltinExtensionPaths!: string[]; - //#endregion - + globalStorageHome!: string; + workspaceStorageHome!: string; diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts index d164f2c127..5a08106f04 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts @@ -806,7 +3134,7 @@ index d164f2c127..5a08106f04 100644 this._checkEnableProposedApi(remoteEnv.extensions); diff --git a/src/vs/workbench/services/extensions/common/extensionsUtil.ts b/src/vs/workbench/services/extensions/common/extensionsUtil.ts -index 75f715cc51..1d6299309d 100644 +index 75f715cc51..4422cfa418 100644 --- a/src/vs/workbench/services/extensions/common/extensionsUtil.ts +++ b/src/vs/workbench/services/extensions/common/extensionsUtil.ts @@ -32,7 +32,8 @@ export function canExecuteOnWorkspace(manifest: IExtensionManifest, productServi @@ -814,7 +3142,7 @@ index 75f715cc51..1d6299309d 100644 export function canExecuteOnWeb(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): boolean { const extensionKind = getExtensionKind(manifest, productService, configurationService); - return extensionKind.some(kind => kind === 'web'); -+ // NOTE@coder: hardcode vim for now. ++ // NOTE@coder: Hardcode vim for now. + return extensionKind.some(kind => kind === 'web') || manifest.name === 'vim'; } @@ -854,7 +3182,7 @@ index 0f35c54431..32fff09b18 100644 } } diff --git a/src/vs/workbench/services/extensions/worker/extHost.services.ts b/src/vs/workbench/services/extensions/worker/extHost.services.ts -index 8a65101aa4..e9c66b3b20 100644 +index 8a65101aa4..1c4923dd6d 100644 --- a/src/vs/workbench/services/extensions/worker/extHost.services.ts +++ b/src/vs/workbench/services/extensions/worker/extHost.services.ts @@ -18,9 +18,10 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa @@ -864,7 +3192,7 @@ index 8a65101aa4..e9c66b3b20 100644 -import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { ExtHostLogService } from 'vs/workbench/api/worker/extHostLogService'; -+import { ExtHostNodeProxy, IExtHostNodeProxy } from 'vs/server/src/browser/extHostNodeProxy'; ++import { ExtHostNodeProxy, IExtHostNodeProxy } from 'vs/server/browser/extHostNodeProxy'; +import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths'; // register singleton services @@ -897,11 +3225,28 @@ index 8a65101aa4..e9c66b3b20 100644 - whenReady = Promise.resolve(); -}); +registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths); +diff --git a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts +index 79455414c0..5ba66b2d83 100644 +--- a/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts ++++ b/src/vs/workbench/services/extensions/worker/extensionHostWorkerMain.ts +@@ -14,7 +14,11 @@ + + require.config({ + baseUrl: monacoBaseUrl, +- catchError: true ++ catchError: true, ++ paths: { ++ '@coder/node-browser': `../../static-{{COMMIT}}/node_modules/@coder/node-browser/out/client/client.js`, ++ '@coder/requirefs': `../../static-{{COMMIT}}/node_modules/@coder/requirefs/out/requirefs.js`, ++ } + }); + + require(['vs/workbench/services/extensions/worker/extensionHostWorker'], () => { }, err => console.error(err)); diff --git a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts -index 99394090da..4891e0fece 100644 +index 99394090da..fa86aef420 100644 --- a/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts +++ b/src/vs/workbench/services/localizations/electron-browser/localizationsService.ts -@@ -5,17 +5,17 @@ +@@ -5,17 +5,18 @@ import { createChannelSender } from 'vs/base/parts/ipc/node/ipc'; import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; @@ -913,6 +3258,7 @@ index 99394090da..4891e0fece 100644 _serviceBrand: undefined; ++ // NOTE@coder: Patched to work in the browser. constructor( - @ISharedProcessService sharedProcessService: ISharedProcessService, + @IRemoteAgentService remoteAgentService: IRemoteAgentService, @@ -922,36 +3268,11 @@ index 99394090da..4891e0fece 100644 } } -diff --git a/src/vs/workbench/services/update/electron-browser/updateService.ts b/src/vs/workbench/services/update/electron-browser/updateService.ts -index b8f6558b2c..b1fe6b14fd 100644 ---- a/src/vs/workbench/services/update/electron-browser/updateService.ts -+++ b/src/vs/workbench/services/update/electron-browser/updateService.ts -@@ -6,7 +6,7 @@ - import { IChannel } from 'vs/base/parts/ipc/common/ipc'; - import { Event, Emitter } from 'vs/base/common/event'; - import { IUpdateService, State } from 'vs/platform/update/common/update'; --import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService'; -+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; - import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; - - export class NativeUpdateService implements IUpdateService { -@@ -21,8 +21,9 @@ export class NativeUpdateService implements IUpdateService { - - private channel: IChannel; - -- constructor(@IMainProcessService mainProcessService: IMainProcessService) { -- this.channel = mainProcessService.getChannel('update'); -+ // NOTE@coder: patched to work in the browser. -+ constructor(@IRemoteAgentService remoteAgentService: IRemoteAgentService) { -+ this.channel = remoteAgentService.getConnection()!.getChannel('update'); - - // always set this._state as the state changes - this.onStateChange(state => this._state = state); diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts -index f424c87d92..af681c3c12 100644 +index f424c87d92..6fb1e4f2ed 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts -@@ -34,11 +34,14 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService'; +@@ -34,7 +34,8 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService'; import 'vs/workbench/services/keybinding/browser/keymapService'; import 'vs/workbench/services/extensions/browser/extensionService'; import 'vs/workbench/services/extensionManagement/common/extensionManagementServerService'; @@ -961,10 +3282,142 @@ index f424c87d92..af681c3c12 100644 import 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; import 'vs/workbench/services/credentials/browser/credentialsService'; import 'vs/workbench/services/url/browser/urlService'; --import 'vs/workbench/services/update/browser/updateService'; -+// NOTE@coder: Use the electron-browser version since it already comes with a -+// channel which lets us actually perform updates. -+import 'vs/workbench/services/update/electron-browser/updateService'; - import 'vs/workbench/contrib/tags/browser/workspaceTagsService'; - import 'vs/workbench/services/workspaces/browser/workspacesService'; - import 'vs/workbench/services/workspaces/browser/workspaceEditingService'; +diff --git a/test/automation/package.json b/test/automation/package.json +index 297dce969b..06e0199c74 100644 +--- a/test/automation/package.json ++++ b/test/automation/package.json +@@ -22,12 +22,12 @@ + "devDependencies": { + "@types/mkdirp": "0.5.1", + "@types/ncp": "2.0.1", +- "@types/node": "8.0.33", ++ "@types/node": "^10.12.12", + "@types/puppeteer": "^1.19.0", + "@types/tmp": "0.1.0", + "concurrently": "^3.5.1", + "cpx": "^1.5.0", +- "typescript": "2.9.2", ++ "typescript": "3.7.2", + "watch": "^1.0.2" + }, + "dependencies": { +diff --git a/test/automation/yarn.lock b/test/automation/yarn.lock +index 94a1350861..d75660c5af 100644 +--- a/test/automation/yarn.lock ++++ b/test/automation/yarn.lock +@@ -21,10 +21,10 @@ + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.1.tgz#3b5c3a26393c19b400844ac422bd0f631a94d69d" + integrity sha512-aK9jxMypeSrhiYofWWBf/T7O+KwaiAHzM4sveCdWPn71lzUSMimRnKzhXDKfKwV1kWoBo2P1aGgaIYGLf9/ljw== + +-"@types/node@8.0.33": +- version "8.0.33" +- resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd" +- integrity sha512-vmCdO8Bm1ExT+FWfC9sd9r4jwqM7o97gGy2WBshkkXbf/2nLAJQUrZfIhw27yVOtLUev6kSZc4cav/46KbDd8A== ++"@types/node@^10.12.12": ++ version "10.17.13" ++ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" ++ integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg== + + "@types/puppeteer@^1.19.0": + version "1.19.1" +@@ -1751,10 +1751,10 @@ typedarray@^0.0.6: + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +-typescript@2.9.2: +- version "2.9.2" +- resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" +- integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== ++typescript@3.7.2: ++ version "3.7.2" ++ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" ++ integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + + union-value@^1.0.0: + version "1.0.1" +diff --git a/test/smoke/package.json b/test/smoke/package.json +index 2ae2926ada..14b0c621ff 100644 +--- a/test/smoke/package.json ++++ b/test/smoke/package.json +@@ -27,7 +27,7 @@ + "rimraf": "^2.6.1", + "strip-json-comments": "^2.0.1", + "tmp": "0.0.33", +- "typescript": "2.9.2", ++ "typescript": "3.7.2", + "watch": "^1.0.2" + } + } +diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock +index 82626a55c7..5d3ee1b69b 100644 +--- a/test/smoke/yarn.lock ++++ b/test/smoke/yarn.lock +@@ -2122,10 +2122,10 @@ tree-kill@^1.1.0: + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36" + integrity sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg== + +-typescript@2.9.2: +- version "2.9.2" +- resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" +- integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== ++typescript@3.7.2: ++ version "3.7.2" ++ resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" ++ integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + + union-value@^1.0.0: + version "1.0.1" +diff --git a/yarn.lock b/yarn.lock +index edbbc9743d..fabb9c1491 100644 +--- a/yarn.lock ++++ b/yarn.lock +@@ -95,6 +95,23 @@ + lodash "^4.17.11" + to-fast-properties "^2.0.0" + ++"@coder/logger@^1.1.11": ++ version "1.1.11" ++ resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.11.tgz#e6f36dba9436ae61e66e3f66787d75c768617605" ++ integrity sha512-EEh1dqSU0AaqjjjMsVqumgZGbrZimKFKIb4t5E6o3FLfVUxJCReSME78Yj2N1xWUVAHMnqafDCxLostpuIotzw== ++ ++"@coder/node-browser@^1.0.8": ++ version "1.0.8" ++ resolved "https://registry.yarnpkg.com/@coder/node-browser/-/node-browser-1.0.8.tgz#c22f581b089ad7d95ad1362fd351c57b7fbc6e70" ++ integrity sha512-NLF9sYMRCN9WK1C224pHax1Cay3qKypg25BhVg7VfNbo3Cpa3daata8RF/rT8JK3lPsu8PmFgDRQjzGC9X1Lrw== ++ ++"@coder/requirefs@^1.0.6": ++ version "1.0.6" ++ resolved "https://registry.yarnpkg.com/@coder/requirefs/-/requirefs-1.0.6.tgz#d2d9b529d55e00da5b779aba0ac37c534a9fe55c" ++ integrity sha512-AEHfWXXJV1FGB0CjTVz+BhyS9G5xUlC0L1+/jDgGE9CuKK2obZzg3xdALFXadZhcpQGa2vXFEmrtkkW2xP6X2A== ++ optionalDependencies: ++ jszip "2.6.0" ++ + "@types/applicationinsights@0.20.0": + version "0.20.0" + resolved "https://registry.yarnpkg.com/@types/applicationinsights/-/applicationinsights-0.20.0.tgz#fa7b36dc954f635fa9037cad27c378446b1048fb" +@@ -4943,6 +4960,13 @@ jsprim@^1.2.2: + json-schema "0.2.3" + verror "1.10.0" + ++jszip@2.6.0: ++ version "2.6.0" ++ resolved "https://registry.yarnpkg.com/jszip/-/jszip-2.6.0.tgz#7fb3e9c2f11c8a9840612db5dabbc8cf3a7534b7" ++ integrity sha1-f7PpwvEciphAYS212rvIzzp1NLc= ++ dependencies: ++ pako "~1.0.0" ++ + just-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" +@@ -6248,6 +6272,11 @@ p-try@^2.0.0: + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" + integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + ++pako@~1.0.0: ++ version "1.0.10" ++ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" ++ integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== ++ + pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" diff --git a/src/browser/api.ts b/src/browser/api.ts index cbc077ce..390dd744 100644 --- a/src/browser/api.ts +++ b/src/browser/api.ts @@ -1,369 +1,82 @@ -import * as vscode from "vscode"; -import { CoderApi, VSCodeApi } from "../../typings/api"; -import { createCSSRule } from "vs/base/browser/dom"; -import { Emitter, Event } from "vs/base/common/event"; -import { IDisposable } from "vs/base/common/lifecycle"; -import { URI } from "vs/base/common/uri"; -import { generateUuid } from "vs/base/common/uuid"; -import { localize } from "vs/nls"; -import { SyncActionDescriptor } from "vs/platform/actions/common/actions"; -import { CommandsRegistry, ICommandService } from "vs/platform/commands/common/commands"; -import { IConfigurationService } from "vs/platform/configuration/common/configuration"; -import { IContextMenuService } from "vs/platform/contextview/browser/contextView"; -import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions } from "vs/platform/files/common/files"; -import { IInstantiationService, ServiceIdentifier } from "vs/platform/instantiation/common/instantiation"; -import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; -import { INotificationService } from "vs/platform/notification/common/notification"; -import { Registry } from "vs/platform/registry/common/platform"; -import { IStatusbarEntry, IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from "vs/workbench/services/statusbar/common/statusbar"; -import { IStorageService } from "vs/platform/storage/common/storage"; -import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { IThemeService } from "vs/platform/theme/common/themeService"; -import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace"; -import * as extHostTypes from "vs/workbench/api/common/extHostTypes"; -import { CustomTreeView, CustomTreeViewPane } from "vs/workbench/browser/parts/views/customView"; -import { ViewContainerViewlet } from "vs/workbench/browser/parts/views/viewsViewlet"; -import { Extensions as ViewletExtensions, ShowViewletAction, ViewletDescriptor, ViewletRegistry } from "vs/workbench/browser/viewlet"; -import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from "vs/workbench/common/actions"; -import { Extensions as ViewsExtensions, ITreeItem, ITreeViewDataProvider, ITreeViewDescriptor, IViewContainersRegistry, IViewsRegistry, TreeItemCollapsibleState } from "vs/workbench/common/views"; -import { IEditorGroupsService } from "vs/workbench/services/editor/common/editorGroupsService"; -import { IEditorService } from "vs/workbench/services/editor/common/editorService"; -import { IExtensionService } from "vs/workbench/services/extensions/common/extensions"; -import { IWorkbenchLayoutService } from "vs/workbench/services/layout/browser/layoutService"; -import { IViewletService } from "vs/workbench/services/viewlet/browser/viewlet"; +import { Application, ApplicationsResponse, CreateSessionResponse, FilesResponse, RecentResponse } from "../common/api" +import { ApiEndpoint, HttpCode, HttpError } from "../common/http" + +export interface AuthBody { + password: string +} /** - * Client-side implementation of VS Code's API. - * TODO: Views aren't quite working. - * TODO: Implement menu items for views (for item actions). - * TODO: File system provider doesn't work. + * Set authenticated status. */ -export const vscodeApi = (serviceCollection: ServiceCollection): VSCodeApi => { - const getService = (id: ServiceIdentifier): T => serviceCollection.get(id) as T; - const commandService = getService(ICommandService); - const notificationService = getService(INotificationService); - const fileService = getService(IFileService); - const viewsRegistry = Registry.as(ViewsExtensions.ViewsRegistry); - const statusbarService = getService(IStatusbarService); - - // It would be nice to just export what VS Code creates but it looks to me - // that it assumes it's running in the extension host and wouldn't work here. - // It is probably possible to create an extension host that runs in the - // browser's main thread, but I'm not sure how much jank that would require. - // We could have a web worker host but we want DOM access. - return { - EventEmitter: Emitter, // It can take T so T | undefined should work. - FileSystemError: extHostTypes.FileSystemError, - FileType, - StatusBarAlignment: extHostTypes.StatusBarAlignment, - ThemeColor: extHostTypes.ThemeColor, - TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState, - Uri: URI, - commands: { - executeCommand: (commandId: string, ...args: any[]): Promise => { - return commandService.executeCommand(commandId, ...args); - }, - registerCommand: (id: string, command: (...args: any[]) => any): IDisposable => { - return CommandsRegistry.registerCommand(id, command); - }, - }, - window: { - createStatusBarItem(alignmentOrOptions?: extHostTypes.StatusBarAlignment | vscode.window.StatusBarItemOptions, priority?: number): StatusBarEntry { - return new StatusBarEntry(statusbarService, alignmentOrOptions, priority); - }, - registerTreeDataProvider: (id: string, dataProvider: vscode.TreeDataProvider): IDisposable => { - const tree = new TreeViewDataProvider(dataProvider); - const view = viewsRegistry.getView(id); - (view as ITreeViewDescriptor).treeView.dataProvider = tree; - return { - dispose: () => tree.dispose(), - }; - }, - showErrorMessage: async (message: string): Promise => { - notificationService.error(message); - return undefined; - }, - }, - workspace: { - registerFileSystemProvider: (scheme: string, provider: vscode.FileSystemProvider): IDisposable => { - return fileService.registerProvider(scheme, new FileSystemProvider(provider)); - }, - }, - }; -}; +export function setAuthed(authed: boolean): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(window as any).setAuthed(authed) +} /** - * Coder API. This should only provide functionality that can't be made - * available through the VS Code API. + * Try making a request. Throw an error if the request is anything except OK. + * Also set authed to false if the request returns unauthorized. */ -export const coderApi = (serviceCollection: ServiceCollection): CoderApi => { - const getService = (id: ServiceIdentifier): T => serviceCollection.get(id) as T; - return { - registerView: (viewId, viewName, containerId, containerName, icon): void => { - const cssClass = `extensionViewlet-${containerId}`; - const id = `workbench.view.extension.${containerId}`; - class CustomViewlet extends ViewContainerViewlet { - public constructor( - @IConfigurationService configurationService: IConfigurationService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - @ITelemetryService telemetryService: ITelemetryService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @IStorageService storageService: IStorageService, - @IEditorService _editorService: IEditorService, - @IInstantiationService instantiationService: IInstantiationService, - @IThemeService themeService: IThemeService, - @IContextMenuService contextMenuService: IContextMenuService, - @IExtensionService extensionService: IExtensionService, - ) { - super(id, `${id}.state`, true, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService); - } - } - - Registry.as(ViewletExtensions.Viewlets).registerViewlet( - ViewletDescriptor.create(CustomViewlet as any, id, containerName, cssClass, undefined, URI.parse(icon)), - ); - - Registry.as(ActionExtensions.WorkbenchActions).registerWorkbenchAction( - SyncActionDescriptor.create(OpenCustomViewletAction as any, id, localize("showViewlet", "Show {0}", containerName)), - "View: Show {0}", - localize("view", "View"), - ); - - // Generate CSS to show the icon in the activity bar. - const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`; - createCSSRule(iconClass, `-webkit-mask: url('${icon}') no-repeat 50% 50%`); - - const container = Registry.as(ViewsExtensions.ViewContainersRegistry).registerViewContainer(containerId); - Registry.as(ViewsExtensions.ViewsRegistry).registerViews([{ - id: viewId, - name: viewName, - ctorDescriptor: { ctor: CustomTreeViewPane }, - treeView: getService(IInstantiationService).createInstance(CustomTreeView as any, viewId, container), - }] as ITreeViewDescriptor[], container); - }, - }; -}; - -class OpenCustomViewletAction extends ShowViewletAction { - public constructor( - id: string, label: string, - @IViewletService viewletService: IViewletService, - @IEditorGroupsService editorGroupService: IEditorGroupsService, - @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, - ) { - super(id, label, id, viewletService, editorGroupService, layoutService); - } +const tryRequest = async (endpoint: string, options?: RequestInit): Promise => { + const response = await fetch("/api" + endpoint + "/", options) + if (response.status === HttpCode.Unauthorized) { + setAuthed(false) + } + if (response.status !== HttpCode.Ok) { + const text = await response.text() + throw new HttpError(text || response.statusText || "unknown error", response.status) + } + return response } -class FileSystemProvider implements IFileSystemProvider { - private readonly _onDidChange = new Emitter(); - - public readonly onDidChangeFile: Event = this._onDidChange.event; - - public readonly capabilities: FileSystemProviderCapabilities; - public readonly onDidChangeCapabilities: Event = Event.None; - - public constructor(private readonly provider: vscode.FileSystemProvider) { - this.capabilities = FileSystemProviderCapabilities.Readonly; - } - - public watch(resource: URI, opts: IWatchOptions): IDisposable { - return this.provider.watch(resource, opts); - } - - public async stat(resource: URI): Promise { - return this.provider.stat(resource); - } - - public async readFile(resource: URI): Promise { - return this.provider.readFile(resource); - } - - public async writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise { - return this.provider.writeFile(resource, content, opts); - } - - public async delete(resource: URI, opts: FileDeleteOptions): Promise { - return this.provider.delete(resource, opts); - } - - public mkdir(_resource: URI): Promise { - throw new Error("not implemented"); - } - - public async readdir(resource: URI): Promise<[string, FileType][]> { - return this.provider.readDirectory(resource); - } - - public async rename(resource: URI, target: URI, opts: FileOverwriteOptions): Promise { - return this.provider.rename(resource, target, opts); - } - - public async copy(resource: URI, target: URI, opts: FileOverwriteOptions): Promise { - return this.provider.copy!(resource, target, opts); - } - - public open(_resource: URI, _opts: FileOpenOptions): Promise { - throw new Error("not implemented"); - } - - public close(_fd: number): Promise { - throw new Error("not implemented"); - } - - public read(_fd: number, _pos: number, _data: Uint8Array, _offset: number, _length: number): Promise { - throw new Error("not implemented"); - } - - public write(_fd: number, _pos: number, _data: Uint8Array, _offset: number, _length: number): Promise { - throw new Error("not implemented"); - } +/** + * Try authenticating. + */ +export const authenticate = async (body?: AuthBody): Promise => { + let formBody: URLSearchParams | undefined + if (body) { + formBody = new URLSearchParams() + formBody.append("password", body.password) + } + const response = await tryRequest(ApiEndpoint.login, { + method: "POST", + body: formBody, + headers: { + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + }, + }) + const json = await response.json() + if (json && json.success) { + setAuthed(true) + } } -class TreeViewDataProvider implements ITreeViewDataProvider { - private readonly root = Symbol("root"); - private readonly values = new Map(); - private readonly children = new Map(); - - public constructor(private readonly provider: vscode.TreeDataProvider) {} - - public async getChildren(item?: ITreeItem): Promise { - const value = item && this.itemToValue(item); - const children = await Promise.all( - (await this.provider.getChildren(value) || []) - .map(async (childValue) => { - const treeItem = await this.provider.getTreeItem(childValue); - const handle = this.createHandle(treeItem); - this.values.set(handle, childValue); - return { - handle, - collapsibleState: TreeItemCollapsibleState.Collapsed, - }; - }) - ); - - this.clear(value || this.root, item); - this.children.set(value || this.root, children); - - return children; - } - - public dispose(): void { - throw new Error("not implemented"); - } - - private itemToValue(item: ITreeItem): T { - if (!this.values.has(item.handle)) { - throw new Error(`No element found with handle ${item.handle}`); - } - return this.values.get(item.handle)!; - } - - private clear(value: T | Symbol, item?: ITreeItem): void { - if (this.children.has(value)) { - this.children.get(value)!.map((c) => this.clear(this.itemToValue(c), c)); - this.children.delete(value); - } - if (item) { - this.values.delete(item.handle); - } - } - - private createHandle(item: vscode.TreeItem): string { - return item.id - ? `coder-tree-item-id/${item.id}` - : `coder-tree-item-uuid/${generateUuid()}`; - } +export const getFiles = async (): Promise => { + const response = await tryRequest(ApiEndpoint.files) + return response.json() } -interface IStatusBarEntry extends IStatusbarEntry { - alignment: StatusbarAlignment; - priority?: number; +export const getRecent = async (): Promise => { + const response = await tryRequest(ApiEndpoint.recent) + return response.json() } -class StatusBarEntry implements vscode.StatusBarItem { - private static ID = 0; - - private _id: number; - private entry: IStatusBarEntry; - private visible?: boolean; - private disposed?: boolean; - private statusId: string; - private statusName: string; - private accessor?: IStatusbarEntryAccessor; - private timeout: any; - - constructor(private readonly statusbarService: IStatusbarService, alignmentOrOptions?: extHostTypes.StatusBarAlignment | vscode.window.StatusBarItemOptions, priority?: number) { - this._id = StatusBarEntry.ID--; - if (alignmentOrOptions && typeof alignmentOrOptions !== "number") { - this.statusId = alignmentOrOptions.id; - this.statusName = alignmentOrOptions.name; - this.entry = { - alignment: alignmentOrOptions.alignment === extHostTypes.StatusBarAlignment.Right - ? StatusbarAlignment.RIGHT : StatusbarAlignment.LEFT, - priority, - text: "", - }; - } else { - this.statusId = "web-api"; - this.statusName = "Web API"; - this.entry = { - alignment: alignmentOrOptions === extHostTypes.StatusBarAlignment.Right - ? StatusbarAlignment.RIGHT : StatusbarAlignment.LEFT, - priority, - text: "", - }; - } - } - - public get alignment(): extHostTypes.StatusBarAlignment { - return this.entry.alignment === StatusbarAlignment.RIGHT - ? extHostTypes.StatusBarAlignment.Right : extHostTypes.StatusBarAlignment.Left; - } - - public get id(): number { return this._id; } - public get priority(): number | undefined { return this.entry.priority; } - public get text(): string { return this.entry.text; } - public get tooltip(): string | undefined { return this.entry.tooltip; } - public get color(): string | extHostTypes.ThemeColor | undefined { return this.entry.color; } - public get command(): string | undefined { return this.entry.command; } - - public set text(text: string) { this.update({ text }); } - public set tooltip(tooltip: string | undefined) { this.update({ tooltip }); } - public set color(color: string | extHostTypes.ThemeColor | undefined) { this.update({ color }); } - public set command(command: string | undefined) { this.update({ command }); } - - public show(): void { - this.visible = true; - this.update(); - } - - public hide(): void { - clearTimeout(this.timeout); - this.visible = false; - if (this.accessor) { - this.accessor.dispose(); - this.accessor = undefined; - } - } - - private update(values?: Partial): void { - this.entry = { ...this.entry, ...values }; - if (this.disposed || !this.visible) { - return; - } - clearTimeout(this.timeout); - this.timeout = setTimeout(() => { - if (!this.accessor) { - this.accessor = this.statusbarService.addEntry(this.entry, this.statusId, this.statusName, this.entry.alignment, this.priority); - } else { - this.accessor.update(this.entry); - } - }, 0); - } - - public dispose(): void { - this.hide(); - this.disposed = true; - } +export const getApplications = async (): Promise => { + const response = await tryRequest(ApiEndpoint.applications) + return response.json() +} + +export const getSession = async (app: Application): Promise => { + const response = await tryRequest(ApiEndpoint.session, { + method: "POST", + body: JSON.stringify(app), + }) + return response.json() +} + +export const killSession = async (app: Application): Promise => { + return tryRequest(ApiEndpoint.session, { + method: "DELETE", + body: JSON.stringify(app), + }) } diff --git a/src/browser/app.css b/src/browser/app.css new file mode 100644 index 00000000..6819ea42 --- /dev/null +++ b/src/browser/app.css @@ -0,0 +1,18 @@ +html, +body, +#root, +iframe { + height: 100%; + width: 100%; +} + +iframe { + border: none; +} + +body { + background: #272727; + margin: 0; + font-family: 'IBM Plex Sans', sans-serif; + overflow: hidden; +} diff --git a/src/browser/app.tsx b/src/browser/app.tsx new file mode 100644 index 00000000..04201995 --- /dev/null +++ b/src/browser/app.tsx @@ -0,0 +1,37 @@ +import * as React from "react" +import { Application } from "../common/api" +import { Route, Switch } from "react-router-dom" +import { HttpError } from "../common/http" +import { Modal } from "./components/modal" +import { getOptions } from "../common/util" + +const App: React.FunctionComponent = () => { + const [authed, setAuthed] = React.useState(false) + const [app, setApp] = React.useState() + const [error, setError] = React.useState() + + React.useEffect(() => { + getOptions() + }, []) + + if (typeof window !== "undefined") { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(window as any).setAuthed = setAuthed + } + + return ( + <> + + } /> + ( + + )} + /> + + + ) +} + +export default App diff --git a/src/browser/client.ts b/src/browser/client.ts deleted file mode 100644 index 80765466..00000000 --- a/src/browser/client.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Emitter } from "vs/base/common/event"; -import { URI } from "vs/base/common/uri"; -import { localize } from "vs/nls"; -import { Extensions, IConfigurationRegistry } from "vs/platform/configuration/common/configurationRegistry"; -import { registerSingleton } from "vs/platform/instantiation/common/extensions"; -import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; -import { ILocalizationsService } from "vs/platform/localizations/common/localizations"; -import { INotificationService, Severity } from "vs/platform/notification/common/notification"; -import { Registry } from "vs/platform/registry/common/platform"; -import { PersistentConnectionEventType } from "vs/platform/remote/common/remoteAgentConnection"; -import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { coderApi, vscodeApi } from "vs/server/src/browser/api"; -import { INodeProxyService, NodeProxyChannelClient } from "vs/server/src/common/nodeProxy"; -import { TelemetryChannelClient } from "vs/server/src/common/telemetry"; -import { split } from "vs/server/src/common/util"; -import "vs/workbench/contrib/localizations/browser/localizations.contribution"; -import { LocalizationsService } from "vs/workbench/services/localizations/electron-browser/localizationsService"; -import { IRemoteAgentService } from "vs/workbench/services/remote/common/remoteAgentService"; - -class TelemetryService extends TelemetryChannelClient { - public constructor( - @IRemoteAgentService remoteAgentService: IRemoteAgentService, - ) { - super(remoteAgentService.getConnection()!.getChannel("telemetry")); - } -} - -const TELEMETRY_SECTION_ID = "telemetry"; - -Registry.as(Extensions.Configuration).registerConfiguration({ - "id": TELEMETRY_SECTION_ID, - "order": 110, - "type": "object", - "title": localize("telemetryConfigurationTitle", "Telemetry"), - "properties": { - "telemetry.enableTelemetry": { - "type": "boolean", - "description": localize("telemetry.enableTelemetry", "Enable usage data and errors to be sent to a Microsoft online service."), - "default": true, - "tags": ["usesOnlineServices"] - } - } -}); - -class NodeProxyService extends NodeProxyChannelClient implements INodeProxyService { - private readonly _onClose = new Emitter(); - public readonly onClose = this._onClose.event; - private readonly _onDown = new Emitter(); - public readonly onDown = this._onDown.event; - private readonly _onUp = new Emitter(); - public readonly onUp = this._onUp.event; - - public constructor( - @IRemoteAgentService remoteAgentService: IRemoteAgentService, - ) { - super(remoteAgentService.getConnection()!.getChannel("nodeProxy")); - remoteAgentService.getConnection()!.onDidStateChange((state) => { - switch (state.type) { - case PersistentConnectionEventType.ConnectionGain: - return this._onUp.fire(); - case PersistentConnectionEventType.ConnectionLost: - return this._onDown.fire(); - case PersistentConnectionEventType.ReconnectionPermanentFailure: - return this._onClose.fire(); - } - }); - } -} - -registerSingleton(ILocalizationsService, LocalizationsService); -registerSingleton(INodeProxyService, NodeProxyService); -registerSingleton(ITelemetryService, TelemetryService); - -/** - * This is called by vs/workbench/browser/web.main.ts after the workbench has - * been initialized so we can initialize our own client-side code. - */ -export const initialize = async (services: ServiceCollection): Promise => { - const target = window as any; - target.ide = coderApi(services); - target.vscode = vscodeApi(services); - - const event = new CustomEvent("ide-ready"); - (event as any).ide = target.ide; - (event as any).vscode = target.vscode; - window.dispatchEvent(event); - - if (!window.isSecureContext) { - (services.get(INotificationService) as INotificationService).notify({ - severity: Severity.Warning, - message: "code-server is being accessed over an insecure domain. Some functionality may not work as expected.", - actions: { - primary: [{ - id: "understand", - label: "I understand", - tooltip: "", - class: undefined, - enabled: true, - checked: true, - dispose: () => undefined, - run: () => { - return Promise.resolve(); - } - }], - } - }); - } -}; - -export interface Query { - [key: string]: string | undefined; -} - -/** - * Return the URL modified with the specified query variables. It's pretty - * stupid so it probably doesn't cover any edge cases. Undefined values will - * unset existing values. Doesn't allow duplicates. - */ -export const withQuery = (url: string, replace: Query): string => { - const uri = URI.parse(url); - const query = { ...replace }; - uri.query.split("&").forEach((kv) => { - const [key, value] = split(kv, "="); - if (!(key in query)) { - query[key] = value; - } - }); - return uri.with({ - query: Object.keys(query) - .filter((k) => typeof query[k] !== "undefined") - .map((k) => `${k}=${query[k]}`).join("&"), - }).toString(true); -}; diff --git a/src/browser/components/animate.tsx b/src/browser/components/animate.tsx new file mode 100644 index 00000000..50a58846 --- /dev/null +++ b/src/browser/components/animate.tsx @@ -0,0 +1,27 @@ +import * as React from "react" + +export interface DelayProps { + readonly show: boolean + readonly delay: number +} + +export const Animate: React.FunctionComponent = (props) => { + const [timer, setTimer] = React.useState() + const [mount, setMount] = React.useState(false) + const [visible, setVisible] = React.useState(false) + + React.useEffect(() => { + if (timer) { + clearTimeout(timer) + } + if (!props.show) { + setVisible(false) + setTimer(setTimeout(() => setMount(false), props.delay)) + } else { + setTimer(setTimeout(() => setVisible(true), props.delay)) + setMount(true) + } + }, [props]) + + return mount ?
{props.children}
: null +} diff --git a/src/browser/components/error.css b/src/browser/components/error.css new file mode 100644 index 00000000..81a1a763 --- /dev/null +++ b/src/browser/components/error.css @@ -0,0 +1,28 @@ +.field-error { + color: red; +} + +.request-error { + align-items: center; + color: rgba(0, 0, 0, 0.37); + display: flex; + flex: 1; + flex-direction: column; + font-weight: 700; + justify-content: center; + padding: 20px; + text-transform: uppercase; +} + +.request-error > .close { + background: transparent; + border: none; + color: #b6b6b6; + cursor: pointer; + margin-top: 10px; + width: 100%; +} + +.request-error + .request-error { + border-top: 1px solid #b6b6b6; +} diff --git a/src/browser/components/error.tsx b/src/browser/components/error.tsx new file mode 100644 index 00000000..1fbf14fa --- /dev/null +++ b/src/browser/components/error.tsx @@ -0,0 +1,48 @@ +import * as React from "react" +import { HttpError } from "../../common/http" + +export interface ErrorProps { + error: HttpError | Error | string + onClose?: () => void +} + +/** + * An error to be displayed in a section where a request has failed. + */ +export const RequestError: React.FunctionComponent = (props) => { + return ( +
+
{typeof props.error === "string" ? props.error : props.error.message}
+ {props.onClose ? ( + + ) : ( + undefined + )} +
+ ) +} + +/** + * Return a more human/natural/useful message for some error codes resulting + * from a form submission. + */ +const humanizeFormError = (error: HttpError | Error | string): string => { + if (typeof error === "string") { + return error + } + switch ((error as HttpError).code) { + case 401: + return "Wrong password" + default: + return error.message + } +} + +/** + * An error to be displayed underneath a field. + */ +export const FieldError: React.FunctionComponent = (props) => { + return
{humanizeFormError(props.error)}
+} diff --git a/src/browser/components/list.css b/src/browser/components/list.css new file mode 100644 index 00000000..3b6eea80 --- /dev/null +++ b/src/browser/components/list.css @@ -0,0 +1,108 @@ +.app-list { + list-style-type: none; + padding: 0; + margin: 0 -10px; /* To counter app padding. */ + flex: 1; +} + +.app-loader { + align-items: center; + color: #b6b6b6; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; +} + +.app-loader > .loader { + color: #b6b6b6; +} + +.app-row { + color: #b6b6b6; + cursor: pointer; + display: flex; + font-size: 1em; + line-height: 1em; + width: 100%; +} + +.app-row > .launch, +.app-row > .kill { + background-color: transparent; + border: none; + color: inherit; + cursor: pointer; + font-size: 1em; + line-height: 1em; + margin: 1px 0; + padding: 3px 10px; +} + +.app-row > .launch { + border-radius: 50px; + display: flex; + flex: 1; +} + +.app-row > .launch:hover, +.app-row > .kill:hover { + color: #000; +} + +.app-row .icon { + height: 1em; + margin-right: 5px; + width: 1em; +} + +.app-row .icon.-missing { + background-color: #eee; + color: #b6b6b6; + text-align: center; +} + +.app-row .icon.-missing::after { + content: "?"; + font-size: 0.7em; + vertical-align: middle; +} + +.app-row.-selected { + background-color: #bcc6fa; +} + +.app-loader > .opening { + margin-bottom: 10px; +} + +.app-loader > .app-row { + color: #000; + justify-content: center; +} + +.app-loader > .cancel { + background: transparent; + border: none; + color: #b6b6b6; + cursor: pointer; + margin-top: 10px; + width: 100%; +} + +.app-list + .app-list { + border-top: 1px solid #b6b6b6; + margin-top: 1em; + padding-top: 1em; +} + +.app-list > .header { + color: #b6b6b6; + font-size: 1em; + margin-bottom: 1em; + margin-top: 0; +} + +.app-list > .loader { + color: #b6b6b6; +} diff --git a/src/browser/components/list.tsx b/src/browser/components/list.tsx new file mode 100644 index 00000000..0266a865 --- /dev/null +++ b/src/browser/components/list.tsx @@ -0,0 +1,169 @@ +import * as React from "react" +import { Application, isExecutableApplication, isRunningApplication } from "../../common/api" +import { HttpError } from "../../common/http" +import { getSession, killSession } from "../api" +import { RequestError } from "../components/error" + +export const AppDetails: React.FunctionComponent = (props) => { + return ( + <> + {props.icon ? ( + + ) : ( +
+ )} +
{props.name}
+ + ) +} + +export interface AppRowProps { + readonly app: Application + onKilled(app: Application): void + open(app: Application): void +} + +export const AppRow: React.FunctionComponent = (props) => { + const [killing, setKilling] = React.useState(false) + const [error, setError] = React.useState() + + function kill(): void { + if (isRunningApplication(props.app)) { + setKilling(true) + killSession(props.app) + .then(() => { + setKilling(false) + props.onKilled(props.app) + }) + .catch((error) => { + setError(error) + setKilling(false) + }) + } + } + + return ( +
+ + {isRunningApplication(props.app) && !killing ? ( + + ) : ( + undefined + )} +
+ ) +} + +export interface AppListProps { + readonly header: string + readonly apps?: ReadonlyArray + open(app: Application): void + onKilled(app: Application): void +} + +export const AppList: React.FunctionComponent = (props) => { + return ( +
+

{props.header}

+ {props.apps && props.apps.length > 0 ? ( + props.apps.map((app, i) => ) + ) : props.apps ? ( + + ) : ( +
loading...
+ )} +
+ ) +} + +export interface ApplicationSection { + readonly apps?: ReadonlyArray + readonly header: string +} + +export interface AppLoaderProps { + readonly app?: Application + setApp(app?: Application): void + getApps(): Promise> +} + +/** + * Display provided applications or sessions and allow opening them. + */ +export const AppLoader: React.FunctionComponent = (props) => { + const [apps, setApps] = React.useState>() + const [error, setError] = React.useState() + + const refresh = (): void => { + props + .getApps() + .then(setApps) + .catch((e) => setError(e.message)) + } + + React.useEffect(() => { + refresh() + }, [props]) + + function open(app: Application): void { + props.setApp(app) + if (!isRunningApplication(app) && isExecutableApplication(app)) { + getSession(app) + .then((session) => { + props.setApp({ ...app, ...session }) + }) + .catch(setError) + } + } + + if (error) { + props.setApp(undefined) + return ( + { + setError(undefined) + }} + /> + ) + } + + if (props.app && !props.app.loaded) { + return ( +
+
Opening
+
+ +
+ +
+ ) + } + + if (!apps) { + return ( +
+
loading
+
+ ) + } + + return ( + <> + {apps.map((section, i) => ( + + ))} + + ) +} diff --git a/src/browser/components/modal.css b/src/browser/components/modal.css new file mode 100644 index 00000000..60bcc343 --- /dev/null +++ b/src/browser/components/modal.css @@ -0,0 +1,147 @@ +.modal-bar { + box-sizing: border-box; + display: flex; + justify-content: center; + left: 0; + padding: 20px; + position: fixed; + pointer-events: none; + top: 0; + width: 100%; + z-index: 30; +} + +.animate > .modal-bar { + transform: translateY(-100%); + transition: transform 200ms; +} + +.animate.-show > .modal-bar { + transform: translateY(0); +} + +.modal-bar > .bar { + background-color: #fcfcfc; + border-radius: 5px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); + box-sizing: border-box; + color: #101010; + display: flex; + font-size: 0.8em; + max-width: 400px; + padding: 20px; + pointer-events: initial; + position: relative; +} + +.modal-bar > .bar > .content { + display: flex; + flex-direction: column; + flex: 1; + justify-content: center; + padding-right: 20px; +} + +.modal-bar > .bar > .open { + display: flex; + flex-direction: column; + justify-content: center; +} + +.modal-bar > .bar > .close { + background-color: transparent; + border: none; + color: #b6b6b6; + cursor: pointer; + position: absolute; + right: 1px; + top: 1px; +} + +.modal-bar > .bar > .open > .button { + background-color: transparent; + border-radius: 5px; + border: 1px solid #101010; + color: #101010; + cursor: pointer; + padding: 1em; +} + +.modal-bar > .bar > .open > .button:hover { + background-color: #bcc6fa; +} + +.modal-container { + align-items: center; + background: rgba(0, 0, 0, 0.1); + box-sizing: border-box; + display: flex; + height: 100%; + justify-content: center; + left: 0; + padding: 20px; + position: fixed; + top: 0; + width: 100%; + z-index: 9999999; +} + +.modal-container > .modal { + background: #fcfcfc; + border-radius: 10px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); + display: flex; + flex-direction: row; + height: 100%; + max-height: 400px; + max-width: 664px; + padding: 20px 0; + position: relative; + width: 100%; +} + +.modal-container > .modal > .sidebar { + border-right: 1.5px solid rgba(0, 0, 0, 0.37); + display: flex; + flex-direction: column; + justify-content: space-between; +} + +.modal-container > .modal > .sidebar > .links { + display: flex; + flex-direction: column; +} + +.modal-container > .modal > .sidebar > .links > .link { + color: rgba(0, 0, 0, 0.37); + font-size: 1.4em; + height: 31px; + margin-bottom: 20px; + padding: 0 35px; + text-decoration: none; + transition: 150ms color ease, 150ms height ease, 150ms margin-bottom ease; +} + +.modal-container > .modal > .sidebar > .footer > .close { + background: transparent; + border: none; + color: #b6b6b6; + cursor: pointer; + width: 100%; +} + +.modal-container > .modal > .sidebar > .footer > .close:hover { + color: #000; +} + +.modal-container > .modal > .links > .link[aria-current="page"] { + color: rgba(0, 0, 0, 1); +} + +.modal-container > .modal > .content { + display: flex; + flex: 1; + flex-direction: column; + overflow: auto; + padding: 0 20px; +} diff --git a/src/browser/components/modal.tsx b/src/browser/components/modal.tsx new file mode 100644 index 00000000..7b4df2c0 --- /dev/null +++ b/src/browser/components/modal.tsx @@ -0,0 +1,192 @@ +import { logger } from "@coder/logger" +import * as React from "react" +import { NavLink, Route, RouteComponentProps, Switch } from "react-router-dom" +import { Application, isExecutableApplication } from "../../common/api" +import { HttpError } from "../../common/http" +import { RequestError } from "../components/error" +import { Browse } from "../pages/browse" +import { Home } from "../pages/home" +import { Login } from "../pages/login" +import { Open } from "../pages/open" +import { Recent } from "../pages/recent" +import { Animate } from "./animate" + +export interface ModalProps { + app?: Application + authed: boolean + error?: HttpError | Error | string + setApp(app?: Application): void + setError(error?: HttpError | Error | string): void +} + +export const Modal: React.FunctionComponent = (props) => { + const [showModal, setShowModal] = React.useState(false) + const [showBar, setShowBar] = React.useState(true) + + const setApp = (app: Application): void => { + setShowModal(false) + props.setApp(app) + } + + React.useEffect(() => { + // Show the bar when hovering around the top area for a while. + let timeout: NodeJS.Timeout | undefined + const hover = (clientY: number): void => { + if (clientY > 30 && timeout) { + clearTimeout(timeout) + timeout = undefined + } else if (clientY <= 30 && !timeout) { + timeout = setTimeout(() => setShowBar(true), 1000) + } + } + + const iframe = + props.app && !isExecutableApplication(props.app) && (document.getElementById("iframe") as HTMLIFrameElement) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const postIframeMessage = (message: any): void => { + if (iframe && iframe.contentWindow) { + iframe.contentWindow.postMessage(message, window.location.origin) + } else { + logger.warn("Tried to post message to missing iframe") + } + } + + const onHover = (event: MouseEvent | MessageEvent): void => { + hover((event as MessageEvent).data ? (event as MessageEvent).data.clientY : (event as MouseEvent).clientY) + } + + const onIframeLoaded = (): void => { + if (props.app) { + setApp({ ...props.app, loaded: true }) + } + } + + // No need to track the mouse if we don't have a hidden bar. + const hasHiddenBar = !props.error && !showModal && props.app && !showBar + + if (props.app && !isExecutableApplication(props.app)) { + // Once the iframe reports it has loaded, tell it to bind mousemove and + // start listening for that instead. + if (!props.app.loaded) { + window.addEventListener("message", onIframeLoaded) + } else if (hasHiddenBar) { + postIframeMessage({ bind: "mousemove", prop: "clientY" }) + window.removeEventListener("message", onIframeLoaded) + window.addEventListener("message", onHover) + } + } else if (hasHiddenBar) { + document.addEventListener("mousemove", onHover) + } + + return (): void => { + document.removeEventListener("mousemove", onHover) + window.removeEventListener("message", onHover) + window.removeEventListener("message", onIframeLoaded) + if (props.app && !isExecutableApplication(props.app)) { + postIframeMessage({ unbind: "mousemove" }) + } + if (timeout) { + clearTimeout(timeout) + } + } + }, [showBar, props.error, showModal, props.app]) + + return props.error || showModal || !props.app || !props.app.loaded ? ( +
+
+ {props.authed && (!props.app || props.app.loaded) ? ( + + ) : ( + undefined + )} + {props.error ? ( + { + props.setApp(undefined) + props.setError(undefined) + }} + /> + ) : ( +
+ + + ( + + )} + /> + + } + /> + + +
+ )} +
+
+ ) : ( + +
+
+
+
+ Hover at the top {/*or press Ctrl+Shift+G*/} to display this menu. +
+
+
+ +
+ +
+
+
+ ) +} diff --git a/src/browser/extHostNodeProxy.ts b/src/browser/extHostNodeProxy.ts deleted file mode 100644 index 63ded64e..00000000 --- a/src/browser/extHostNodeProxy.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Emitter } from "vs/base/common/event"; -import { createDecorator } from "vs/platform/instantiation/common/instantiation"; -import { ExtHostNodeProxyShape, MainContext, MainThreadNodeProxyShape } from "vs/workbench/api/common/extHost.protocol"; -import { IExtHostRpcService } from "vs/workbench/api/common/extHostRpcService"; - -export class ExtHostNodeProxy implements ExtHostNodeProxyShape { - _serviceBrand: any; - - private readonly _onMessage = new Emitter(); - public readonly onMessage = this._onMessage.event; - private readonly _onClose = new Emitter(); - public readonly onClose = this._onClose.event; - private readonly _onDown = new Emitter(); - public readonly onDown = this._onDown.event; - private readonly _onUp = new Emitter(); - public readonly onUp = this._onUp.event; - - private readonly proxy: MainThreadNodeProxyShape; - - constructor(@IExtHostRpcService rpc: IExtHostRpcService) { - this.proxy = rpc.getProxy(MainContext.MainThreadNodeProxy); - } - - public $onMessage(message: string): void { - this._onMessage.fire(message); - } - - public $onClose(): void { - this._onClose.fire(); - } - - public $onUp(): void { - this._onUp.fire(); - } - - public $onDown(): void { - this._onDown.fire(); - } - - public send(message: string): void { - this.proxy.$send(message); - } -} - -export interface IExtHostNodeProxy extends ExtHostNodeProxy { } -export const IExtHostNodeProxy = createDecorator("IExtHostNodeProxy"); diff --git a/src/browser/index.html b/src/browser/index.html new file mode 100644 index 00000000..65cd442c --- /dev/null +++ b/src/browser/index.html @@ -0,0 +1,19 @@ + + + + + + + code-server + + + + + + + + +
{{COMPONENT}}
+ + + diff --git a/src/browser/index.tsx b/src/browser/index.tsx new file mode 100644 index 00000000..60b6b382 --- /dev/null +++ b/src/browser/index.tsx @@ -0,0 +1,18 @@ +import * as React from "react" +import * as ReactDOM from "react-dom" +import App from "./app" +import { BrowserRouter } from "react-router-dom" + +import "./app.css" +import "./pages/home.css" +import "./pages/login.css" +import "./components/error.css" +import "./components/list.css" +import "./components/modal.css" + +ReactDOM.hydrate( + + + , + document.getElementById("root") +) diff --git a/src/browser/login.html b/src/browser/login.html deleted file mode 100644 index 0440c4ed..00000000 --- a/src/browser/login.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - Authenticate: code-server - - - - - - - - - - diff --git a/src/browser/mainThreadNodeProxy.ts b/src/browser/mainThreadNodeProxy.ts deleted file mode 100644 index ab23d3ad..00000000 --- a/src/browser/mainThreadNodeProxy.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { IDisposable } from "vs/base/common/lifecycle"; -import { INodeProxyService } from "vs/server/src/common/nodeProxy"; -import { ExtHostContext, IExtHostContext, MainContext, MainThreadNodeProxyShape } from "vs/workbench/api/common/extHost.protocol"; -import { extHostNamedCustomer } from "vs/workbench/api/common/extHostCustomers"; - -@extHostNamedCustomer(MainContext.MainThreadNodeProxy) -export class MainThreadNodeProxy implements MainThreadNodeProxyShape { - private disposed = false; - private disposables = []; - - constructor( - extHostContext: IExtHostContext, - @INodeProxyService private readonly proxyService: INodeProxyService, - ) { - if (!extHostContext.remoteAuthority) { // HACK: A terrible way to detect if running in the worker. - const proxy = extHostContext.getProxy(ExtHostContext.ExtHostNodeProxy); - this.disposables = [ - this.proxyService.onMessage((message: string) => proxy.$onMessage(message)), - this.proxyService.onClose(() => proxy.$onClose()), - this.proxyService.onDown(() => proxy.$onDown()), - this.proxyService.onUp(() => proxy.$onUp()), - ]; - } - } - - $send(message: string): void { - if (!this.disposed) { - this.proxyService.send(message); - } - } - - dispose(): void { - this.disposables.forEach((d) => d.dispose()); - this.disposables = []; - this.disposed = true; - } -} diff --git a/src/media/code-server.png b/src/browser/media/code-server.png similarity index 100% rename from src/media/code-server.png rename to src/browser/media/code-server.png diff --git a/src/media/favicon.ico b/src/browser/media/favicon.ico similarity index 100% rename from src/media/favicon.ico rename to src/browser/media/favicon.ico diff --git a/src/browser/media/manifest.json b/src/browser/media/manifest.json new file mode 100644 index 00000000..513304e1 --- /dev/null +++ b/src/browser/media/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "code-server", + "short_name": "code-server", + "start_url": "../../../..", + "display": "fullscreen", + "background-color": "#fff", + "description": "Run editors on a remote server.", + "icons": [{ + "src": "./code-server.png", + "sizes": "384x384", + "type": "image/png" + }] +} diff --git a/src/browser/pages/browse.tsx b/src/browser/pages/browse.tsx new file mode 100644 index 00000000..cc362fd1 --- /dev/null +++ b/src/browser/pages/browse.tsx @@ -0,0 +1,34 @@ +import * as React from "react" +import { RouteComponentProps } from "react-router" +import { FilesResponse } from "../../common/api" +import { HttpError } from "../../common/http" +import { getFiles } from "../api" +import { RequestError } from "../components/error" + +/** + * File browser. + */ +export const Browse: React.FunctionComponent = (props) => { + const [response, setResponse] = React.useState() + const [error, setError] = React.useState() + + React.useEffect(() => { + getFiles() + .then(setResponse) + .catch((e) => setError(e.message)) + }, [props]) + + return ( + <> + {error || (response && response.files.length === 0) ? ( + + ) : ( +
    + {((response && response.files) || []).map((f, i) => ( +
  • {f.name}
  • + ))} +
+ )} + + ) +} diff --git a/src/browser/pages/home.css b/src/browser/pages/home.css new file mode 100644 index 00000000..6e56edd7 --- /dev/null +++ b/src/browser/pages/home.css @@ -0,0 +1,8 @@ +.orientation-guide { + align-items: center; + color: #b6b6b6; + display: flex; + flex: 1; + flex-direction: column; + justify-content: center; +} diff --git a/src/browser/pages/home.tsx b/src/browser/pages/home.tsx new file mode 100644 index 00000000..8c10548b --- /dev/null +++ b/src/browser/pages/home.tsx @@ -0,0 +1,22 @@ +import * as React from "react" +import { RouteComponentProps } from "react-router" +import { authenticate } from "../api" + +export const Home: React.FunctionComponent = (props) => { + React.useEffect(() => { + authenticate() + .then(() => { + // TEMP: Always redirect to VS Code. + props.history.push("./vscode/") + }) + .catch(() => { + props.history.push("./login/") + }) + }, []) + + return ( +
+
Welcome to code-server.
+
+ ) +} diff --git a/src/browser/pages/login.css b/src/browser/pages/login.css new file mode 100644 index 00000000..77bf72f3 --- /dev/null +++ b/src/browser/pages/login.css @@ -0,0 +1,35 @@ +.login-form { + align-items: center; + color: rgba(0, 0, 0, 0.37); + display: flex; + flex: 1; + flex-direction: column; + font-weight: 700; + justify-content: center; + text-transform: uppercase; +} + +.login-form > .field { + display: flex; + flex-direction: row; + width: 100%; +} + +.login-form > .field-error { + margin-top: 10px; +} + +.login-form > .field > .input { + border: 1px solid #b6b6b6; + box-sizing: border-box; + padding: 10px; + flex: 1; +} + +.login-form > .field > .submit { + background-color: transparent; + border: 1px solid #b6b6b6; + box-sizing: border-box; + margin-left: -1px; + padding: 10px 20px; +} diff --git a/src/browser/pages/login.tsx b/src/browser/pages/login.tsx new file mode 100644 index 00000000..a2cdec4e --- /dev/null +++ b/src/browser/pages/login.tsx @@ -0,0 +1,55 @@ +import * as React from "react" +import { RouteComponentProps } from "react-router" +import { HttpError } from "../../common/http" +import { authenticate } from "../api" +import { FieldError } from "../components/error" + +/** + * Login page. Will redirect on success. + */ +export const Login: React.FunctionComponent = (props) => { + const [password, setPassword] = React.useState("") + const [error, setError] = React.useState() + + function redirect(): void { + // TEMP: Always redirect to VS Code. + console.log("is authed") + props.history.push("../vscode/") + // const params = new URLSearchParams(window.location.search) + // props.history.push(params.get("to") || "/") + } + + async function handleSubmit(event: React.FormEvent): Promise { + event.preventDefault() + authenticate({ password }) + .then(redirect) + .catch(setError) + } + + React.useEffect(() => { + authenticate() + .then(redirect) + .catch(() => { + // Do nothing; we're already at the login page. + }) + }, []) + + return ( +
+
+ ): void => setPassword(event.target.value)} + /> + +
+ {error ? : undefined} + + ) +} diff --git a/src/browser/pages/open.tsx b/src/browser/pages/open.tsx new file mode 100644 index 00000000..e2bd0027 --- /dev/null +++ b/src/browser/pages/open.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import { Application } from "../../common/api" +import { getApplications } from "../api" +import { ApplicationSection, AppLoader } from "../components/list" + +export interface OpenProps { + app?: Application + setApp(app: Application): void +} + +/** + * Display recently used applications. + */ +export const Open: React.FunctionComponent = (props) => { + return ( + > => { + const response = await getApplications() + return [ + { + header: "Applications", + apps: response && response.applications, + }, + ] + }} + {...props} + /> + ) +} diff --git a/src/browser/pages/recent.tsx b/src/browser/pages/recent.tsx new file mode 100644 index 00000000..da57ddc5 --- /dev/null +++ b/src/browser/pages/recent.tsx @@ -0,0 +1,33 @@ +import * as React from "react" +import { Application } from "../../common/api" +import { getRecent } from "../api" +import { ApplicationSection, AppLoader } from "../components/list" + +export interface RecentProps { + app?: Application + setApp(app: Application): void +} + +/** + * Display recently used applications. + */ +export const Recent: React.FunctionComponent = (props) => { + return ( + > => { + const response = await getRecent() + return [ + { + header: "Running Applications", + apps: response && response.running, + }, + { + header: "Recent Applications", + apps: response && response.recent, + }, + ] + }} + {...props} + /> + ) +} diff --git a/src/browser/socket.ts b/src/browser/socket.ts new file mode 100644 index 00000000..23d969f4 --- /dev/null +++ b/src/browser/socket.ts @@ -0,0 +1,208 @@ +import { field, logger, Logger } from "@coder/logger" +import { Emitter } from "../common/emitter" +import { generateUuid } from "../common/util" + +const decoder = new TextDecoder("utf8") +export const decode = (buffer: string | ArrayBuffer): string => { + return typeof buffer !== "string" ? decoder.decode(buffer) : buffer +} + +/** + * A web socket that reconnects itself when it closes. Sending messages while + * disconnected will throw an error. + */ +export class ReconnectingSocket { + protected readonly _onMessage = new Emitter() + public readonly onMessage = this._onMessage.event + protected readonly _onDisconnect = new Emitter() + public readonly onDisconnect = this._onDisconnect.event + protected readonly _onClose = new Emitter() + public readonly onClose = this._onClose.event + protected readonly _onConnect = new Emitter() + public readonly onConnect = this._onConnect.event + + // This helps distinguish messages between sockets. + private readonly logger: Logger + + private socket?: WebSocket + private connecting?: Promise + private closed = false + private readonly openTimeout = 10000 + + // Every time the socket fails to connect, the retry will be increasingly + // delayed up to a maximum. + private readonly retryBaseDelay = 1000 + private readonly retryMaxDelay = 10000 + private retryDelay?: number + private readonly retryDelayFactor = 1.5 + + // The socket must be connected for this amount of time before resetting the + // retry delay. This prevents rapid retries when the socket does connect but + // is closed shortly after. + private resetRetryTimeout?: NodeJS.Timeout + private readonly resetRetryDelay = 10000 + + private _binaryType: typeof WebSocket.prototype.binaryType = "arraybuffer" + + public constructor(private customPath?: string, public readonly id: string = generateUuid(4)) { + // On Firefox the socket seems to somehow persist a page reload so the close + // event runs and we see "attempting to reconnect". + if (typeof window !== "undefined") { + window.addEventListener("beforeunload", () => this.close()) + } + this.logger = logger.named(this.id) + } + + public set binaryType(b: typeof WebSocket.prototype.binaryType) { + this._binaryType = b + if (this.socket) { + this.socket.binaryType = b + } + } + + /** + * Permanently close the connection. Will not attempt to reconnect. Will + * remove event listeners. + */ + public close(code?: number): void { + if (this.closed) { + return + } + + if (code) { + this.logger.info(`closing with code ${code}`) + } + + if (this.resetRetryTimeout) { + clearTimeout(this.resetRetryTimeout) + } + + this.closed = true + + if (this.socket) { + this.socket.close() + } else { + this._onClose.emit(code) + } + } + + public dispose(): void { + this._onMessage.dispose() + this._onDisconnect.dispose() + this._onClose.dispose() + this._onConnect.dispose() + this.logger.debug("disposed handlers") + } + + /** + * Send a message on the socket. Logs an error if currently disconnected. + */ + public send(message: string | ArrayBuffer): void { + this.logger.trace(() => ["sending message", field("message", decode(message))]) + if (!this.socket) { + return logger.error("tried to send message on closed socket") + } + this.socket.send(message) + } + + /** + * Connect to the socket. Can also be called to wait until the connection is + * established in the case of disconnections. Multiple calls will be handled + * correctly. + */ + public async connect(): Promise { + if (!this.connecting) { + this.connecting = new Promise((resolve, reject) => { + const tryConnect = (): void => { + if (this.closed) { + return reject(new Error("disconnected")) // Don't keep trying if we've closed permanently. + } + if (typeof this.retryDelay === "undefined") { + this.retryDelay = 0 + } else { + this.retryDelay = this.retryDelay * this.retryDelayFactor || this.retryBaseDelay + if (this.retryDelay > this.retryMaxDelay) { + this.retryDelay = this.retryMaxDelay + } + } + this._connect() + .then((socket) => { + this.logger.info("connected") + this.socket = socket + this.socket.binaryType = this._binaryType + if (this.resetRetryTimeout) { + clearTimeout(this.resetRetryTimeout) + } + this.resetRetryTimeout = setTimeout(() => (this.retryDelay = undefined), this.resetRetryDelay) + this.connecting = undefined + this._onConnect.emit() + resolve() + }) + .catch((error) => { + this.logger.error(`failed to connect: ${error.message}`) + tryConnect() + }) + } + tryConnect() + }) + } + return this.connecting + } + + private async _connect(): Promise { + const socket = await new Promise((resolve, _reject) => { + if (this.retryDelay) { + this.logger.info(`retrying in ${this.retryDelay}ms...`) + } + setTimeout(() => { + this.logger.info("connecting...") + const socket = new WebSocket( + `${location.protocol === "https:" ? "wss" : "ws"}://${location.host}${this.customPath || location.pathname}${ + location.search ? `?${location.search}` : "" + }` + ) + + const reject = (): void => { + _reject(new Error("socket closed")) + } + + const timeout = setTimeout(() => { + // eslint-disable-next-line @typescript-eslint/no-use-before-define + socket.removeEventListener("open", open) + socket.removeEventListener("close", reject) + _reject(new Error("timeout")) + }, this.openTimeout) + + const open = (): void => { + clearTimeout(timeout) + socket.removeEventListener("close", reject) + resolve(socket) + } + + socket.addEventListener("open", open) + socket.addEventListener("close", reject) + }, this.retryDelay) + }) + + socket.addEventListener("message", (event) => { + this.logger.trace(() => ["got message", field("message", decode(event.data))]) + this._onMessage.emit(event.data) + }) + socket.addEventListener("close", (event) => { + this.socket = undefined + if (!this.closed) { + this._onDisconnect.emit(event.code) + // It might be closed in the event handler. + if (!this.closed) { + this.logger.info("connection closed; attempting to reconnect") + this.connect() + } + } else { + this._onClose.emit(event.code) + this.logger.info("connection closed permanently") + } + }) + + return socket + } +} diff --git a/src/browser/workbench-build.html b/src/browser/workbench-build.html deleted file mode 100644 index 014cc1f3..00000000 --- a/src/browser/workbench-build.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/browser/workbench.html b/src/browser/workbench.html deleted file mode 100644 index 4e566bdc..00000000 --- a/src/browser/workbench.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/browser/worker.ts b/src/browser/worker.ts deleted file mode 100644 index ed7ea6c9..00000000 --- a/src/browser/worker.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { URI } from "vs/base/common/uri"; -import { IExtensionDescription } from "vs/platform/extensions/common/extensions"; -import { ILogService } from "vs/platform/log/common/log"; -import { Client } from "vs/server/node_modules/@coder/node-browser/out/client/client"; -import { fromTar } from "vs/server/node_modules/@coder/requirefs/out/requirefs"; -import { ExtensionActivationTimesBuilder } from "vs/workbench/api/common/extHostExtensionActivator"; -import { IExtHostNodeProxy } from "./extHostNodeProxy"; - -export const loadCommonJSModule = async ( - module: IExtensionDescription, - activationTimesBuilder: ExtensionActivationTimesBuilder, - nodeProxy: IExtHostNodeProxy, - logService: ILogService, - vscode: any, -): Promise => { - const fetchUri = URI.from({ - scheme: self.location.protocol.replace(":", ""), - authority: self.location.host, - path: `${self.location.pathname.replace(/\/static.*\/out\/vs\/workbench\/services\/extensions\/worker\/extensionHostWorkerMain.js$/, "")}/tar`, - query: `path=${encodeURIComponent(module.extensionLocation.path)}`, - }); - const response = await fetch(fetchUri.toString(true)); - if (response.status !== 200) { - throw new Error(`Failed to download extension "${module.extensionLocation.path}"`); - } - const client = new Client(nodeProxy, { logger: logService }); - const init = await client.handshake(); - const buffer = new Uint8Array(await response.arrayBuffer()); - const rfs = fromTar(buffer); - (self).global = self; - rfs.provide("vscode", vscode); - Object.keys(client.modules).forEach((key) => { - const mod = (client.modules as any)[key]; - if (key === "process") { - (self).process = mod; - (self).process.env = init.env; - return; - } - - rfs.provide(key, mod); - switch (key) { - case "buffer": - (self).Buffer = mod.Buffer; - break; - case "timers": - (self).setImmediate = mod.setImmediate; - break; - } - }); - - try { - activationTimesBuilder.codeLoadingStart(); - return rfs.require("."); - } finally { - activationTimesBuilder.codeLoadingStop(); - } -}; diff --git a/src/common/api.ts b/src/common/api.ts new file mode 100644 index 00000000..2763f7fd --- /dev/null +++ b/src/common/api.ts @@ -0,0 +1,78 @@ +export interface Application { + readonly comment?: string + readonly directory?: string + readonly exec?: string + readonly icon?: string + readonly loaded?: boolean + readonly name: string + readonly path: string + readonly sessionId?: string +} + +export interface ApplicationsResponse { + readonly applications: ReadonlyArray +} + +export enum SessionError { + NotFound = 4000, + FailedToStart, + Starting, + InvalidState, + Unknown, +} + +export interface LoginResponse { + success: boolean +} + +export interface CreateSessionResponse { + sessionId: string +} + +export interface ExecutableApplication extends Application { + exec: string +} + +export const isExecutableApplication = (app: Application): app is ExecutableApplication => { + return !!(app as ExecutableApplication).exec +} + +export interface RunningApplication extends ExecutableApplication { + sessionId: string +} + +export const isRunningApplication = (app: Application): app is RunningApplication => { + return !!(app as RunningApplication).sessionId +} + +export interface RecentResponse { + readonly recent: ReadonlyArray + readonly running: ReadonlyArray +} + +export interface FileEntry { + readonly type: "file" | "directory" + readonly name: string + readonly size: number +} + +export interface FilesResponse { + files: FileEntry[] +} + +export interface HealthRequest { + readonly event: "health" +} + +export type ClientMessage = HealthRequest + +export interface HealthResponse { + readonly event: "health" + readonly connections: number +} + +export type ServerMessage = HealthResponse + +export interface ReadyMessage { + protocol: string +} diff --git a/src/common/emitter.ts b/src/common/emitter.ts new file mode 100644 index 00000000..e30e0543 --- /dev/null +++ b/src/common/emitter.ts @@ -0,0 +1,40 @@ +export interface Disposable { + dispose(): void +} + +export interface Event { + (listener: (value: T) => void): Disposable +} + +/** + * Emitter typecasts for a single event type. + */ +export class Emitter { + private listeners: Array<(value: T) => void> = [] + + public get event(): Event { + return (cb: (value: T) => void): Disposable => { + this.listeners.push(cb) + + return { + dispose: (): void => { + const i = this.listeners.indexOf(cb) + if (i !== -1) { + this.listeners.splice(i, 1) + } + }, + } + } + } + + /** + * Emit an event with a value. + */ + public emit(value: T): void { + this.listeners.forEach((cb) => cb(value)) + } + + public dispose(): void { + this.listeners = [] + } +} diff --git a/src/common/http.ts b/src/common/http.ts new file mode 100644 index 00000000..99c69d1a --- /dev/null +++ b/src/common/http.ts @@ -0,0 +1,24 @@ +export enum HttpCode { + Ok = 200, + Redirect = 302, + NotFound = 404, + BadRequest = 400, + Unauthorized = 401, + LargePayload = 413, + ServerError = 500, +} + +export class HttpError extends Error { + public constructor(message: string, public readonly code: number) { + super(message) + this.name = this.constructor.name + } +} + +export enum ApiEndpoint { + applications = "/applications", + files = "/files", + login = "/login", + recent = "/recent", + session = "/session", +} diff --git a/src/common/nodeProxy.ts b/src/common/nodeProxy.ts deleted file mode 100644 index bfbd6575..00000000 --- a/src/common/nodeProxy.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Event } from "vs/base/common/event"; -import { IChannel, IServerChannel } from "vs/base/parts/ipc/common/ipc"; -import { createDecorator } from "vs/platform/instantiation/common/instantiation"; -import { ReadWriteConnection } from "vs/server/node_modules/@coder/node-browser/out/common/connection"; - -export const INodeProxyService = createDecorator("nodeProxyService"); - -export interface INodeProxyService extends ReadWriteConnection { - _serviceBrand: any; - send(message: string): void; - onMessage: Event; - onUp: Event; - onClose: Event; - onDown: Event; -} - -export class NodeProxyChannel implements IServerChannel { - constructor(private service: INodeProxyService) {} - - listen(_: unknown, event: string): Event { - switch (event) { - case "onMessage": return this.service.onMessage; - } - throw new Error(`Invalid listen ${event}`); - } - - async call(_: unknown, command: string, args?: any): Promise { - switch (command) { - case "send": return this.service.send(args[0]); - } - throw new Error(`Invalid call ${command}`); - } -} - -export class NodeProxyChannelClient { - _serviceBrand: any; - - public readonly onMessage: Event; - - constructor(private readonly channel: IChannel) { - this.onMessage = this.channel.listen("onMessage"); - } - - public send(data: string): void { - this.channel.call("send", [data]); - } -} diff --git a/src/common/telemetry.ts b/src/common/telemetry.ts deleted file mode 100644 index 28adaed5..00000000 --- a/src/common/telemetry.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ITelemetryData } from "vs/base/common/actions"; -import { Event } from "vs/base/common/event"; -import { IChannel, IServerChannel } from "vs/base/parts/ipc/common/ipc"; -import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from "vs/platform/telemetry/common/gdprTypings"; -import { ITelemetryInfo, ITelemetryService } from "vs/platform/telemetry/common/telemetry"; - -export class TelemetryChannel implements IServerChannel { - constructor(private service: ITelemetryService) {} - - listen(_: unknown, event: string): Event { - throw new Error(`Invalid listen ${event}`); - } - - call(_: unknown, command: string, args?: any): Promise { - switch (command) { - case "publicLog": return this.service.publicLog(args[0], args[1], args[2]); - case "publicLog2": return this.service.publicLog2(args[0], args[1], args[2]); - case "setEnabled": return Promise.resolve(this.service.setEnabled(args[0])); - case "getTelemetryInfo": return this.service.getTelemetryInfo(); - } - throw new Error(`Invalid call ${command}`); - } -} - -export class TelemetryChannelClient implements ITelemetryService { - _serviceBrand: any; - - constructor(private readonly channel: IChannel) {} - - public publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise { - return this.channel.call("publicLog", [eventName, data, anonymizeFilePaths]); - } - - public publicLog2 = never, T extends GDPRClassification = never>(eventName: string, data?: StrictPropertyCheck, anonymizeFilePaths?: boolean): Promise { - return this.channel.call("publicLog2", [eventName, data, anonymizeFilePaths]); - } - - public setEnabled(value: boolean): void { - this.channel.call("setEnable", [value]); - } - - public getTelemetryInfo(): Promise { - return this.channel.call("getTelemetryInfo"); - } - - public get isOptedIn(): boolean { - return true; - } -} diff --git a/src/common/util.ts b/src/common/util.ts index 9be7dbe7..8394e5f3 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -1,10 +1,48 @@ +import { logger } from "@coder/logger" + +export interface Options { + logLevel?: number +} + /** * Split a string up to the delimiter. If the delimiter doesn't exist the first * item will have all the text and the second item will be an empty string. */ export const split = (str: string, delimiter: string): [string, string] => { - const index = str.indexOf(delimiter); - return index !== -1 - ? [str.substring(0, index).trim(), str.substring(index + 1)] - : [str, ""]; -}; + const index = str.indexOf(delimiter) + return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, ""] +} + +export const plural = (count: number): string => (count === 1 ? "" : "s") + +export const generateUuid = (length = 24): string => { + const possible = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + return Array(length) + .fill(1) + .map(() => possible[Math.floor(Math.random() * possible.length)]) + .join("") +} + +/** + * Get options embedded in the HTML from the server. + */ +export const getOptions = (): T => { + const el = document.getElementById("coder-options") + try { + if (!el) { + throw new Error("no options element") + } + const value = el.getAttribute("data-settings") + if (!value) { + throw new Error("no options value") + } + const options = JSON.parse(value) + if (typeof options.logLevel !== "undefined") { + logger.level = options.logLevel + } + return options + } catch (error) { + logger.warn(error.message) + return {} as T + } +} diff --git a/src/media/login.css b/src/media/login.css deleted file mode 100644 index f075a638..00000000 --- a/src/media/login.css +++ /dev/null @@ -1,94 +0,0 @@ -html { - box-sizing: border-box; -} - -*, *:before, *:after { - box-sizing: inherit; -} - -html, body { - background-color: #FFFFFF; - height: 100%; - min-height: 100%; -} - -body { - align-items: center; - display: flex; - font-family: "monospace"; - justify-content: center; - margin: 0; - padding: 10px; -} - -.login-form { - border-radius: 5px; - box-shadow: 0 18px 80px 10px rgba(69, 65, 78, 0.08); - color: #575962; - margin-top: -10%; - max-width: 328px; - padding: 40px; - position: relative; - width: 100%; -} - -.login-form > .title { - text-align: center; - text-transform: uppercase; - font-size: 12px; - font-weight: 500; - letter-spacing: 1.5px; - line-height: 15px; - margin-bottom: 0px; - margin-bottom: 5px; - margin-top: 0px; -} - -.login-form > .subtitle { - font-size: 19px; - font-weight: bold; - line-height: 25px; - margin-bottom: 45px; - margin: 0; - text-align: center; -} - -.login-form > .field { - text-align: left; - font-size: 12px; - color: #797E84; - margin: 16px 0; -} - -.login-form > .field > .input { - background: none !important; - border: 1px solid #ccc; - border-radius: 2px; - padding: 5px; - width: 100%; -} - -.login-form > .button { - border: none; - border-radius: 24px; - box-shadow: 0 12px 17px 2px rgba(171,173,163,0.14), 0 5px 22px 4px rgba(171,173,163,0.12), 0 7px 8px -4px rgba(171,173,163,0.2); - cursor: pointer; - display: block; - padding: 15px 5px; - width: 100%; -} - -.login-form > .button:hover { - background-color: rgb(0, 122, 204); - color: #fff; -} - -.error-display { - box-sizing: border-box; - color: #bb2d0f; - font-size: 14px; - font-weight: 400; - line-height: 12px; - padding: 20px 8px 0; - text-align: center; -} diff --git a/src/media/manifest.json b/src/media/manifest.json deleted file mode 100644 index 2495e2ba..00000000 --- a/src/media/manifest.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "code-server", - "short_name": "code-server", - "start_url": ".", - "display": "standalone", - "background-color": "#fff", - "description": "Run VS Code on a remote server.", - "icons": [{ - "src": "./code-server.png", - "sizes": "384x384", - "type": "image/png" - }] -} diff --git a/src/node/api/server.ts b/src/node/api/server.ts new file mode 100644 index 00000000..10061530 --- /dev/null +++ b/src/node/api/server.ts @@ -0,0 +1,159 @@ +import { field, logger } from "@coder/logger" +import * as http from "http" +import * as net from "net" +import * as querystring from "querystring" +import * as ws from "ws" +import { ApplicationsResponse, ClientMessage, FilesResponse, LoginResponse, ServerMessage } from "../../common/api" +import { ApiEndpoint, HttpCode } from "../../common/http" +import { HttpProvider, HttpProviderOptions, HttpResponse, HttpServer, PostData } from "../http" +import { hash } from "../util" + +interface LoginPayload extends PostData { + password?: string | string[] +} + +/** + * API HTTP provider. + */ +export class ApiHttpProvider extends HttpProvider { + private readonly ws = new ws.Server({ noServer: true }) + + public constructor(private readonly server: HttpServer, options: HttpProviderOptions) { + super(options) + } + + public async handleRequest( + base: string, + _requestPath: string, + _query: querystring.ParsedUrlQuery, + request: http.IncomingMessage + ): Promise { + switch (base) { + case ApiEndpoint.login: + if (request.method === "POST") { + return this.login(request) + } + break + default: + if (!this.authenticated(request)) { + return { code: HttpCode.Unauthorized } + } + switch (base) { + case ApiEndpoint.applications: + return this.applications() + case ApiEndpoint.files: + return this.files() + } + } + return undefined + } + + public async handleWebSocket( + _base: string, + _requestPath: string, + _query: querystring.ParsedUrlQuery, + request: http.IncomingMessage, + socket: net.Socket, + head: Buffer + ): Promise { + if (!this.authenticated(request)) { + throw new Error("not authenticated") + } + await new Promise((resolve) => { + this.ws.handleUpgrade(request, socket, head, (ws) => { + const send = (event: ServerMessage): void => { + ws.send(JSON.stringify(event)) + } + ws.on("message", (data) => { + logger.trace("got message", field("message", data)) + try { + const message: ClientMessage = JSON.parse(data.toString()) + this.getMessageResponse(message.event).then(send) + } catch (error) { + logger.error(error.message, field("message", data)) + } + }) + resolve() + }) + }) + return true + } + + private async getMessageResponse(event: "health"): Promise { + switch (event) { + case "health": + return { event, connections: await this.server.getConnections() } + default: + throw new Error("unexpected message") + } + } + + /** + * Return OK and a cookie if the user is authenticated otherwise return + * unauthorized. + */ + private async login(request: http.IncomingMessage): Promise> { + const ok = (password: string | true): HttpResponse => { + return { + content: { + success: true, + }, + cookie: typeof password === "string" ? { key: "key", value: password } : undefined, + } + } + + // Already authenticated via cookies? + const providedPassword = this.authenticated(request) + if (providedPassword) { + return ok(providedPassword) + } + + const data = await this.getData(request) + const payload: LoginPayload = data ? querystring.parse(data) : {} + const password = this.authenticated(request, { + key: typeof payload.password === "string" ? [hash(payload.password)] : undefined, + }) + if (password) { + return ok(password) + } + + console.error( + "Failed login attempt", + JSON.stringify({ + xForwardedFor: request.headers["x-forwarded-for"], + remoteAddress: request.connection.remoteAddress, + userAgent: request.headers["user-agent"], + timestamp: Math.floor(new Date().getTime() / 1000), + }) + ) + + return { code: HttpCode.Unauthorized } + } + + /** + * Return files at the requested directory. + */ + private async files(): Promise> { + return { + content: { + files: [], + }, + } + } + + /** + * Return available applications. + */ + private async applications(): Promise> { + return { + content: { + applications: [ + { + name: "VS Code", + path: "/vscode", + }, + ], + }, + } + } +} diff --git a/src/node/app/server.tsx b/src/node/app/server.tsx new file mode 100644 index 00000000..6d928a25 --- /dev/null +++ b/src/node/app/server.tsx @@ -0,0 +1,37 @@ +import { logger } from "@coder/logger" +import * as React from "react" +import * as ReactDOMServer from "react-dom/server" +import * as ReactRouterDOM from "react-router-dom" +import App from "../../browser/app" +import { HttpProvider, HttpResponse } from "../http" + +/** + * Top-level and fallback HTTP provider. + */ +export class MainHttpProvider extends HttpProvider { + public async handleRequest(base: string, requestPath: string): Promise { + if (base === "/static") { + const response = await this.getResource(this.rootPath, requestPath) + response.cache = true + return response + } + + const response = await this.getUtf8Resource(this.rootPath, "src/browser/index.html") + response.content = response.content + .replace(/{{COMMIT}}/g, "") // TODO + .replace(/"{{OPTIONS}}"/g, `'${JSON.stringify({ logLevel: logger.level })}'`) + .replace( + /{{COMPONENT}}/g, + ReactDOMServer.renderToString( + + + + ) + ) + return response + } + + public async handleWebSocket(): Promise { + return undefined + } +} diff --git a/src/node/channel.ts b/src/node/channel.ts deleted file mode 100644 index 4d21b473..00000000 --- a/src/node/channel.ts +++ /dev/null @@ -1,343 +0,0 @@ -import * as path from "path"; -import { VSBuffer, VSBufferReadableStream } from "vs/base/common/buffer"; -import { Emitter, Event } from "vs/base/common/event"; -import { IDisposable } from "vs/base/common/lifecycle"; -import { OS } from "vs/base/common/platform"; -import { ReadableStreamEventPayload } from "vs/base/common/stream"; -import { URI, UriComponents } from "vs/base/common/uri"; -import { transformOutgoingURIs } from "vs/base/common/uriIpc"; -import { IServerChannel } from "vs/base/parts/ipc/common/ipc"; -import { IDiagnosticInfo } from "vs/platform/diagnostics/common/diagnostics"; -import { IEnvironmentService } from "vs/platform/environment/common/environment"; -import { ExtensionIdentifier, IExtensionDescription } from "vs/platform/extensions/common/extensions"; -import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileReadStreamOptions, FileType, FileWriteOptions, IStat, IWatchOptions } from "vs/platform/files/common/files"; -import { createReadStream } from "vs/platform/files/common/io"; -import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider"; -import { ILogService } from "vs/platform/log/common/log"; -import product from "vs/platform/product/common/product"; -import { IRemoteAgentEnvironment, RemoteAgentConnectionContext } from "vs/platform/remote/common/remoteAgentEnvironment"; -import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { INodeProxyService } from "vs/server/src/common/nodeProxy"; -import { getTranslations } from "vs/server/src/node/nls"; -import { getUriTransformer, localRequire } from "vs/server/src/node/util"; -import { IFileChangeDto } from "vs/workbench/api/common/extHost.protocol"; -import { ExtensionScanner, ExtensionScannerInput } from "vs/workbench/services/extensions/node/extensionPoints"; - -/** - * Extend the file provider to allow unwatching. - */ -class Watcher extends DiskFileSystemProvider { - public readonly watches = new Map(); - - public dispose(): void { - this.watches.forEach((w) => w.dispose()); - this.watches.clear(); - super.dispose(); - } - - public _watch(req: number, resource: URI, opts: IWatchOptions): void { - this.watches.set(req, this.watch(resource, opts)); - } - - public unwatch(req: number): void { - this.watches.get(req)!.dispose(); - this.watches.delete(req); - } -} - -export class FileProviderChannel implements IServerChannel, IDisposable { - private readonly provider: DiskFileSystemProvider; - private readonly watchers = new Map(); - - public constructor( - private readonly environmentService: IEnvironmentService, - private readonly logService: ILogService, - ) { - this.provider = new DiskFileSystemProvider(this.logService); - } - - public listen(context: RemoteAgentConnectionContext, event: string, args?: any): Event { - switch (event) { - case "filechange": return this.filechange(context, args[0]); - case "readFileStream": return this.readFileStream(args[0], args[1]); - } - - throw new Error(`Invalid listen "${event}"`); - } - - private filechange(context: RemoteAgentConnectionContext, session: string): Event { - const emitter = new Emitter({ - onFirstListenerAdd: () => { - const provider = new Watcher(this.logService); - this.watchers.set(session, provider); - const transformer = getUriTransformer(context.remoteAuthority); - provider.onDidChangeFile((events) => { - emitter.fire(events.map((event) => ({ - ...event, - resource: transformer.transformOutgoing(event.resource), - }))); - }); - provider.onDidErrorOccur((event) => this.logService.error(event)); - }, - onLastListenerRemove: () => { - this.watchers.get(session)!.dispose(); - this.watchers.delete(session); - }, - }); - - return emitter.event; - } - - private readFileStream(resource: UriComponents, opts: FileReadStreamOptions): Event> { - let fileStream: VSBufferReadableStream | undefined; - const emitter = new Emitter>({ - onFirstListenerAdd: () => { - if (!fileStream) { - fileStream = createReadStream(this.provider, this.transform(resource), { - ...opts, - bufferSize: 64 * 1024, // From DiskFileSystemProvider - }); - fileStream.on("data", (data) => emitter.fire(data)); - fileStream.on("error", (error) => emitter.fire(error)); - fileStream.on("end", () => emitter.fire("end")); - } - }, - onLastListenerRemove: () => fileStream && fileStream.destroy(), - }); - - return emitter.event; - } - - public call(_: unknown, command: string, args?: any): Promise { - switch (command) { - case "stat": return this.stat(args[0]); - case "open": return this.open(args[0], args[1]); - case "close": return this.close(args[0]); - case "read": return this.read(args[0], args[1], args[2]); - case "readFile": return this.readFile(args[0]); - case "write": return this.write(args[0], args[1], args[2], args[3], args[4]); - case "writeFile": return this.writeFile(args[0], args[1], args[2]); - case "delete": return this.delete(args[0], args[1]); - case "mkdir": return this.mkdir(args[0]); - case "readdir": return this.readdir(args[0]); - case "rename": return this.rename(args[0], args[1], args[2]); - case "copy": return this.copy(args[0], args[1], args[2]); - case "watch": return this.watch(args[0], args[1], args[2], args[3]); - case "unwatch": return this.unwatch(args[0], args[1]); - } - - throw new Error(`Invalid call "${command}"`); - } - - public dispose(): void { - this.watchers.forEach((w) => w.dispose()); - this.watchers.clear(); - } - - private async stat(resource: UriComponents): Promise { - return this.provider.stat(this.transform(resource)); - } - - private async open(resource: UriComponents, opts: FileOpenOptions): Promise { - return this.provider.open(this.transform(resource), opts); - } - - private async close(fd: number): Promise { - return this.provider.close(fd); - } - - private async read(fd: number, pos: number, length: number): Promise<[VSBuffer, number]> { - const buffer = VSBuffer.alloc(length); - const bytesRead = await this.provider.read(fd, pos, buffer.buffer, 0, length); - return [buffer, bytesRead]; - } - - private async readFile(resource: UriComponents): Promise { - return VSBuffer.wrap(await this.provider.readFile(this.transform(resource))); - } - - private write(fd: number, pos: number, buffer: VSBuffer, offset: number, length: number): Promise { - return this.provider.write(fd, pos, buffer.buffer, offset, length); - } - - private writeFile(resource: UriComponents, buffer: VSBuffer, opts: FileWriteOptions): Promise { - return this.provider.writeFile(this.transform(resource), buffer.buffer, opts); - } - - private async delete(resource: UriComponents, opts: FileDeleteOptions): Promise { - return this.provider.delete(this.transform(resource), opts); - } - - private async mkdir(resource: UriComponents): Promise { - return this.provider.mkdir(this.transform(resource)); - } - - private async readdir(resource: UriComponents): Promise<[string, FileType][]> { - return this.provider.readdir(this.transform(resource)); - } - - private async rename(resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise { - return this.provider.rename(this.transform(resource), URI.from(target), opts); - } - - private copy(resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise { - return this.provider.copy(this.transform(resource), URI.from(target), opts); - } - - private async watch(session: string, req: number, resource: UriComponents, opts: IWatchOptions): Promise { - this.watchers.get(session)!._watch(req, this.transform(resource), opts); - } - - private async unwatch(session: string, req: number): Promise { - this.watchers.get(session)!.unwatch(req); - } - - private transform(resource: UriComponents): URI { - // Used for walkthrough content. - if (/^\/static[^/]*\//.test(resource.path)) { - return URI.file(this.environmentService.appRoot + resource.path.replace(/^\/static[^/]*\//, "/")); - // Used by the webview service worker to load resources. - } else if (resource.path === "/vscode-resource" && resource.query) { - try { - const query = JSON.parse(resource.query); - if (query.requestResourcePath) { - return URI.file(query.requestResourcePath); - } - } catch (error) { /* Carry on. */ } - } - return URI.from(resource); - } -} - -export class ExtensionEnvironmentChannel implements IServerChannel { - public constructor( - private readonly environment: IEnvironmentService, - private readonly log: ILogService, - private readonly telemetry: ITelemetryService, - private readonly connectionToken: string, - ) {} - - public listen(_: unknown, event: string): Event { - throw new Error(`Invalid listen "${event}"`); - } - - public async call(context: any, command: string, args?: any): Promise { - switch (command) { - case "getEnvironmentData": - return transformOutgoingURIs( - await this.getEnvironmentData(args.language), - getUriTransformer(context.remoteAuthority), - ); - case "getDiagnosticInfo": return this.getDiagnosticInfo(); - case "disableTelemetry": return this.disableTelemetry(); - } - throw new Error(`Invalid call "${command}"`); - } - - private async getEnvironmentData(locale: string): Promise { - return { - pid: process.pid, - connectionToken: this.connectionToken, - appRoot: URI.file(this.environment.appRoot), - appSettingsHome: this.environment.appSettingsHome, - settingsPath: this.environment.machineSettingsHome, - logsPath: URI.file(this.environment.logsPath), - extensionsPath: URI.file(this.environment.extensionsPath!), - extensionHostLogsPath: URI.file(path.join(this.environment.logsPath, "extension-host")), - globalStorageHome: URI.file(this.environment.globalStorageHome), - userHome: URI.file(this.environment.userHome), - extensions: await this.scanExtensions(locale), - os: OS, - }; - } - - private async scanExtensions(locale: string): Promise { - const translations = await getTranslations(locale, this.environment.userDataPath); - - const scanMultiple = (isBuiltin: boolean, isUnderDevelopment: boolean, paths: string[]): Promise => { - return Promise.all(paths.map((path) => { - return ExtensionScanner.scanExtensions(new ExtensionScannerInput( - product.version, - product.commit, - locale, - !!process.env.VSCODE_DEV, - path, - isBuiltin, - isUnderDevelopment, - translations, - ), this.log); - })); - }; - - const scanBuiltin = async (): Promise => { - return scanMultiple(true, false, [this.environment.builtinExtensionsPath, ...this.environment.extraBuiltinExtensionPaths]); - }; - - const scanInstalled = async (): Promise => { - return scanMultiple(false, true, [this.environment.extensionsPath!, ...this.environment.extraExtensionPaths]); - }; - - return Promise.all([scanBuiltin(), scanInstalled()]).then((allExtensions) => { - const uniqueExtensions = new Map(); - allExtensions.forEach((multipleExtensions) => { - multipleExtensions.forEach((extensions) => { - extensions.forEach((extension) => { - const id = ExtensionIdentifier.toKey(extension.identifier); - if (uniqueExtensions.has(id)) { - const oldPath = uniqueExtensions.get(id)!.extensionLocation.fsPath; - const newPath = extension.extensionLocation.fsPath; - this.log.warn(`${oldPath} has been overridden ${newPath}`); - } - uniqueExtensions.set(id, extension); - }); - }); - }); - return Array.from(uniqueExtensions.values()); - }); - } - - private getDiagnosticInfo(): Promise { - throw new Error("not implemented"); - } - - private async disableTelemetry(): Promise { - this.telemetry.setEnabled(false); - } -} - -export class NodeProxyService implements INodeProxyService { - public _serviceBrand = undefined; - - public readonly server: import("@coder/node-browser/out/server/server").Server; - - private readonly _onMessage = new Emitter(); - public readonly onMessage = this._onMessage.event; - private readonly _$onMessage = new Emitter(); - public readonly $onMessage = this._$onMessage.event; - public readonly _onDown = new Emitter(); - public readonly onDown = this._onDown.event; - public readonly _onUp = new Emitter(); - public readonly onUp = this._onUp.event; - - // Unused because the server connection will never permanently close. - private readonly _onClose = new Emitter(); - public readonly onClose = this._onClose.event; - - public constructor() { - // TODO: down/up - const { Server } = localRequire("@coder/node-browser/out/server/server"); - this.server = new Server({ - onMessage: this.$onMessage, - onClose: this.onClose, - onDown: this.onDown, - onUp: this.onUp, - send: (message: string): void => { - this._onMessage.fire(message); - } - }); - } - - public send(message: string): void { - this._$onMessage.fire(message); - } -} diff --git a/src/node/cli.ts b/src/node/cli.ts deleted file mode 100644 index e31cd93c..00000000 --- a/src/node/cli.ts +++ /dev/null @@ -1,299 +0,0 @@ -import * as cp from "child_process"; -import * as os from "os"; -import * as path from "path"; -import { setUnexpectedErrorHandler } from "vs/base/common/errors"; -import { main as vsCli } from "vs/code/node/cliProcessMain"; -import { validatePaths } from "vs/code/node/paths"; -import { ParsedArgs } from "vs/platform/environment/common/environment"; -import { buildHelpMessage, buildVersionMessage, Option as VsOption, OPTIONS, OptionDescriptions } from "vs/platform/environment/node/argv"; -import { parseMainProcessArgv } from "vs/platform/environment/node/argvHelper"; -import product from "vs/platform/product/common/product"; -import { ipcMain } from "vs/server/src/node/ipc"; -import { enableCustomMarketplace } from "vs/server/src/node/marketplace"; -import { MainServer } from "vs/server/src/node/server"; -import { AuthType, buildAllowedMessage, enumToArray, FormatType, generateCertificate, generatePassword, localRequire, open, unpackExecutables } from "vs/server/src/node/util"; - -const { logger } = localRequire("@coder/logger/out/index"); -setUnexpectedErrorHandler((error) => logger.warn(error.message)); - -interface Args extends ParsedArgs { - auth?: AuthType; - "base-path"?: string; - cert?: string; - "cert-key"?: string; - format?: string; - host?: string; - open?: boolean; - port?: string; - socket?: string; -} - -// @ts-ignore: Force `keyof Args` to work. -interface Option extends VsOption { - id: keyof Args; -} - -const getArgs = (): Args => { - // Remove options that won't work or don't make sense. - for (let key in OPTIONS) { - switch (key) { - case "add": - case "diff": - case "file-uri": - case "folder-uri": - case "goto": - case "new-window": - case "reuse-window": - case "wait": - case "disable-gpu": - // TODO: pretty sure these don't work but not 100%. - case "prof-startup": - case "inspect-extensions": - case "inspect-brk-extensions": - delete OPTIONS[key]; - break; - } - } - - const options = OPTIONS as OptionDescriptions>; - options["base-path"] = { type: "string", cat: "o", description: "Base path of the URL at which code-server is hosted (used for login redirects)." }; - options["cert"] = { type: "string", cat: "o", description: "Path to certificate. If the path is omitted, both this and --cert-key will be generated." }; - options["cert-key"] = { type: "string", cat: "o", description: "Path to the certificate's key if one was provided." }; - options["format"] = { type: "string", cat: "o", description: `Format for the version. ${buildAllowedMessage(FormatType)}.` }; - options["host"] = { type: "string", cat: "o", description: "Host for the server." }; - options["auth"] = { type: "string", cat: "o", description: `The type of authentication to use. ${buildAllowedMessage(AuthType)}.` }; - options["open"] = { type: "boolean", cat: "o", description: "Open in the browser on startup." }; - options["port"] = { type: "string", cat: "o", description: "Port for the main server." }; - options["socket"] = { type: "string", cat: "o", description: "Listen on a socket instead of host:port." }; - - const args = parseMainProcessArgv(process.argv); - if (!args["user-data-dir"]) { - args["user-data-dir"] = path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local/share"), "code-server"); - } - if (!args["extensions-dir"]) { - args["extensions-dir"] = path.join(args["user-data-dir"], "extensions"); - } - - if (!args.verbose && !args.log && process.env.LOG_LEVEL) { - args.log = process.env.LOG_LEVEL; - } - - return validatePaths(args); -}; - -const startVscode = async (args: Args): Promise => { - const extra = args["_"] || []; - const options = { - auth: args.auth || AuthType.Password, - basePath: args["base-path"], - cert: args.cert, - certKey: args["cert-key"], - openUri: extra.length > 1 ? extra[extra.length - 1] : undefined, - host: args.host, - password: process.env.PASSWORD, - }; - - if (enumToArray(AuthType).filter((t) => t === options.auth).length === 0) { - throw new Error(`'${options.auth}' is not a valid authentication type.`); - } else if (options.auth === "password" && !options.password) { - options.password = await generatePassword(); - } - - if (!options.certKey && typeof options.certKey !== "undefined") { - throw new Error(`--cert-key cannot be blank`); - } else if (options.certKey && !options.cert) { - throw new Error(`--cert-key was provided but --cert was not`); - } if (!options.cert && typeof options.cert !== "undefined") { - const { cert, certKey } = await generateCertificate(); - options.cert = cert; - options.certKey = certKey; - } - - enableCustomMarketplace(); - - const server = new MainServer({ - ...options, - port: typeof args.port !== "undefined" ? parseInt(args.port, 10) : 8080, - socket: args.socket, - }, args); - - const [serverAddress, /* ignore */] = await Promise.all([ - server.listen(), - unpackExecutables(), - ]); - logger.info(`Server listening on ${serverAddress}`); - - if (options.auth === "password" && !process.env.PASSWORD) { - logger.info(` - Password is ${options.password}`); - logger.info(" - To use your own password, set the PASSWORD environment variable"); - if (!args.auth) { - logger.info(" - To disable use `--auth none`"); - } - } else if (options.auth === "password") { - logger.info(" - Using custom password for authentication"); - } else { - logger.info(" - No authentication"); - } - - if (server.protocol === "https") { - logger.info( - args.cert - ? ` - Using provided certificate${args["cert-key"] ? " and key" : ""} for HTTPS` - : ` - Using generated certificate and key for HTTPS`, - ); - } else { - logger.info(" - Not serving HTTPS"); - } - - if (!server.options.socket && args.open) { - // The web socket doesn't seem to work if browsing with 0.0.0.0. - const openAddress = serverAddress.replace(/:\/\/0.0.0.0/, "://localhost"); - await open(openAddress).catch(console.error); - logger.info(` - Opened ${openAddress}`); - } -}; - -const startCli = (args: Args): boolean | Promise => { - if (args.help) { - const executable = `${product.applicationName}${os.platform() === "win32" ? ".exe" : ""}`; - console.log(buildHelpMessage(product.nameLong, executable, product.codeServerVersion, OPTIONS, false)); - return true; - } - - if (args.version) { - if (args.format === "json") { - console.log(JSON.stringify({ - codeServerVersion: product.codeServerVersion, - commit: product.commit, - vscodeVersion: product.version, - })); - } else { - buildVersionMessage(product.codeServerVersion, product.commit).split("\n").map((line) => logger.info(line)); - } - return true; - } - - const shouldSpawnCliProcess = (): boolean => { - return !!args["install-source"] - || !!args["list-extensions"] - || !!args["install-extension"] - || !!args["uninstall-extension"] - || !!args["locate-extension"] - || !!args["telemetry"]; - }; - - if (shouldSpawnCliProcess()) { - enableCustomMarketplace(); - return vsCli(args); - } - - return false; -}; - -export class WrapperProcess { - private process?: cp.ChildProcess; - private started?: Promise; - private currentVersion = product.codeServerVersion; - - public constructor(private readonly args: Args) { - ipcMain.onMessage(async (message) => { - switch (message.type) { - case "relaunch": - logger.info(`Relaunching: ${this.currentVersion} -> ${message.version}`); - this.currentVersion = message.version; - this.started = undefined; - if (this.process) { - this.process.removeAllListeners(); - this.process.kill(); - } - try { - await this.start(); - } catch (error) { - logger.error(error.message); - process.exit(typeof error.code === "number" ? error.code : 1); - } - break; - default: - logger.error(`Unrecognized message ${message}`); - break; - } - }); - } - - public start(): Promise { - if (!this.started) { - const child = this.spawn(); - this.started = ipcMain.handshake(child).then(() => { - child.once("exit", (code) => exit(code!)); - }); - this.process = child; - } - return this.started; - } - - private spawn(): cp.ChildProcess { - // Flags to pass along to the Node binary. We use the environment variable - // since otherwise the code-server binary will swallow them. - const maxMemory = this.args["max-memory"] || 2048; - let nodeOptions = `${process.env.NODE_OPTIONS || ""} ${this.args["js-flags"] || ""}`; - if (!/max_old_space_size=(\d+)/g.exec(nodeOptions)) { - nodeOptions += ` --max_old_space_size=${maxMemory}`; - } - - // If we're using loose files then we need to specify the path. If we're in - // the binary we need to let the binary determine the path (via nbin) since - // it could be different between binaries which presents a problem when - // upgrading (different version numbers or different staging directories). - const isBinary = (global as any).NBIN_LOADED; - return cp.spawn(process.argv[0], process.argv.slice(isBinary ? 2 : 1), { - env: { - ...process.env, - LAUNCH_VSCODE: "true", - NBIN_BYPASS: undefined, - VSCODE_PARENT_PID: process.pid.toString(), - NODE_OPTIONS: nodeOptions, - }, - stdio: ["inherit", "inherit", "inherit", "ipc"], - }); - } -} - -const main = async(): Promise => { - const args = getArgs(); - if (process.env.LAUNCH_VSCODE) { - await ipcMain.handshake(); - return startVscode(args); - } - return startCli(args) || new WrapperProcess(args).start(); -}; - -const exit = process.exit; -process.exit = function (code?: number) { - const err = new Error(`process.exit() was prevented: ${code || "unknown code"}.`); - console.warn(err.stack); -} as (code?: number) => never; - -// Copy the extension host behavior of killing oneself if the parent dies. This -// also exists in bootstrap-fork.js but spawning with that won't work because we -// override process.exit. -if (typeof process.env.VSCODE_PARENT_PID !== "undefined") { - const parentPid = parseInt(process.env.VSCODE_PARENT_PID, 10); - setInterval(() => { - try { - process.kill(parentPid, 0); // Throws an exception if the process doesn't exist anymore. - } catch (e) { - exit(); - } - }, 5000); -} - -// It's possible that the pipe has closed (for example if you run code-server -// --version | head -1). Assume that means we're done. -if (!process.stdout.isTTY) { - process.stdout.on("error", () => exit()); -} - -main().catch((error) => { - logger.error(error.message); - exit(typeof error.code === "number" ? error.code : 1); -}); diff --git a/src/node/connection.ts b/src/node/connection.ts deleted file mode 100644 index 98bebd33..00000000 --- a/src/node/connection.ts +++ /dev/null @@ -1,156 +0,0 @@ -import * as cp from "child_process"; -import { getPathFromAmdModule } from "vs/base/common/amd"; -import { VSBuffer } from "vs/base/common/buffer"; -import { Emitter } from "vs/base/common/event"; -import { ISocket } from "vs/base/parts/ipc/common/ipc.net"; -import { NodeSocket } from "vs/base/parts/ipc/node/ipc.net"; -import { IEnvironmentService } from "vs/platform/environment/common/environment"; -import { ILogService } from "vs/platform/log/common/log"; -import { getNlsConfiguration } from "vs/server/src/node/nls"; -import { Protocol } from "vs/server/src/node/protocol"; -import { uriTransformerPath } from "vs/server/src/node/util"; -import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol"; - -export abstract class Connection { - private readonly _onClose = new Emitter(); - public readonly onClose = this._onClose.event; - private disposed = false; - private _offline: number | undefined; - - public constructor(protected protocol: Protocol, public readonly token: string) {} - - public get offline(): number | undefined { - return this._offline; - } - - public reconnect(socket: ISocket, buffer: VSBuffer): void { - this._offline = undefined; - this.doReconnect(socket, buffer); - } - - public dispose(): void { - if (!this.disposed) { - this.disposed = true; - this.doDispose(); - this._onClose.fire(); - } - } - - protected setOffline(): void { - if (!this._offline) { - this._offline = Date.now(); - } - } - - /** - * Set up the connection on a new socket. - */ - protected abstract doReconnect(socket: ISocket, buffer: VSBuffer): void; - protected abstract doDispose(): void; -} - -/** - * Used for all the IPC channels. - */ -export class ManagementConnection extends Connection { - public constructor(protected protocol: Protocol, token: string) { - super(protocol, token); - protocol.onClose(() => this.dispose()); // Explicit close. - protocol.onSocketClose(() => this.setOffline()); // Might reconnect. - } - - protected doDispose(): void { - this.protocol.sendDisconnect(); - this.protocol.dispose(); - this.protocol.getSocket().end(); - } - - protected doReconnect(socket: ISocket, buffer: VSBuffer): void { - this.protocol.beginAcceptReconnection(socket, buffer); - this.protocol.endAcceptReconnection(); - } -} - -export class ExtensionHostConnection extends Connection { - private process?: cp.ChildProcess; - - public constructor( - locale:string, protocol: Protocol, buffer: VSBuffer, token: string, - private readonly log: ILogService, - private readonly environment: IEnvironmentService, - ) { - super(protocol, token); - this.protocol.dispose(); - this.spawn(locale, buffer).then((p) => this.process = p); - this.protocol.getUnderlyingSocket().pause(); - } - - protected doDispose(): void { - if (this.process) { - this.process.kill(); - } - this.protocol.getSocket().end(); - } - - protected doReconnect(socket: ISocket, buffer: VSBuffer): void { - // This is just to set the new socket. - this.protocol.beginAcceptReconnection(socket, null); - this.protocol.dispose(); - this.sendInitMessage(buffer); - } - - private sendInitMessage(buffer: VSBuffer): void { - const socket = this.protocol.getUnderlyingSocket(); - socket.pause(); - this.process!.send({ // Process must be set at this point. - type: "VSCODE_EXTHOST_IPC_SOCKET", - initialDataChunk: (buffer.buffer as Buffer).toString("base64"), - skipWebSocketFrames: this.protocol.getSocket() instanceof NodeSocket, - }, socket); - } - - private async spawn(locale: string, buffer: VSBuffer): Promise { - const config = await getNlsConfiguration(locale, this.environment.userDataPath); - const proc = cp.fork( - getPathFromAmdModule(require, "bootstrap-fork"), - [ "--type=extensionHost", `--uriTransformerPath=${uriTransformerPath}` ], - { - env: { - ...process.env, - AMD_ENTRYPOINT: "vs/workbench/services/extensions/node/extensionHostProcess", - PIPE_LOGGING: "true", - VERBOSE_LOGGING: "true", - VSCODE_EXTHOST_WILL_SEND_SOCKET: "true", - VSCODE_HANDLES_UNCAUGHT_ERRORS: "true", - VSCODE_LOG_STACK: "false", - VSCODE_LOG_LEVEL: this.environment.verbose ? "trace" : this.environment.log, - VSCODE_NLS_CONFIG: JSON.stringify(config), - }, - silent: true, - }, - ); - - proc.on("error", () => this.dispose()); - proc.on("exit", () => this.dispose()); - proc.stdout.setEncoding("utf8").on("data", (d) => this.log.info("Extension host stdout", d)); - proc.stderr.setEncoding("utf8").on("data", (d) => this.log.error("Extension host stderr", d)); - proc.on("message", (event) => { - if (event && event.type === "__$console") { - const severity = (this.log)[event.severity] ? event.severity : "info"; - (this.log)[severity]("Extension host", event.arguments); - } - if (event && event.type === "VSCODE_EXTHOST_DISCONNECTED") { - this.setOffline(); - } - }); - - const listen = (message: IExtHostReadyMessage) => { - if (message.type === "VSCODE_EXTHOST_IPC_READY") { - proc.removeListener("message", listen); - this.sendInitMessage(buffer); - } - }; - - return proc.on("message", listen); - } -} diff --git a/src/node/entry.ts b/src/node/entry.ts new file mode 100644 index 00000000..a2e2f60f --- /dev/null +++ b/src/node/entry.ts @@ -0,0 +1,87 @@ +import { logger } from "@coder/logger" +import { ApiHttpProvider } from "./api/server" +import { MainHttpProvider } from "./app/server" +import { AuthType, HttpServer } from "./http" +import { generateCertificate, generatePassword, hash, open } from "./util" +import { VscodeHttpProvider } from "./vscode/server" +import { ipcMain, wrap } from "./wrapper" + +export interface Args { + auth?: AuthType + "base-path"?: string + cert?: string + "cert-key"?: string + format?: string + host?: string + open?: boolean + port?: string + socket?: string + _?: string[] +} + +const main = async (args: Args = {}): Promise => { + // Spawn the main HTTP server. + const options = { + basePath: args["base-path"], + cert: args.cert, + certKey: args["cert-key"], + host: args.host || (args.auth === AuthType.Password && typeof args.cert !== "undefined" ? "0.0.0.0" : "localhost"), + port: typeof args.port !== "undefined" ? parseInt(args.port, 10) : 8080, + socket: args.socket, + } + if (!options.cert && typeof options.cert !== "undefined") { + const { cert, certKey } = await generateCertificate() + options.cert = cert + options.certKey = certKey + } + const httpServer = new HttpServer(options) + + // Register all the providers. + // TODO: Might be cleaner to be able to register with just the class name + // then let HttpServer instantiate with the common arguments. + const auth = args.auth || AuthType.Password + const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword())) + const password = originalPassword && hash(originalPassword) + httpServer.registerHttpProvider("/", new MainHttpProvider({ base: "/", auth, password })) + httpServer.registerHttpProvider("/api", new ApiHttpProvider(httpServer, { base: "/", auth, password })) + httpServer.registerHttpProvider( + "/vscode-embed", + new VscodeHttpProvider([], { base: "/vscode-embed", auth, password }) + ) + + ipcMain.onDispose(() => httpServer.dispose()) + + const serverAddress = await httpServer.listen() + logger.info(`Server listening on ${serverAddress}`) + + if (auth === AuthType.Password && !process.env.PASSWORD) { + logger.info(` - Password is ${originalPassword}`) + logger.info(" - To use your own password, set the PASSWORD environment variable") + if (!args.auth) { + logger.info(" - To disable use `--auth none`") + } + } else if (auth === AuthType.Password) { + logger.info(" - Using custom password for authentication") + } else { + logger.info(" - No authentication") + } + + if (httpServer.protocol === "https") { + logger.info( + args.cert + ? ` - Using provided certificate${args["cert-key"] ? " and key" : ""} for HTTPS` + : ` - Using generated certificate and key for HTTPS` + ) + } else { + logger.info(" - Not serving HTTPS") + } + + if (serverAddress && !options.socket && args.open) { + // The web socket doesn't seem to work if browsing with 0.0.0.0. + const openAddress = serverAddress.replace(/:\/\/0.0.0.0/, "://localhost") + await open(openAddress).catch(console.error) + logger.info(` - Opened ${openAddress}`) + } +} + +wrap(main) diff --git a/src/node/http.ts b/src/node/http.ts new file mode 100644 index 00000000..3982bdb2 --- /dev/null +++ b/src/node/http.ts @@ -0,0 +1,579 @@ +import { logger } from "@coder/logger" +import * as fs from "fs-extra" +import * as http from "http" +import * as httpolyglot from "httpolyglot" +import * as https from "https" +import * as net from "net" +import * as path from "path" +import * as querystring from "querystring" +import safeCompare from "safe-compare" +import { Readable } from "stream" +import * as tarFs from "tar-fs" +import * as tls from "tls" +import * as url from "url" +import { HttpCode, HttpError } from "../common/http" +import { plural, split } from "../common/util" +import { getMediaMime, normalize, xdgLocalDir } from "./util" + +export type Cookies = { [key: string]: string[] | undefined } +export type PostData = { [key: string]: string | string[] | undefined } + +interface AuthPayload extends Cookies { + key?: string[] +} + +export enum AuthType { + Password = "password", + None = "none", +} + +export type Query = { [key: string]: string | string[] | undefined } + +export interface HttpResponse { + /* + * Whether to set cache-control headers for this response. + */ + cache?: boolean + /** + * If the code cannot be determined automatically set it here. The + * defaults are 302 for redirects and 200 for successful requests. For errors + * you should throw an HttpError and include the code there. If you + * use Error it will default to 404 for ENOENT and EISDIR and 500 otherwise. + */ + code?: number + /** + * Content to write in the response. Mutually exclusive with stream. + */ + content?: T + /** + * Cookie to write with the response. + */ + cookie?: { key: string; value: string } + /** + * Used to automatically determine the appropriate mime type. + */ + filePath?: string + /** + * Additional headers to include. + */ + headers?: http.OutgoingHttpHeaders + /** + * If the mime type cannot be determined automatically set it here. + */ + mime?: string + /** + * Redirect to this path. Will rewrite against the base path but NOT the + * provider endpoint so you must include it. This allows redirecting outside + * of your endpoint. Use `withBase()` to redirect within your endpoint. + */ + redirect?: string + /** + * Stream this to the response. Mutually exclusive with content. + */ + stream?: Readable + /** + * Query variables to add in addition to current ones when redirecting. Use + * `undefined` to remove a query variable. + */ + query?: Query +} + +/** + * Use when you need to run search and replace on a file's content before + * sending it. + */ +export interface HttpStringFileResponse extends HttpResponse { + content: string + filePath: string +} + +export interface HttpServerOptions { + readonly basePath?: string + readonly cert?: string + readonly certKey?: string + readonly host?: string + readonly port?: number + readonly socket?: string +} + +interface ProviderRoute { + base: string + requestPath: string + query: querystring.ParsedUrlQuery + provider: HttpProvider + fullPath: string + originalPath: string +} + +export interface HttpProviderOptions { + readonly base: string + readonly auth: AuthType + readonly password: string | false +} + +/** + * Provides HTTP responses. This abstract class provides some helpers for + * interpreting, creating, and authenticating responses. + */ +export abstract class HttpProvider { + protected readonly rootPath = path.resolve(__dirname, "../..") + + public constructor(private readonly options: HttpProviderOptions) {} + + public dispose(): void { + // No default behavior. + } + + /** + * Handle web sockets on the registered endpoint. + */ + public abstract handleWebSocket( + base: string, + requestPath: string, + query: querystring.ParsedUrlQuery, + request: http.IncomingMessage, + socket: net.Socket, + head: Buffer + ): Promise + + /** + * Handle requests to the registered endpoint. + */ + public abstract handleRequest( + base: string, + requestPath: string, + query: querystring.ParsedUrlQuery, + request: http.IncomingMessage + ): Promise + + /** + * Return the specified path with the base path prepended. + */ + protected withBase(path: string): string { + return normalize(`${this.options.base}/${path}`) + } + + /** + * Get a file resource. + * TODO: Would a stream be faster, at least for large files? + */ + protected async getResource(...parts: string[]): Promise { + const filePath = path.join(...parts) + return { content: await fs.readFile(filePath), filePath } + } + + /** + * Get a file resource as a string. + */ + protected async getUtf8Resource(...parts: string[]): Promise { + const filePath = path.join(...parts) + return { content: await fs.readFile(filePath, "utf8"), filePath } + } + + /** + * Tar up and stream a directory. + */ + protected async getTarredResource(...parts: string[]): Promise { + const filePath = path.join(...parts) + return { stream: tarFs.pack(filePath), filePath, mime: "application/tar", cache: true } + } + + /** + * Helper to error on anything that's not a GET. + */ + protected ensureGet(request: http.IncomingMessage): void { + if (request.method !== "GET") { + throw new HttpError(`Unsupported method ${request.method}`, HttpCode.BadRequest) + } + } + + /** + * Helper to error if not authorized. + */ + protected ensureAuthenticated(request: http.IncomingMessage): void { + if (!this.authenticated(request)) { + throw new HttpError("Unauthorized", HttpCode.Unauthorized) + } + } + + /** + * Use the first query value or the default if there isn't one. + */ + protected queryOrDefault(value: string | string[] | undefined, def: string): string { + if (Array.isArray(value)) { + value = value[0] + } + return typeof value !== "undefined" ? value : def + } + + /** + * Return the provided password value if the payload contains the right + * password otherwise return false. If no payload is specified use cookies. + */ + protected authenticated(request: http.IncomingMessage, payload?: AuthPayload): string | boolean { + switch (this.options.auth) { + case AuthType.None: + return true + case AuthType.Password: + if (typeof payload === "undefined") { + payload = this.parseCookies(request) + } + if (this.options.password && payload.key) { + for (let i = 0; i < payload.key.length; ++i) { + if (safeCompare(payload.key[i], this.options.password)) { + return payload.key[i] + } + } + } + return false + default: + throw new Error(`Unsupported auth type ${this.options.auth}`) + } + } + + /** + * Parse POST data. + */ + protected getData(request: http.IncomingMessage): Promise { + return request.method === "POST" || request.method === "DELETE" + ? new Promise((resolve, reject) => { + let body = "" + const onEnd = (): void => { + off() // eslint-disable-line @typescript-eslint/no-use-before-define + resolve(body || undefined) + } + const onError = (error: Error): void => { + off() // eslint-disable-line @typescript-eslint/no-use-before-define + reject(error) + } + const onData = (d: Buffer): void => { + body += d + if (body.length > 1e6) { + onError(new HttpError("Payload is too large", HttpCode.LargePayload)) + request.connection.destroy() + } + } + const off = (): void => { + request.off("error", onError) + request.off("data", onError) + request.off("end", onEnd) + } + request.on("error", onError) + request.on("data", onData) + request.on("end", onEnd) + }) + : Promise.resolve(undefined) + } + + /** + * Parse cookies. + */ + protected parseCookies(request: http.IncomingMessage): T { + const cookies: { [key: string]: string[] } = {} + if (request.headers.cookie) { + request.headers.cookie.split(";").forEach((keyValue) => { + const [key, value] = split(keyValue, "=") + if (!cookies[key]) { + cookies[key] = [] + } + cookies[key].push(decodeURI(value)) + }) + } + return cookies as T + } +} + +/** + * Provides a heartbeat using a local file to indicate activity. + */ +export class Heart { + private heartbeatTimer?: NodeJS.Timeout + private heartbeatInterval = 60000 + private lastHeartbeat = 0 + + public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise) {} + + /** + * Write to the heartbeat file if we haven't already done so within the + * timeout and start or reset a timer that keeps running as long as there is + * activity. Failures are logged as warnings. + */ + public beat(): void { + const now = Date.now() + if (now - this.lastHeartbeat >= this.heartbeatInterval) { + logger.trace("heartbeat") + fs.outputFile(this.heartbeatPath, "").catch((error) => { + logger.warn(error.message) + }) + this.lastHeartbeat = now + if (typeof this.heartbeatTimer !== "undefined") { + clearTimeout(this.heartbeatTimer) + } + this.heartbeatTimer = setTimeout(() => { + this.isActive().then((active) => { + if (active) { + this.beat() + } + }) + }, this.heartbeatInterval) + } + } +} + +/** + * An HTTP server. Its main role is to route incoming HTTP requests to the + * appropriate provider for that endpoint then write out the response. It also + * covers some common use cases like redirects and caching. + */ +export class HttpServer { + protected readonly server: http.Server | https.Server + private listenPromise: Promise | undefined + public readonly protocol: "http" | "https" + private readonly providers = new Map() + private readonly options: HttpServerOptions + private readonly heart: Heart + + public constructor(options: HttpServerOptions) { + this.heart = new Heart(path.join(xdgLocalDir, "heartbeat"), async () => { + const connections = await this.getConnections() + logger.trace(`${connections} active connection${plural(connections)}`) + return connections !== 0 + }) + this.options = { + ...options, + basePath: options.basePath ? options.basePath.replace(/\/+$/, "") : "", + } + this.protocol = this.options.cert ? "https" : "http" + if (this.protocol === "https") { + this.server = httpolyglot.createServer( + { + cert: this.options.cert && fs.readFileSync(this.options.cert), + key: this.options.certKey && fs.readFileSync(this.options.certKey), + }, + this.onRequest + ) + } else { + this.server = http.createServer(this.onRequest) + } + } + + public dispose(): void { + this.providers.forEach((p) => p.dispose()) + } + + public async getConnections(): Promise { + return new Promise((resolve, reject) => { + this.server.getConnections((error, count) => { + return error ? reject(error) : resolve(count) + }) + }) + } + + /** + * Register a provider for a top-level endpoint. + */ + public registerHttpProvider(endpoint: string, provider: T): void { + endpoint = endpoint.replace(/^\/+|\/+$/g, "") + if (this.providers.has(`/${endpoint}`)) { + throw new Error(`${endpoint} is already registered`) + } + if (/\//.test(endpoint)) { + throw new Error(`Only top-level endpoints are supported (got ${endpoint})`) + } + this.providers.set(`/${endpoint}`, provider) + } + + /** + * Start listening on the specified port. + */ + public listen(): Promise { + if (!this.listenPromise) { + this.listenPromise = new Promise((resolve, reject) => { + this.server.on("error", reject) + this.server.on("upgrade", this.onUpgrade) + const onListen = (): void => resolve(this.address()) + if (this.options.socket) { + this.server.listen(this.options.socket, onListen) + } else { + this.server.listen(this.options.port, this.options.host, onListen) + } + }) + } + return this.listenPromise + } + + /** + * The *local* address of the server. + */ + public address(): string | null { + const address = this.server.address() + const endpoint = + typeof address !== "string" && address !== null + ? (address.address === "::" ? "localhost" : address.address) + ":" + address.port + : address + return endpoint && `${this.protocol}://${endpoint}` + } + + private onRequest = async (request: http.IncomingMessage, response: http.ServerResponse): Promise => { + try { + this.heart.beat() + const route = this.parseUrl(request) + const payload = + this.maybeRedirect(request, route) || + (await route.provider.handleRequest(route.base, route.requestPath, route.query, request)) + if (!payload) { + throw new HttpError("Not found", HttpCode.NotFound) + } + const basePath = this.options.basePath || "/" + response.writeHead(payload.redirect ? HttpCode.Redirect : payload.code || HttpCode.Ok, { + "Content-Type": payload.mime || getMediaMime(payload.filePath), + ...(payload.redirect + ? { + Location: this.constructRedirect( + request.headers.host as string, + route.fullPath, + normalize(`${basePath}/${payload.redirect}`) + "/", + { ...route.query, ...(payload.query || {}) } + ), + } + : {}), + ...(request.headers["service-worker"] ? { "Service-Worker-Allowed": basePath } : {}), + ...(payload.cache ? { "Cache-Control": "public, max-age=31536000" } : {}), + ...(payload.cookie + ? { + "Set-Cookie": `${payload.cookie.key}=${payload.cookie.value}; Path=${basePath}; HttpOnly; SameSite=strict`, + } + : {}), + ...payload.headers, + }) + if (payload.stream) { + payload.stream.on("error", (error: NodeJS.ErrnoException) => { + response.writeHead(error.code === "ENOENT" ? HttpCode.NotFound : HttpCode.ServerError) + response.end(error.message) + }) + payload.stream.pipe(response) + } else if (typeof payload.content === "string" || payload.content instanceof Buffer) { + response.end(payload.content) + } else if (payload.content && typeof payload.content === "object") { + response.end(JSON.stringify(payload.content)) + } else { + response.end() + } + } catch (error) { + let e = error + if (error.code === "ENOENT" || error.code === "EISDIR") { + e = new HttpError("Not found", HttpCode.NotFound) + } else { + logger.error(error.stack) + } + response.writeHead(typeof e.code === "number" ? e.code : HttpCode.ServerError) + response.end(error.message) + } + } + + /** + * Return any necessary redirection before delegating to a provider. + */ + private maybeRedirect(request: http.IncomingMessage, route: ProviderRoute): HttpResponse | undefined { + // Redirect to HTTPS. + if (this.options.cert && !(request.connection as tls.TLSSocket).encrypted) { + return { redirect: route.fullPath } + } + // Redirect indexes to a trailing slash so relative paths will operate + // against the provider. + if (route.requestPath === "/index.html" && !route.originalPath.endsWith("/")) { + return { redirect: route.fullPath } // Redirect always includes a trailing slash. + } + return undefined + } + + private onUpgrade = async (request: http.IncomingMessage, socket: net.Socket, head: Buffer): Promise => { + try { + this.heart.beat() + socket.on("error", () => socket.destroy()) + + if (this.options.cert && !(socket as tls.TLSSocket).encrypted) { + throw new HttpError("HTTP websocket", HttpCode.BadRequest) + } + + if (!request.headers.upgrade || request.headers.upgrade.toLowerCase() !== "websocket") { + throw new HttpError("HTTP/1.1 400 Bad Request", HttpCode.BadRequest) + } + + const { base, requestPath, query, provider } = this.parseUrl(request) + if (!provider) { + throw new HttpError("Not found", HttpCode.NotFound) + } + + if (!(await provider.handleWebSocket(base, requestPath, query, request, socket, head))) { + throw new HttpError("Not found", HttpCode.NotFound) + } + } catch (error) { + socket.destroy(error) + logger.warn(`discarding socket connection: ${error.message}`) + } + } + + /** + * Parse a request URL so we can route it. + */ + private parseUrl(request: http.IncomingMessage): ProviderRoute { + const parse = (fullPath: string): { base: string; requestPath: string } => { + const match = fullPath.match(/^(\/?[^/]*)(.*)$/) + let [, /* ignore */ base, requestPath] = match ? match.map((p) => p.replace(/\/+$/, "")) : ["", "", ""] + if (base.indexOf(".") !== -1) { + // Assume it's a file at the root. + requestPath = base + base = "/" + } else if (base === "") { + // Happens if it's a plain `domain.com`. + base = "/" + } + requestPath = requestPath || "/index.html" + // Allow for a versioned static endpoint. This lets us cache every static + // resource underneath the path based on the version without any work and + // without adding query parameters which have their own issues. + if (/^\/static-/.test(base)) { + base = "/static" + } + + return { base, requestPath } + } + + const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}, pathname: "" } + const originalPath = parsedUrl.pathname || "" + const fullPath = normalize(originalPath) + const { base, requestPath } = parse(fullPath) + + // Providers match on the path after their base so we need to account for + // that by shifting the next base out of the request path. + let provider = this.providers.get(base) + if (base !== "/" && provider) { + return { ...parse(requestPath), fullPath, query: parsedUrl.query, provider, originalPath } + } + + // Fall back to the top-level provider. + provider = this.providers.get("/") + if (!provider) { + throw new Error(`No provider for ${base}`) + } + return { base, fullPath, requestPath, query: parsedUrl.query, provider, originalPath } + } + + /** + * Return the request URL with the specified base and new path. + */ + private constructRedirect(host: string, oldPath: string, newPath: string, query: Query): string { + if (oldPath && oldPath !== "/" && !query.to && /\/login(\/|$)/.test(newPath) && !/\/login(\/|$)/.test(oldPath)) { + query.to = oldPath + } + Object.keys(query).forEach((key) => { + if (typeof query[key] === "undefined") { + delete query[key] + } + }) + return ( + `${this.protocol}://${host}${newPath}` + (Object.keys(query).length > 0 ? `?${querystring.stringify(query)}` : "") + ) + } +} diff --git a/src/node/insights.ts b/src/node/insights.ts deleted file mode 100644 index 691d9e3e..00000000 --- a/src/node/insights.ts +++ /dev/null @@ -1,124 +0,0 @@ -import * as appInsights from "applicationinsights"; -import * as https from "https"; -import * as http from "http"; -import * as os from "os"; - -class Channel { - public get _sender() { - throw new Error("unimplemented"); - } - public get _buffer() { - throw new Error("unimplemented"); - } - - public setUseDiskRetryCaching(): void { - throw new Error("unimplemented"); - } - public send(): void { - throw new Error("unimplemented"); - } - public triggerSend(): void { - throw new Error("unimplemented"); - } -} - -export class TelemetryClient { - public context: any = undefined; - public commonProperties: any = undefined; - public config: any = {}; - - public channel: any = new Channel(); - - public addTelemetryProcessor(): void { - throw new Error("unimplemented"); - } - - public clearTelemetryProcessors(): void { - throw new Error("unimplemented"); - } - - public runTelemetryProcessors(): void { - throw new Error("unimplemented"); - } - - public trackTrace(): void { - throw new Error("unimplemented"); - } - - public trackMetric(): void { - throw new Error("unimplemented"); - } - - public trackException(): void { - throw new Error("unimplemented"); - } - - public trackRequest(): void { - throw new Error("unimplemented"); - } - - public trackDependency(): void { - throw new Error("unimplemented"); - } - - public track(): void { - throw new Error("unimplemented"); - } - - public trackNodeHttpRequestSync(): void { - throw new Error("unimplemented"); - } - - public trackNodeHttpRequest(): void { - throw new Error("unimplemented"); - } - - public trackNodeHttpDependency(): void { - throw new Error("unimplemented"); - } - - public trackEvent(options: appInsights.Contracts.EventTelemetry): void { - if (!options.properties) { - options.properties = {}; - } - if (!options.measurements) { - options.measurements = {}; - } - - try { - const cpus = os.cpus(); - options.measurements.cores = cpus.length; - options.properties["common.cpuModel"] = cpus[0].model; - } catch (error) {} - - try { - options.measurements.memoryFree = os.freemem(); - options.measurements.memoryTotal = os.totalmem(); - } catch (error) {} - - try { - options.properties["common.shell"] = os.userInfo().shell; - options.properties["common.release"] = os.release(); - options.properties["common.arch"] = os.arch(); - } catch (error) {} - - try { - const url = process.env.TELEMETRY_URL || "https://v1.telemetry.coder.com/track"; - const request = (/^http:/.test(url) ? http : https).request(url, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - }); - request.on("error", () => { /* We don"t care. */ }); - request.write(JSON.stringify(options)); - request.end(); - } catch (error) {} - } - - public flush(options: { callback: (v: string) => void }): void { - if (options.callback) { - options.callback(""); - } - } -} diff --git a/src/node/ipc.ts b/src/node/ipc.ts deleted file mode 100644 index c92ea872..00000000 --- a/src/node/ipc.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as cp from "child_process"; -import { Emitter } from "vs/base/common/event"; - -enum ControlMessage { - okToChild = "ok>", - okFromChild = "ok<", -} - -interface RelaunchMessage { - type: "relaunch"; - version: string; -} - -export type Message = RelaunchMessage; - -class IpcMain { - protected readonly _onMessage = new Emitter(); - public readonly onMessage = this._onMessage.event; - - public handshake(child?: cp.ChildProcess): Promise { - return new Promise((resolve, reject) => { - const target = child || process; - if (!target.send) { - throw new Error("Not spawned with IPC enabled"); - } - target.on("message", (message) => { - if (message === child ? ControlMessage.okFromChild : ControlMessage.okToChild) { - target.removeAllListeners(); - target.on("message", (msg) => this._onMessage.fire(msg)); - if (child) { - target.send!(ControlMessage.okToChild); - } - resolve(); - } - }); - if (child) { - child.once("error", reject); - child.once("exit", (code) => { - const error = new Error(`Unexpected exit with code ${code}`); - (error as any).code = code; - reject(error); - }); - } else { - target.send(ControlMessage.okFromChild); - } - }); - } - - public relaunch(version: string): void { - this.send({ type: "relaunch", version }); - } - - private send(message: Message): void { - if (!process.send) { - throw new Error("Not a child process with IPC enabled"); - } - process.send(message); - } -} - -export const ipcMain = new IpcMain(); diff --git a/src/node/marketplace.ts b/src/node/marketplace.ts deleted file mode 100644 index 9aec797c..00000000 --- a/src/node/marketplace.ts +++ /dev/null @@ -1,176 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import * as util from "util"; -import { CancellationToken } from "vs/base/common/cancellation"; -import { mkdirp } from "vs/base/node/pfs"; -import * as vszip from "vs/base/node/zip"; -import * as nls from "vs/nls"; -import product from "vs/platform/product/common/product"; -import { localRequire } from "vs/server/src/node/util"; - -const tarStream = localRequire("tar-stream/index"); - -// We will be overriding these, so keep a reference to the original. -const vszipExtract = vszip.extract; -const vszipBuffer = vszip.buffer; - -export interface IExtractOptions { - overwrite?: boolean; - /** - * Source path within the TAR/ZIP archive. Only the files - * contained in this path will be extracted. - */ - sourcePath?: string; -} - -export interface IFile { - path: string; - contents?: Buffer | string; - localPath?: string; -} - -export const tar = async (tarPath: string, files: IFile[]): Promise => { - const pack = tarStream.pack(); - const chunks: Buffer[] = []; - const ended = new Promise((resolve) => { - pack.on("end", () => resolve(Buffer.concat(chunks))); - }); - pack.on("data", (chunk: Buffer) => chunks.push(chunk)); - for (let i = 0; i < files.length; i++) { - const file = files[i]; - pack.entry({ name: file.path }, file.contents); - } - pack.finalize(); - await util.promisify(fs.writeFile)(tarPath, await ended); - return tarPath; -}; - -export const extract = async (archivePath: string, extractPath: string, options: IExtractOptions = {}, token: CancellationToken): Promise => { - try { - await extractTar(archivePath, extractPath, options, token); - } catch (error) { - if (error.toString().includes("Invalid tar header")) { - await vszipExtract(archivePath, extractPath, options, token); - } - } -}; - -export const buffer = (targetPath: string, filePath: string): Promise => { - return new Promise(async (resolve, reject) => { - try { - let done: boolean = false; - await extractAssets(targetPath, new RegExp(filePath), (assetPath: string, data: Buffer) => { - if (path.normalize(assetPath) === path.normalize(filePath)) { - done = true; - resolve(data); - } - }); - if (!done) { - throw new Error("couldn't find asset " + filePath); - } - } catch (error) { - if (error.toString().includes("Invalid tar header")) { - vszipBuffer(targetPath, filePath).then(resolve).catch(reject); - } else { - reject(error); - } - } - }); -}; - -const extractAssets = async (tarPath: string, match: RegExp, callback: (path: string, data: Buffer) => void): Promise => { - return new Promise((resolve, reject): void => { - const extractor = tarStream.extract(); - const fail = (error: Error) => { - extractor.destroy(); - reject(error); - }; - extractor.once("error", fail); - extractor.on("entry", async (header, stream, next) => { - const name = header.name; - if (match.test(name)) { - extractData(stream).then((data) => { - callback(name, data); - next(); - }).catch(fail); - } else { - stream.on("end", () => next()); - stream.resume(); // Just drain it. - } - }); - extractor.on("finish", resolve); - fs.createReadStream(tarPath).pipe(extractor); - }); -}; - -const extractData = (stream: NodeJS.ReadableStream): Promise => { - return new Promise((resolve, reject): void => { - const fileData: Buffer[] = []; - stream.on("error", reject); - stream.on("end", () => resolve(Buffer.concat(fileData))); - stream.on("data", (data) => fileData.push(data)); - }); -}; - -const extractTar = async (tarPath: string, targetPath: string, options: IExtractOptions = {}, token: CancellationToken): Promise => { - return new Promise((resolve, reject): void => { - const sourcePathRegex = new RegExp(options.sourcePath ? `^${options.sourcePath}` : ""); - const extractor = tarStream.extract(); - const fail = (error: Error) => { - extractor.destroy(); - reject(error); - }; - extractor.once("error", fail); - extractor.on("entry", async (header, stream, next) => { - const nextEntry = (): void => { - stream.on("end", () => next()); - stream.resume(); - }; - - const rawName = path.normalize(header.name); - if (token.isCancellationRequested || !sourcePathRegex.test(rawName)) { - return nextEntry(); - } - - const fileName = rawName.replace(sourcePathRegex, ""); - const targetFileName = path.join(targetPath, fileName); - if (/\/$/.test(fileName)) { - return mkdirp(targetFileName).then(nextEntry); - } - - const dirName = path.dirname(fileName); - const targetDirName = path.join(targetPath, dirName); - if (targetDirName.indexOf(targetPath) !== 0) { - return fail(new Error(nls.localize("invalid file", "Error extracting {0}. Invalid file.", fileName))); - } - - await mkdirp(targetDirName, undefined); - - const fstream = fs.createWriteStream(targetFileName, { mode: header.mode }); - fstream.once("close", () => next()); - fstream.once("error", fail); - stream.pipe(fstream); - }); - extractor.once("finish", resolve); - fs.createReadStream(tarPath).pipe(extractor); - }); -}; - -/** - * Override original functionality so we can use a custom marketplace with - * either tars or zips. - */ -export const enableCustomMarketplace = (): void => { - (product).extensionsGallery = { // Use `any` to override readonly. - serviceUrl: process.env.SERVICE_URL || "https://v1.extapi.coder.com", - itemUrl: process.env.ITEM_URL || "", - controlUrl: "", - recommendationsUrl: "", - ...(product.extensionsGallery || {}), - }; - - const target = vszip as typeof vszip; - target.zip = tar; - target.extract = extract; - target.buffer = buffer; -}; diff --git a/src/node/nls.ts b/src/node/nls.ts deleted file mode 100644 index 6f8d4e3d..00000000 --- a/src/node/nls.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import * as util from "util"; -import { getPathFromAmdModule } from "vs/base/common/amd"; -import * as lp from "vs/base/node/languagePacks"; -import product from "vs/platform/product/common/product"; -import { Translations } from "vs/workbench/services/extensions/common/extensionPoints"; - -const configurations = new Map>(); -const metadataPath = path.join(getPathFromAmdModule(require, ""), "nls.metadata.json"); - -export const isInternalConfiguration = (config: lp.NLSConfiguration): config is lp.InternalNLSConfiguration => { - return config && !!(config)._languagePackId; -}; - -const DefaultConfiguration = { - locale: "en", - availableLanguages: {}, -}; - -export const getNlsConfiguration = async (locale: string, userDataPath: string): Promise => { - const id = `${locale}: ${userDataPath}`; - if (!configurations.has(id)) { - configurations.set(id, new Promise(async (resolve) => { - const config = product.commit && await util.promisify(fs.exists)(metadataPath) - ? await lp.getNLSConfiguration(product.commit, userDataPath, metadataPath, locale) - : DefaultConfiguration; - if (isInternalConfiguration(config)) { - config._languagePackSupport = true; - } - // If the configuration has no results keep trying since code-server - // doesn't restart when a language is installed so this result would - // persist (the plugin might not be installed yet or something). - if (config.locale !== "en" && config.locale !== "en-us" && Object.keys(config.availableLanguages).length === 0) { - configurations.delete(id); - } - resolve(config); - })); - } - return configurations.get(id)!; -}; - -export const getTranslations = async (locale: string, userDataPath: string): Promise => { - const config = await getNlsConfiguration(locale, userDataPath); - if (isInternalConfiguration(config)) { - try { - return JSON.parse(await util.promisify(fs.readFile)(config._translationsConfigFile, "utf8")); - } catch (error) { /* Nothing yet. */} - } - return {}; -}; - -export const getLocaleFromConfig = async (userDataPath: string): Promise => { - let locale = "en"; - try { - const localeConfigUri = path.join(userDataPath, "User/locale.json"); - const content = stripComments(await util.promisify(fs.readFile)(localeConfigUri, "utf8")); - locale = JSON.parse(content).locale; - } catch (error) { /* Ignore. */ } - return locale; -}; - -// Taken from src/main.js in the main VS Code source. -const stripComments = (content: string): string => { - const regexp = /("(?:[^\\"]*(?:\\.)?)*")|('(?:[^\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g; - - return content.replace(regexp, (match, _m1, _m2, m3, m4) => { - // Only one of m1, m2, m3, m4 matches - if (m3) { - // A block comment. Replace with nothing - return ''; - } else if (m4) { - // A line comment. If it ends in \r?\n then keep it. - const length_1 = m4.length; - if (length_1 > 2 && m4[length_1 - 1] === '\n') { - return m4[length_1 - 2] === '\r' ? '\r\n' : '\n'; - } - else { - return ''; - } - } else { - // We match a string - return match; - } - }); -}; diff --git a/src/node/protocol.ts b/src/node/protocol.ts deleted file mode 100644 index fde6662a..00000000 --- a/src/node/protocol.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as net from "net"; -import { VSBuffer } from "vs/base/common/buffer"; -import { PersistentProtocol } from "vs/base/parts/ipc/common/ipc.net"; -import { NodeSocket, WebSocketNodeSocket } from "vs/base/parts/ipc/node/ipc.net"; -import { AuthRequest, ConnectionTypeRequest, HandshakeMessage } from "vs/platform/remote/common/remoteAgentConnection"; - -export interface SocketOptions { - readonly reconnectionToken: string; - readonly reconnection: boolean; - readonly skipWebSocketFrames: boolean; -} - -export class Protocol extends PersistentProtocol { - public constructor(socket: net.Socket, public readonly options: SocketOptions) { - super( - options.skipWebSocketFrames - ? new NodeSocket(socket) - : new WebSocketNodeSocket(new NodeSocket(socket)), - ); - } - - public getUnderlyingSocket(): net.Socket { - const socket = this.getSocket(); - return socket instanceof NodeSocket - ? socket.socket - : (socket as WebSocketNodeSocket).socket.socket; - } - - /** - * Perform a handshake to get a connection request. - */ - public handshake(): Promise { - return new Promise((resolve, reject) => { - const handler = this.onControlMessage((rawMessage) => { - try { - const message = JSON.parse(rawMessage.toString()); - switch (message.type) { - case "auth": return this.authenticate(message); - case "connectionType": - handler.dispose(); - return resolve(message); - default: throw new Error("Unrecognized message type"); - } - } catch (error) { - handler.dispose(); - reject(error); - } - }); - }); - } - - /** - * TODO: This ignores the authentication process entirely for now. - */ - private authenticate(_message: AuthRequest): void { - this.sendMessage({ type: "sign", data: "" }); - } - - /** - * TODO: implement. - */ - public tunnel(): void { - throw new Error("Tunnel is not implemented yet"); - } - - /** - * Send a handshake message. In the case of the extension host, it just sends - * back a debug port. - */ - public sendMessage(message: HandshakeMessage | { debugPort?: number } ): void { - this.sendControl(VSBuffer.fromString(JSON.stringify(message))); - } -} diff --git a/src/node/server.ts b/src/node/server.ts deleted file mode 100644 index bce26612..00000000 --- a/src/node/server.ts +++ /dev/null @@ -1,957 +0,0 @@ -import * as crypto from "crypto"; -import * as fs from "fs"; -import * as http from "http"; -import * as https from "https"; -import * as net from "net"; -import * as path from "path"; -import * as querystring from "querystring"; -import { Readable } from "stream"; -import * as tls from "tls"; -import * as url from "url"; -import * as util from "util"; -import { Emitter } from "vs/base/common/event"; -import { sanitizeFilePath } from "vs/base/common/extpath"; -import { Schemas } from "vs/base/common/network"; -import { URI, UriComponents } from "vs/base/common/uri"; -import { generateUuid } from "vs/base/common/uuid"; -import { getMachineId } from 'vs/base/node/id'; -import { NLSConfiguration } from "vs/base/node/languagePacks"; -import { mkdirp, rimraf } from "vs/base/node/pfs"; -import { ClientConnectionEvent, IPCServer, IServerChannel } from "vs/base/parts/ipc/common/ipc"; -import { createChannelReceiver } from "vs/base/parts/ipc/node/ipc"; -import { LogsDataCleaner } from "vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner"; -import { IConfigurationService } from "vs/platform/configuration/common/configuration"; -import { ConfigurationService } from "vs/platform/configuration/node/configurationService"; -import { ExtensionHostDebugBroadcastChannel } from "vs/platform/debug/common/extensionHostDebugIpc"; -import { IEnvironmentService, ParsedArgs } from "vs/platform/environment/common/environment"; -import { EnvironmentService } from "vs/platform/environment/node/environmentService"; -import { ExtensionGalleryService } from "vs/platform/extensionManagement/common/extensionGalleryService"; -import { IExtensionGalleryService, IExtensionManagementService } from "vs/platform/extensionManagement/common/extensionManagement"; -import { ExtensionManagementChannel } from "vs/platform/extensionManagement/common/extensionManagementIpc"; -import { ExtensionManagementService } from "vs/platform/extensionManagement/node/extensionManagementService"; -import { IFileService } from "vs/platform/files/common/files"; -import { FileService } from "vs/platform/files/common/fileService"; -import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider"; -import { SyncDescriptor } from "vs/platform/instantiation/common/descriptors"; -import { InstantiationService } from "vs/platform/instantiation/common/instantiationService"; -import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; -import { ILocalizationsService } from "vs/platform/localizations/common/localizations"; -import { LocalizationsService } from "vs/platform/localizations/node/localizations"; -import { getLogLevel, ILogService } from "vs/platform/log/common/log"; -import { LoggerChannel } from "vs/platform/log/common/logIpc"; -import { SpdLogService } from "vs/platform/log/node/spdlogService"; -import product from 'vs/platform/product/common/product'; -import { IProductService } from "vs/platform/product/common/productService"; -import { ConnectionType, ConnectionTypeRequest } from "vs/platform/remote/common/remoteAgentConnection"; -import { RemoteAgentConnectionContext } from "vs/platform/remote/common/remoteAgentEnvironment"; -import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from "vs/platform/remote/common/remoteAgentFileSystemChannel"; -import { IRequestService } from "vs/platform/request/common/request"; -import { RequestChannel } from "vs/platform/request/common/requestIpc"; -import { RequestService } from "vs/platform/request/node/requestService"; -import ErrorTelemetry from "vs/platform/telemetry/browser/errorTelemetry"; -import { ITelemetryService } from "vs/platform/telemetry/common/telemetry"; -import { ITelemetryServiceConfig, TelemetryService } from "vs/platform/telemetry/common/telemetryService"; -import { combinedAppender, LogAppender, NullTelemetryService } from "vs/platform/telemetry/common/telemetryUtils"; -import { AppInsightsAppender } from "vs/platform/telemetry/node/appInsightsAppender"; -import { resolveCommonProperties } from "vs/platform/telemetry/node/commonProperties"; -import { UpdateChannel } from "vs/platform/update/electron-main/updateIpc"; -import { INodeProxyService, NodeProxyChannel } from "vs/server/src/common/nodeProxy"; -import { TelemetryChannel } from "vs/server/src/common/telemetry"; -import { split } from "vs/server/src/common/util"; -import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService } from "vs/server/src/node/channel"; -import { Connection, ExtensionHostConnection, ManagementConnection } from "vs/server/src/node/connection"; -import { TelemetryClient } from "vs/server/src/node/insights"; -import { getLocaleFromConfig, getNlsConfiguration } from "vs/server/src/node/nls"; -import { Protocol } from "vs/server/src/node/protocol"; -import { UpdateService } from "vs/server/src/node/update"; -import { AuthType, getMediaMime, getUriTransformer, hash, localRequire, tmpdir } from "vs/server/src/node/util"; -import { RemoteExtensionLogFileName } from "vs/workbench/services/remote/common/remoteAgentService"; -import { IWorkbenchConstructionOptions } from "vs/workbench/workbench.web.api"; - -const tarFs = localRequire("tar-fs/index"); - -export enum HttpCode { - Ok = 200, - Redirect = 302, - NotFound = 404, - BadRequest = 400, - Unauthorized = 401, - LargePayload = 413, - ServerError = 500, -} - -export interface Options { - WORKBENCH_WEB_CONFIGURATION: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents }; - REMOTE_USER_DATA_URI: UriComponents | URI; - PRODUCT_CONFIGURATION: Partial; - NLS_CONFIGURATION: NLSConfiguration; -} - -export interface Response { - cache?: boolean; - code?: number; - content?: string | Buffer; - filePath?: string; - headers?: http.OutgoingHttpHeaders; - mime?: string; - redirect?: string; - stream?: Readable; -} - -export interface LoginPayload { - password?: string; -} - -export interface AuthPayload { - key?: string[]; -} - -export class HttpError extends Error { - public constructor(message: string, public readonly code: number) { - super(message); - // @ts-ignore - this.name = this.constructor.name; - Error.captureStackTrace(this, this.constructor); - } -} - -export interface ServerOptions { - readonly auth: AuthType; - readonly basePath?: string; - readonly connectionToken?: string; - readonly cert?: string; - readonly certKey?: string; - readonly openUri?: string; - readonly host?: string; - readonly password?: string; - readonly port?: number; - readonly socket?: string; -} - -export abstract class Server { - protected readonly server: http.Server | https.Server; - protected rootPath = path.resolve(__dirname, "../../../../.."); - protected serverRoot = path.join(this.rootPath, "/out/vs/server/src"); - protected readonly allowedRequestPaths: string[] = [this.rootPath]; - private listenPromise: Promise | undefined; - public readonly protocol: "http" | "https"; - public readonly options: ServerOptions; - - public constructor(options: ServerOptions) { - this.options = { - host: options.auth === "password" && options.cert ? "0.0.0.0" : "localhost", - ...options, - basePath: options.basePath ? options.basePath.replace(/\/+$/, "") : "", - password: options.password ? hash(options.password) : undefined, - }; - this.protocol = this.options.cert ? "https" : "http"; - if (this.protocol === "https") { - const httpolyglot = localRequire("httpolyglot/lib/index"); - this.server = httpolyglot.createServer({ - cert: this.options.cert && fs.readFileSync(this.options.cert), - key: this.options.certKey && fs.readFileSync(this.options.certKey), - }, this.onRequest); - } else { - this.server = http.createServer(this.onRequest); - } - } - - public listen(): Promise { - if (!this.listenPromise) { - this.listenPromise = new Promise((resolve, reject) => { - this.server.on("error", reject); - this.server.on("upgrade", this.onUpgrade); - const onListen = () => resolve(this.address()); - if (this.options.socket) { - this.server.listen(this.options.socket, onListen); - } else { - this.server.listen(this.options.port, this.options.host, onListen); - } - }); - } - return this.listenPromise; - } - - /** - * The *local* address of the server. - */ - public address(): string { - const address = this.server.address(); - const endpoint = typeof address !== "string" - ? (address.address === "::" ? "localhost" : address.address) + ":" + address.port - : address; - return `${this.protocol}://${endpoint}`; - } - - protected abstract handleWebSocket( - socket: net.Socket, - parsedUrl: url.UrlWithParsedQuery - ): Promise; - - protected abstract handleRequest( - base: string, - requestPath: string, - parsedUrl: url.UrlWithParsedQuery, - request: http.IncomingMessage, - ): Promise; - - protected async getResource(...parts: string[]): Promise { - const filePath = this.ensureAuthorizedFilePath(...parts); - return { content: await util.promisify(fs.readFile)(filePath), filePath }; - } - - protected async getAnyResource(...parts: string[]): Promise { - const filePath = path.join(...parts); - return { content: await util.promisify(fs.readFile)(filePath), filePath }; - } - - protected async getTarredResource(...parts: string[]): Promise { - const filePath = this.ensureAuthorizedFilePath(...parts); - return { stream: tarFs.pack(filePath), filePath, mime: "application/tar", cache: true }; - } - - protected ensureAuthorizedFilePath(...parts: string[]): string { - const filePath = path.join(...parts); - if (!this.isAllowedRequestPath(filePath)) { - throw new HttpError("Unauthorized", HttpCode.Unauthorized); - } - return filePath; - } - - protected withBase(request: http.IncomingMessage, path: string): string { - const [, query] = request.url ? split(request.url, "?") : []; - return `${this.protocol}://${request.headers.host}${this.options.basePath}${path}${query ? `?${query}` : ""}`; - } - - private isAllowedRequestPath(path: string): boolean { - for (let i = 0; i < this.allowedRequestPaths.length; ++i) { - if (path.indexOf(this.allowedRequestPaths[i]) === 0) { - return true; - } - } - return false; - } - - private onRequest = async (request: http.IncomingMessage, response: http.ServerResponse): Promise => { - try { - const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}}; - const payload = await this.preHandleRequest(request, parsedUrl); - response.writeHead(payload.redirect ? HttpCode.Redirect : payload.code || HttpCode.Ok, { - "Content-Type": payload.mime || getMediaMime(payload.filePath), - ...(payload.redirect ? { Location: this.withBase(request, payload.redirect) } : {}), - ...(request.headers["service-worker"] ? { "Service-Worker-Allowed": this.options.basePath || "/" } : {}), - ...(payload.cache ? { "Cache-Control": "public, max-age=31536000" } : {}), - ...payload.headers, - }); - if (payload.stream) { - payload.stream.on("error", (error: NodeJS.ErrnoException) => { - response.writeHead(error.code === "ENOENT" ? HttpCode.NotFound : HttpCode.ServerError); - response.end(error.message); - }); - payload.stream.pipe(response); - } else { - response.end(payload.content); - } - } catch (error) { - if (error.code === "ENOENT" || error.code === "EISDIR") { - error = new HttpError("Not found", HttpCode.NotFound); - } - response.writeHead(typeof error.code === "number" ? error.code : HttpCode.ServerError); - response.end(error.message); - } - } - - private async preHandleRequest(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise { - const secure = (request.connection as tls.TLSSocket).encrypted; - if (this.options.cert && !secure) { - return { redirect: request.url }; - } - - const fullPath = decodeURIComponent(parsedUrl.pathname || "/"); - const match = fullPath.match(/^(\/?[^/]*)(.*)$/); - let [/* ignore */, base, requestPath] = match - ? match.map((p) => p.replace(/\/+$/, "")) - : ["", "", ""]; - if (base.indexOf(".") !== -1) { // Assume it's a file at the root. - requestPath = base; - base = "/"; - } else if (base === "") { // Happens if it's a plain `domain.com`. - base = "/"; - } - base = path.normalize(base); - requestPath = path.normalize(requestPath || "/index.html"); - - if (base !== "/login" || this.options.auth !== "password" || requestPath !== "/index.html") { - this.ensureGet(request); - } - - // Allow for a versioned static endpoint. This lets us cache every static - // resource underneath the path based on the version without any work and - // without adding query parameters which have their own issues. - // REVIEW: Discuss whether this is the best option; this is sort of a quick - // hack almost to get caching in the meantime but it does work pretty well. - if (/^\/static-/.test(base)) { - base = "/static"; - } - - switch (base) { - case "/": - switch (requestPath) { - // NOTE: This must be served at the correct location based on the - // start_url in the manifest. - case "/manifest.json": - case "/code-server.png": - const response = await this.getResource(this.serverRoot, "media", requestPath); - response.cache = true; - return response; - } - if (!this.authenticate(request)) { - return { redirect: "/login" }; - } - break; - case "/static": - const response = await this.getResource(this.rootPath, requestPath); - response.cache = true; - return response; - case "/login": - if (this.options.auth !== "password" || requestPath !== "/index.html") { - throw new HttpError("Not found", HttpCode.NotFound); - } - return this.tryLogin(request); - default: - if (!this.authenticate(request)) { - throw new HttpError("Unauthorized", HttpCode.Unauthorized); - } - break; - } - - return this.handleRequest(base, requestPath, parsedUrl, request); - } - - private onUpgrade = async (request: http.IncomingMessage, socket: net.Socket): Promise => { - try { - await this.preHandleWebSocket(request, socket); - } catch (error) { - socket.destroy(); - console.error(error.message); - } - } - - private preHandleWebSocket(request: http.IncomingMessage, socket: net.Socket): Promise { - socket.on("error", () => socket.destroy()); - socket.on("end", () => socket.destroy()); - - this.ensureGet(request); - if (!this.authenticate(request)) { - throw new HttpError("Unauthorized", HttpCode.Unauthorized); - } else if (!request.headers.upgrade || request.headers.upgrade.toLowerCase() !== "websocket") { - throw new Error("HTTP/1.1 400 Bad Request"); - } - - // This magic value is specified by the websocket spec. - const magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - const reply = crypto.createHash("sha1") - .update(request.headers["sec-websocket-key"] + magic) - .digest("base64"); - socket.write([ - "HTTP/1.1 101 Switching Protocols", - "Upgrade: websocket", - "Connection: Upgrade", - `Sec-WebSocket-Accept: ${reply}`, - ].join("\r\n") + "\r\n\r\n"); - - const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}}; - return this.handleWebSocket(socket, parsedUrl); - } - - private async tryLogin(request: http.IncomingMessage): Promise { - const redirect = (password: string | true) => { - return { - redirect: "/", - headers: typeof password === "string" - ? { "Set-Cookie": `key=${password}; Path=${this.options.basePath || "/"}; HttpOnly; SameSite=strict` } - : {}, - }; - }; - const providedPassword = this.authenticate(request); - if (providedPassword && (request.method === "GET" || request.method === "POST")) { - return redirect(providedPassword); - } - if (request.method === "POST") { - const data = await this.getData(request); - const password = this.authenticate(request, { - key: typeof data.password === "string" ? [hash(data.password)] : undefined, - }); - if (password) { - return redirect(password); - } - console.error("Failed login attempt", JSON.stringify({ - xForwardedFor: request.headers["x-forwarded-for"], - remoteAddress: request.connection.remoteAddress, - userAgent: request.headers["user-agent"], - timestamp: Math.floor(new Date().getTime() / 1000), - })); - return this.getLogin("Invalid password", data); - } - this.ensureGet(request); - return this.getLogin(); - } - - private async getLogin(error: string = "", payload?: LoginPayload): Promise { - const filePath = path.join(this.serverRoot, "browser/login.html"); - const content = (await util.promisify(fs.readFile)(filePath, "utf8")) - .replace("{{ERROR}}", error) - .replace("display:none", error ? "display:block" : "display:none") - .replace('value=""', `value="${payload && payload.password || ""}"`); - return { content, filePath }; - } - - private ensureGet(request: http.IncomingMessage): void { - if (request.method !== "GET") { - throw new HttpError(`Unsupported method ${request.method}`, HttpCode.BadRequest); - } - } - - private getData(request: http.IncomingMessage): Promise { - return request.method === "POST" - ? new Promise((resolve, reject) => { - let body = ""; - const onEnd = (): void => { - off(); - resolve(querystring.parse(body) as T); - }; - const onError = (error: Error): void => { - off(); - reject(error); - }; - const onData = (d: Buffer): void => { - body += d; - if (body.length > 1e6) { - onError(new HttpError("Payload is too large", HttpCode.LargePayload)); - request.connection.destroy(); - } - }; - const off = (): void => { - request.off("error", onError); - request.off("data", onError); - request.off("end", onEnd); - }; - request.on("error", onError); - request.on("data", onData); - request.on("end", onEnd); - }) - : Promise.resolve({} as T); - } - - private authenticate(request: http.IncomingMessage, payload?: AuthPayload): string | boolean { - if (this.options.auth === "none") { - return true; - } - const safeCompare = localRequire("safe-compare/index"); - if (typeof payload === "undefined") { - payload = this.parseCookies(request); - } - if (this.options.password && payload.key) { - for (let i = 0; i < payload.key.length; ++i) { - if (safeCompare(payload.key[i], this.options.password)) { - return payload.key[i]; - } - } - } - return false; - } - - private parseCookies(request: http.IncomingMessage): T { - const cookies: { [key: string]: string[] } = {}; - if (request.headers.cookie) { - request.headers.cookie.split(";").forEach((keyValue) => { - const [key, value] = split(keyValue, "="); - if (!cookies[key]) { - cookies[key] = []; - } - cookies[key].push(decodeURI(value)); - }); - } - return cookies as T; - } -} - -interface StartPath { - path?: string[] | string; - workspace?: boolean; -} - -interface Settings { - lastVisited?: StartPath; -} - -export class MainServer extends Server { - public readonly _onDidClientConnect = new Emitter(); - public readonly onDidClientConnect = this._onDidClientConnect.event; - private readonly ipc = new IPCServer(this.onDidClientConnect); - - private readonly maxExtraOfflineConnections = 0; - private readonly connections = new Map>(); - - private readonly services = new ServiceCollection(); - private readonly servicesPromise: Promise; - - public readonly _onProxyConnect = new Emitter(); - private proxyPipe = path.join(tmpdir, "tls-proxy"); - private _proxyServer?: Promise; - private readonly proxyTimeout = 5000; - - private settings: Settings = {}; - private heartbeatTimer?: NodeJS.Timeout; - private heartbeatInterval = 60000; - private lastHeartbeat = 0; - - public constructor(options: ServerOptions, args: ParsedArgs) { - super(options); - this.servicesPromise = this.initializeServices(args); - } - - public async listen(): Promise { - const environment = (this.services.get(IEnvironmentService) as EnvironmentService); - const [address] = await Promise.all([ - super.listen(), ...[ - environment.extensionsPath, - ].map((p) => mkdirp(p).then(() => p)), - ]); - return address; - } - - protected async handleWebSocket(socket: net.Socket, parsedUrl: url.UrlWithParsedQuery): Promise { - this.heartbeat(); - if (!parsedUrl.query.reconnectionToken) { - throw new Error("Reconnection token is missing from query parameters"); - } - const protocol = new Protocol(await this.createProxy(socket), { - reconnectionToken: parsedUrl.query.reconnectionToken, - reconnection: parsedUrl.query.reconnection === "true", - skipWebSocketFrames: parsedUrl.query.skipWebSocketFrames === "true", - }); - try { - await this.connect(await protocol.handshake(), protocol); - } catch (error) { - protocol.sendMessage({ type: "error", reason: error.message }); - protocol.dispose(); - protocol.getSocket().dispose(); - } - } - - protected async handleRequest( - base: string, - requestPath: string, - parsedUrl: url.UrlWithParsedQuery, - request: http.IncomingMessage, - ): Promise { - this.heartbeat(); - switch (base) { - case "/": return this.getRoot(request, parsedUrl); - case "/resource": - case "/vscode-remote-resource": - if (typeof parsedUrl.query.path === "string") { - return this.getAnyResource(parsedUrl.query.path); - } - break; - case "/tar": - if (typeof parsedUrl.query.path === "string") { - return this.getTarredResource(parsedUrl.query.path); - } - break; - case "/webview": - if (/^\/vscode-resource/.test(requestPath)) { - return this.getAnyResource(requestPath.replace(/^\/vscode-resource(\/file)?/, "")); - } - return this.getResource( - this.rootPath, - "out/vs/workbench/contrib/webview/browser/pre", - requestPath - ); - } - throw new HttpError("Not found", HttpCode.NotFound); - } - - private async getRoot(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise { - const filePath = path.join(this.serverRoot, "browser/workbench.html"); - let [content, startPath] = await Promise.all([ - util.promisify(fs.readFile)(filePath, "utf8"), - this.getFirstValidPath([ - { path: parsedUrl.query.workspace, workspace: true }, - { path: parsedUrl.query.folder, workspace: false }, - (await this.readSettings()).lastVisited, - { path: this.options.openUri } - ]), - this.servicesPromise, - ]); - - if (startPath) { - this.writeSettings({ - lastVisited: { - path: startPath.uri.fsPath, - workspace: startPath.workspace - }, - }); - } - - const logger = this.services.get(ILogService) as ILogService; - logger.info("request.url", `"${request.url}"`); - - const remoteAuthority = request.headers.host as string; - const transformer = getUriTransformer(remoteAuthority); - - const environment = this.services.get(IEnvironmentService) as IEnvironmentService; - const options: Options = { - WORKBENCH_WEB_CONFIGURATION: { - workspaceUri: startPath && startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined, - folderUri: startPath && !startPath.workspace ? transformer.transformOutgoing(startPath.uri) : undefined, - remoteAuthority, - logLevel: getLogLevel(environment), - }, - REMOTE_USER_DATA_URI: transformer.transformOutgoing(URI.file(environment.userDataPath)), - PRODUCT_CONFIGURATION: { - extensionsGallery: product.extensionsGallery, - }, - NLS_CONFIGURATION: await getNlsConfiguration(environment.args.locale || await getLocaleFromConfig(environment.userDataPath), environment.userDataPath), - }; - - content = content.replace(/{{COMMIT}}/g, product.commit || ""); - for (const key in options) { - content = content.replace(`"{{${key}}}"`, `'${JSON.stringify(options[key as keyof Options])}'`); - } - - return { content, filePath }; - } - - /** - * Choose the first valid path. If `workspace` is undefined then either a - * workspace or a directory are acceptable. Otherwise it must be a file if a - * workspace or a directory otherwise. - */ - private async getFirstValidPath(startPaths: Array): Promise<{ uri: URI, workspace?: boolean} | undefined> { - const logger = this.services.get(ILogService) as ILogService; - const cwd = process.env.VSCODE_CWD || process.cwd(); - for (let i = 0; i < startPaths.length; ++i) { - const startPath = startPaths[i]; - if (!startPath) { - continue; - } - const paths = typeof startPath.path === "string" ? [startPath.path] : (startPath.path || []); - for (let j = 0; j < paths.length; ++j) { - const uri = URI.file(sanitizeFilePath(paths[j], cwd)); - try { - const stat = await util.promisify(fs.stat)(uri.fsPath); - if (typeof startPath.workspace === "undefined" || startPath.workspace !== stat.isDirectory()) { - return { uri, workspace: !stat.isDirectory() }; - } - } catch (error) { - logger.warn(error.message); - } - } - } - return undefined; - } - - private async connect(message: ConnectionTypeRequest, protocol: Protocol): Promise { - if (product.commit && message.commit !== product.commit) { - throw new Error(`Version mismatch (${message.commit} instead of ${product.commit})`); - } - - switch (message.desiredConnectionType) { - case ConnectionType.ExtensionHost: - case ConnectionType.Management: - if (!this.connections.has(message.desiredConnectionType)) { - this.connections.set(message.desiredConnectionType, new Map()); - } - const connections = this.connections.get(message.desiredConnectionType)!; - - const ok = async () => { - return message.desiredConnectionType === ConnectionType.ExtensionHost - ? { debugPort: await this.getDebugPort() } - : { type: "ok" }; - }; - - const token = protocol.options.reconnectionToken; - if (protocol.options.reconnection && connections.has(token)) { - protocol.sendMessage(await ok()); - const buffer = protocol.readEntireBuffer(); - protocol.dispose(); - return connections.get(token)!.reconnect(protocol.getSocket(), buffer); - } else if (protocol.options.reconnection || connections.has(token)) { - throw new Error(protocol.options.reconnection - ? "Unrecognized reconnection token" - : "Duplicate reconnection token" - ); - } - - protocol.sendMessage(await ok()); - - let connection: Connection; - if (message.desiredConnectionType === ConnectionType.Management) { - connection = new ManagementConnection(protocol, token); - this._onDidClientConnect.fire({ - protocol, onDidClientDisconnect: connection.onClose, - }); - // TODO: Need a way to match clients with a connection. For now - // dispose everything which only works because no extensions currently - // utilize long-running proxies. - (this.services.get(INodeProxyService) as NodeProxyService)._onUp.fire(); - connection.onClose(() => (this.services.get(INodeProxyService) as NodeProxyService)._onDown.fire()); - } else { - const buffer = protocol.readEntireBuffer(); - connection = new ExtensionHostConnection( - message.args ? message.args.language : "en", - protocol, buffer, token, - this.services.get(ILogService) as ILogService, - this.services.get(IEnvironmentService) as IEnvironmentService, - ); - } - connections.set(token, connection); - connection.onClose(() => connections.delete(token)); - this.disposeOldOfflineConnections(connections); - break; - case ConnectionType.Tunnel: return protocol.tunnel(); - default: throw new Error("Unrecognized connection type"); - } - } - - private disposeOldOfflineConnections(connections: Map): void { - const offline = Array.from(connections.values()) - .filter((connection) => typeof connection.offline !== "undefined"); - for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) { - offline[i].dispose(); - } - } - - private async initializeServices(args: ParsedArgs): Promise { - const environmentService = new EnvironmentService(args, process.execPath); - const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService)); - const fileService = new FileService(logService); - fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(logService)); - - this.allowedRequestPaths.push( - path.join(environmentService.userDataPath, "clp"), // Language packs. - environmentService.extensionsPath, - environmentService.builtinExtensionsPath, - ...environmentService.extraExtensionPaths, - ...environmentService.extraBuiltinExtensionPaths, - ); - - this.ipc.registerChannel("logger", new LoggerChannel(logService)); - this.ipc.registerChannel(ExtensionHostDebugBroadcastChannel.ChannelName, new ExtensionHostDebugBroadcastChannel()); - - this.services.set(ILogService, logService); - this.services.set(IEnvironmentService, environmentService); - this.services.set(IConfigurationService, new SyncDescriptor(ConfigurationService, [environmentService.machineSettingsResource])); - this.services.set(IRequestService, new SyncDescriptor(RequestService)); - this.services.set(IFileService, fileService); - this.services.set(IProductService, { _serviceBrand: undefined, ...product }); - this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); - this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); - - if (!environmentService.args["disable-telemetry"]) { - this.services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [{ - appender: combinedAppender( - new AppInsightsAppender("code-server", null, () => new TelemetryClient() as any, logService), - new LogAppender(logService), - ), - commonProperties: resolveCommonProperties( - product.commit, product.codeServerVersion, await getMachineId(), - [], environmentService.installSourcePath, "code-server", - ), - piiPaths: this.allowedRequestPaths, - } as ITelemetryServiceConfig])); - } else { - this.services.set(ITelemetryService, NullTelemetryService); - } - - await new Promise((resolve) => { - const instantiationService = new InstantiationService(this.services); - this.services.set(ILocalizationsService, instantiationService.createInstance(LocalizationsService)); - this.services.set(INodeProxyService, instantiationService.createInstance(NodeProxyService)); - - instantiationService.invokeFunction(() => { - instantiationService.createInstance(LogsDataCleaner); - const telemetryService = this.services.get(ITelemetryService) as ITelemetryService; - this.ipc.registerChannel("extensions", new ExtensionManagementChannel( - this.services.get(IExtensionManagementService) as IExtensionManagementService, - (context) => getUriTransformer(context.remoteAuthority), - )); - this.ipc.registerChannel("remoteextensionsenvironment", new ExtensionEnvironmentChannel( - environmentService, logService, telemetryService, this.options.connectionToken || "", - )); - this.ipc.registerChannel("request", new RequestChannel(this.services.get(IRequestService) as IRequestService)); - this.ipc.registerChannel("telemetry", new TelemetryChannel(telemetryService)); - this.ipc.registerChannel("nodeProxy", new NodeProxyChannel(this.services.get(INodeProxyService) as INodeProxyService)); - this.ipc.registerChannel("localizations", >createChannelReceiver(this.services.get(ILocalizationsService) as ILocalizationsService)); - this.ipc.registerChannel("update", new UpdateChannel(instantiationService.createInstance(UpdateService))); - this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); - resolve(new ErrorTelemetry(telemetryService)); - }); - }); - } - - /** - * TODO: implement. - */ - private async getDebugPort(): Promise { - return undefined; - } - - /** - * Since we can't pass TLS sockets to children, use this to proxy the socket - * and pass a non-TLS socket. - */ - private createProxy = async (socket: net.Socket): Promise => { - if (!(socket instanceof tls.TLSSocket)) { - return socket; - } - - await this.startProxyServer(); - - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - listener.dispose(); - socket.destroy(); - proxy.destroy(); - reject(new Error("TLS socket proxy timed out")); - }, this.proxyTimeout); - - const listener = this._onProxyConnect.event((connection) => { - connection.once("data", (data) => { - if (!socket.destroyed && !proxy.destroyed && data.toString() === id) { - clearTimeout(timeout); - listener.dispose(); - [[proxy, socket], [socket, proxy]].forEach(([a, b]) => { - a.pipe(b); - a.on("error", () => b.destroy()); - a.on("close", () => b.destroy()); - a.on("end", () => b.end()); - }); - resolve(connection); - } - }); - }); - - const id = generateUuid(); - const proxy = net.connect(this.proxyPipe); - proxy.once("connect", () => proxy.write(id)); - }); - } - - private async startProxyServer(): Promise { - if (!this._proxyServer) { - this._proxyServer = new Promise(async (resolve) => { - this.proxyPipe = await this.findFreeSocketPath(this.proxyPipe); - await mkdirp(tmpdir); - await rimraf(this.proxyPipe); - const proxyServer = net.createServer((p) => this._onProxyConnect.fire(p)); - proxyServer.once("listening", resolve); - proxyServer.listen(this.proxyPipe); - }); - } - return this._proxyServer; - } - - private async findFreeSocketPath(basePath: string, maxTries: number = 100): Promise { - const canConnect = (path: string): Promise => { - return new Promise((resolve) => { - const socket = net.connect(path); - socket.once("error", () => resolve(false)); - socket.once("connect", () => { - socket.destroy(); - resolve(true); - }); - }); - }; - - let i = 0; - let path = basePath; - while (await canConnect(path) && i < maxTries) { - path = `${basePath}-${++i}`; - } - return path; - } - - /** - * Return the file path for Coder settings. - */ - private get settingsPath(): string { - const environment = this.services.get(IEnvironmentService) as IEnvironmentService; - return path.join(environment.userDataPath, "coder.json"); - } - - /** - * Read settings from the file. On a failure return last known settings and - * log a warning. - * - */ - private async readSettings(): Promise { - try { - const raw = (await util.promisify(fs.readFile)(this.settingsPath, "utf8")).trim(); - this.settings = raw ? JSON.parse(raw) : {}; - } catch (error) { - if (error.code !== "ENOENT") { - (this.services.get(ILogService) as ILogService).warn(error.message); - } - } - return this.settings; - } - - /** - * Write settings combined with current settings. On failure log a warning. - */ - private async writeSettings(newSettings: Partial): Promise { - this.settings = { ...this.settings, ...newSettings }; - try { - await util.promisify(fs.writeFile)(this.settingsPath, JSON.stringify(this.settings)); - } catch (error) { - (this.services.get(ILogService) as ILogService).warn(error.message); - } - } - - /** - * Return the file path for the heartbeat file. - */ - private get heartbeatPath(): string { - const environment = this.services.get(IEnvironmentService) as IEnvironmentService; - return path.join(environment.userDataPath, "heartbeat"); - } - - /** - * Return all online connections regardless of type. - */ - private get onlineConnections(): Connection[] { - const online = []; - this.connections.forEach((connections) => { - connections.forEach((connection) => { - if (typeof connection.offline === "undefined") { - online.push(connection); - } - }); - }); - return online; - } - - /** - * Write to the heartbeat file if we haven't already done so within the - * timeout and start or reset a timer that keeps running as long as there are - * active connections. Failures are logged as warnings. - */ - private heartbeat(): void { - const now = Date.now(); - if (now - this.lastHeartbeat >= this.heartbeatInterval) { - util.promisify(fs.writeFile)(this.heartbeatPath, "").catch((error) => { - (this.services.get(ILogService) as ILogService).warn(error.message); - }); - this.lastHeartbeat = now; - clearTimeout(this.heartbeatTimer!); // We can clear undefined so ! is fine. - this.heartbeatTimer = setTimeout(() => { - if (this.onlineConnections.length > 0) { - this.heartbeat(); - } - }, this.heartbeatInterval); - } - } -} diff --git a/src/node/settings.ts b/src/node/settings.ts new file mode 100644 index 00000000..6432a119 --- /dev/null +++ b/src/node/settings.ts @@ -0,0 +1,40 @@ +import * as fs from "fs-extra" +import { logger } from "@coder/logger" +import { extend } from "./util" + +export type Settings = { [key: string]: Settings | string | boolean | number } + +/** + * Provides read and write access to settings. + */ +export class SettingsProvider { + public constructor(private readonly settingsPath: string) {} + + /** + * Read settings from the file. On a failure return last known settings and + * log a warning. + */ + public async read(): Promise { + try { + const raw = (await fs.readFile(this.settingsPath, "utf8")).trim() + return raw ? JSON.parse(raw) : {} + } catch (error) { + if (error.code !== "ENOENT") { + logger.warn(error.message) + } + } + return {} as T + } + + /** + * Write settings combined with current settings. On failure log a warning. + * Objects will be merged and everything else will be replaced. + */ + public async write(settings: Partial): Promise { + try { + await fs.writeFile(this.settingsPath, JSON.stringify(extend(this.read(), settings))) + } catch (error) { + logger.warn(error.message) + } + } +} diff --git a/src/node/socket.ts b/src/node/socket.ts new file mode 100644 index 00000000..e5fe6677 --- /dev/null +++ b/src/node/socket.ts @@ -0,0 +1,110 @@ +import * as fs from "fs-extra" +import * as net from "net" +import * as path from "path" +import * as tls from "tls" +import { Emitter } from "../common/emitter" +import { generateUuid } from "../common/util" +import { tmpdir } from "./util" + +/** + * Provides a way to proxy a TLS socket. Can be used when you need to pass a + * socket to a child process since you can't pass the TLS socket. + */ +export class SocketProxyProvider { + private readonly onProxyConnect = new Emitter() + private proxyPipe = path.join(tmpdir, "tls-proxy") + private _proxyServer?: Promise + private readonly proxyTimeout = 5000 + + /** + * Stop the proxy server. + */ + public stop(): void { + if (this._proxyServer) { + this._proxyServer.then((server) => server.close()) + this._proxyServer = undefined + } + } + + /** + * Create a socket proxy for TLS sockets. If it's not a TLS socket the + * original socket is returned. This will spawn a proxy server on demand. + */ + public async createProxy(socket: net.Socket): Promise { + if (!(socket instanceof tls.TLSSocket)) { + return socket + } + + await this.startProxyServer() + + return new Promise((resolve, reject) => { + const id = generateUuid() + const proxy = net.connect(this.proxyPipe) + proxy.once("connect", () => proxy.write(id)) + + const timeout = setTimeout(() => { + listener.dispose() // eslint-disable-line @typescript-eslint/no-use-before-define + socket.destroy() + proxy.destroy() + reject(new Error("TLS socket proxy timed out")) + }, this.proxyTimeout) + + const listener = this.onProxyConnect.event((connection) => { + connection.once("data", (data) => { + if (!socket.destroyed && !proxy.destroyed && data.toString() === id) { + clearTimeout(timeout) + listener.dispose() + ;[ + [proxy, socket], + [socket, proxy], + ].forEach(([a, b]) => { + a.pipe(b) + a.on("error", () => b.destroy()) + a.on("close", () => b.destroy()) + a.on("end", () => b.end()) + }) + resolve(connection) + } + }) + }) + }) + } + + private async startProxyServer(): Promise { + if (!this._proxyServer) { + this._proxyServer = this.findFreeSocketPath(this.proxyPipe) + .then((pipe) => { + this.proxyPipe = pipe + return Promise.all([fs.mkdirp(tmpdir), fs.remove(this.proxyPipe)]) + }) + .then(() => { + return new Promise((resolve) => { + const proxyServer = net.createServer((p) => this.onProxyConnect.emit(p)) + proxyServer.once("listening", () => resolve(proxyServer)) + proxyServer.listen(this.proxyPipe) + }) + }) + } + return this._proxyServer + } + + public async findFreeSocketPath(basePath: string, maxTries = 100): Promise { + const canConnect = (path: string): Promise => { + return new Promise((resolve) => { + const socket = net.connect(path) + socket.once("error", () => resolve(false)) + socket.once("connect", () => { + socket.destroy() + resolve(true) + }) + }) + } + + let i = 0 + let path = basePath + while ((await canConnect(path)) && i < maxTries) { + path = `${basePath}-${++i}` + } + return path + } +} diff --git a/src/node/update.ts b/src/node/update.ts deleted file mode 100644 index c2056c34..00000000 --- a/src/node/update.ts +++ /dev/null @@ -1,141 +0,0 @@ -import * as cp from "child_process"; -import * as os from "os"; -import * as path from "path"; -import * as util from "util"; -import { CancellationToken } from "vs/base/common/cancellation"; -import { URI } from "vs/base/common/uri"; -import * as pfs from "vs/base/node/pfs"; -import { IConfigurationService } from "vs/platform/configuration/common/configuration"; -import { IEnvironmentService } from "vs/platform/environment/common/environment"; -import { IFileService } from "vs/platform/files/common/files"; -import { ILogService } from "vs/platform/log/common/log"; -import product from "vs/platform/product/common/product"; -import { asJson, IRequestService } from "vs/platform/request/common/request"; -import { AvailableForDownload, State, UpdateType, StateType } from "vs/platform/update/common/update"; -import { AbstractUpdateService } from "vs/platform/update/electron-main/abstractUpdateService"; -import { ipcMain } from "vs/server/src/node/ipc"; -import { extract } from "vs/server/src/node/marketplace"; -import { tmpdir } from "vs/server/src/node/util"; - -interface IUpdate { - name: string; -} - -export class UpdateService extends AbstractUpdateService { - _serviceBrand: any; - - constructor( - @IConfigurationService configurationService: IConfigurationService, - @IEnvironmentService environmentService: IEnvironmentService, - @IRequestService requestService: IRequestService, - @ILogService logService: ILogService, - @IFileService private readonly fileService: IFileService, - ) { - super(null, configurationService, environmentService, requestService, logService); - } - - /** - * Return true if the currently installed version is the latest. - */ - public async isLatestVersion(latest?: IUpdate | null): Promise { - if (!latest) { - latest = await this.getLatestVersion(); - } - if (latest) { - const latestMajor = parseInt(latest.name); - const currentMajor = parseInt(product.codeServerVersion); - // If these are invalid versions we can't compare meaningfully. - return isNaN(latestMajor) || isNaN(currentMajor) || - // This can happen when there is a pre-release for a new major version. - currentMajor > latestMajor || - // Otherwise assume that if it's not the same then we're out of date. - latest.name === product.codeServerVersion; - } - return true; - } - - protected buildUpdateFeedUrl(quality: string): string { - return `${product.updateUrl}/${quality}`; - } - - public async doQuitAndInstall(): Promise { - if (this.state.type === StateType.Ready) { - ipcMain.relaunch(this.state.update.version); - } - } - - protected async doCheckForUpdates(context: any): Promise { - this.setState(State.CheckingForUpdates(context)); - try { - const update = await this.getLatestVersion(); - if (!update || await this.isLatestVersion(update)) { - this.setState(State.Idle(UpdateType.Archive)); - } else { - this.setState(State.AvailableForDownload({ - version: update.name, - productVersion: update.name, - })); - } - } catch (error) { - this.onRequestError(error, !!context); - } - } - - private async getLatestVersion(): Promise { - const data = await this.requestService.request({ - url: this.url, - headers: { "User-Agent": "code-server" }, - }, CancellationToken.None); - return asJson(data); - } - - protected async doDownloadUpdate(state: AvailableForDownload): Promise { - this.setState(State.Downloading(state.update)); - const target = os.platform(); - const releaseName = await this.buildReleaseName(state.update.version); - const url = "https://github.com/cdr/code-server/releases/download/" - + `${state.update.version}/${releaseName}` - + `.${target === "darwin" ? "zip" : "tar.gz"}`; - const downloadPath = path.join(tmpdir, `${state.update.version}-archive`); - const extractPath = path.join(tmpdir, state.update.version); - try { - await pfs.mkdirp(tmpdir); - const context = await this.requestService.request({ url }, CancellationToken.None, true); - await this.fileService.writeFile(URI.file(downloadPath), context.stream); - await extract(downloadPath, extractPath, undefined, CancellationToken.None); - const newBinary = path.join(extractPath, releaseName, "code-server"); - if (!pfs.exists(newBinary)) { - throw new Error("No code-server binary in extracted archive"); - } - await pfs.unlink(process.argv[0]); // Must unlink first to avoid ETXTBSY. - await pfs.move(newBinary, process.argv[0]); - this.setState(State.Ready(state.update)); - } catch (error) { - this.onRequestError(error, true); - } - await Promise.all([downloadPath, extractPath].map((p) => pfs.rimraf(p))); - } - - private onRequestError(error: Error, showNotification?: boolean): void { - this.logService.error(error); - this.setState(State.Idle(UpdateType.Archive, showNotification ? (error.message || error.toString()) : undefined)); - } - - private async buildReleaseName(release: string): Promise { - let target: string = os.platform(); - if (target === "linux") { - const result = await util.promisify(cp.exec)("ldd --version").catch((error) => ({ - stderr: error.message, - stdout: "", - })); - if (/musl/.test(result.stderr) || /musl/.test(result.stdout)) { - target = "alpine"; - } - } - let arch = os.arch(); - if (arch === "x64") { - arch = "x86_64"; - } - return `code-server${release}-${target}-${arch}`; - } -} diff --git a/src/node/uriTransformer.js b/src/node/uriTransformer.js deleted file mode 100644 index fc69441c..00000000 --- a/src/node/uriTransformer.js +++ /dev/null @@ -1,24 +0,0 @@ -// This file is included via a regular Node require. I'm not sure how (or if) -// we can write this in Typescript and have it compile to non-AMD syntax. -module.exports = (remoteAuthority) => { - return { - transformIncoming: (uri) => { - switch (uri.scheme) { - case "vscode-remote": return { scheme: "file", path: uri.path }; - default: return uri; - } - }, - transformOutgoing: (uri) => { - switch (uri.scheme) { - case "file": return { scheme: "vscode-remote", authority: remoteAuthority, path: uri.path }; - default: return uri; - } - }, - transformOutgoingScheme: (scheme) => { - switch (scheme) { - case "file": return "vscode-remote"; - default: return scheme; - } - }, - }; -}; diff --git a/src/node/util.ts b/src/node/util.ts index f5dae6bd..599ad897 100644 --- a/src/node/util.ts +++ b/src/node/util.ts @@ -1,144 +1,216 @@ -import * as cp from "child_process"; -import * as crypto from "crypto"; -import * as fs from "fs"; -import * as os from "os"; -import * as path from "path"; -import * as util from "util"; -import * as rg from "vscode-ripgrep"; +import * as cp from "child_process" +import * as crypto from "crypto" +import * as fs from "fs-extra" +import * as os from "os" +import * as path from "path" +import * as util from "util" -import { getPathFromAmdModule } from "vs/base/common/amd"; -import { getMediaMime as vsGetMediaMime } from "vs/base/common/mime"; -import { extname } from "vs/base/common/path"; -import { URITransformer, IRawURITransformer } from "vs/base/common/uriIpc"; -import { mkdirp } from "vs/base/node/pfs"; +export const tmpdir = path.join(os.tmpdir(), "code-server") -export enum AuthType { - Password = "password", - None = "none", +const getXdgDataDir = (): string => { + switch (process.platform) { + case "win32": + return path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), "AppData/Local"), "code-server/Data") + case "darwin": + return path.join( + process.env.XDG_DATA_HOME || path.join(os.homedir(), "Library/Application Support"), + "code-server" + ) + default: + return path.join(process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local/share"), "code-server") + } } -export enum FormatType { - Json = "json", +export const xdgLocalDir = getXdgDataDir() + +export const generateCertificate = async (): Promise<{ cert: string; certKey: string }> => { + const paths = { + cert: path.join(tmpdir, "self-signed.cert"), + certKey: path.join(tmpdir, "self-signed.key"), + } + const checks = await Promise.all([fs.pathExists(paths.cert), fs.pathExists(paths.certKey)]) + if (!checks[0] || !checks[1]) { + // Require on demand so openssl isn't required if you aren't going to + // generate certificates. + const pem = require("pem") as typeof import("pem") + const certs = await new Promise((resolve, reject): void => { + pem.createCertificate({ selfSigned: true }, (error, result) => { + return error ? reject(error) : resolve(result) + }) + }) + await fs.mkdirp(tmpdir) + await Promise.all([fs.writeFile(paths.cert, certs.certificate), fs.writeFile(paths.certKey, certs.serviceKey)]) + } + return paths } -export const tmpdir = path.join(os.tmpdir(), "code-server"); - -export const generateCertificate = async (): Promise<{ cert: string, certKey: string }> => { - const paths = { - cert: path.join(tmpdir, "self-signed.cert"), - certKey: path.join(tmpdir, "self-signed.key"), - }; - - const exists = await Promise.all([ - util.promisify(fs.exists)(paths.cert), - util.promisify(fs.exists)(paths.certKey), - ]); - - if (!exists[0] || !exists[1]) { - const pem = localRequire("pem/lib/pem"); - const certs = await new Promise((resolve, reject): void => { - pem.createCertificate({ selfSigned: true }, (error, result) => { - if (error) { - return reject(error); - } - resolve(result); - }); - }); - await mkdirp(tmpdir); - await Promise.all([ - util.promisify(fs.writeFile)(paths.cert, certs.certificate), - util.promisify(fs.writeFile)(paths.certKey, certs.serviceKey), - ]); - } - - return paths; -}; - -export const uriTransformerPath = getPathFromAmdModule(require, "vs/server/src/node/uriTransformer"); -export const getUriTransformer = (remoteAuthority: string): URITransformer => { - const rawURITransformerFactory = require.__$__nodeRequire(uriTransformerPath); - const rawURITransformer = rawURITransformerFactory(remoteAuthority); - return new URITransformer(rawURITransformer); -}; - -export const generatePassword = async (length: number = 24): Promise => { - const buffer = Buffer.alloc(Math.ceil(length / 2)); - await util.promisify(crypto.randomFill)(buffer); - return buffer.toString("hex").substring(0, length); -}; +export const generatePassword = async (length = 24): Promise => { + const buffer = Buffer.alloc(Math.ceil(length / 2)) + await util.promisify(crypto.randomFill)(buffer) + return buffer.toString("hex").substring(0, length) +} export const hash = (str: string): string => { - return crypto.createHash("sha256").update(str).digest("hex"); -}; + return crypto + .createHash("sha256") + .update(str) + .digest("hex") +} + +const mimeTypes: { [key: string]: string } = { + ".aac": "audio/x-aac", + ".avi": "video/x-msvideo", + ".bmp": "image/bmp", + ".css": "text/css", + ".flv": "video/x-flv", + ".gif": "image/gif", + ".html": "text/html", + ".ico": "image/x-icon", + ".jpe": "image/jpg", + ".jpeg": "image/jpg", + ".jpg": "image/jpg", + ".js": "application/javascript", + ".json": "application/json", + ".m1v": "video/mpeg", + ".m2a": "audio/mpeg", + ".m2v": "video/mpeg", + ".m3a": "audio/mpeg", + ".mid": "audio/midi", + ".midi": "audio/midi", + ".mk3d": "video/x-matroska", + ".mks": "video/x-matroska", + ".mkv": "video/x-matroska", + ".mov": "video/quicktime", + ".movie": "video/x-sgi-movie", + ".mp2": "audio/mpeg", + ".mp2a": "audio/mpeg", + ".mp3": "audio/mpeg", + ".mp4": "video/mp4", + ".mp4a": "audio/mp4", + ".mp4v": "video/mp4", + ".mpe": "video/mpeg", + ".mpeg": "video/mpeg", + ".mpg": "video/mpeg", + ".mpg4": "video/mp4", + ".mpga": "audio/mpeg", + ".oga": "audio/ogg", + ".ogg": "audio/ogg", + ".ogv": "video/ogg", + ".png": "image/png", + ".psd": "image/vnd.adobe.photoshop", + ".qt": "video/quicktime", + ".spx": "audio/ogg", + ".svg": "image/svg+xml", + ".tga": "image/x-tga", + ".tif": "image/tiff", + ".tiff": "image/tiff", + ".txt": "text/plain", + ".wav": "audio/x-wav", + ".wasm": "application/wasm", + ".webm": "video/webm", + ".webp": "image/webp", + ".wma": "audio/x-ms-wma", + ".wmv": "video/x-ms-wmv", + ".woff": "application/font-woff", +} export const getMediaMime = (filePath?: string): string => { - return filePath && (vsGetMediaMime(filePath) || (<{[index: string]: string}>{ - ".css": "text/css", - ".html": "text/html", - ".js": "application/javascript", - ".json": "application/json", - })[extname(filePath)]) || "text/plain"; -}; + return (filePath && mimeTypes[path.extname(filePath)]) || "text/plain" +} export const isWsl = async (): Promise => { - return process.platform === "linux" - && os.release().toLowerCase().indexOf("microsoft") !== -1 - || (await util.promisify(fs.readFile)("/proc/version", "utf8")) - .toLowerCase().indexOf("microsoft") !== -1; -}; + return ( + (process.platform === "linux" && + os + .release() + .toLowerCase() + .indexOf("microsoft") !== -1) || + (await fs.readFile("/proc/version", "utf8")).toLowerCase().indexOf("microsoft") !== -1 + ) +} +/** + * Try opening a URL using whatever the system has set for opening URLs. + */ export const open = async (url: string): Promise => { - const args = []; - const options = {}; - const platform = await isWsl() ? "wsl" : process.platform; - let command = platform === "darwin" ? "open" : "xdg-open"; - if (platform === "win32" || platform === "wsl") { - command = platform === "wsl" ? "cmd.exe" : "cmd"; - args.push("/c", "start", '""', "/b"); - url = url.replace(/&/g, "^&"); - } - const proc = cp.spawn(command, [...args, url], options); - await new Promise((resolve, reject) => { - proc.on("error", reject); - proc.on("close", (code) => { - return code !== 0 - ? reject(new Error(`Failed to open with code ${code}`)) - : resolve(); - }); - }); -}; + const args = [] as string[] + const options = {} as cp.SpawnOptions + const platform = (await isWsl()) ? "wsl" : process.platform + let command = platform === "darwin" ? "open" : "xdg-open" + if (platform === "win32" || platform === "wsl") { + command = platform === "wsl" ? "cmd.exe" : "cmd" + args.push("/c", "start", '""', "/b") + url = url.replace(/&/g, "^&") + } + const proc = cp.spawn(command, [...args, url], options) + await new Promise((resolve, reject) => { + proc.on("error", reject) + proc.on("close", (code) => { + return code !== 0 ? reject(new Error(`Failed to open with code ${code}`)) : resolve() + }) + }) +} /** - * Extract executables to the temporary directory. This is required since we - * can't execute binaries stored within our binary. + * Extract a file to the temporary directory and make it executable. This is + * required since we can't execute binaries stored within our binary. */ -export const unpackExecutables = async (): Promise => { - const rgPath = (rg as any).binaryRgPath; - const destination = path.join(tmpdir, path.basename(rgPath || "")); - if (rgPath && !(await util.promisify(fs.exists)(destination))) { - await mkdirp(tmpdir); - await util.promisify(fs.writeFile)(destination, await util.promisify(fs.readFile)(rgPath)); - await util.promisify(fs.chmod)(destination, "755"); - } -}; +export const unpackExecutables = async (filePath: string): Promise => { + const destination = path.join(tmpdir, "binaries", path.basename(filePath)) + if (filePath && !(await util.promisify(fs.exists)(destination))) { + await fs.mkdirp(tmpdir) + await fs.writeFile(destination, await fs.readFile(filePath)) + await util.promisify(fs.chmod)(destination, "755") + } +} +/** + * For iterating over an enum's values. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export const enumToArray = (t: any): string[] => { - const values = []; - for (const k in t) { - values.push(t[k]); - } - return values; -}; - -export const buildAllowedMessage = (t: any): string => { - const values = enumToArray(t); - return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(", ")}`; -}; + const values = [] as string[] + for (const k in t) { + values.push(t[k]) + } + return values +} /** - * Require a local module. This is necessary since VS Code's loader only looks - * at the root for Node modules. + * For displaying all allowed options in an enum. */ -export const localRequire = (modulePath: string): T => { - return require.__$__nodeRequire(path.resolve(__dirname, "../../node_modules", modulePath)); -}; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const buildAllowedMessage = (t: any): string => { + const values = enumToArray(t) + return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(", ")}` +} + +export const isObject = (obj: T): obj is T => { + return !Array.isArray(obj) && typeof obj === "object" && obj !== null +} + +/** + * Extend a with b and return a new object. Properties with objects will be + * recursively merged while all other properties are just overwritten. + */ +export function extend(a: A, b: B): A & B +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function extend(...args: any[]): any { + const c = {} as any // eslint-disable-line @typescript-eslint/no-explicit-any + for (const obj of args) { + if (!isObject(obj)) { + continue + } + for (const key in obj) { + c[key] = isObject(obj[key]) ? extend(c[key], obj[key]) : obj[key] + } + } + return c +} + +/** + * Remove extra and trailing slashes in a URL. + */ +export const normalize = (url: string): string => { + return url.replace(/\/\/+/g, "/").replace(/\/+$/, "") +} diff --git a/src/node/vscode/README.md b/src/node/vscode/README.md new file mode 100644 index 00000000..752c2948 --- /dev/null +++ b/src/node/vscode/README.md @@ -0,0 +1,59 @@ +Implementation of [VS Code](https://code.visualstudio.com/) remote/web for use +in `code-server`. + +## Docker + +To debug Golang in VS Code using the +[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go), +you need to add `--security-opt seccomp=unconfined` to your `docker run` +arguments when launching code-server with Docker. See +[#725](https://github.com/cdr/code-server/issues/725) for details. + +## Known Issues + +- Creating custom VS Code extensions and debugging them doesn't work. +- Extension profiling and tips are currently disabled. + +## Extensions + +`code-server` does not provide access to the official +[Visual Studio Marketplace](https://marketplace.visualstudio.com/vscode). Instead, +Coder has created a custom extension marketplace that we manage for open-source +extensions. If you want to use an extension with code-server that we do not have +in our marketplace please look for a release in the extension’s repository, +contact us to see if we have one in the works or, if you build an extension +locally from open source, you can copy it to the `extensions` folder. If you +build one locally from open-source please contribute it to the project and let +us know so we can give you props! If you have your own custom marketplace, it is +possible to point code-server to it by setting the `SERVICE_URL` and `ITEM_URL` +environment variables. + +## Development: upgrading VS Code + +We patch VS Code to provide and fix some functionality. As the web portion of VS +Code matures, we'll be able to shrink and maybe even entirely eliminate our +patch. In the meantime, however, upgrading the VS Code version requires ensuring +that the patch still applies and has the intended effects. + +If functionality doesn't depend on code from VS Code then it should be moved +into code-server otherwise it should be in the patch. + +To generate a new patch, **stage all the changes** you want to be included in +the patch in the VS Code source, then run `yarn patch:generate` in this +directory. + +Our changes include: + +- Allow multiple extension directories (both user and built-in). +- Modify the loader, websocket, webview, service worker, and asset requests to + use the URL of the page as a base (and TLS if necessary for the websocket). +- Send client-side telemetry through the server. +- Make changing the display language work. +- Make it possible for us to load code on the client. +- Make extensions work in the browser. +- Fix getting permanently disconnected when you sleep or hibernate for a while. +- Make it possible to automatically update the binary. + +## Future + +- Run VS Code unit tests against our builds to ensure features work as expected. diff --git a/src/node/vscode/server.ts b/src/node/vscode/server.ts new file mode 100644 index 00000000..8b3d077c --- /dev/null +++ b/src/node/vscode/server.ts @@ -0,0 +1,204 @@ +import { field, logger } from "@coder/logger" +import * as cp from "child_process" +import * as crypto from "crypto" +import * as http from "http" +import * as net from "net" +import * as path from "path" +import * as querystring from "querystring" +import { + CodeServerMessage, + Settings, + VscodeMessage, + VscodeOptions, + WorkbenchOptions, +} from "../../../lib/vscode/src/vs/server/ipc" +import { generateUuid } from "../../common/util" +import { HttpProvider, HttpProviderOptions, HttpResponse } from "../http" +import { SettingsProvider } from "../settings" +import { xdgLocalDir } from "../util" + +export class VscodeHttpProvider extends HttpProvider { + private readonly serverRootPath: string + private readonly vsRootPath: string + private readonly settings = new SettingsProvider(path.join(xdgLocalDir, "coder.json")) + private _vscode?: Promise + private workbenchOptions?: WorkbenchOptions + + public constructor(private readonly args: string[], options: HttpProviderOptions) { + super(options) + this.vsRootPath = path.resolve(this.rootPath, "lib/vscode") + this.serverRootPath = path.join(this.vsRootPath, "out/vs/server") + } + + private async initialize(options: VscodeOptions): Promise { + const id = generateUuid() + const vscode = await this.fork() + + logger.debug("Setting up VS Code...") + return new Promise((resolve, reject) => { + vscode.once("message", (message: VscodeMessage) => { + logger.debug("Got message from VS Code", field("message", message)) + return message.type === "options" && message.id === id + ? resolve(message.options) + : reject(new Error("Unexpected response during initialization")) + }) + vscode.once("error", reject) + vscode.once("exit", (code) => reject(new Error(`VS Code exited unexpectedly with code ${code}`))) + this.send({ type: "init", id, options }, vscode) + }) + } + + private fork(): Promise { + if (!this._vscode) { + logger.debug("Forking VS Code...") + const vscode = cp.fork(path.join(this.serverRootPath, "fork")) + vscode.on("error", (error) => { + logger.error(error.message) + this._vscode = undefined + }) + vscode.on("exit", (code) => { + logger.error(`VS Code exited unexpectedly with code ${code}`) + this._vscode = undefined + }) + + this._vscode = new Promise((resolve, reject) => { + vscode.once("message", (message: VscodeMessage) => { + logger.debug("Got message from VS Code", field("message", message)) + return message.type === "ready" + ? resolve(vscode) + : reject(new Error("Unexpected response waiting for ready response")) + }) + vscode.once("error", reject) + vscode.once("exit", (code) => reject(new Error(`VS Code exited unexpectedly with code ${code}`))) + }) + } + + return this._vscode + } + + public async handleWebSocket( + _base: string, + _requestPath: string, + query: querystring.ParsedUrlQuery, + request: http.IncomingMessage, + socket: net.Socket + ): Promise { + if (!this.authenticated(request)) { + throw new Error("not authenticated") + } + + // VS Code expects a raw socket. It will handle all the web socket frames. + // We just need to handle the initial upgrade. + // This magic value is specified by the websocket spec. + const magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + const reply = crypto + .createHash("sha1") + .update(request.headers["sec-websocket-key"] + magic) + .digest("base64") + socket.write( + [ + "HTTP/1.1 101 Switching Protocols", + "Upgrade: websocket", + "Connection: Upgrade", + `Sec-WebSocket-Accept: ${reply}`, + ].join("\r\n") + "\r\n\r\n" + ) + + const vscode = await this._vscode + this.send({ type: "socket", query }, vscode, socket) + return true + } + + private send(message: CodeServerMessage, vscode?: cp.ChildProcess, socket?: net.Socket): void { + if (!vscode || vscode.killed) { + throw new Error("vscode is not running") + } + vscode.send(message, socket) + } + + public async handleRequest( + base: string, + requestPath: string, + query: querystring.ParsedUrlQuery, + request: http.IncomingMessage + ): Promise { + this.ensureGet(request) + switch (base) { + case "/": + if (!this.authenticated(request)) { + return { redirect: "/login" } + } + return this.getRoot(request, query) + case "/static": { + switch (requestPath) { + case "/out/vs/workbench/services/extensions/worker/extensionHostWorkerMain.js": { + const response = await this.getUtf8Resource(this.vsRootPath, requestPath) + response.content = response.content.replace( + /{{COMMIT}}/g, + this.workbenchOptions ? this.workbenchOptions.commit : "" + ) + response.cache = true + return response + } + } + const response = await this.getResource(this.vsRootPath, requestPath) + response.cache = true + return response + } + case "/resource": + case "/vscode-remote-resource": + this.ensureAuthenticated(request) + if (typeof query.path === "string") { + return this.getResource(query.path) + } + break + case "/tar": + this.ensureAuthenticated(request) + if (typeof query.path === "string") { + return this.getTarredResource(query.path) + } + break + case "/webview": + this.ensureAuthenticated(request) + if (/^\/vscode-resource/.test(requestPath)) { + return this.getResource(requestPath.replace(/^\/vscode-resource(\/file)?/, "")) + } + return this.getResource(this.vsRootPath, "out/vs/workbench/contrib/webview/browser/pre", requestPath) + } + return undefined + } + + private async getRoot(request: http.IncomingMessage, query: querystring.ParsedUrlQuery): Promise { + const settings = await this.settings.read() + const [response, options] = await Promise.all([ + this.getUtf8Resource(this.serverRootPath, "browser/workbench.html"), + this.initialize({ + args: this.args, + query, + remoteAuthority: request.headers.host as string, + settings, + }), + ]) + + this.workbenchOptions = options + + if (options.startPath) { + this.settings.write({ + lastVisited: { + path: options.startPath.path, + workspace: options.startPath.workspace, + }, + }) + } + + return { + ...response, + content: response.content + .replace(/{{COMMIT}}/g, options.commit) + .replace(`"{{REMOTE_USER_DATA_URI}}"`, `'${JSON.stringify(options.remoteUserDataUri)}'`) + .replace(`"{{PRODUCT_CONFIGURATION}}"`, `'${JSON.stringify(options.productConfiguration)}'`) + .replace(`"{{WORKBENCH_WEB_CONFIGURATION}}"`, `'${JSON.stringify(options.workbenchWebConfiguration)}'`) + .replace(`"{{NLS_CONFIGURATION}}"`, `'${JSON.stringify(options.nlsConfiguration)}'`), + } + } +} diff --git a/src/node/wrapper.ts b/src/node/wrapper.ts new file mode 100644 index 00000000..69978b96 --- /dev/null +++ b/src/node/wrapper.ts @@ -0,0 +1,223 @@ +import { logger, field } from "@coder/logger" +import * as cp from "child_process" +import { Emitter } from "../common/emitter" + +interface HandshakeMessage { + type: "handshake" +} + +interface RelaunchMessage { + type: "relaunch" + version: string +} + +export type Message = RelaunchMessage | HandshakeMessage + +export class ProcessError extends Error { + public constructor(message: string, public readonly code: number | undefined) { + super(message) + this.name = this.constructor.name + Error.captureStackTrace(this, this.constructor) + } +} + +/** + * Ensure we control when the process exits. + */ +const exit = process.exit +process.exit = function(code?: number) { + logger.warn(`process.exit() was prevented: ${code || "unknown code"}.`) +} as (code?: number) => never + +/** + * Allows the wrapper and inner processes to communicate. + */ +export class IpcMain { + private readonly _onMessage = new Emitter() + public readonly onMessage = this._onMessage.event + private readonly _onDispose = new Emitter() + public readonly onDispose = this._onDispose.event + + public constructor(public readonly parentPid?: number) { + process.on("SIGINT", () => this._onDispose.emit("SIGINT")) + process.on("SIGTERM", () => this._onDispose.emit("SIGTERM")) + process.on("exit", () => this._onDispose.emit(undefined)) + + this.onDispose((signal) => { + // Remove listeners to avoid possibly triggering disposal again. + process.removeAllListeners() + + // Let any other handlers run first then exit. + logger.debug(`${parentPid ? "inner process" : "wrapper"} ${process.pid} disposing`, field("code", signal)) + setTimeout(() => exit(0), 0) + }) + + // Kill the inner process if the parent dies. This is for the case where the + // parent process is forcefully terminated and cannot clean up. + if (parentPid) { + setInterval(() => { + try { + // process.kill throws an exception if the process doesn't exist. + process.kill(parentPid, 0) + } catch (_) { + // Consider this an error since it should have been able to clean up + // the child process unless it was forcefully killed. + logger.error(`parent process ${parentPid} died`) + this._onDispose.emit(undefined) + } + }, 5000) + } + } + + public handshake(child?: cp.ChildProcess): Promise { + return new Promise((resolve, reject) => { + const target = child || process + const onMessage = (message: Message): void => { + logger.debug( + `${child ? "wrapper" : "inner process"} ${process.pid} received message from ${ + child ? child.pid : this.parentPid + }`, + field("message", message) + ) + if (message.type === "handshake") { + target.removeListener("message", onMessage) + target.on("message", (msg) => this._onMessage.emit(msg)) + // The wrapper responds once the inner process starts the handshake. + if (child) { + if (!target.send) { + throw new Error("child not spawned with IPC") + } + target.send({ type: "handshake" }) + } + resolve() + } + } + target.on("message", onMessage) + if (child) { + child.once("error", reject) + child.once("exit", (code) => { + reject(new ProcessError(`Unexpected exit with code ${code}`, code !== null ? code : undefined)) + }) + } else { + // The inner process initiates the handshake. + this.send({ type: "handshake" }) + } + }) + } + + public relaunch(version: string): void { + this.send({ type: "relaunch", version }) + } + + private send(message: Message): void { + if (!process.send) { + throw new Error("not spawned with IPC") + } + process.send(message) + } +} + +export const ipcMain = new IpcMain( + typeof process.env.CODE_SERVER_PARENT_PID !== "undefined" ? parseInt(process.env.CODE_SERVER_PARENT_PID) : undefined +) + +export interface WrapperOptions { + maxMemory?: number + nodeOptions?: string +} + +/** + * Provides a way to wrap a process for the purpose of updating the running + * instance. + */ +export class WrapperProcess { + private process?: cp.ChildProcess + private started?: Promise + + public constructor(private currentVersion: string, private readonly options?: WrapperOptions) { + ipcMain.onDispose(() => { + if (this.process) { + this.process.removeAllListeners() + this.process.kill() + } + }) + + ipcMain.onMessage(async (message) => { + switch (message.type) { + case "relaunch": + logger.info(`Relaunching: ${this.currentVersion} -> ${message.version}`) + this.currentVersion = message.version + this.started = undefined + if (this.process) { + this.process.removeAllListeners() + this.process.kill() + } + try { + await this.start() + } catch (error) { + logger.error(error.message) + exit(typeof error.code === "number" ? error.code : 1) + } + break + default: + logger.error(`Unrecognized message ${message}`) + break + } + }) + } + + public start(): Promise { + if (!this.started) { + const child = this.spawn() + logger.debug(`spawned inner process ${child.pid}`) + this.started = ipcMain.handshake(child).then(() => { + child.once("exit", (code) => { + logger.debug(`inner process ${child.pid} exited unexpectedly`) + exit(code || 0) + }) + }) + this.process = child + } + return this.started + } + + private spawn(): cp.ChildProcess { + // Flags to pass along to the Node binary. + let nodeOptions = `${process.env.NODE_OPTIONS || ""} ${(this.options && this.options.nodeOptions) || ""}` + if (!/max_old_space_size=(\d+)/g.exec(nodeOptions)) { + nodeOptions += ` --max_old_space_size=${(this.options && this.options.maxMemory) || 2048}` + } + + return cp.fork(process.argv[1], process.argv.slice(2), { + env: { + ...process.env, + CODE_SERVER_PARENT_PID: process.pid.toString(), + NODE_OPTIONS: nodeOptions, + }, + }) + } +} + +// // It's possible that the pipe has closed (for example if you run code-server +// // --version | head -1). Assume that means we're done. +if (!process.stdout.isTTY) { + process.stdout.on("error", () => exit()) +} + +export const wrap = (fn: () => Promise): void => { + if (ipcMain.parentPid) { + ipcMain + .handshake() + .then(() => fn()) + .catch((error: ProcessError): void => { + logger.error(error.message) + exit(typeof error.code === "number" ? error.code : 1) + }) + } else { + const wrapper = new WrapperProcess(require("../../package.json").version) + wrapper.start().catch((error) => { + logger.error(error.message) + exit(typeof error.code === "number" ? error.code : 1) + }) + } +} diff --git a/test/socket.test.ts b/test/socket.test.ts new file mode 100644 index 00000000..c1312d82 --- /dev/null +++ b/test/socket.test.ts @@ -0,0 +1,124 @@ +import { field, logger } from "@coder/logger" +import * as assert from "assert" +import * as fs from "fs-extra" +import "leaked-handles" +import * as net from "net" +import * as path from "path" +import * as tls from "tls" +import { Emitter } from "../src/common/emitter" +import { generateCertificate, tmpdir } from "../src/node/util" +import { SocketProxyProvider } from "../src/node/socket" + +describe("SocketProxyProvider", () => { + const provider = new SocketProxyProvider() + + const onServerError = new Emitter<{ event: string; error: Error }>() + const onClientError = new Emitter<{ event: string; error: Error }>() + const onProxyError = new Emitter<{ event: string; error: Error }>() + const fromServerToClient = new Emitter() + const fromClientToServer = new Emitter() + const fromClientToProxy = new Emitter() + + let errors = 0 + let close = false + const onError = ({ event, error }: { event: string; error: Error }): void => { + if (!close || event === "error") { + logger.error(event, field("error", error.message)) + ++errors + } + } + onServerError.event(onError) + onClientError.event(onError) + onProxyError.event(onError) + + let server: tls.TLSSocket + let proxy: net.Socket + let client: tls.TLSSocket + + const getData = (emitter: Emitter): Promise => { + return new Promise((resolve) => { + const d = emitter.event((t) => { + d.dispose() + resolve(t) + }) + }) + } + + before(async () => { + const cert = await generateCertificate() + const options = { + cert: fs.readFileSync(cert.cert), + key: fs.readFileSync(cert.certKey), + rejectUnauthorized: false, + } + + await fs.mkdirp(path.join(tmpdir, "tests")) + const socketPath = await provider.findFreeSocketPath(path.join(tmpdir, "tests/tls-socket-proxy")) + await fs.remove(socketPath) + + return new Promise((_resolve) => { + const resolved: { [key: string]: boolean } = { client: false, server: false } + const resolve = (type: "client" | "server"): void => { + resolved[type] = true + if (resolved.client && resolved.server) { + // We don't need any more connections. + main.close() // eslint-disable-line @typescript-eslint/no-use-before-define + _resolve() + } + } + const main = tls + .createServer(options, (s) => { + server = s + server + .on("data", (d) => fromClientToServer.emit(d)) + .on("error", (error) => onServerError.emit({ event: "error", error })) + .on("end", () => onServerError.emit({ event: "end", error: new Error("unexpected end") })) + .on("close", () => onServerError.emit({ event: "close", error: new Error("unexpected close") })) + resolve("server") + }) + .on("error", (error) => onServerError.emit({ event: "error", error })) + .on("end", () => onServerError.emit({ event: "end", error: new Error("unexpected end") })) + .on("close", () => onServerError.emit({ event: "close", error: new Error("unexpected close") })) + .listen(socketPath, () => { + client = tls + .connect({ ...options, path: socketPath }) + .on("data", (d) => fromServerToClient.emit(d)) + .on("error", (error) => onClientError.emit({ event: "error", error })) + .on("end", () => onClientError.emit({ event: "end", error: new Error("unexpected end") })) + .on("close", () => onClientError.emit({ event: "close", error: new Error("unexpected close") })) + .once("connect", () => resolve("client")) + }) + }) + }) + + it("should work without a proxy", async () => { + server.write("server->client") + assert.equal(await getData(fromServerToClient), "server->client") + client.write("client->server") + assert.equal(await getData(fromClientToServer), "client->server") + assert.equal(errors, 0) + }) + + it("should work with a proxy", async () => { + assert.equal(server instanceof tls.TLSSocket, true) + proxy = (await provider.createProxy(server)) + .on("data", (d) => fromClientToProxy.emit(d)) + .on("error", (error) => onProxyError.emit({ event: "error", error })) + .on("end", () => onProxyError.emit({ event: "end", error: new Error("unexpected end") })) + .on("close", () => onProxyError.emit({ event: "close", error: new Error("unexpected close") })) + + provider.stop() // We don't need more proxies. + + proxy.write("server proxy->client") + assert.equal(await getData(fromServerToClient), "server proxy->client") + client.write("client->server proxy") + assert.equal(await getData(fromClientToProxy), "client->server proxy") + assert.equal(errors, 0) + }) + + it("should close", async () => { + close = true + client.end() + proxy.end() + }) +}) diff --git a/test/util.test.ts b/test/util.test.ts new file mode 100644 index 00000000..6a9c3a3c --- /dev/null +++ b/test/util.test.ts @@ -0,0 +1,49 @@ +import * as assert from "assert" +import { extend, normalize } from "../src/node/util" + +describe("util", () => { + describe("extend", () => { + it("should extend", () => { + const a = { foo: { bar: 0, baz: 2 }, garply: 4, waldo: 6 } + const b = { foo: { bar: 1, qux: 3 }, garply: "5", fred: 7 } + const extended = extend(a, b) + assert.deepEqual(extended, { + foo: { bar: 1, baz: 2, qux: 3 }, + garply: "5", + waldo: 6, + fred: 7, + }) + }) + + it("should make deep copies of the original objects", () => { + const a = { foo: 0, bar: { frobnozzle: 2 }, mumble: { qux: { thud: 4 } } } + const b = { foo: 1, bar: { chad: 3 } } + const extended = extend(a, b) + assert.notEqual(a.bar, extended.bar) + assert.notEqual(b.bar, extended.bar) + assert.notEqual(a.mumble, extended.mumble) + assert.notEqual(a.mumble.qux, extended.mumble.qux) + }) + + it("should handle mismatch in type", () => { + const a = { foo: { bar: 0, baz: 2, qux: { mumble: 11 } }, garply: 4, waldo: { thud: 10 } } + const b = { foo: { bar: [1], baz: { plugh: 8 }, qux: 12 }, garply: { nox: 9 }, waldo: 7 } + const extended = extend(a, b) + assert.deepEqual(extended, { + foo: { bar: [1], baz: { plugh: 8 }, qux: 12 }, + garply: { nox: 9 }, + waldo: 7, + }) + }) + }) + + describe("normalize", () => { + it("should remove multiple slashes", () => { + assert.equal(normalize("//foo//bar//baz///mumble"), "/foo/bar/baz/mumble") + }) + + it("should remove trailing slashes", () => { + assert.equal(normalize("qux///"), "qux") + }) + }) +}) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..9510fea9 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./out", + "allowJs": false, + "jsx": "react", + "declaration": true, + "experimentalDecorators": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "tsBuildInfoFile": "./.tsbuildinfo", + "incremental": true, + "rootDir": "./src", + "typeRoots": ["./node_modules/@types", "./typings"] + }, + "include": [ + "./src/**/*.ts", + "./src/**/*.tsx" + ] +} diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 9c957f3e..00000000 --- a/tslint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "../../../tslint.json" - ], - "rules": { - "no-unexternalized-strings": false - } -} diff --git a/typings/.npmignore b/typings/.npmignore deleted file mode 100644 index 228e70f9..00000000 --- a/typings/.npmignore +++ /dev/null @@ -1 +0,0 @@ -httpolyglot.d.ts \ No newline at end of file diff --git a/typings/api.d.ts b/typings/api.d.ts deleted file mode 100644 index 6657f6eb..00000000 --- a/typings/api.d.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as vscode from "vscode"; - -// Only export the subset of VS Code we have implemented. -export interface VSCodeApi { - EventEmitter: typeof vscode.EventEmitter; - FileSystemError: typeof vscode.FileSystemError; - FileType: typeof vscode.FileType; - StatusBarAlignment: typeof vscode.StatusBarAlignment; - ThemeColor: typeof vscode.ThemeColor; - TreeItemCollapsibleState: typeof vscode.TreeItemCollapsibleState; - Uri: typeof vscode.Uri; - commands: { - executeCommand: typeof vscode.commands.executeCommand; - registerCommand: typeof vscode.commands.registerCommand; - }; - window: { - createStatusBarItem: typeof vscode.window.createStatusBarItem; - registerTreeDataProvider: typeof vscode.window.registerTreeDataProvider; - showErrorMessage: typeof vscode.window.showErrorMessage; - }; - workspace: { - registerFileSystemProvider: typeof vscode.workspace.registerFileSystemProvider; - }; -} - -export interface CoderApi { - registerView: (viewId: string, viewName: string, containerId: string, containerName: string, icon: string) => void; -} - -export interface IdeReadyEvent extends CustomEvent { - readonly vscode: VSCodeApi; - readonly ide: CoderApi; -} - -declare global { - interface Window { - /** - * Full VS Code extension API. - */ - vscode?: VSCodeApi; - - /** - * Coder API. - */ - ide?: CoderApi; - - /** - * Listen for when the IDE API has been set and is ready to use. - */ - addEventListener(event: "ide-ready", callback: (event: IdeReadyEvent) => void): void; - } -} diff --git a/typings/httpolyglot.d.ts b/typings/httpolyglot.d.ts deleted file mode 100644 index aeb2fc05..00000000 --- a/typings/httpolyglot.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -declare module "httpolyglot" { - import * as http from "http"; - import * as https from "https"; - - function createServer(requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void): http.Server; - function createServer(options: https.ServerOptions, requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void): https.Server; -} diff --git a/typings/httpolyglot/index.d.ts b/typings/httpolyglot/index.d.ts new file mode 100644 index 00000000..7b644a8b --- /dev/null +++ b/typings/httpolyglot/index.d.ts @@ -0,0 +1,10 @@ +declare module "httpolyglot" { + import * as http from "http" + import * as https from "https" + + function createServer(requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void): http.Server + function createServer( + options: https.ServerOptions, + requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void + ): https.Server +} diff --git a/typings/package.json b/typings/package.json deleted file mode 100644 index 11c1652e..00000000 --- a/typings/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@coder/ide-api", - "version": "2.0.3", - "typings": "api.d.ts", - "license": "MIT", - "author": "Coder", - "description": "API for interfacing with the API created for content-scripts.", - "dependencies": { - "@types/vscode": "^1.37.0" - } -} diff --git a/yarn.lock b/yarn.lock index a13a4ad7..887738c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,764 @@ # yarn lockfile v1 -"@coder/logger@^1.1.12", "@coder/logger@^1.1.8": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/compat-data@^7.8.4": + version "7.8.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.5.tgz#d28ce872778c23551cbb9432fc68d28495b613b9" + integrity sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg== + dependencies: + browserslist "^4.8.5" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@>=7.2.2", "@babel/core@^7.4.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" + integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.4" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.4.4", "@babel/generator@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== + dependencies: + "@babel/types" "^7.8.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" + integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-builder-react-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" + integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ== + dependencies: + "@babel/types" "^7.8.3" + esutils "^2.0.0" + +"@babel/helper-call-delegate@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" + integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-compilation-targets@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88" + integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg== + dependencies: + "@babel/compat-data" "^7.8.4" + browserslist "^4.8.5" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/helper-create-regexp-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" + integrity sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q== + dependencies: + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.6.0" + +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" + integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== + dependencies: + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-transforms@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590" + integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" + integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.4.4", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== + +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" + integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" + integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" + integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" + integrity sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-flow@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz#f2c883bd61a6316f2c89380ae5122f923ba4527f" + integrity sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" + integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" + integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8" + integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" + integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-destructuring@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b" + integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" + integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-flow-strip-types@^7.4.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.8.3.tgz#da705a655466b2a9b36046b57bf0cbcd53551bd4" + integrity sha512-g/6WTWG/xbdd2exBBzMfygjX/zw4eyNC4X8pRaq7aRHRoDUCzAIu3kGYIXviOv8BjCuWm8vDBwjHcjiRNgXrPA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-flow" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d" + integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" + integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-modules-amd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" + integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.4.4", "@babel/plugin-transform-modules-commonjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" + integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" + integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" + integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3" + integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA== + dependencies: + "@babel/helper-call-delegate" "^7.8.3" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" + integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" + integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g== + dependencies: + "@babel/helper-builder-react-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-regenerator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8" + integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/preset-env@^7.4.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e" + integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w== + dependencies: + "@babel/compat-data" "^7.8.4" + "@babel/helper-compilation-targets" "^7.8.4" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.8.3" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.8.3" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.8.4" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.8.3" + "@babel/plugin-transform-modules-commonjs" "^7.8.3" + "@babel/plugin-transform-modules-systemjs" "^7.8.3" + "@babel/plugin-transform-modules-umd" "^7.8.3" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.4" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.3" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/types" "^7.8.3" + browserslist "^4.8.5" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.4", "@babel/runtime@^7.6.3": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" + integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/template@^7.4.4", "@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/traverse@^7.4.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" + integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.4" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.4.4", "@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@coder/logger@1.1.11": + version "1.1.11" + resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.11.tgz#e6f36dba9436ae61e66e3f66787d75c768617605" + integrity sha512-EEh1dqSU0AaqjjjMsVqumgZGbrZimKFKIb4t5E6o3FLfVUxJCReSME78Yj2N1xWUVAHMnqafDCxLostpuIotzw== + +"@coder/logger@^1.1.8": version "1.1.12" resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.12.tgz#def113b7183abc35a8da2b57f0929f7e9626f4e0" integrity sha512-oM0j3lTVPqApUm3e0bKKcXpfAiJEys31fgEfQlHmvEA13ujsC4zDuXnt0uzDtph48eMoNRLOF/EE4mNShVJKVw== @@ -19,17 +776,103 @@ node-fetch "^2.3.0" ora "^3.2.0" -"@coder/node-browser@^1.0.6": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@coder/node-browser/-/node-browser-1.0.8.tgz#c22f581b089ad7d95ad1362fd351c57b7fbc6e70" - integrity sha512-NLF9sYMRCN9WK1C224pHax1Cay3qKypg25BhVg7VfNbo3Cpa3daata8RF/rT8JK3lPsu8PmFgDRQjzGC9X1Lrw== +"@iarna/toml@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" + integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg== -"@coder/requirefs@^1.0.6": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@coder/requirefs/-/requirefs-1.1.2.tgz#20b0be27dde1b714853afc67b031a353d11988d7" - integrity sha512-dXslHsPr6PkgtiFV1oUr6XwgCBia4Ct3fmJJCJbzGn7bDNToy5RzB84pZ6we/yj5w2z1awzpQdKusX52OKh3VA== - optionalDependencies: - jszip "2.6.0" +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@parcel/fs@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-1.11.0.tgz#fb8a2be038c454ad46a50dc0554c1805f13535cd" + integrity sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA== + dependencies: + "@parcel/utils" "^1.11.0" + mkdirp "^0.5.1" + rimraf "^2.6.2" + +"@parcel/logger@^1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-1.11.1.tgz#c55b0744bcbe84ebc291155627f0ec406a23e2e6" + integrity sha512-9NF3M6UVeP2udOBDILuoEHd8VrF4vQqoWHEafymO1pfSoOMfxrSJZw1MfyAAIUN/IFp9qjcpDCUbDZB+ioVevA== + dependencies: + "@parcel/workers" "^1.11.0" + chalk "^2.1.0" + grapheme-breaker "^0.3.2" + ora "^2.1.0" + strip-ansi "^4.0.0" + +"@parcel/utils@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-1.11.0.tgz#539e08fff8af3b26eca11302be80b522674b51ea" + integrity sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ== + +"@parcel/watcher@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-1.12.1.tgz#b98b3df309fcab93451b5583fc38e40826696dad" + integrity sha512-od+uCtCxC/KoNQAIE1vWx1YTyKYY+7CTrxBJPRh3cDWw/C0tCtlBMVlrbplscGoEpt6B27KhJDCv82PBxOERNA== + dependencies: + "@parcel/utils" "^1.11.0" + chokidar "^2.1.5" + +"@parcel/workers@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-1.11.0.tgz#7b8dcf992806f4ad2b6cecf629839c41c2336c59" + integrity sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ== + dependencies: + "@parcel/utils" "^1.11.0" + physical-cpu-count "^2.0.0" + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + +"@types/express-serve-static-core@*": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz#f6f41fa35d42e79dbf6610eccbb2637e6008a0cf" + integrity sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg== + dependencies: + "@types/node" "*" + "@types/range-parser" "*" "@types/fs-extra@^8.0.1": version "8.0.1" @@ -38,10 +881,47 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@^10.12.12": - version "10.17.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" - integrity sha512-pMCcqU2zT4TjqYFrWtYHKal7Sl30Ims6ulZ4UFXxI4xbtQqK/qqKwkDoBFCfooRqqmRu9vY3xaJRwxSh673aYg== +"@types/history@*": + version "4.7.5" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.5.tgz#527d20ef68571a4af02ed74350164e7a67544860" + integrity sha512-wLD/Aq2VggCJXSjxEwrMafIP51Z+13H78nXIX0ABEuIGhmB5sNGbR113MOKo+yfw+RDo1ZU3DM6yfnnRF/+ouw== + +"@types/json-schema@^7.0.3": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + +"@types/mocha@^5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + +"@types/node@*", "@types/node@^12.12.7": + version "12.12.26" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.26.tgz#213e153babac0ed169d44a6d919501e68f59dea9" + integrity sha512-UmUm94/QZvU5xLcUlNR8hA7Ac+fGpO1EG/a8bcWVz0P0LqtxFmun9Y2bbtuckwGboWJIT70DoWq1r3hb56n3DA== + +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/parcel-bundler@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@types/parcel-bundler/-/parcel-bundler-1.12.1.tgz#21c16a4912393b2d6414d1f1f9e886a30f79f2e6" + integrity sha512-I7Cy3Uy/HqMa3E7dyPxTkiPFx0gi3bIQxAcZCP8v1vFx+esdVFgbZBnusa6VfoIeFk61/fnVl25RyYKgDHVLtw== + dependencies: + "@types/express-serve-static-core" "*" + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/pem@^1.9.5": version "1.9.5" @@ -50,6 +930,53 @@ dependencies: "@types/node" "*" +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/react-dom@^16.9.5": + version "16.9.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.5.tgz#5de610b04a35d07ffd8f44edad93a71032d9aaa7" + integrity sha512-BX6RQ8s9D+2/gDhxrj8OW+YD4R+8hj7FEM/OJHGNR0KipE1h1mSsf39YeyC81qafkq+N3rU3h3RFbLSwE5VqUg== + dependencies: + "@types/react" "*" + +"@types/react-router-dom@^5.1.3": + version "5.1.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.3.tgz#b5d28e7850bd274d944c0fbbe5d57e6b30d71196" + integrity sha512-pCq7AkOvjE65jkGS5fQwQhvUp4+4PVD9g39gXLZViP2UqFiFzsEpB3PKf0O6mdbKsewSK8N14/eegisa/0CwnA== + dependencies: + "@types/history" "*" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.4" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.4.tgz#7d70bd905543cb6bcbdcc6bd98902332054f31a6" + integrity sha512-PZtnBuyfL07sqCJvGg3z+0+kt6fobc/xmle08jBiezLS8FrmGeiGkJnuxL/8Zgy9L83ypUhniV5atZn/L8n9MQ== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react@*", "@types/react@^16.9.18": + version "16.9.19" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.19.tgz#c842aa83ea490007d29938146ff2e4d9e4360c40" + integrity sha512-LJV97//H+zqKWMms0kvxaKYJDG05U2TtQB3chRLF8MPNs+MQh/H1aGlyDUxjaHvu08EAGerdX2z4LTBc7ns77A== + dependencies: + "@types/prop-types" "*" + csstype "^2.2.0" + "@types/safe-compare@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/safe-compare/-/safe-compare-1.1.0.tgz#47ed9b9ca51a3a791b431cd59b28f47fa9bf1224" @@ -70,6 +997,77 @@ dependencies: "@types/node" "*" +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" + integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== + +"@types/vfile-message@*": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/vfile-message/-/vfile-message-2.0.0.tgz#690e46af0fdfc1f9faae00cd049cc888957927d5" + integrity sha512-GpTIuDpb9u4zIO165fUy9+fXcULdD8HFRNli04GehoMVbeNq7D6OBnqSmg3lxZnC+UvgUhEWKxdKiwYUkGltIw== + dependencies: + vfile-message "*" + +"@types/vfile@^3.0.0": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/vfile/-/vfile-3.0.2.tgz#19c18cd232df11ce6fa6ad80259bc86c366b09b9" + integrity sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw== + dependencies: + "@types/node" "*" + "@types/unist" "*" + "@types/vfile-message" "*" + +"@types/ws@^6.0.4": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-6.0.4.tgz#7797707c8acce8f76d8c34b370d4645b70421ff1" + integrity sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^2.0.0": + version "2.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.0.tgz#bf743448a4633e4b52bee0c40148ba072ab3adbd" + integrity sha512-u7IcQ9qwsB6U806LupZmINRnQjC+RJyv36sV/ugaFWMHTbFm/hlLTRx3gGYJgHisxcGSTnf+I/fPDieRMhPSQQ== + dependencies: + "@typescript-eslint/experimental-utils" "2.19.0" + eslint-utils "^1.4.3" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.19.0": + version "2.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.0.tgz#d5ca732f22c009e515ba09fcceb5f2127d841568" + integrity sha512-zwpg6zEOPbhB3+GaQfufzlMUOO6GXCNZq6skk+b2ZkZAIoBhVoanWK255BS1g5x9bMwHpLhX0Rpn5Fc3NdCZdg== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.19.0" + eslint-scope "^5.0.0" + +"@typescript-eslint/parser@^2.0.0": + version "2.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.19.0.tgz#912160d9425395d09857dcd5382352bc98be11ae" + integrity sha512-s0jZoxAWjHnuidbbN7aA+BFVXn4TCcxEVGPV8lWMxZglSs3NRnFFAlL+aIENNmzB2/1jUJuySi6GiM6uACPmpg== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.19.0" + "@typescript-eslint/typescript-estree" "2.19.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.19.0": + version "2.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.0.tgz#6bd7310b9827e04756fe712909f26956aac4b196" + integrity sha512-n6/Xa37k0jQdwpUszffi19AlNbVCR0sdvCs3DmSKMD7wBttKY31lhD2fug5kMD91B2qW4mQldaTEc1PEzvGu8w== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + JSONStream@^1.0.3: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -78,10 +1076,23 @@ JSONStream@^1.0.3: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abab@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" + integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + +acorn-globals@^4.3.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" + integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== + dependencies: + acorn "^6.0.1" + acorn-walk "^6.0.1" + +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: version "1.8.2" @@ -92,22 +1103,62 @@ acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: acorn-walk "^7.0.0" xtend "^4.0.2" +acorn-walk@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" + integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== + acorn-walk@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.0.0.tgz#c8ba6f0f1aac4b0a9e32d1f0af12be769528f36b" integrity sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg== -acorn@^7.0.0: +acorn@^5.0.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + +acorn@^6.0.1, acorn@^6.0.4: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + +acorn@^7.0.0, acorn@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: + version "6.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" + integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== dependencies: - string-width "^2.0.0" + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" @@ -119,13 +1170,38 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-styles@^3.2.1: +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +ansi-to-html@^0.6.4: + version "0.6.13" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.13.tgz#c72eae8b63e5ca0643aab11bfc6e6f2217425833" + integrity sha512-Ys2/umuaTlQvP9DLkaa7UzRKF2FLrfod/hNHXS9QhXCrw7seObG6ksOGmNz3UoK+adwM8L9vQfG7mvaxfJ3Jvw== + dependencies: + entities "^1.1.2" + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -139,6 +1215,13 @@ arg@^4.1.0: resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -154,11 +1237,43 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + +array-includes@^3.0.3, array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flat@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -168,7 +1283,19 @@ asn1.js@^4.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -assert@^1.4.0: +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1, assert@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== @@ -181,16 +1308,93 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-each@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +autoprefixer@^9.7.3: + version "9.7.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" + integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== + dependencies: + browserslist "^4.8.3" + caniuse-lite "^1.0.30001020" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.26" + postcss-value-parser "^4.0.2" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-runtime@^6.11.6, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-types@^6.15.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon-walk@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" + integrity sha1-OxWl3btIKni0zpwByLoYFwLZ1s4= + dependencies: + babel-runtime "^6.11.6" + babel-types "^6.15.0" + lodash.clone "^4.5.0" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -214,6 +1418,13 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -238,18 +1449,10 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== -boxen@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= brace-expansion@^1.1.7: version "1.1.11" @@ -275,6 +1478,23 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brfs@^1.2.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" + integrity sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ== + dependencies: + quote-stream "^1.0.1" + resolve "^1.1.5" + static-module "^2.2.0" + through2 "^2.0.0" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -292,6 +1512,11 @@ browser-pack@^6.0.1: through2 "^2.0.0" umd "^3.0.0" +browser-process-hrtime@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" + integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== + browser-resolve@^1.11.0, browser-resolve@^1.7.0: version "1.11.3" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" @@ -299,6 +1524,11 @@ browser-resolve@^1.11.0, browser-resolve@^1.7.0: dependencies: resolve "1.1.7" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -351,7 +1581,7 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@~0.2.0: +browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== @@ -412,6 +1642,15 @@ browserify@^16.5.0: vm-browserify "^1.0.0" xtend "^4.0.0" +browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.8.3, browserslist@^4.8.5: + version "4.8.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e" + integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg== + dependencies: + caniuse-lite "^1.0.30001023" + electron-to-chromium "^1.3.341" + node-releases "^1.1.47" + 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" @@ -425,6 +1664,11 @@ buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs= + buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" @@ -440,6 +1684,15 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + buffer@^5.0.2: version "5.4.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" @@ -473,17 +1726,86 @@ cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== -camelcase@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -capture-stack-trace@^1.0.0: +call-me-maybe@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" - integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= -chalk@^2.0.1, chalk@^2.4.2: +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-keys@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.1.2.tgz#531a289aeea93249b63ec1249db9265f305041f7" + integrity sha512-QfFrU0CIw2oltVvpndW32kuJ/9YOJwUnmWrjlXt1nnJZHCaS9i6bfOpg9R4Lw8aZjStkJWM+jc0cdXjWBgVJSw== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001023: + version "1.0.30001024" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001024.tgz#7feb6793fd5c9d7e0d4c01c80321855592a46b73" + integrity sha512-LubRSEPpOlKlhZw9wGlLHo8ZVj6ugGU3xGUfLPneNBledSd9lIM5cCGZ9Mz/mMCJUhEt4jZpYteZNVRdJw5FRA== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +ccount@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" + integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw== + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -492,12 +1814,45 @@ chalk@^2.0.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-html4@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.4.tgz#0e64b0a3753ddbf1fdc044c5fd01d0199a02e125" + integrity sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g== + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -chokidar@^2.1.8: +chokidar@^2.1.5: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -521,11 +1876,6 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== -ci-info@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -544,11 +1894,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -556,16 +1901,68 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== + cli-spinners@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-regexp@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f" + integrity sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q== + dependencies: + is-regexp "^2.0.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -574,18 +1971,46 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + combine-source-map@^0.8.0, combine-source-map@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" @@ -596,6 +2021,23 @@ combine-source-map@^0.8.0, combine-source-map@~0.8.0: lodash.memoize "~3.0.3" source-map "~0.5.3" +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" + integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== + +commander@^2.11.0, commander@^2.19.0, commander@^2.20.0: + 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== + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -616,28 +2058,28 @@ concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -configstore@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" - integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -constants-browserify@~1.0.0: +constants-browserify@^1.0.0, 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= + +convert-source-map@^1.5.1, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + convert-source-map@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" @@ -648,11 +2090,45 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-util-is@~1.0.0: +core-js-compat@^3.6.2: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" + integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== + dependencies: + browserslist "^4.8.3" + semver "7.0.0" + +core-js@^2.4.0, core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +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" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -661,13 +2137,6 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= - dependencies: - capture-stack-trace "^1.0.0" - create-hash@^1.1.0, create-hash@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" @@ -691,12 +2160,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= +cross-spawn@^6.0.4, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: - lru-cache "^4.0.1" + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" shebang-command "^1.2.0" which "^1.2.9" @@ -705,7 +2176,7 @@ crypt@~0.0.1: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -crypto-browserify@^3.0.0: +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== @@ -722,39 +2193,252 @@ crypto-browserify@^3.0.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-modules-loader-core@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16" + integrity sha1-WQhmgpShvs0mGuCkziGwtVHyHRY= + dependencies: + icss-replace-symbols "1.1.0" + postcss "6.0.1" + postcss-modules-extract-imports "1.1.0" + postcss-modules-local-by-default "1.2.0" + postcss-modules-scope "1.1.0" + postcss-modules-values "1.3.0" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-selector-tokenizer@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d" + integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA== + dependencies: + cssesc "^0.1.0" + fastparse "^1.1.1" + regexpu-core "^1.0.0" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +cssesc@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" + integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q= + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.0.0, cssnano@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" + integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + dependencies: + css-tree "1.0.0-alpha.37" + +cssom@0.3.x, cssom@^0.3.4: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" + integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== + dependencies: + cssom "0.3.x" + +csstype@^2.2.0: + version "2.6.8" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.8.tgz#0fb6fc2417ffd2816a418c9336da74d7f07db431" + integrity sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA== dash-ast@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== -debug@^2.2.0, debug@^2.3.3: +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" + integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: + abab "^2.0.0" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + +deasync@^0.1.14: + version "0.1.19" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" + integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.7.1" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, 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.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= defaults@^1.0.3: version "1.0.3" @@ -797,6 +2481,16 @@ defined@^1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + deps-sort@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" @@ -815,6 +2509,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= + detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -824,6 +2523,11 @@ detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diff@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" @@ -838,29 +2542,121 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -domain-browser@^1.2.0: +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +domain-browser@^1.1.1, domain-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -dot-prop@^4.1.0: +domelementtype@1, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@^1.5.1, domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== dependencies: is-obj "^1.0.0" -duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" + integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= dependencies: readable-stream "^2.0.2" -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + 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.341: + version "1.3.344" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz#f1397a633c35e726730c24be1084cd25c3ee8148" + integrity sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw== elliptic@^6.0.0: version "6.5.2" @@ -875,6 +2671,21 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +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.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -882,6 +2693,45 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +entities@^1.1.1, entities@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +envinfo@^7.3.1: + version "7.5.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.0.tgz#91410bb6db262fb4f1409bd506e9ff57e91023f4" + integrity sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ== + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.0, es-abstract@^1.17.2: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + es-abstract@^1.17.0-next.1: version "1.17.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" @@ -913,16 +2763,230 @@ es6-promisify@^6.0.0: resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.2.tgz#525c23725b8510f5f1f2feb5a1fbad93a93e29b4" integrity sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg== -escape-string-regexp@^1.0.5: +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.2, 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= +escodegen@^1.11.0, escodegen@^1.11.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.13.0.tgz#c7adf9bd3f3cc675bb752f202f79a720189cab29" + integrity sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw== + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@~1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" + integrity sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@^6.0.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz#7b15e303bf9c956875c948f6b21500e48ded6a7f" + integrity sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg== + dependencies: + get-stdin "^6.0.0" + +eslint-import-resolver-node@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" + integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz#7878f7504824e1b857dd2505b59a8e5eda26a708" + integrity sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.18.2: + version "2.20.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3" + integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw== + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.1" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.12.0" + +eslint-plugin-prettier@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react-hooks@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz#6210b6d5a37205f0b92858f895a4e827020a7d04" + integrity sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA== + +eslint-plugin-react@^7.14.3: + version "7.18.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.18.3.tgz#8be671b7f6be095098e79d27ac32f9580f599bc8" + integrity sha512-Bt56LNHAQCoou88s8ViKRjMB2+36XRejCQ1VoLj716KI1MoE99HpTVvIThJ0rvFmG4E4Gsq+UgToEjn+j044Bg== + dependencies: + array-includes "^3.1.1" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.2.3" + object.entries "^1.1.1" + object.fromentries "^2.0.2" + object.values "^1.1.1" + prop-types "^15.7.2" + resolve "^1.14.2" + string.prototype.matchall "^4.0.2" + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@^6.2.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.0, esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + events@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -931,18 +2995,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= +execall@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" + integrity sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow== dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" + clone-regexp "^2.1.0" expand-brackets@^2.1.4: version "2.1.4" @@ -972,6 +3030,20 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -986,16 +3058,110 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +falafel@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" + integrity sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw= + dependencies: + acorn "^5.0.0" + foreach "^2.0.5" + isarray "0.0.1" + object-keys "^1.0.6" + +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^2.2.2: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fast-glob@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + fast-safe-stringify@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== +fastparse@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" + integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== + +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== +filesize@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1006,11 +3172,80 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -1018,6 +3253,11 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +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" @@ -1059,21 +3299,53 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-assigned-identifiers@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== -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-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-port@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + +get-stdin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" + integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -1082,7 +3354,31 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob@^7.1.0, glob@^7.1.3: +glob-parent@^5.0.0, glob-parent@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1094,40 +3390,121 @@ glob@^7.1.0, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" - integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== dependencies: - ini "^1.3.4" + global-prefix "^3.0.0" -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" + integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.0.tgz#56fd0e9f0d4f8fb0c456f1ab0dee96e1380bc154" + integrity sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +globjoin@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" + integrity sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM= + +gonzales-pe@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/gonzales-pe/-/gonzales-pe-4.2.4.tgz#356ae36a312c46fe0f1026dd6cb539039f8500d2" + integrity sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ== + dependencies: + minimist "1.1.x" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +grapheme-breaker@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" + integrity sha1-W55reMODJFLSuiuxy4MPlidkEKw= + dependencies: + brfs "^1.2.0" + unicode-trie "^0.3.1" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +hard-rejection@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -1164,7 +3541,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.3: +has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -1187,6 +3564,28 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + +history@^4.9.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1196,11 +3595,101 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hosted-git-info@^2.1.4: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + +html-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== + dependencies: + whatwg-encoding "^1.0.1" + +html-tags@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98" + integrity sha1-x43mW1Zjqll5id0rerSSANfk25g= + +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== + htmlescape@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= +htmlnano@^0.2.2: + version "0.2.5" + resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.2.5.tgz#134fd9548c7cbe51c8508ce434a3f9488cff1b0b" + integrity sha512-X1iPSwXG/iF9bVs+/obt2n6F64uH0ETkA8zp7qFDmLW9/+A6ueHGeb/+qD67T21qUY22owZPMdawljN50ajkqA== + dependencies: + cssnano "^4.1.10" + normalize-html-whitespace "^1.0.0" + posthtml "^0.12.0" + posthtml-render "^1.1.5" + purgecss "^1.4.0" + svgo "^1.3.2" + terser "^4.3.9" + uncss "^0.17.2" + +htmlparser2@^3.10.0, htmlparser2@^3.9.2: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + httpolyglot@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/httpolyglot/-/httpolyglot-0.1.2.tgz#e4d347fe8984a62f467d4060df527f1851f6997b" @@ -1211,26 +3700,69 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= + ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ignore-by-default@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +ignore@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" + integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1239,7 +3771,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1254,7 +3786,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -1266,6 +3798,25 @@ inline-source-map@~0.6.0: dependencies: source-map "~0.5.3" +inquirer@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.4.tgz#99af5bde47153abca23f5c7fc30db247f39da703" + integrity sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + insert-module-globals@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" @@ -1282,6 +3833,32 @@ insert-module-globals@^7.0.0: undeclared-identifiers "^1.1.2" xtend "^4.0.0" +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== + dependencies: + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" + +invariant@^2.2.2, invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-absolute-url@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -1296,10 +3873,33 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-arguments@^1.0.4: +is-alphabetical@^1.0.0: version "1.0.4" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" - integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumeric@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" + integrity sha1-Spzvcdr0wAHB2B1j0UDPU/1oifQ= + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== is-binary-path@^1.0.0: version "1.0.1" @@ -1313,17 +3913,27 @@ is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.1: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@^2.0.0, is-buffer@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-callable@^1.1.4, is-callable@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== -is-ci@^1.0.10: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" - integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= dependencies: - ci-info "^1.5.0" + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" is-data-descriptor@^0.1.4: version "0.1.4" @@ -1344,6 +3954,11 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -1362,6 +3977,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -1384,10 +4004,10 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-generator-function@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^3.1.0: version "3.1.0" @@ -1396,25 +4016,24 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0: +is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" -is-installed-globally@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" - integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= - dependencies: - global-dirs "^0.1.0" - is-path-inside "^1.0.0" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= +is-html@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-html/-/is-html-1.1.0.tgz#e04f1c18d39485111396f9a0273eab51af218464" + integrity sha1-4E8cGNOUhRETlvmgJz6rUa8hhGQ= + dependencies: + html-tags "^1.0.0" is-number@^3.0.0: version "3.0.0" @@ -1423,17 +4042,20 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" - integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= - dependencies: - path-is-inside "^1.0.1" +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" @@ -1442,10 +4064,10 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.5: version "1.0.5" @@ -1454,15 +4076,27 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== +is-regexp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" + integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA== -is-stream@^1.0.0, is-stream@^1.1.0: +is-resolvable@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" is-symbol@^1.0.2: version "1.0.3" @@ -1471,12 +4105,42 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-url@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -isarray@1.0.0, isarray@~1.0.0: +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -1498,6 +4162,91 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b" + integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng== + dependencies: + abab "^2.0.0" + acorn "^6.0.4" + acorn-globals "^4.3.0" + array-equal "^1.0.0" + cssom "^0.3.4" + cssstyle "^1.1.1" + data-urls "^1.1.0" + domexception "^1.0.1" + escodegen "^1.11.0" + html-encoding-sniffer "^1.0.2" + nwsapi "^2.1.3" + parse5 "5.1.0" + pn "^1.1.0" + request "^2.88.0" + request-promise-native "^1.0.5" + saxes "^3.1.9" + symbol-tree "^3.2.2" + tough-cookie "^2.5.0" + w3c-hr-time "^1.0.1" + w3c-xmlserializer "^1.1.2" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^7.0.0" + ws "^6.1.2" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json-stable-stringify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" @@ -1505,6 +4254,25 @@ json-stable-stringify@~0.0.0: dependencies: jsonify "~0.0.0" +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1522,12 +4290,23 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= -jszip@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-2.6.0.tgz#7fb3e9c2f11c8a9840612db5dabbc8cf3a7534b7" - integrity sha1-f7PpwvEciphAYS212rvIzzp1NLc= +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= dependencies: - pako "~1.0.0" + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jsx-ast-utils@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f" + integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA== + dependencies: + array-includes "^3.0.3" + object.assign "^4.1.0" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" @@ -1553,6 +4332,11 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== +known-css-properties@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.17.0.tgz#1c535f530ee8e9e3e27bb6a718285780e1d07326" + integrity sha512-Vi3nxDGMm/z+lAaCjvAR1u+7fiv+sG6gU/iYDj5QOF8h76ytK9EW/EKfF0NeTyiGBi8Jy6Hklty/vxISrLox3w== + labeled-stream-splicer@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz#42a41a16abcd46fd046306cf4f2c3576fffb1c21" @@ -1561,44 +4345,135 @@ labeled-stream-splicer@^2.0.0: inherits "^2.0.1" stream-splicer "^2.0.0" -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= +leaked-handles@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/leaked-handles/-/leaked-handles-5.2.0.tgz#67228e90293b7e0ee36c4190e1f541cddece627f" + integrity sha1-ZyKOkCk7fg7jbEGQ4fVBzd7OYn8= dependencies: - package-json "^4.0.0" + process "^0.10.0" + weakmap-shim "^1.1.0" + xtend "^4.0.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.clone@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" + integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= -log-symbols@^2.2.0: +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-symbols@2.2.0, log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" -lowercase-keys@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" + chalk "^2.4.2" -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== +longest-streak@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" + integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: - pify "^3.0.0" + js-tokens "^3.0.0 || ^4.0.0" + +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + integrity sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w== + dependencies: + vlq "^0.2.2" make-error@^1.1.1: version "1.3.5" @@ -1610,6 +4485,16 @@ map-cache@^0.2.2: resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" + integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -1617,6 +4502,21 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +markdown-table@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== + +mathml-tag-names@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" + integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -1635,7 +4535,48 @@ md5@^2.2.1: crypt "~0.0.1" is-buffer "~1.1.1" -micromatch@^3.1.10, micromatch@^3.1.4: +mdast-util-compact@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.4.tgz#d531bb7667b5123abf20859be086c4d06c894593" + integrity sha512-3YDMQHI5vRiS2uygEFYaqckibpJtKq5Sj2c8JioeOQBU6INpKbdWzfyLqFFnDwEcEnRFIdMsguzs5pC1Jp4Isg== + dependencies: + unist-util-visit "^1.1.0" + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +meow@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-6.0.0.tgz#949196fdf21d979379e3bdccb0411e60f8cffd93" + integrity sha512-x4rYsjigPBDAxY+BGuK83YLhUIqui5wYyZoqb6QJCUOs+0fiYq+i/NV4Jt8OgIfObZFxG9iTyvLDu4UTohGTFw== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.1.1" + decamelize-keys "^1.1.0" + hard-rejection "^2.0.0" + minimist-options "^4.0.1" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.0" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.8.1" + yargs-parser "^16.1.0" + +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + integrity sha1-pd5GU42uhNQRTMXqArR3KmNGcB8= + dependencies: + source-map "^0.5.6" + +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -1654,6 +4595,14 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -1662,11 +4611,47 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +min-indent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.0.tgz#cfc45c37e9ec0d8f0a0ec3dd4ef7f7c3abe39256" + integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= + +mini-create-react-context@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" + integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw== + dependencies: + "@babel/runtime" "^7.4.0" + gud "^1.0.0" + tiny-warning "^1.0.2" + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -1677,19 +4662,32 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" +minimist-options@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.0.2.tgz#29c4021373ded40d546186725e57761e4b1984a7" + integrity sha512-seq4hpWkYSUh1y7NXxzucwAN9yVlBc3Upgdjz8vLCP97jG8kaOmzYrVH/m7tQ1NYD1wdtZbSLfdy4zFmRWuc/w== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.1.0, minimist@^1.1.1, minimist@^1.2.0: +minimist@1.1.x: + version "1.1.3" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.1.3.tgz#3bedfd91a92d39016fcfaa1c681e8faa1a1efda8" + integrity sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag= + +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= @@ -1702,13 +4700,42 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" +mocha@^6.2.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + module-deps@^6.0.0: version "6.2.2" resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.2.tgz#d8a15c2265dfc119153c29bb47386987d0ee423b" @@ -1735,11 +4762,21 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.12.1: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -1762,33 +4799,89 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" + integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== + +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch@^2.3.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== -nodemon@^1.19.1: - version "1.19.4" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.4.tgz#56db5c607408e0fdf8920d2b444819af1aae0971" - integrity sha512-VGPaqQBNk193lrJFotBU8nvWZPqEZY2eIzymy2jjY0fJ9qIsxA0sxQ8ATPl0gZC645gijYEc1jtZvpS8QWzJGQ== - dependencies: - chokidar "^2.1.8" - debug "^3.2.6" - ignore-by-default "^1.0.1" - minimatch "^3.0.4" - pstree.remy "^1.1.7" - semver "^5.7.1" - supports-color "^5.5.0" - touch "^3.1.0" - undefsafe "^2.0.2" - update-notifier "^2.5.0" +node-forge@^0.7.1: + version "0.7.6" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" + integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== -nopt@~1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= +node-libs-browser@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: - abbrev "1" + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-releases@^1.1.47: + version "1.1.47" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4" + integrity sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA== + dependencies: + semver "^6.3.0" + +normalize-html-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-1.0.0.tgz#5e3c8e192f1b06c3b9eee4b7e7f28854c7601e34" + integrity sha512-9ui7CGtOOlehQu0t/OhhlmDyc71mKVlv+4vF+me4iZLPrNtRL2xoquEdfZxasC/bdQi/Hr3iTrpyRKIG+ocabA== + +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" normalize-path@^2.1.1: version "2.1.1" @@ -1802,12 +4895,42 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-selector@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" + integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: - path-key "^2.0.0" + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + +nwsapi@^2.1.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== object-assign@^4.1.1: version "4.1.1" @@ -1828,7 +4951,12 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-inspect@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" + integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -1840,7 +4968,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: +object.assign@4.1.0, object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -1850,7 +4978,7 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.entries@^1.1.0: +object.entries@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== @@ -1860,6 +4988,24 @@ object.entries@^1.1.0: function-bind "^1.1.1" has "^1.0.3" +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -1867,6 +5013,23 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.1.0, object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +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" + 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" @@ -1881,6 +5044,44 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +opn@^5.1.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + +optionator@^0.8.1, optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +ora@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" + integrity sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA== + dependencies: + chalk "^2.3.1" + cli-cursor "^2.1.0" + cli-spinners "^1.1.0" + log-symbols "^2.2.0" + strip-ansi "^4.0.0" + wcwidth "^1.0.1" + ora@^3.2.0: version "3.4.0" resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" @@ -1893,36 +5094,143 @@ ora@^3.2.0: strip-ansi "^5.2.0" wcwidth "^1.0.1" -os-browserify@~0.3.0: +os-browserify@^0.3.0, 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-tmpdir@^1.0.1: +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" + p-try "^1.0.0" -pako@~1.0.0, pako@~1.0.5: +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@^0.2.5: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= + +pako@~1.0.5: version "1.0.10" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== +parcel-bundler@^1.12.4: + version "1.12.4" + resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.12.4.tgz#31223f4ab4d00323a109fce28d5e46775409a9ee" + integrity sha512-G+iZGGiPEXcRzw0fiRxWYCKxdt/F7l9a0xkiU4XbcVRJCSlBnioWEwJMutOCCpoQmaQtjB4RBHDGIHN85AIhLQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.4.4" + "@babel/generator" "^7.4.4" + "@babel/parser" "^7.4.4" + "@babel/plugin-transform-flow-strip-types" "^7.4.4" + "@babel/plugin-transform-modules-commonjs" "^7.4.4" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/preset-env" "^7.4.4" + "@babel/runtime" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" + "@iarna/toml" "^2.2.0" + "@parcel/fs" "^1.11.0" + "@parcel/logger" "^1.11.1" + "@parcel/utils" "^1.11.0" + "@parcel/watcher" "^1.12.1" + "@parcel/workers" "^1.11.0" + ansi-to-html "^0.6.4" + babylon-walk "^1.0.2" + browserslist "^4.1.0" + chalk "^2.1.0" + clone "^2.1.1" + command-exists "^1.2.6" + commander "^2.11.0" + core-js "^2.6.5" + cross-spawn "^6.0.4" + css-modules-loader-core "^1.1.0" + cssnano "^4.0.0" + deasync "^0.1.14" + dotenv "^5.0.0" + dotenv-expand "^5.1.0" + envinfo "^7.3.1" + fast-glob "^2.2.2" + filesize "^3.6.0" + get-port "^3.2.0" + htmlnano "^0.2.2" + is-glob "^4.0.0" + is-url "^1.2.2" + js-yaml "^3.10.0" + json5 "^1.0.1" + micromatch "^3.0.4" + mkdirp "^0.5.1" + node-forge "^0.7.1" + node-libs-browser "^2.0.0" + opn "^5.1.0" + postcss "^7.0.11" + postcss-value-parser "^3.3.1" + posthtml "^0.11.2" + posthtml-parser "^0.4.0" + posthtml-render "^1.1.3" + resolve "^1.4.0" + semver "^5.4.1" + serialize-to-js "^3.0.0" + serve-static "^1.12.4" + source-map "0.6.1" + terser "^3.7.3" + v8-compile-cache "^2.0.0" + ws "^5.1.1" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parents@^1.0.0, parents@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" @@ -1942,12 +5250,59 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-entities@^1.0.2, parse-entities@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" + integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + +parse5@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" + integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@~0.0.0: +path-browserify@0.0.1, path-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== @@ -1957,17 +5312,22 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "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: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0: +path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= @@ -1982,6 +5342,25 @@ path-platform@~0.11.15: resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -2003,40 +5382,545 @@ pem@^1.14.2: os-tmpdir "^1.0.1" which "^1.3.1" -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= +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +physical-cpu-count@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" + integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= + +picomatch@^2.0.5: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +postcss-calc@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + +postcss-html@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== + dependencies: + htmlparser2 "^3.10.0" + +postcss-jsx@^0.36.3: + version "0.36.4" + resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.4.tgz#37a68f300a39e5748d547f19a747b3257240bd50" + integrity sha512-jwO/7qWUvYuWYnpOb0+4bIIgJt7003pgU3P6nETBLaOyBXuTD55ho21xnals5nBrlpTIFodyd3/jBi6UO3dHvA== + dependencies: + "@babel/core" ">=7.2.2" + +postcss-less@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.4.tgz#369f58642b5928ef898ffbc1a6e93c958304c5ad" + integrity sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA== + dependencies: + postcss "^7.0.14" + +postcss-markdown@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560" + integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ== + dependencies: + remark "^10.0.1" + unist-util-find-all-after "^1.0.2" + +postcss-media-query-parser@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" + integrity sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ= + +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-modules-extract-imports@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" + integrity sha1-thTJcgvmgW6u41+zpfqh26agXds= + dependencies: + postcss "^6.0.1" + +postcss-modules-local-by-default@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" + integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk= + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-scope@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" + integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A= + dependencies: + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" + +postcss-modules-values@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" + integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA= + dependencies: + icss-replace-symbols "^1.1.0" + postcss "^6.0.1" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-reporter@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f" + integrity sha512-LpmQjfRWyabc+fRygxZjpRxfhRf9u/fdlKf4VHG4TSPbV2XNsuISzYW1KL+1aQzx53CAppa1bKG4APIB/DOXXw== + dependencies: + chalk "^2.4.1" + lodash "^4.17.11" + log-symbols "^2.2.0" + postcss "^7.0.7" + +postcss-resolve-nested-selector@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz#29ccbc7c37dedfac304e9fff0bf1596b3f6a0e4e" + integrity sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4= + +postcss-safe-parser@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea" + integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ== + dependencies: + postcss "^7.0.0" + +postcss-sass@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.4.2.tgz#7d1f8ddf6960d329de28fb3ff43c9c42013646bc" + integrity sha512-hcRgnd91OQ6Ot9R90PE/khUDCJHG8Uxxd3F7Y0+9VHjBiJgNv7sK5FxyHMCBtoLmmkzVbSj3M3OlqUfLJpq0CQ== + dependencies: + gonzales-pe "^4.2.4" + postcss "^7.0.21" + +postcss-scss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-2.0.0.tgz#248b0a28af77ea7b32b1011aba0f738bda27dea1" + integrity sha512-um9zdGKaDZirMm+kZFKKVsnKPF7zF7qBAtIfTSnZXD1jZ0JNZIxdB6TxQOjCnlSzLRInVl2v3YdBh/M881C4ug== + dependencies: + postcss "^7.0.0" + +postcss-selector-parser@6.0.2, postcss-selector-parser@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^3.0.0, postcss-selector-parser@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-syntax@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== + +postcss@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" + integrity sha1-AA29H47vIXqjaLmiEsX8QLKo8/I= + dependencies: + chalk "^1.1.3" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.1: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.5, postcss@^7.0.7: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +posthtml-parser@^0.4.0, posthtml-parser@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.2.tgz#a132bbdf0cd4bc199d34f322f5c1599385d7c6c1" + integrity sha512-BUIorsYJTvS9UhXxPTzupIztOMVNPa/HtAm9KHni9z6qEfiJ1bpOBL5DfUOL9XAc3XkLIEzBzpph+Zbm4AdRAg== + dependencies: + htmlparser2 "^3.9.2" + +posthtml-render@^1.1.3, posthtml-render@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.5.tgz#387934e85438a3de77085fbc7d264efb00bd0e0f" + integrity sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w== + +posthtml@^0.11.2: + version "0.11.6" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.6.tgz#e349d51af7929d0683b9d8c3abd8166beecc90a8" + integrity sha512-C2hrAPzmRdpuL3iH0TDdQ6XCc9M7Dcc3zEW5BLerY65G4tWWszwv6nG/ksi6ul5i2mx22ubdljgktXCtNkydkw== + dependencies: + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + +posthtml@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.12.0.tgz#6e2a2fcd774eaed1a419a95c5cc3a92b676a40a6" + integrity sha512-aNUEP/SfKUXAt+ghG51LC5MmafChBZeslVe/SSdfKIgLGUVRE68mrMF4V8XbH07ZifM91tCSuxY3eHIFLlecQw== + dependencies: + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^1.18.2: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + +private@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -process@~0.11.0: +process@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/process/-/process-0.10.1.tgz#842457cc51cfed72dc775afeeafb8c6034372725" + integrity sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU= + +process@^0.11.10, process@~0.11.0: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -pstree.remy@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3" - integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A== +prop-types@^15.6.2, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +psl@^1.1.24, psl@^1.1.28: + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -2063,12 +5947,37 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.3.2: +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -querystring-es3@~0.2.0: +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +purgecss@^1.4.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-1.4.2.tgz#67ab50cb4f5c163fcefde56002467c974e577f41" + integrity sha512-hkOreFTgiyMHMmC2BxzdIw5DuC6kxAbP/gGOGd3MEsF3+5m69rIvUEPaxrnoUtfODTFKe9hcXjGwC6jcjoyhOw== + dependencies: + glob "^7.1.3" + postcss "^7.0.14" + postcss-selector-parser "^6.0.0" + yargs "^14.0.0" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystring-es3@^0.2.0, querystring-es3@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= @@ -2078,6 +5987,20 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + +quote-stream@^1.0.1, quote-stream@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" + integrity sha1-hJY/jJwmuULhU/7rU6rnRlK34LI= + dependencies: + buffer-equal "0.0.1" + minimist "^1.1.3" + through2 "^2.0.0" + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -2093,15 +6016,63 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -rc@^1.0.1, rc@^1.1.6: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +react-dom@^16.12.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" + integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.18.0" + +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" + integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== + +react-router-dom@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" + integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.1.2" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418" + integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.3.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react@^16.12.0: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" + integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" read-only-stream@^2.0.0: version "2.0.0" @@ -2110,7 +6081,43 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@~2.3.6: +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg-up@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, 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== @@ -2123,7 +6130,7 @@ readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1: +readable-stream@^3.0.1, readable-stream@^3.1.1: version "3.4.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== @@ -2132,6 +6139,15 @@ readable-stream@^3.0.1, readable-stream@^3.0.6, readable-stream@^3.1.1: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.0.6: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.5.0.tgz#465d70e6d1087f6162d079cd0b5db7fbebfd1606" + integrity sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -2141,6 +6157,43 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.2.1, regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-runtime@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + +regenerator-transform@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -2149,20 +6202,118 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -registry-auth-token@^3.0.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" - integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== +regexp.prototype.flags@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +regexpp@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.0.0.tgz#dd63982ee3300e67b41c1956f850aa680d9d330e" + integrity sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g== + +regexpu-core@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" + integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs= dependencies: - rc "^1.0.1" + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsgen@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +regjsparser@^0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.2.tgz#fd62c753991467d9d1ffe0a9f67f27a529024b96" + integrity sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q== + dependencies: + jsesc "~0.5.0" + +remark-parse@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-6.0.3.tgz#c99131052809da482108413f87b0ee7f52180a3a" + integrity sha512-QbDXWN4HfKTUC0hHa4teU463KclLAnwpn/FBn87j9cKYJWWawbiLgMfP2Q4XwhxxuuuOxHlw+pSN0OKuJwyVvg== + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + +remark-stringify@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-6.0.4.tgz#16ac229d4d1593249018663c7bddf28aafc4e088" + integrity sha512-eRWGdEPMVudijE/psbIDNcnJLRVx3xhfuEsTDGgH4GsFF91dVhw5nhmnBppafJ7+NWINW6C7ZwWbi30ImJzqWg== + dependencies: + ccount "^1.0.0" + is-alphanumeric "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + longest-streak "^2.0.1" + markdown-escapes "^1.0.0" + markdown-table "^1.1.0" + mdast-util-compact "^1.0.0" + parse-entities "^1.0.2" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + stringify-entities "^1.0.1" + unherit "^1.0.4" + xtend "^4.0.1" + +remark@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark/-/remark-10.0.1.tgz#3058076dc41781bf505d8978c291485fe47667df" + integrity sha512-E6lMuoLIy2TyiokHprMjcWNJ5UxfGQjaMSMhV+f4idM625UjjK4j798+gPs5mfjzDE6vL0oFKVeZM6gZVSVrzQ== + dependencies: + remark-parse "^6.0.0" + remark-stringify "^6.0.0" + unified "^7.0.0" remove-trailing-separator@^1.0.1: version "1.1.0" @@ -2174,11 +6325,88 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.6.1: +repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +replace-ext@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request-promise-core@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" + integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== + dependencies: + lodash "^4.17.15" + +request-promise-native@^1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" + integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== + dependencies: + request-promise-core "1.1.3" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -2189,7 +6417,14 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.4, resolve@^1.4.0: +resolve@^1.1.4, resolve@^1.1.5, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.3.2: + version "1.15.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.0.tgz#1b7ca96073ebb52e741ffd799f6b39ea462c67f5" + integrity sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw== + dependencies: + path-parse "^1.0.6" + +resolve@^1.4.0: version "1.14.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== @@ -2204,11 +6439,48 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rimraf@^2.6.2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -2217,6 +6489,25 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +rxjs@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== + dependencies: + tslib "^1.9.0" + 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.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -2236,18 +6527,85 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= - dependencies: - semver "^5.0.3" +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^5.0.3, semver@^5.1.0, semver@^5.7.1: +sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +saxes@^3.1.9: + version "3.1.11" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" + integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== + dependencies: + xmlchars "^2.1.1" + +scheduler@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" + integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-to-js@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-3.1.1.tgz#b3e77d0568ee4a60bfe66287f991e104d3a1a4ac" + integrity sha512-F+NGU0UHMBO4Q965tjw7rvieNVjlH6Lqi2emq/Lc9LUURYJbiCzmpi4Cy1OOjjVPtxu0c+NE85LU6968Wko5ZA== + +serve-static@^1.12.4: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -2258,6 +6616,16 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" @@ -2266,6 +6634,11 @@ sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-copy@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + integrity sha1-QV9CcC1z2BAzApLMXuhurhoRoXA= + shasum-object@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shasum-object/-/shasum-object-1.0.0.tgz#0b7b74ff5b66ecf9035475522fa05090ac47e29e" @@ -2298,7 +6671,15 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== -signal-exit@^3.0.0, signal-exit@^3.0.2: +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + +signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= @@ -2308,6 +6689,27 @@ simple-concat@^1.0.0: resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -2349,7 +6751,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.6: +source-map-support@^0.5.6, source-map-support@~0.5.10, source-map-support@~0.5.12: version "0.5.16" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== @@ -2362,15 +6764,46 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.6, source-map@~0.5.3: +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +specificity@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" + integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -2379,6 +6812,43 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + +static-eval@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.3.tgz#cb62fc79946bd4d5f623a45ad428233adace4d72" + integrity sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w== + dependencies: + escodegen "^1.11.1" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -2387,7 +6857,37 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -stream-browserify@^2.0.0: +static-module@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" + integrity sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ== + dependencies: + concat-stream "~1.6.0" + convert-source-map "^1.5.1" + duplexer2 "~0.1.4" + escodegen "~1.9.0" + falafel "^2.1.0" + has "^1.0.1" + magic-string "^0.22.4" + merge-source-map "1.0.4" + object-inspect "~1.4.0" + quote-stream "~1.0.2" + readable-stream "~2.3.3" + shallow-copy "~0.0.1" + static-eval "^2.0.0" + through2 "~2.0.3" + +"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" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^2.0.0, stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== @@ -2403,6 +6903,17 @@ stream-combiner2@^1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + stream-http@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.0.tgz#22fb33fe9b4056b4eccf58bd8f400c4b993ffe57" @@ -2421,7 +6932,7 @@ stream-splicer@^2.0.0: inherits "^2.0.1" readable-stream "^2.0.2" -string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -2429,6 +6940,36 @@ string-width@^2.0.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.matchall@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" + integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + string.prototype.trimleft@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" @@ -2445,7 +6986,7 @@ string.prototype.trimright@^2.1.1: define-properties "^1.1.3" function-bind "^1.1.1" -string_decoder@^1.1.1: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -2459,6 +7000,23 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +stringify-entities@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" + integrity sha512-nrBAQClJAPN2p+uGCVJRPIPakKeKWZ9GtBCmormE7pWOSlHat7+x5A8gx85M7HM5Dt0BP3pP5RhVW77WdbJJ3A== + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + is-alphanumerical "^1.0.0" + is-hexadecimal "^1.0.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -2466,23 +7024,122 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.2.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" -strip-json-comments@~2.0.1: +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +style-search@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/style-search/-/style-search-0.1.0.tgz#7958c793e47e32e07d2b5cafe5c0bf8e12e77902" + integrity sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI= + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +stylelint-config-recommended@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz#e0e547434016c5539fe2650afd58049a2fd1d657" + integrity sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ== + +stylelint-config-standard@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-19.0.0.tgz#66f0cf13f33b8a9e34965881493b38fc1313693a" + integrity sha512-VvcODsL1PryzpYteWZo2YaA5vU/pWfjqBpOvmeA8iB2MteZ/ZhI1O4hnrWMidsS4vmEJpKtjdhLdfGJmmZm6Cg== + dependencies: + stylelint-config-recommended "^3.0.0" + +stylelint@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-13.0.0.tgz#532007f7154c1a5ed14245d857a5884316f5111f" + integrity sha512-6sjgOJbM3iLhnUtmRO0J1vvxie9VnhIZX/2fCehjylv9Gl9u0ytehGCTm9Lhw2p1F8yaNZn5UprvhCB8C3g/Tg== + dependencies: + autoprefixer "^9.7.3" + balanced-match "^1.0.0" + chalk "^3.0.0" + cosmiconfig "^6.0.0" + debug "^4.1.1" + execall "^2.0.0" + file-entry-cache "^5.0.1" + get-stdin "^7.0.0" + global-modules "^2.0.0" + globby "^11.0.0" + globjoin "^0.1.4" + html-tags "^3.1.0" + ignore "^5.1.4" + import-lazy "^4.0.0" + imurmurhash "^0.1.4" + known-css-properties "^0.17.0" + leven "^3.1.0" + lodash "^4.17.15" + log-symbols "^3.0.0" + mathml-tag-names "^2.1.1" + meow "^6.0.0" + micromatch "^4.0.2" + normalize-selector "^0.2.0" + postcss "^7.0.26" + postcss-html "^0.36.0" + postcss-jsx "^0.36.3" + postcss-less "^3.1.4" + postcss-markdown "^0.36.0" + postcss-media-query-parser "^0.2.3" + postcss-reporter "^6.0.1" + postcss-resolve-nested-selector "^0.1.1" + postcss-safe-parser "^4.0.1" + postcss-sass "^0.4.2" + postcss-scss "^2.0.0" + postcss-selector-parser "^3.1.0" + postcss-syntax "^0.36.2" + postcss-value-parser "^4.0.2" + resolve-from "^5.0.0" + slash "^3.0.0" + specificity "^0.4.1" + string-width "^4.2.0" + strip-ansi "^6.0.0" + style-search "^0.1.0" + sugarss "^2.0.0" + svg-tags "^1.0.0" + table "^5.4.6" + v8-compile-cache "^2.1.0" + write-file-atomic "^3.0.1" + subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" @@ -2490,13 +7147,82 @@ subarg@^1.0.0: dependencies: minimist "^1.1.0" -supports-color@^5.3.0, supports-color@^5.5.0: +sugarss@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-2.0.0.tgz#ddd76e0124b297d40bf3cca31c8b22ecb43bc61d" + integrity sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ== + dependencies: + postcss "^7.0.2" + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +svg-tags@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" + integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= + +svgo@^1.0.0, svgo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +symbol-tree@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + syntax-error@^1.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" @@ -2504,6 +7230,16 @@ syntax-error@^1.1.1: dependencies: acorn-node "^1.2.0" +table@^5.2.3, table@^5.4.6: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tar-fs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" @@ -2525,14 +7261,30 @@ tar-stream@^2.0.0, tar-stream@^2.1.0: inherits "^2.0.3" readable-stream "^3.1.1" -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= +terser@^3.7.3: + version "3.17.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" + integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== dependencies: - execa "^0.7.0" + commander "^2.19.0" + source-map "~0.6.1" + source-map-support "~0.5.10" -through2@^2.0.0: +terser@^4.3.9: + version "4.6.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" + integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.0, through2@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== @@ -2540,16 +7292,11 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -"through@>=2.2.7 <3": +"through@>=2.2.7 <3", through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - timers-browserify@^1.0.1: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" @@ -2557,6 +7304,55 @@ timers-browserify@^1.0.1: dependencies: process "~0.11.0" +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + +tiny-inflate@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4" + integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw== + +tiny-invariant@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" + integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + +tiny-warning@^1.0.0, tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" @@ -2572,6 +7368,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +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" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -2582,12 +7385,53 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -touch@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" - integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== +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" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== dependencies: - nopt "~1.0.10" + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +trim-newlines@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" + integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== + +trim-trailing-lines@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz#7f0739881ff76657b7776e10874128004b625a94" + integrity sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== ts-node@^8.4.1: version "8.5.4" @@ -2600,26 +7444,94 @@ ts-node@^8.4.1: source-map-support "^0.5.6" yn "^3.0.0" +tslib@^1.8.1, tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + tty-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.6: - version "3.6.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d" - integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg== +typescript@3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" + integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== umd@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== +uncss@^0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/uncss/-/uncss-0.17.2.tgz#fac1c2429be72108e8a47437c647d58cf9ea66f1" + integrity sha512-hu2HquwDItuGDem4YsJROdAD8SknmWtM24zwhQax6J1se8tPjV1cnwPKhtjodzBaUhaL8Zb3hlGdZ2WAUpbAOg== + dependencies: + commander "^2.20.0" + glob "^7.1.4" + is-absolute-url "^3.0.1" + is-html "^1.1.0" + jsdom "^14.1.0" + lodash "^4.17.15" + postcss "^7.0.17" + postcss-selector-parser "6.0.2" + request "^2.88.0" + undeclared-identifiers@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz#9254c1d37bdac0ac2b52de4b6722792d2a91e30f" @@ -2631,12 +7543,58 @@ undeclared-identifiers@^1.1.2: simple-concat "^1.0.0" xtend "^4.0.1" -undefsafe@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" - integrity sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY= +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== dependencies: - debug "^2.2.0" + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +unicode-trie@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" + integrity sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU= + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + +unified@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" + integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== + dependencies: + "@types/unist" "^2.0.0" + "@types/vfile" "^3.0.0" + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^3.0.0" + x-is-string "^0.1.0" union-value@^1.0.0: version "1.0.1" @@ -2648,18 +7606,71 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + +unist-util-find-all-after@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unist-util-find-all-after/-/unist-util-find-all-after-1.0.5.tgz#5751a8608834f41d117ad9c577770c5f2f1b2899" + integrity sha512-lWgIc3rrTMTlK1Y0hEuL+k+ApzFk78h+lsaa2gHf63Gp5Ww+mt11huDniuaoq1H+XMK2lIIjjPkncxXcDp3QDw== dependencies: - crypto-random-string "^1.0.0" + unist-util-is "^3.0.0" + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-remove-position@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" + integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== + dependencies: + unist-util-visit "^1.1.0" + +unist-util-stringify-position@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== + +unist-util-stringify-position@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz#5a3866e7138d55974b640ec69a94bc19e0f3fa12" + integrity sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -2668,45 +7679,24 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= - upath@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-notifier@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" - integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: - boxen "^1.2.1" - chalk "^2.0.1" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-ci "^1.0.10" - is-installed-globally "^0.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" + punycode "^2.1.0" urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url@~0.11.0: +url@^0.11.0, url@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= @@ -2724,6 +7714,16 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + util@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -2731,16 +7731,12 @@ util@0.10.3: dependencies: inherits "2.0.1" -util@^0.12.1: - version "0.12.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.1.tgz#f908e7b633e7396c764e694dd14e716256ce8ade" - integrity sha512-MREAtYOp+GTt9/+kwf00IYoHZyjM8VU4aVrkzUlejyqaIjd2GztVl5V9hGXKlvBKE3gENn/FMfHE5v6hElXGcQ== +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - object.entries "^1.1.0" - safe-buffer "^5.1.2" + inherits "2.0.3" util@~0.10.1: version "0.10.4" @@ -2749,11 +7745,92 @@ util@~0.10.1: dependencies: inherits "2.0.3" -vm-browserify@^1.0.0: +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@^2.0.0, v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== + +vendors@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vfile-location@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" + integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== + +vfile-message@*, vfile-message@^1.0.0, vfile-message@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.2.tgz#75ba05090ec758fa8420f2c11ce049bcddd8cf3e" + integrity sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" + integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== + dependencies: + is-buffer "^2.0.0" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== + +vm-browserify@^1.0.0, vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + +w3c-xmlserializer@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" + integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== + dependencies: + domexception "^1.0.1" + webidl-conversions "^4.0.2" + xml-name-validator "^3.0.0" + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -2761,48 +7838,208 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -which@^1.2.9, which@^1.3.1: +weakmap-shim@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/weakmap-shim/-/weakmap-shim-1.1.1.tgz#d65afd784109b2166e00ff571c33150ec2a40b49" + integrity sha1-1lr9eEEJshZuAP9XHDMVDsKkC0k= + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -widest-line@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: - string-width "^2.1.1" + string-width "^1.0.2 || 2" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^2.0.0: - version "2.4.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" - integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== +write-file-atomic@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.1.tgz#558328352e673b5bb192cf86500d60b230667d4b" + integrity sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw== dependencies: - graceful-fs "^4.1.11" imurmurhash "^0.1.4" + is-typedarray "^1.0.0" signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" -xdg-basedir@^3.0.0: +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +ws@^5.1.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== + dependencies: + async-limiter "~1.0.0" + +ws@^6.1.2: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.2.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.1.tgz#03ed52423cd744084b2cf42ed197c8b65a936b8e" + integrity sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A== + +x-is-string@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + integrity sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI= + +xml-name-validator@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yaml@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.7.2.tgz#f26aabf738590ab61efaca502358e48dc9f348b2" + integrity sha512-qXROVp90sb83XtAoqE8bP9RwAkTTZbugRUTm5YeFCBfNRPEp2YzTeqWiz7m5OORHzEvrA/qcGS8hp/E+MMROYw== + dependencies: + "@babel/runtime" "^7.6.3" + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" + integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-16.1.0.tgz#73747d53ae187e7b8dbe333f95714c76ea00ecf1" + integrity sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + +yargs@^14.0.0: + version "14.2.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" + integrity sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.0" yn@^3.0.0: version "3.1.1"