Compare commits

..

1 Commits

Author SHA1 Message Date
Akash Satheesan
c041986976 chore(release): bump version to 3.11.0 2021-07-15 00:50:40 +05:30
69 changed files with 652 additions and 1235 deletions

View File

@@ -62,11 +62,6 @@ Additionally, collecting core dumps (you may need to enable them first) if
code-server crashes can be helpful.
-->
<!--
If you're having issues with installation please include the installation logs
i.e. the output of `yarn global add code-server` if you installed with `yarn`
-->
## Screenshot
<!-- Ideally provide a screenshot, gif, video or screen recording. -->

3
.github/codecov.yml vendored
View File

@@ -5,8 +5,7 @@ codecov:
coverage:
precision: 2
round: down
range: "40...70"
patch: off
range: "70...100"
parsers:
gcov:

32
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
time: "11:00"
ignore:
# GitHub always delivers the latest versions for each major
# release tag, so handle updates manually
- dependency-name: "actions/*"
- dependency-name: "github/codeql-action/*"
- dependency-name: "microsoft/playwright-github-action"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
time: "11:00"
ignore:
- dependency-name: "@types/node"
update-types: ["version-update:semver-major"]
- dependency-name: "xdg-basedir"
# 5.0.0 has breaking changes as they switch to named exports
# and convert the module to ESM
# We can't use it until we switch to ESM across the project
# See release notes: https://github.com/sindresorhus/xdg-basedir/releases/tag/v5.0.0
versions: ["5.x"]
- dependency-name: "limiter"
# 2.0.0 has breaking changes
# so we can't update yet.
versions: ["2.x"]

View File

@@ -352,8 +352,8 @@ jobs:
with:
node-version: "14"
- name: Install playwright OS dependencies
run: npx playwright install-deps
- name: Install playwright
uses: microsoft/playwright-github-action@v1
- name: Fetch dependencies from cache
id: cache-yarn
@@ -402,6 +402,73 @@ jobs:
- name: Remove release packages and test artifacts
run: rm -rf ./release-packages ./test/test-results
# Builds both amd64 and arm64 images
docker-images:
runs-on: ubuntu-latest
needs: [package-linux-amd64, package-linux-arm64]
steps:
- uses: actions/checkout@v2
- name: Download release package
uses: actions/download-artifact@v2
with:
name: release-packages
path: ./release-packages
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Run ./ci/steps/build-docker-image.sh
run: ./ci/steps/build-docker-image.sh
- name: Upload release images
uses: actions/upload-artifact@v2
with:
name: release-images
path: ./release-images
trivy-scan-image:
runs-on: ubuntu-20.04
needs: docker-images
# NOTE@jsjoeio: disabling due to a memory issue upstream
# See: https://github.com/github/codeql-action/issues/528
if: 1 == 2
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Download release images
uses: actions/download-artifact@v2
with:
name: release-images
path: ./release-images
- name: Run Trivy vulnerability scanner in image mode
# Commit SHA for v0.0.17
uses: aquasecurity/trivy-action@ac8de07fd168680dd0331bef43681c0e150e9ad1
with:
input: "./release-images/code-server-amd64-*.tar"
scan-type: "image"
ignore-unfixed: true
format: "template"
template: "@/contrib/sarif.tpl"
output: "trivy-image-results.sarif"
severity: "HIGH,CRITICAL"
- name: Debug Trivy SARIF file
run: cat trivy-image-results.sarif && ls -l trivy-image-results.sarif
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: "trivy-image-results.sarif"
# We have to use two trivy jobs
# because GitHub only allows
# codeql/upload-sarif action per job
trivy-scan-repo:
runs-on: ubuntu-20.04
steps:
@@ -409,7 +476,7 @@ jobs:
uses: actions/checkout@v2
- name: Run Trivy vulnerability scanner in repo mode
#Commit SHA for v0.0.17
uses: aquasecurity/trivy-action@9438b49cc3156b2e8c77c1ba8ffbaa3bae24e3c2
uses: aquasecurity/trivy-action@ac8de07fd168680dd0331bef43681c0e150e9ad1
with:
scan-type: "fs"
scan-ref: "."

View File

@@ -1,28 +0,0 @@
name: Publish on Docker
on:
# Shows the manual trigger in GitHub UI
# helpful as a back-up in case the GitHub Actions Workflow fails
workflow_dispatch:
release:
types: [published]
jobs:
docker-images:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Run ./ci/steps/docker-buildx-push.sh
run: ./ci/steps/docker-buildx-push.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -1,4 +1,4 @@
name: Publish on npm and brew
name: publish
on:
# Shows the manual trigger in GitHub UI
@@ -22,6 +22,20 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# NOTE: this job requires curl, jq and docker
# All of them are included in ubuntu-latest.
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run ./ci/steps/push-docker-manifest.sh
run: ./ci/steps/push-docker-manifest.sh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
homebrew:
# The newest version of code-server needs to be available on npm when this runs
# otherwise, it will 404 and won't open a PR to bump version on homebrew/homebrew-core

View File

@@ -1 +0,0 @@
14

1
.nvmrc
View File

@@ -1 +0,0 @@
.node-version

View File

@@ -78,8 +78,8 @@ You can disable minification by setting `MINIFY=`.
This directory contains the release docker container image.
- [./ci/steps/build-docker-buildx-push.sh](./ci/steps/docker-buildx-push.sh)
- Builds the release containers with tags `codercom/code-server-$ARCH:$VERSION` for amd64 and arm64 with `docker buildx` and pushes them.
- [./ci/steps/build-docker-image.sh](./ci/steps/build-docker-image.sh)
- Builds the release containers with tags `codercom/code-server-$ARCH:$VERSION` for amd64 and arm64 with `docker buildx`.
- Assumes debian releases are ready in `./release-packages`.
## images
@@ -107,8 +107,8 @@ Helps avoid clobbering the CI configuration.
release packages into `./release-packages`.
- [./steps/publish-npm.sh](./steps/publish-npm.sh)
- Grabs the `npm-package` release artifact for the current commit and publishes it on npm.
- [./steps/docker-buildx-push.sh](./steps/docker-buildx-push.sh)
- Builds the docker image and then pushes it.
- [./steps/build-docker-image.sh](./steps/build-docker-image.sh)
- Builds the docker image and then saves it into `./release-images/code-server-$ARCH-$VERSION.tar`.
- [./steps/push-docker-manifest.sh](./steps/push-docker-manifest.sh)
- Loads all images in `./release-images` and then builds and pushes a multi architecture
docker manifest for the amd64 and arm64 images to `codercom/code-server:$VERSION` and

View File

@@ -3,7 +3,7 @@ set -euo pipefail
main() {
cd "$(dirname "$0")/../.."
cd test/unit/node/test-plugin
cd test/unit/test-plugin
make -s out/index.js
# We must keep jest in a sub-directory. See ../../test/package.json for more
# information. We must also run it from the root otherwise coverage will not

View File

@@ -20,4 +20,4 @@ version: 1.0.3
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 3.11.1
appVersion: 3.11.0

View File

@@ -1,6 +1,6 @@
# code-server
![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.11.1](https://img.shields.io/badge/AppVersion-3.11.1-informational?style=flat-square)
![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.11.0](https://img.shields.io/badge/AppVersion-3.11.0-informational?style=flat-square)
[code-server](https://github.com/cdr/code-server) code-server is VS Code running
on a remote server, accessible through the browser.
@@ -73,7 +73,7 @@ and their default values.
| hostnameOverride | string | `""` | |
| image.pullPolicy | string | `"Always"` | |
| image.repository | string | `"codercom/code-server"` | |
| image.tag | string | `"3.11.1"` | |
| image.tag | string | `"3.11.0"` | |
| imagePullSecrets | list | `[]` | |
| ingress.enabled | bool | `false` | |
| nameOverride | string | `""` | |

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '3.11.1'
tag: '3.11.0'
pullPolicy: Always
imagePullSecrets: []

View File

@@ -57,12 +57,12 @@ arch() {
# https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
get_artifacts_url() {
local artifacts_url
local workflow_runs_url="repos/:owner/:repo/actions/workflows/ci.yaml/runs?event=pull_request"
local version_branch="v$VERSION"
local workflow_runs_url="repos/:owner/:repo/actions/workflows/ci.yaml/runs?event=pull_request&branch=$version_branch"
artifacts_url=$(gh api "$workflow_runs_url" | jq -r ".workflow_runs[] | select(.head_branch == \"$version_branch\") | .artifacts_url" | head -n 1)
if [[ -z "$artifacts_url" ]]; then
echo >&2 "ERROR: artifacts_url came back empty"
echo >&2 "We looked for a successful run triggered by a pull_request with for code-server version: $VERSION and a branch named $version_branch"
echo >&2 "We looked for a successful run triggered by a pull_request with for code-server version: $code_server_version and a branch named $version_branch"
echo >&2 "URL used for gh API call: $workflow_runs_url"
exit 1
fi

View File

@@ -7,11 +7,19 @@ variable "VERSION" {
}
group "default" {
targets = ["code-server"]
targets = ["code-server-amd64", "code-server-arm64"]
}
target "code-server" {
target "code-server-amd64" {
dockerfile = "ci/release-image/Dockerfile"
tags = ["docker.io/codercom/code-server:${VERSION}"]
platforms = ["linux/amd64", "linux/arm64"]
tags = ["docker.io/codercom/code-server-amd64:${VERSION}"]
platforms = ["linux/amd64"]
output = ["type=tar,dest=./release-images/code-server-amd64-${VERSION}.tar"]
}
target "code-server-arm64" {
dockerfile = "ci/release-image/Dockerfile"
tags = ["docker.io/codercom/code-server-arm64:${VERSION}"]
platforms = ["linux/arm64"]
output = ["type=tar,dest=./release-images/code-server-arm64-${VERSION}.tar"]
}

View File

@@ -19,10 +19,10 @@ main() {
echo "Adding Homebrew/homebrew-core as $(upstream)"
git remote add upstream https://github.com/Homebrew/homebrew-core.git
echo "Fetching upstream Homebrew/hombrew-core commits"
echo "Fetching upstream commits..."
git fetch upstream
echo "Merging in latest Homebrew/homebrew-core changes"
echo "Merging in latest changes"
git merge upstream/master
echo "Pushing changes to cdrci/homebrew-core fork on GitHub"
@@ -37,15 +37,7 @@ main() {
# Find the docs for bump-formula-pr here
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
local output
if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit 2>&1); then
if [[ $output == *"Duplicate PRs should not be opened"* ]]; then
echo "$VERSION is already submitted"
else
echo "$output"
exit 1
fi
fi
brew bump-formula-pr --force --version="${VERSION}" code-server --no-browse --no-audit
# Clean up and remove homebrew-core
cd ..

12
ci/steps/build-docker-image.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
main() {
cd "$(dirname "$0")/../.."
source ./ci/lib.sh
mkdir -p release-images
docker buildx bake -f ci/release-image/docker-bake.hcl
}
main "$@"

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# See if this version already exists on Docker Hub.
function version_exists() {
local output
output=$(curl --silent "https://index.docker.io/v1/repositories/codercom/code-server/tags/$VERSION")
if [[ $output == "Tag not found" ]]; then
return 1
else
return 0
fi
}
main() {
cd "$(dirname "$0")/../.."
# ci/lib.sh sets VERSION and provides download_artifact here
source ./ci/lib.sh
if version_exists; then
echo "$VERSION is already pushed"
return
fi
# Download the release-packages artifact
download_artifact release-packages ./release-packages
# Login to Docker
if [[ ${CI-} ]]; then
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
fi
docker buildx bake -f ci/release-image/docker-bake.hcl --push
}
main "$@"

View File

@@ -5,14 +5,6 @@ main() {
cd "$(dirname "$0")/../.."
source ./ci/lib.sh
# npm view won't exit with non-zero so we have to check the output.
local hasVersion
hasVersion=$(npm view "code-server@$VERSION" version)
if [[ $hasVersion == "$VERSION" ]]; then
echo "$VERSION is already published"
return
fi
if [[ ${CI-} ]]; then
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
fi

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
main() {
cd "$(dirname "$0")/../.."
source ./ci/lib.sh
download_artifact release-images ./release-images
if [[ ${CI-} ]]; then
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
fi
for img in ./release-images/*; do
docker load -i "$img"
done
# We have to ensure the amd64 and arm64 images exist on the remote registry
# in order to build the manifest.
# We don't put the arch in the tag to avoid polluting the main repository.
# These other repositories are private so they don't pollute our organization namespace.
docker push "codercom/code-server-amd64:$VERSION"
docker push "codercom/code-server-arm64:$VERSION"
export DOCKER_CLI_EXPERIMENTAL=enabled
docker manifest create "codercom/code-server:$VERSION" \
"codercom/code-server-amd64:$VERSION" \
"codercom/code-server-arm64:$VERSION"
docker manifest push --purge "codercom/code-server:$VERSION"
docker manifest create "codercom/code-server:latest" \
"codercom/code-server-amd64:$VERSION" \
"codercom/code-server-arm64:$VERSION"
docker manifest push --purge "codercom/code-server:latest"
}
main "$@"

View File

@@ -29,7 +29,6 @@ Here is what is needed:
- `node` v14.x
- `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com)
- [`yarn`](https://classic.yarnpkg.com/en/)
- Used to install JS packages and run scripts
- [`nfpm`](https://classic.yarnpkg.com/en/)
@@ -143,7 +142,7 @@ Our unit tests are written in TypeScript and run using
These live under [test/unit](../test/unit).
We use unit tests for functions and things that can be tested in isolation. The file structure is modeled closely after `/src` so it's easy for people to know where test files should live.
We use unit tests for functions and things that can be tested in isolation.
### Integration tests

View File

@@ -28,6 +28,7 @@
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
- [What's the difference between code-server and VS Code Codespaces?](#whats-the-difference-between-code-server-and-vs-code-codespaces)
- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
- [Enterprise](#enterprise)
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -389,13 +390,20 @@ Codespaces web dashboard instead of connecting directly to it.
On the other hand, code-server is free, open-source, and can be run on any
machine with few limitations.
<<<<<<< HEAD
## Does code-server have any security login validation?
code-server supports setting a single password and limits logins to two per
minute plus an additional twelve per hour.
code-server only supports a single password and limits logins to two per minute plus twelve per hour.
## Enterprise
=======
## Are there community projects involving code-server?
> > > > > > > Edit code-server docs
Visit the [awesome-code-server](https://github.com/cdr/awesome-code-server)
repository to view community projects and guides with code-server! Feel free to
add your own!

View File

@@ -1,6 +1,6 @@
# code-server
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/cdr/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://cdr.co/join-community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/cdr/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/cdr/code-server) [![See v3.11.1 docs](https://img.shields.io/static/v1?label=Docs&message=see%20v3.11.1%20&color=blue)](https://github.com/cdr/code-server/tree/v3.11.1/docs)
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/cdr/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://cdr.co/join-community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/cdr/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/cdr/code-server) [![See v3.11.0 docs](https://img.shields.io/static/v1?label=Docs&message=see%20v3.11.0%20&color=blue)](https://github.com/cdr/code-server/tree/v3.11.0/docs)
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
access it in the browser.
@@ -30,7 +30,7 @@ There are three ways to get started:
automates most of the process. The script uses the system package manager if
possible.
2. Manually [installing
code-server](https://coder.com/docs/code-server/v3.11.1/install)
code-server](https://coder.com/docs/code-server/v3.11.0/install)
3. Using our one-click buttons and guides to [deploy code-server to a cloud
provider](https://github.com/cdr/deploy-code-server) ⚡
@@ -51,7 +51,7 @@ When done, the install script prints out instructions for running and starting
code-server.
We also have an in-depth [setup and
configuration](https://coder.com/docs/code-server/v3.11.1/guide) guide.
configuration](https://coder.com/docs/code-server/v3.11.0/guide) guide.
### code-server --link
@@ -71,11 +71,11 @@ Proxying code-server, you can access your IDE at https://example.cdr.co
## Questions?
See answers to [frequently asked
questions](https://coder.com/docs/code-server/v3.11.1/FAQ).
questions](https://coder.com/docs/code-server/v3.11.0/FAQ).
## Want to help?
See [Contributing](https://coder.com/docs/code-server/v3.11.1/CONTRIBUTING) for
See [Contributing](https://coder.com/docs/code-server/v3.11.0/CONTRIBUTING) for
details.
## Hiring

View File

@@ -8,8 +8,8 @@
- [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx)
- [Using a self-signed certificate](#using-a-self-signed-certificate)
- [External authentication](#external-authentication)
- [HTTPS and self-signed certificates](#https-and-self-signed-certificates)
- [Accessing web services](#accessing-web-services)
- [HTTPS](#https)
- [Self Signed Certificate](#self-signed-certificate)
- [Using a subdomain](#using-a-subdomain)
- [Using a subpath](#using-a-subpath)
- [Stripping `/proxy/<port>` from the request path](#stripping-proxyport-from-the-request-path)
@@ -261,7 +261,7 @@ Google), you can do this with a reverse proxy such as:
- [oauth2_proxy](https://github.com/pusher/oauth2_proxy)
- [Cloudflare Access](https://teams.cloudflare.com/access)
## HTTPS and self-signed certificates
## HTTPS
For HTTPS, you can use a self-signed certificate by:
@@ -280,9 +280,9 @@ redirect all HTTP requests to HTTPS.
Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it will change the address displayed in the green section of code-server in the bottom left to show the correct address.
## Accessing web services
### Self Signed Certificate
If you're working on web services and want to access it locally, code-server
If you're working on a web service and want to access it locally, code-server
can proxy to any port using either a subdomain or a subpath, allowing you to
securely access these services using code-server's built-in authentication.

View File

@@ -15,11 +15,6 @@
- [Raspberry Pi](#raspberry-pi)
- [Termux](#termux)
- [Cloud providers](#cloud-providers)
- [Uninstall](#uninstall)
- [install.sh](#installsh-1)
- [Homebrew](#homebrew)
- [yarn, npm](#yarn-npm-1)
- [Debian, Ubuntu](#debian-ubuntu-1)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -234,7 +229,7 @@ alternative](https://hub.docker.com/r/linuxserver/code-server).
## Helm
You can install code-server via [Helm](https://github.com/cdr/code-server/blob/main/ci/helm-chart/README.md).
You can install code-server via [Helm](../ci/helm-chart/README.md).
## Raspberry Pi
@@ -251,54 +246,3 @@ information.
We maintain [one-click apps and install scripts for cloud
providers](https://github.com/cdr/deploy-code-server) such as DigitalOcean,
Railway, Heroku, and Azure.
## Uninstall
code-server can be completely uninstalled by removing the application directory, and your user configuration directory.
To delete settings and data:
```shell
rm -rf ~/.local/share/code-server ~/.config/code-server
```
### install.sh
If you installed with the install script, by default code-server will be in `~/.local/lib/code-server-<version>` and you can remove it with `rm -rf`. e.g.
```shell
rm -rf ~/.local/lib/code-server-*
```
### Homebrew
To remove the code-server homebrew package, run:
```shell
brew remove code-server
# Alternatively
brew uninstall code-server
```
### yarn, npm
To remove the code-server global module, run:
```shell
yarn global remove code-server
```
or
```shell
npm uninstall -g code-server
```
### Debian, Ubuntu
To uninstall, run:
```shell
sudo apt remove code-server
```

View File

@@ -1,88 +0,0 @@
{
"versions": ["v3.11.1", "v3.11.0"],
"routes": [
{
"title": "Home",
"description": "Learn how to install and run code-server.",
"path": "./README.md",
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16px\" xml:space=\"preserve\"><path d=\"M15.45,7L14,5.551V2c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v0.553L9,0.555C8.727,0.297,8.477,0,8,0S7.273,0.297,7,0.555 L0.55,7C0.238,7.325,0,7.562,0,8c0,0.563,0.432,1,1,1h1v6c0,0.55,0.45,1,1,1h3v-5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v5h3 c0.55,0,1-0.45,1-1V9h1c0.568,0,1-0.437,1-1C16,7.562,15.762,7.325,15.45,7z\"></path></svg>"
},
{
"title": "Requirements",
"description": "Learn about what you need to run code-server.",
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 2V11H2V15C2 16.7 3.3 18 5 18H15C16.7 18 18 16.7 18 15V2H6ZM16 15C16 15.6 15.6 16 15 16H8V4H16V15Z\" /><path d=\"M14 7H10V9H14V7Z\" /><path d=\"M14 11H10V13H14V11Z\" /></svg>",
"path": "./requirements.md"
},
{
"title": "Install",
"description": "How to install code-server.",
"icon": "<svg class=\"MuiSvgIcon-root jss172\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z\"></path></svg>",
"path": "./install.md",
"children": [
{
"title": "npm",
"description": "How to install code-server using npm or yarn",
"path": "./npm.md"
}
]
},
{
"title": "Usage",
"description": "How to set up and use code-server.",
"icon": "<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 10l-2.5-1.5L15 12V4h5v8z\"></path></svg>",
"path": "./guide.md",
"children": [
{
"title": "iPad",
"description": "How to access your code-server installation using an iPad.",
"path": "./ipad.md"
},
{
"title": "Termux",
"description": "How to install Termux to run code-server on an Android device.",
"path": "./termux.md"
}
]
},
{
"title": "Upgrade",
"description": "How to upgrade code-server.",
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.35028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0302 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944 3.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>",
"path": "./upgrade.md"
},
{
"title": "FAQ",
"description": "Frequently asked questions on installing and running code-server.",
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.0001 18.3333C14.6025 18.3333 18.3334 14.6024 18.3334 10C18.3334 5.39762 14.6025 1.66666 10.0001 1.66666C5.39771 1.66666 1.66675 5.39762 1.66675 10C1.66675 14.6024 5.39771 18.3333 10.0001 18.3333Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.57495 7.5C7.77087 6.94306 8.15758 6.47342 8.66658 6.17428C9.17558 5.87513 9.77403 5.76578 10.3559 5.86559C10.9378 5.96541 11.4656 6.26794 11.8458 6.71961C12.2261 7.17128 12.4342 7.74294 12.4333 8.33333C12.4333 10 9.93328 10.8333 9.93328 10.8333\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 14.1667H10.0083\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>",
"path": "./FAQ.md"
},
{
"title": "Contributing",
"description": "How to contribute to code-server.",
"icon": "<svg width=\"20\" height=\"20\" fill=\"none\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 2.5V12.5\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 7.5C16.3807 7.5 17.5 6.38071 17.5 5C17.5 3.61929 16.3807 2.5 15 2.5C13.6193 2.5 12.5 3.61929 12.5 5C12.5 6.38071 13.6193 7.5 15 7.5Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 17.5C6.38071 17.5 7.5 16.3807 7.5 15C7.5 13.6193 6.38071 12.5 5 12.5C3.61929 12.5 2.5 13.6193 2.5 15C2.5 16.3807 3.61929 17.5 5 17.5Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 7.5C15 9.48912 14.2098 11.3968 12.8033 12.8033C11.3968 14.2098 9.48912 15 7.5 15\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>",
"path": "./CONTRIBUTING.md",
"children": [
{
"title": "Code of conduct",
"description": "Coder expects contributors to code-server to behave in a manner that creates an open and welcoming environment.",
"path": "./CODE_OF_CONDUCT.md"
},
{
"title": "Maintenance",
"description": "Learn about the workflow followed by code-server's maintainers.",
"path": "./MAINTAINING.md"
},
{
"title": "Triage",
"description": "How the maintainers triage issues with code-server.",
"path": "./triage.md"
},
{
"title": "Security",
"description": "Learn about the tools used to detect vulnerabilities in code-server, and how you can report vulnerabilities.",
"path": "./SECURITY.md"
}
]
}
]
}

View File

@@ -9,7 +9,7 @@ At the minimum, we recommend:
- 2 CPU cores
You can use any Linux distribution, but [our
docs](https://coder.com/docs/code-server/v3.11.1/guide) assume that you're using
docs](https://coder.com/docs/code-server/v3.11.0/guide) assume that you're using
Debian hosted by Google Cloud (see the following section for instructions on
setting this up).

View File

@@ -2,7 +2,7 @@
set -eu
# code-server's automatic install script.
# See https://coder.com/docs/code-server/v3.11.1/install
# See https://coder.com/docs/code-server/v3.11.0/install
usage() {
arg0="$0"
@@ -66,7 +66,7 @@ fall back to npm so on architectures without pre-built releases this will error.
The installer will cache all downloaded assets into ~/.cache/code-server
More installation docs are at https://coder.com/docs/code-server/v3.11.1/install
More installation docs are at https://coder.com/docs/code-server/v3.11.0/install
EOF
}
@@ -433,7 +433,7 @@ install_npm() {
fi
echoerr "Please install npm or yarn to install code-server!"
echoerr "You will need at least node v12 and a few C dependencies."
echoerr "See the docs https://coder.com/docs/code-server/v3.11.1/install#yarn-npm"
echoerr "See the docs https://coder.com/docs/code-server/v3.11.0/install#yarn-npm"
exit 1
}

View File

@@ -55,12 +55,9 @@ export function asWebviewUri(
});
}
// NOTE@coder: Add the port separately because if the port is in the domain the
// URL will be invalid and the browser will not request it.
const authorityUrl = new URL(`${resource.scheme}://${resource.authority}`);
return URI.from({
scheme: Schemas.https,
authority: `${resource.scheme}+${authorityUrl.hostname}.${webviewRootResourceAuthority}${authorityUrl.port ? (':' + authorityUrl.port) : ''}`,
authority: `${resource.scheme}+${resource.authority}.${webviewRootResourceAuthority}`,
path: resource.path,
fragment: resource.fragment,
query: resource.query,

View File

@@ -256,7 +256,7 @@ async function processResourceRequest(event, requestUrl) {
const firstHostSegment = requestUrl.hostname.slice(0, requestUrl.hostname.length - (resourceBaseAuthority.length + 1));
const scheme = firstHostSegment.split('+', 1)[0];
const authority = firstHostSegment.slice(scheme.length + 1) + requestUrl.port ? (':' + requestUrl.port) : ''; // may be empty
const authority = firstHostSegment.slice(scheme.length + 1); // may be empty
for (const parentClient of parentClients) {
parentClient.postMessage({

View File

@@ -1,7 +1,7 @@
{
"name": "code-server",
"license": "MIT",
"version": "3.11.1",
"version": "3.11.0",
"description": "Run VS Code on a remote server.",
"homepage": "https://github.com/cdr/code-server",
"bugs": {
@@ -57,7 +57,7 @@
"@typescript-eslint/parser": "^4.7.0",
"audit-ci": "^4.0.0",
"browserify": "^17.0.0",
"codecov": "^3.8.3",
"codecov": "^3.8.1",
"doctoc": "^2.0.0",
"eslint": "^7.7.0",
"eslint-config-prettier": "^8.1.0",
@@ -79,8 +79,7 @@
"postcss": "^8.2.1",
"browserslist": "^4.16.5",
"safe-buffer": "^5.1.1",
"vfile-message": "^2.0.2",
"argon2/@mapbox/node-pre-gyp/tar": "^6.1.3"
"vfile-message": "^2.0.2"
},
"dependencies": {
"@coder/logger": "1.1.16",
@@ -95,16 +94,16 @@
"js-yaml": "^4.0.0",
"limiter": "^1.1.5",
"pem": "^1.14.2",
"proxy-agent": "^5.0.0",
"proxy-agent": "^4.0.0",
"proxy-from-env": "^1.1.0",
"qs": "6.10.1",
"qs": "6.7.0",
"rotating-file-stream": "^2.1.1",
"safe-buffer": "^5.1.1",
"safe-compare": "^1.1.4",
"semver": "^7.1.3",
"split2": "^3.2.2",
"tar-fs": "^2.0.0",
"ws": "^8.0.0",
"ws": "^7.2.0",
"xdg-basedir": "^4.0.0",
"yarn": "^1.22.4"
},
@@ -149,7 +148,7 @@
],
"coverageThreshold": {
"global": {
"lines": 60
"lines": 40
}
},
"modulePathIgnorePatterns": [

View File

@@ -1,18 +0,0 @@
{
"rangeStrategy": "replace",
"extends": ["config:base"],
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch", "digest"],
"automerge": true,
"groupName": "Minor dependency updates"
},
{
"matchPaths": ["lib/vscode/"],
"enabled": false
}
],
"vulnerabilityAlerts": {
"enabled": "true"
}
}

View File

@@ -1,8 +1,10 @@
import { getOptions, Options } from "../../common/util"
import { getOptions } from "../../common/util"
import "../register"
// TODO@jsjoeio: Add proper types.
type FixMeLater = any
const options = getOptions()
// TODO: Add proper types.
/* eslint-disable @typescript-eslint/no-explicit-any */
// NOTE@jsjoeio
// This lives here ../../../lib/vscode/src/vs/base/common/platform.ts#L106
@@ -17,20 +19,7 @@ type NlsConfiguration = {
_resolvedLanguagePackCoreLocation?: string
_corruptedFile?: string
_languagePackSupport?: boolean
loadBundle?: FixMeLater
}
/**
* Helper function to create the path to the bundle
* for getNlsConfiguration.
*/
export function createBundlePath(_resolvedLanguagePackCoreLocation: string, bundle: string) {
// NOTE@jsjoeio - this comment was here before me
// Refers to operating systems that use a different path separator.
// Probably just Windows but we're not sure if "/" breaks on Windows
// so we'll leave it alone for now.
// FIXME: Only works if path separators are /.
return _resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
loadBundle?: any
}
/**
@@ -41,10 +30,14 @@ export function createBundlePath(_resolvedLanguagePackCoreLocation: string, bund
*
* Make sure to wrap this in a try/catch block when you call it.
**/
export function getNlsConfiguration(_document: Document, base: string) {
export function getNlsConfiguration(document: Document) {
const errorMsgPrefix = "[vscode]"
const nlsConfigElement = _document?.getElementById(nlsConfigElementId)
const dataSettings = nlsConfigElement?.getAttribute("data-settings")
const nlsConfigElement = document?.getElementById(nlsConfigElementId)
const nlsConfig = nlsConfigElement?.getAttribute("data-settings")
if (!document) {
throw new Error(`${errorMsgPrefix} Could not parse NLS configuration. document is undefined.`)
}
if (!nlsConfigElement) {
throw new Error(
@@ -52,34 +45,27 @@ export function getNlsConfiguration(_document: Document, base: string) {
)
}
if (!dataSettings) {
if (!nlsConfig) {
throw new Error(
`${errorMsgPrefix} Could not parse NLS configuration. Found nlsConfigElement but missing data-settings attribute.`,
)
}
const nlsConfig = JSON.parse(dataSettings) as NlsConfiguration
return JSON.parse(nlsConfig) as NlsConfiguration
}
try {
const nlsConfig = getNlsConfiguration(document)
if (nlsConfig._resolvedLanguagePackCoreLocation) {
// NOTE@jsjoeio
// Not sure why we use Object.create(null) instead of {}
// They are not the same
// See: https://stackoverflow.com/a/15518712/3015595
// We copied this from ../../../lib/vscode/src/bootstrap.js#L143
const bundles: {
[key: string]: string
} = Object.create(null)
type LoadBundleCallback = (_: undefined, result?: string) => void
nlsConfig.loadBundle = (bundle: string, _language: string, cb: LoadBundleCallback): void => {
const bundles = Object.create(null)
nlsConfig.loadBundle = (bundle: any, _language: any, cb: any): void => {
const result = bundles[bundle]
if (result) {
return cb(undefined, result)
}
// FIXME: Only works if path separators are /.
const path = createBundlePath(nlsConfig._resolvedLanguagePackCoreLocation || "", bundle)
fetch(`${base}/vscode/resource/?path=${encodeURIComponent(path)}`)
const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
fetch(`${options.base}/vscode/resource/?path=${encodeURIComponent(path)}`)
.then((response) => response.json())
.then((json) => {
bundles[bundle] = json
@@ -88,61 +74,17 @@ export function getNlsConfiguration(_document: Document, base: string) {
.catch(cb)
}
}
return nlsConfig
}
type GetLoaderParams = {
nlsConfig: NlsConfiguration
options: Options
_window: Window
}
/**
* Link to types in the loader source repo
* https://github.com/microsoft/vscode-loader/blob/main/src/loader.d.ts#L280
*/
type Loader = {
baseUrl: string
recordStats: boolean
// TODO@jsjoeio: There don't appear to be any types for trustedTypes yet.
trustedTypesPolicy: FixMeLater
paths: {
[key: string]: string
}
"vs/nls": NlsConfiguration
}
/**
* A helper function which creates a script url if the value
* is valid.
*
* Extracted into a function to make it easier to test
*/
export function _createScriptURL(value: string, origin: string): string {
if (value.startsWith(origin)) {
return value
}
throw new Error(`Invalid script url: ${value}`)
}
/**
* A helper function to get the require loader
*
* This used by VSCode/code-server
* to load files.
*
* We extracted the logic into a function so that
* it's easier to test.
**/
export function getConfigurationForLoader({ nlsConfig, options, _window }: GetLoaderParams) {
const loader: Loader = {
;(self.require as any) = {
// Without the full URL VS Code will try to load file://.
baseUrl: `${window.location.origin}${options.csStaticBase}/lib/vscode/out`,
recordStats: true,
trustedTypesPolicy: (_window as FixMeLater).trustedTypes?.createPolicy("amdLoader", {
// TODO: There don't appear to be any types for trustedTypes yet.
trustedTypesPolicy: (window as any).trustedTypes?.createPolicy("amdLoader", {
createScriptURL(value: string): string {
return _createScriptURL(value, window.location.origin)
if (value.startsWith(window.location.origin)) {
return value
}
throw new Error(`Invalid script url: ${value}`)
},
}),
paths: {
@@ -158,16 +100,25 @@ export function getConfigurationForLoader({ nlsConfig, options, _window }: GetLo
},
"vs/nls": nlsConfig,
}
return loader
} catch (error) {
console.error(error)
/* Probably fine. */
}
/**
* Sets the body background color to match the theme.
*/
export function setBodyBackgroundToThemeBackgroundColor(_document: Document, _localStorage: Storage) {
export function setBodyBackgroundToThemeBackgroundColor(document: Document, localStorage: Storage) {
const errorMsgPrefix = "[vscode]"
const colorThemeData = _localStorage.getItem("colorThemeData")
if (!document) {
throw new Error(`${errorMsgPrefix} Could not set body background to theme background color. Document is undefined.`)
}
if (!localStorage) {
throw new Error(
`${errorMsgPrefix} Could not set body background to theme background color. localStorage is undefined.`,
)
}
const colorThemeData = localStorage.getItem("colorThemeData")
if (!colorThemeData) {
throw new Error(
@@ -204,48 +155,14 @@ export function setBodyBackgroundToThemeBackgroundColor(_document: Document, _lo
)
}
_document.body.style.background = editorBgColor
document.body.style.background = editorBgColor
return null
}
/**
* A helper function to encapsulate all the
* logic used in this file.
*
* We purposely include all of this in a single function
* so that it's easier to test.
*/
export function main(_document: Document | undefined, _window: Window | undefined, _localStorage: Storage | undefined) {
if (!_document) {
throw new Error(`document is undefined.`)
}
if (!_window) {
throw new Error(`window is undefined.`)
}
if (!_localStorage) {
throw new Error(`localStorage is undefined.`)
}
const options = getOptions()
const nlsConfig = getNlsConfiguration(_document, options.base)
const loader = getConfigurationForLoader({
nlsConfig,
options,
_window,
})
;(self.require as unknown as Loader) = loader
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
}
try {
main(document, window, localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
} catch (error) {
console.error("[vscode] failed to initialize VS Code")
console.error("Something went wrong setting the body background to the theme background color.")
console.error(error)
}

View File

@@ -5,7 +5,7 @@ export async function registerServiceWorker(): Promise<void> {
const options = getOptions()
logger.level = options.logLevel
const path = normalize(`${options.csStaticBase}/out/browser/serviceWorker.js`)
const path = normalize(`${options.csStaticBase}/dist/serviceWorker.js`)
try {
await navigator.serviceWorker.register(path, {
scope: options.base + "/",

View File

@@ -62,7 +62,7 @@ function newProxyAgent(inVSCode: boolean): http.Agent {
// If they have $NO_PROXY set to example.com then this check won't work!
// But that's drastically unlikely.
export function shouldEnableProxy(): boolean {
function shouldEnableProxy(): boolean {
let shouldEnable = false
const httpProxy = proxyFromEnv.getProxyForUrl(`http://example.com`)

View File

@@ -63,10 +63,9 @@ router.get("/", async (req, res) => {
* TODO: Might currently be unused.
*/
router.get("/resource(/*)?", ensureAuthenticated, async (req, res) => {
const path = getFirstString(req.query.path)
if (path) {
res.set("Content-Type", getMediaMime(path))
res.send(await fs.readFile(pathToFsPath(path)))
if (typeof req.query.path === "string") {
res.set("Content-Type", getMediaMime(req.query.path))
res.send(await fs.readFile(pathToFsPath(req.query.path)))
}
})
@@ -74,10 +73,9 @@ router.get("/resource(/*)?", ensureAuthenticated, async (req, res) => {
* Used by VS Code to load files.
*/
router.get("/vscode-remote-resource(/*)?", ensureAuthenticated, async (req, res) => {
const path = getFirstString(req.query.path)
if (path) {
res.set("Content-Type", getMediaMime(path))
res.send(await fs.readFile(pathToFsPath(path)))
if (typeof req.query.path === "string") {
res.set("Content-Type", getMediaMime(req.query.path))
res.send(await fs.readFile(pathToFsPath(req.query.path)))
}
})

View File

@@ -458,11 +458,17 @@ enum CharCode {
* Taken from vs/base/common/uri.ts. It's not imported to avoid also importing
* everything that file imports.
*/
export function pathToFsPath(path: string, keepDriveLetterCasing = false): string {
export function pathToFsPath(path: string | string[], keepDriveLetterCasing = false): string {
const isWindows = process.platform === "win32"
const uri = { authority: undefined, path: getFirstString(path) || "", scheme: "file" }
const uri = { authority: undefined, path: getFirstString(path), scheme: "file" }
let value: string
if (typeof uri.path !== "string") {
throw new Error(
`Could not compute fsPath from given uri. Expected path to be of type string, but was of type ${typeof uri.path}.`,
)
}
if (uri.authority && uri.path.length > 1 && uri.scheme === "file") {
// unc path: file://shares/c$/far/boo
value = `//${uri.authority}${uri.path}`

View File

@@ -16,8 +16,5 @@
"ts-jest": "^26.4.4",
"@types/wtfnode": "^0.7.0",
"wtfnode": "^0.9.0"
},
"resolutions": {
"argon2/@mapbox/node-pre-gyp/tar": "^6.1.3"
}
}

View File

@@ -1,5 +1,5 @@
import { JSDOM } from "jsdom"
import { LocationLike } from "../../common/util.test"
import { LocationLike } from "../../util.test"
describe("login", () => {
describe("there is an element with id 'base'", () => {

View File

@@ -5,47 +5,48 @@ import { JSDOM } from "jsdom"
import {
getNlsConfiguration,
nlsConfigElementId,
getConfigurationForLoader,
setBodyBackgroundToThemeBackgroundColor,
_createScriptURL,
main,
createBundlePath,
} from "../../../../src/browser/pages/vscode"
describe("vscode", () => {
describe("getNlsConfiguration", () => {
let _document: Document
beforeEach(() => {
// We use underscores to not confuse with global values
const { window: _window } = new JSDOM()
_document = _window.document
const { window } = new JSDOM()
global.document = window.document
})
it("should throw an error if Document is undefined", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not parse NLS configuration. document is undefined.`
expect(() => {
getNlsConfiguration(undefined as any as Document)
}).toThrowError(errorMessage)
})
it("should throw an error if no nlsConfigElement", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not parse NLS configuration. Could not find nlsConfigElement with id: ${nlsConfigElementId}`
expect(() => {
getNlsConfiguration(_document, "")
getNlsConfiguration(document)
}).toThrowError(errorMessage)
})
it("should throw an error if no nlsConfig", () => {
const mockElement = _document.createElement("div")
const mockElement = document.createElement("div")
mockElement.setAttribute("id", nlsConfigElementId)
_document.body.appendChild(mockElement)
document.body.appendChild(mockElement)
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not parse NLS configuration. Found nlsConfigElement but missing data-settings attribute.`
expect(() => {
getNlsConfiguration(_document, "")
getNlsConfiguration(document)
}).toThrowError(errorMessage)
_document.body.removeChild(mockElement)
document.body.removeChild(mockElement)
})
it("should return the correct configuration", () => {
const mockElement = _document.createElement("div")
const mockElement = document.createElement("div")
const dataSettings = {
first: "Jane",
last: "Doe",
@@ -53,52 +54,22 @@ describe("vscode", () => {
mockElement.setAttribute("id", nlsConfigElementId)
mockElement.setAttribute("data-settings", JSON.stringify(dataSettings))
_document.body.appendChild(mockElement)
const actual = getNlsConfiguration(_document, "")
document.body.appendChild(mockElement)
const actual = getNlsConfiguration(global.document)
expect(actual).toStrictEqual(dataSettings)
_document.body.removeChild(mockElement)
})
it("should return have loadBundle property if _resolvedLangaugePackCoreLocation", () => {
const mockElement = _document.createElement("div")
const dataSettings = {
locale: "en",
availableLanguages: ["en", "de"],
_resolvedLanguagePackCoreLocation: "./",
}
mockElement.setAttribute("id", nlsConfigElementId)
mockElement.setAttribute("data-settings", JSON.stringify(dataSettings))
_document.body.appendChild(mockElement)
const nlsConfig = getNlsConfiguration(_document, "")
expect(nlsConfig._resolvedLanguagePackCoreLocation).not.toBe(undefined)
expect(nlsConfig.loadBundle).not.toBe(undefined)
_document.body.removeChild(mockElement)
})
})
describe("createBundlePath", () => {
it("should return the correct path", () => {
const _resolvedLangaugePackCoreLocation = "./languages"
const bundle = "/bundle.js"
const expected = "./languages/!bundle.js.nls.json"
const actual = createBundlePath(_resolvedLangaugePackCoreLocation, bundle)
expect(actual).toBe(expected)
document.body.removeChild(mockElement)
})
})
describe("setBodyBackgroundToThemeBackgroundColor", () => {
let _document: Document
let _localStorage: Storage
beforeEach(() => {
// We need to set the url in the JSDOM constructor
// to prevent this error "SecurityError: localStorage is not available for opaque origins"
// See: https://github.com/jsdom/jsdom/issues/2304#issuecomment-622314949
const { window: _window } = new JSDOM("", { url: "http://localhost" })
_document = _window.document
_localStorage = _window.localStorage
const { window } = new JSDOM("", { url: "http://localhost" })
global.document = window.document
global.localStorage = window.localStorage
})
it("should return null", () => {
const test = {
@@ -106,31 +77,49 @@ describe("vscode", () => {
[`editor.background`]: "#ff3270",
},
}
_localStorage.setItem("colorThemeData", JSON.stringify(test))
localStorage.setItem("colorThemeData", JSON.stringify(test))
expect(setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)).toBeNull()
expect(setBodyBackgroundToThemeBackgroundColor(document, localStorage)).toBeNull()
_localStorage.removeItem("colorThemeData")
localStorage.removeItem("colorThemeData")
})
it("should throw an error if Document is undefined", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not set body background to theme background color. Document is undefined.`
expect(() => {
// @ts-expect-error We need to test when document is undefined
setBodyBackgroundToThemeBackgroundColor(undefined, localStorage)
}).toThrowError(errorMessage)
})
it("should throw an error if localStorage is undefined", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not set body background to theme background color. localStorage is undefined.`
expect(() => {
// @ts-expect-error We need to test when localStorage is undefined
setBodyBackgroundToThemeBackgroundColor(document, undefined)
}).toThrowError(errorMessage)
})
it("should throw an error if it can't find colorThemeData in localStorage", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not set body background to theme background color. Could not find colorThemeData in localStorage.`
expect(() => {
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
}).toThrowError(errorMessage)
})
it("should throw an error if there is an error parsing colorThemeData from localStorage", () => {
const errorMsgPrefix = "[vscode]"
const errorMessage = `${errorMsgPrefix} Could not set body background to theme background color. Could not parse colorThemeData from localStorage.`
_localStorage.setItem(
localStorage.setItem(
"colorThemeData",
'{"id":"vs-dark max-SS-Cyberpunk-themes-cyberpunk-umbra-color-theme-json","label":"Activate UMBRA protocol","settingsId":"Activate "errorForeground":"#ff3270","foreground":"#ffffff","sideBarTitle.foreground":"#bbbbbb"},"watch\\":::false}',
)
expect(() => {
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
}).toThrowError(errorMessage)
localStorage.removeItem("colorThemeData")
@@ -142,13 +131,13 @@ describe("vscode", () => {
const test = {
id: "hey-joe",
}
_localStorage.setItem("colorThemeData", JSON.stringify(test))
localStorage.setItem("colorThemeData", JSON.stringify(test))
expect(() => {
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
}).toThrowError(errorMessage)
_localStorage.removeItem("colorThemeData")
localStorage.removeItem("colorThemeData")
})
it("should throw an error if there is no editor.background color", () => {
const errorMsgPrefix = "[vscode]"
@@ -160,13 +149,13 @@ describe("vscode", () => {
editor: "#fff",
},
}
_localStorage.setItem("colorThemeData", JSON.stringify(test))
localStorage.setItem("colorThemeData", JSON.stringify(test))
expect(() => {
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
}).toThrowError(errorMessage)
_localStorage.removeItem("colorThemeData")
localStorage.removeItem("colorThemeData")
})
it("should set the body background to the editor background color", () => {
const test = {
@@ -174,188 +163,16 @@ describe("vscode", () => {
[`editor.background`]: "#ff3270",
},
}
_localStorage.setItem("colorThemeData", JSON.stringify(test))
localStorage.setItem("colorThemeData", JSON.stringify(test))
setBodyBackgroundToThemeBackgroundColor(_document, _localStorage)
setBodyBackgroundToThemeBackgroundColor(document, localStorage)
// When the body.style.backgroundColor is set using hex
// it is converted to rgb
// which is why we use that in the assertion
expect(_document.body.style.backgroundColor).toBe("rgb(255, 50, 112)")
expect(document.body.style.backgroundColor).toBe("rgb(255, 50, 112)")
_localStorage.removeItem("colorThemeData")
})
})
describe("getConfigurationForLoader", () => {
let _window: Window
beforeEach(() => {
const { window: __window } = new JSDOM()
// @ts-expect-error the Window from JSDOM is not exactly the same as Window
// so we expect an error here
_window = __window
})
it("should return a loader object (with undefined trustedTypesPolicy)", () => {
const options = {
base: ".",
csStaticBase: "/",
logLevel: 1,
}
const nlsConfig = {
first: "Jane",
last: "Doe",
locale: "en",
availableLanguages: {},
}
const loader = getConfigurationForLoader({
options,
_window,
nlsConfig: nlsConfig,
})
expect(loader).toStrictEqual({
baseUrl: "http://localhost//lib/vscode/out",
paths: {
"iconv-lite-umd": "../node_modules/iconv-lite-umd/lib/iconv-lite-umd.js",
jschardet: "../node_modules/jschardet/dist/jschardet.min.js",
"tas-client-umd": "../node_modules/tas-client-umd/lib/tas-client-umd.js",
"vscode-oniguruma": "../node_modules/vscode-oniguruma/release/main",
"vscode-textmate": "../node_modules/vscode-textmate/release/main",
xterm: "../node_modules/xterm/lib/xterm.js",
"xterm-addon-search": "../node_modules/xterm-addon-search/lib/xterm-addon-search.js",
"xterm-addon-unicode11": "../node_modules/xterm-addon-unicode11/lib/xterm-addon-unicode11.js",
"xterm-addon-webgl": "../node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js",
},
recordStats: true,
// TODO@jsjoeio address trustedTypesPolicy part
// might need to look up types
// and find a way to test the function
// maybe extract function into function
// and test manually
trustedTypesPolicy: undefined,
"vs/nls": {
availableLanguages: {},
first: "Jane",
last: "Doe",
locale: "en",
},
})
})
it("should return a loader object with trustedTypesPolicy", () => {
interface PolicyOptions {
createScriptUrl: (url: string) => string
}
function mockCreatePolicy(policyName: string, options: PolicyOptions) {
return {
name: policyName,
...options,
}
}
const mockFn = jest.fn(mockCreatePolicy)
// @ts-expect-error we are adding a custom property to window
_window.trustedTypes = {
createPolicy: mockFn,
}
const options = {
base: "/",
csStaticBase: "/",
logLevel: 1,
}
const nlsConfig = {
first: "Jane",
last: "Doe",
locale: "en",
availableLanguages: {},
}
const loader = getConfigurationForLoader({
options,
_window,
nlsConfig: nlsConfig,
})
expect(loader.trustedTypesPolicy).not.toBe(undefined)
expect(loader.trustedTypesPolicy.name).toBe("amdLoader")
})
})
describe("_createScriptURL", () => {
it("should return the correct url", () => {
const url = _createScriptURL("localhost/foo/bar.js", "localhost")
expect(url).toBe("localhost/foo/bar.js")
})
it("should throw if the value doesn't start with the origin", () => {
expect(() => {
_createScriptURL("localhost/foo/bar.js", "coder.com")
}).toThrow("Invalid script url: localhost/foo/bar.js")
})
})
describe("main", () => {
let _window: Window
let _document: Document
let _localStorage: Storage
beforeEach(() => {
// We need to set the url in the JSDOM constructor
// to prevent this error "SecurityError: localStorage is not available for opaque origins"
// See: https://github.com/jsdom/jsdom/issues/2304#issuecomment-62231494
const { window: __window } = new JSDOM("", { url: "http://localhost" })
// @ts-expect-error the Window from JSDOM is not exactly the same as Window
// so we expect an error here
_window = __window
_document = __window.document
_localStorage = __window.localStorage
const mockElement = _document.createElement("div")
const dataSettings = {
first: "Jane",
last: "Doe",
}
mockElement.setAttribute("id", nlsConfigElementId)
mockElement.setAttribute("data-settings", JSON.stringify(dataSettings))
_document.body.appendChild(mockElement)
const test = {
colorMap: {
[`editor.background`]: "#ff3270",
},
}
_localStorage.setItem("colorThemeData", JSON.stringify(test))
})
afterEach(() => {
_localStorage.removeItem("colorThemeData")
})
it("should throw if document is missing", () => {
expect(() => {
main(undefined, _window, _localStorage)
}).toThrow("document is undefined.")
})
it("should throw if window is missing", () => {
expect(() => {
main(_document, undefined, _localStorage)
}).toThrow("window is undefined.")
})
it("should throw if localStorage is missing", () => {
expect(() => {
main(_document, _window, undefined)
}).toThrow("localStorage is undefined.")
})
it("should add loader to self.require", () => {
main(_document, _window, _localStorage)
expect(Object.prototype.hasOwnProperty.call(self, "require")).toBe(true)
})
it("should not throw in browser context", () => {
// Assuming we call it in a normal browser context
// where everything is defined
expect(() => {
main(_document, _window, _localStorage)
}).not.toThrow()
localStorage.removeItem("colorThemeData")
})
})
})

View File

@@ -1,7 +1,7 @@
import { JSDOM } from "jsdom"
import { registerServiceWorker } from "../../../src/browser/register"
import { createLoggerMock } from "../../utils/helpers"
import { LocationLike } from "../common/util.test"
import { LocationLike } from "../util.test"
describe("register", () => {
describe("when navigator and serviceWorker are defined", () => {
@@ -155,7 +155,7 @@ describe("register", () => {
await registerServiceWorker()
expect(mockFn).toBeCalled()
expect(serviceWorkerPath).toMatch(`${csStaticBasePath}/out/browser/serviceWorker.js`)
expect(serviceWorkerPath).toMatch(`${csStaticBasePath}/dist/serviceWorker.js`)
expect(serviceWorkerScope).toMatch("/")
})
it("should register when options.base is defined", async () => {
@@ -176,7 +176,7 @@ describe("register", () => {
await registerServiceWorker()
expect(mockFn).toBeCalled()
expect(serviceWorkerPath).toMatch(`/out/browser/serviceWorker.js`)
expect(serviceWorkerPath).toMatch(`/dist/serviceWorker.js`)
expect(serviceWorkerScope).toMatch("/")
})
})

View File

@@ -3,9 +3,9 @@ import { promises as fs } from "fs"
import * as net from "net"
import * as os from "os"
import * as path from "path"
import { Args, parse, setDefaults, shouldOpenInExistingInstance, splitOnFirstEquals } from "../../../src/node/cli"
import { tmpdir } from "../../../src/node/constants"
import { paths } from "../../../src/node/util"
import { Args, parse, setDefaults, shouldOpenInExistingInstance, splitOnFirstEquals } from "../../src/node/cli"
import { tmpdir } from "../../src/node/constants"
import { paths } from "../../src/node/util"
type Mutable<T> = {
-readonly [P in keyof T]: T[P]

View File

@@ -1,7 +1,7 @@
import { createLoggerMock } from "../../utils/helpers"
import { createLoggerMock } from "../utils/helpers"
describe("constants", () => {
let constants: typeof import("../../../src/node/constants")
let constants: typeof import("../../src/node/constants")
describe("with package.json defined", () => {
const loggerModule = createLoggerMock()
@@ -15,8 +15,8 @@ describe("constants", () => {
beforeAll(() => {
jest.mock("@coder/logger", () => loggerModule)
jest.mock("../../../package.json", () => mockPackageJson, { virtual: true })
constants = require("../../../src/node/constants")
jest.mock("../../package.json", () => mockPackageJson, { virtual: true })
constants = require("../../src/node/constants")
})
afterAll(() => {
@@ -57,8 +57,8 @@ describe("constants", () => {
}
beforeAll(() => {
jest.mock("../../../package.json", () => mockPackageJson, { virtual: true })
constants = require("../../../src/node/constants")
jest.mock("../../package.json", () => mockPackageJson, { virtual: true })
constants = require("../../src/node/constants")
})
afterAll(() => {

View File

@@ -1,8 +1,8 @@
// Note: we need to import logger from the root
// because this is the logger used in logError in ../src/common/util
import { logger } from "@coder/logger"
import { logger } from "../../node_modules/@coder/logger"
import { Emitter } from "../../../src/common/emitter"
import { Emitter } from "../../src/common/emitter"
describe("emitter", () => {
let spy: jest.SpyInstance

View File

@@ -1,5 +1,5 @@
import { promises as fs } from "fs"
import { getAvailablePort, tmpdir, useEnv } from "../../test/utils/helpers"
import { tmpdir } from "../../test/utils/helpers"
/**
* This file is for testing test helpers (not core code).
@@ -12,43 +12,3 @@ describe("test helpers", () => {
expect(fs.access(pathToTempDir)).resolves.toStrictEqual(undefined)
})
})
describe("useEnv", () => {
beforeAll(() => {
jest.resetModules()
process.env.TEST_USE_ENV = "test environment variable"
})
afterAll(() => {
delete process.env.TEST_USE_ENV
})
it("should set and reset the env var", () => {
const envKey = "TEST_ENV_VAR"
const [setValue, resetValue] = useEnv(envKey)
setValue("hello-world")
expect(process.env[envKey]).toEqual("hello-world")
resetValue()
expect(process.env[envKey]).toEqual(undefined)
})
it("should set and reset the env var where a value was already set", () => {
const envKey = "TEST_USE_ENV"
expect(process.env[envKey]).toEqual("test environment variable")
const [setValue, resetValue] = useEnv(envKey)
setValue("hello there")
expect(process.env[envKey]).toEqual("hello there")
resetValue()
expect(process.env[envKey]).toEqual("test environment variable")
})
})
describe("getAvailablePort", () => {
it("should return a valid port", async () => {
const port = await getAvailablePort()
expect(port).toBeGreaterThan(0)
expect(port).toBeLessThanOrEqual(65535)
})
it("should return different ports for different calls", async () => {
const portOne = await getAvailablePort()
const portTwo = await getAvailablePort()
expect(portOne).not.toEqual(portTwo)
})
})

View File

@@ -1,4 +1,4 @@
import { HttpCode, HttpError } from "../../../src/common/http"
import { HttpCode, HttpError } from "../../src/common/http"
describe("http", () => {
describe("HttpCode", () => {

View File

@@ -1,215 +0,0 @@
import bodyParser from "body-parser"
import * as express from "express"
import * as nodeFetch from "node-fetch"
import * as http from "http"
import { HttpCode } from "../../../src/common/http"
import { proxy } from "../../../src/node/proxy"
import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration"
import { getAvailablePort } from "../../utils/helpers"
describe("proxy", () => {
const nhooyrDevServer = new httpserver.HttpServer()
let codeServer: httpserver.HttpServer | undefined
let proxyPath: string
let absProxyPath: string
let e: express.Express
beforeAll(async () => {
await nhooyrDevServer.listen((req, res) => {
e(req, res)
})
proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
})
afterAll(async () => {
await nhooyrDevServer.close()
})
beforeEach(() => {
e = express.default()
})
afterEach(async () => {
if (codeServer) {
await codeServer.close()
codeServer = undefined
}
})
it("should rewrite the base path", async () => {
e.get("/wsup", (req, res) => {
res.json("asher is the best")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath)
expect(resp.status).toBe(200)
const json = await resp.json()
expect(json).toBe("asher is the best")
})
it("should not rewrite the base path", async () => {
e.get(absProxyPath, (req, res) => {
res.json("joe is the best")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(absProxyPath)
expect(resp.status).toBe(200)
const json = await resp.json()
expect(json).toBe("joe is the best")
})
it("should rewrite redirects", async () => {
e.post("/wsup", (req, res) => {
res.redirect(307, "/finale")
})
e.post("/finale", (req, res) => {
res.json("redirect success")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "POST",
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("redirect success")
})
it("should not rewrite redirects", async () => {
const finalePath = absProxyPath.replace("/wsup", "/finale")
e.post(absProxyPath, (req, res) => {
res.redirect(307, finalePath)
})
e.post(finalePath, (req, res) => {
res.json("redirect success")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(absProxyPath, {
method: "POST",
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("redirect success")
})
it("should allow post bodies", async () => {
e.use(bodyParser.json({ strict: false }))
e.post("/wsup", (req, res) => {
res.json(req.body)
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "post",
body: JSON.stringify("coder is the best"),
headers: {
"Content-Type": "application/json",
},
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("coder is the best")
})
it("should handle bad requests", async () => {
e.use(bodyParser.json({ strict: false }))
e.post("/wsup", (req, res) => {
res.json(req.body)
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "post",
body: "coder is the best",
headers: {
"Content-Type": "application/json",
},
})
expect(resp.status).toBe(400)
expect(resp.statusText).toMatch("Bad Request")
})
it("should handle invalid routes", async () => {
e.post("/wsup", (req, res) => {
res.json(req.body)
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(`${proxyPath}/hello`)
expect(resp.status).toBe(404)
expect(resp.statusText).toMatch("Not Found")
})
it("should handle errors", async () => {
e.use(bodyParser.json({ strict: false }))
e.post("/wsup", (req, res) => {
throw new Error("BROKEN")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "post",
body: JSON.stringify("coder is the best"),
headers: {
"Content-Type": "application/json",
},
})
expect(resp.status).toBe(500)
expect(resp.statusText).toMatch("Internal Server Error")
})
})
// NOTE@jsjoeio
// Both this test suite and the one above it are very similar
// The main difference is this one uses http and node-fetch
// and specifically tests the proxy in isolation vs. using
// the httpserver abstraction we've built.
//
// Leaving this as a separate test suite for now because
// we may consider refactoring the httpserver abstraction
// in the future.
//
// If you're writing a test specifically for code in
// src/node/proxy.ts, you should probably add it to
// this test suite.
describe("proxy (standalone)", () => {
let URL = ""
let PROXY_URL = ""
let testServer: http.Server
let proxyTarget: http.Server
beforeEach(async () => {
const PORT = await getAvailablePort()
const PROXY_PORT = await getAvailablePort()
URL = `http://localhost:${PORT}`
PROXY_URL = `http://localhost:${PROXY_PORT}`
// Define server and a proxy server
testServer = http.createServer((req, res) => {
proxy.web(req, res, {
target: PROXY_URL,
})
})
proxyTarget = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" })
res.end()
})
// Start both servers
await proxyTarget.listen(PROXY_PORT)
await testServer.listen(PORT)
})
afterEach(async () => {
await testServer.close()
await proxyTarget.close()
})
it("should return a 500 when proxy target errors ", async () => {
// Close the proxy target so that proxy errors
await proxyTarget.close()
const errorResp = await nodeFetch.default(`${URL}/error`)
expect(errorResp.status).toBe(HttpCode.ServerError)
expect(errorResp.statusText).toBe("Internal Server Error")
})
it("should proxy correctly", async () => {
const resp = await nodeFetch.default(`${URL}/route`)
expect(resp.status).toBe(200)
expect(resp.statusText).toBe("OK")
})
})

View File

@@ -1,39 +0,0 @@
import { shouldEnableProxy } from "../../../src/node/proxy_agent"
import { useEnv } from "../../utils/helpers"
describe("shouldEnableProxy", () => {
const [setHTTPProxy, resetHTTPProxy] = useEnv("HTTP_PROXY")
const [setHTTPSProxy, resetHTTPSProxy] = useEnv("HTTPS_PROXY")
const [setNoProxy, resetNoProxy] = useEnv("NO_PROXY")
beforeEach(() => {
jest.resetModules() // Most important - it clears the cache
resetHTTPProxy()
resetNoProxy()
resetHTTPSProxy()
})
it("returns true when HTTP_PROXY is set", () => {
setHTTPProxy("http://proxy.example.com")
expect(shouldEnableProxy()).toBe(true)
})
it("returns true when HTTPS_PROXY is set", () => {
setHTTPSProxy("https://proxy.example.com")
expect(shouldEnableProxy()).toBe(true)
})
it("returns false when NO_PROXY is set", () => {
setNoProxy("*")
expect(shouldEnableProxy()).toBe(false)
})
it("should return false when neither HTTP_PROXY nor HTTPS_PROXY is set", () => {
expect(shouldEnableProxy()).toBe(false)
})
it("should return false when NO_PROXY is set to https://example.com", () => {
setNoProxy("https://example.com")
expect(shouldEnableProxy()).toBe(false)
})
it("should return false when NO_PROXY is set to http://example.com", () => {
setNoProxy("http://example.com")
expect(shouldEnableProxy()).toBe(false)
})
})

View File

@@ -1,8 +1,5 @@
import * as cp from "child_process"
import { promises as fs } from "fs"
import * as path from "path"
import { generateUuid } from "../../../src/common/util"
import { tmpdir } from "../../../src/node/constants"
import * as util from "../../../src/node/util"
describe("getEnvPaths", () => {
@@ -467,8 +464,22 @@ describe("pathToFsPath", () => {
it("should keep drive letter casing when set to true", () => {
expect(util.pathToFsPath("/C:/far/bo", true)).toBe("C:/far/bo")
})
it("should throw an error if a non-string is passed in for path", () => {
expect(() =>
util
// @ts-expect-error We need to check other types
.pathToFsPath({}),
).toThrow(`Could not compute fsPath from given uri. Expected path to be of type string, but was of type undefined.`)
})
it("should not throw an error for a string array", () => {
// @ts-expect-error We need to check other types
expect(() => util.pathToFsPath(["/hello/foo", "/hello/bar"]).not.toThrow())
})
it("should use the first string in a string array", () => {
expect(util.pathToFsPath(["/hello/foo", "/hello/bar"])).toBe("/hello/foo")
})
it("should replace / with \\ on Windows", () => {
const ORIGINAL_PLATFORM = process.platform
let ORIGINAL_PLATFORM = process.platform
Object.defineProperty(process, "platform", {
value: "win32",
@@ -481,23 +492,3 @@ describe("pathToFsPath", () => {
})
})
})
describe("isFile", () => {
const testDir = path.join(tmpdir, "tests", "isFile")
let pathToFile = ""
beforeEach(async () => {
pathToFile = path.join(testDir, "foo.txt")
await fs.mkdir(testDir, { recursive: true })
await fs.writeFile(pathToFile, "hello")
})
afterEach(async () => {
await fs.rm(testDir, { recursive: true, force: true })
})
it("should return false if the path doesn't exist", async () => {
expect(await util.isFile(testDir)).toBe(false)
})
it("should return true if is file", async () => {
expect(await util.isFile(pathToFile)).toBe(true)
})
})

View File

@@ -2,11 +2,11 @@ import { logger } from "@coder/logger"
import * as express from "express"
import * as fs from "fs"
import * as path from "path"
import { HttpCode } from "../../../src/common/http"
import { AuthType } from "../../../src/node/cli"
import { codeServer, PluginAPI } from "../../../src/node/plugin"
import * as apps from "../../../src/node/routes/apps"
import * as httpserver from "../../utils/httpserver"
import { HttpCode } from "../../src/common/http"
import { AuthType } from "../../src/node/cli"
import { codeServer, PluginAPI } from "../../src/node/plugin"
import * as apps from "../../src/node/routes/apps"
import * as httpserver from "../utils/httpserver"
const fsp = fs.promises
// Jest overrides `require` so our usual override doesn't work.

105
test/unit/proxy.test.ts Normal file
View File

@@ -0,0 +1,105 @@
import bodyParser from "body-parser"
import * as express from "express"
import * as httpserver from "../utils/httpserver"
import * as integration from "../utils/integration"
describe("proxy", () => {
const nhooyrDevServer = new httpserver.HttpServer()
let codeServer: httpserver.HttpServer | undefined
let proxyPath: string
let absProxyPath: string
let e: express.Express
beforeAll(async () => {
await nhooyrDevServer.listen((req, res) => {
e(req, res)
})
proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
})
afterAll(async () => {
await nhooyrDevServer.close()
})
beforeEach(() => {
e = express.default()
})
afterEach(async () => {
if (codeServer) {
await codeServer.close()
codeServer = undefined
}
})
it("should rewrite the base path", async () => {
e.get("/wsup", (req, res) => {
res.json("asher is the best")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath)
expect(resp.status).toBe(200)
const json = await resp.json()
expect(json).toBe("asher is the best")
})
it("should not rewrite the base path", async () => {
e.get(absProxyPath, (req, res) => {
res.json("joe is the best")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(absProxyPath)
expect(resp.status).toBe(200)
const json = await resp.json()
expect(json).toBe("joe is the best")
})
it("should rewrite redirects", async () => {
e.post("/wsup", (req, res) => {
res.redirect(307, "/finale")
})
e.post("/finale", (req, res) => {
res.json("redirect success")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "POST",
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("redirect success")
})
it("should not rewrite redirects", async () => {
const finalePath = absProxyPath.replace("/wsup", "/finale")
e.post(absProxyPath, (req, res) => {
res.redirect(307, finalePath)
})
e.post(finalePath, (req, res) => {
res.json("redirect success")
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(absProxyPath, {
method: "POST",
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("redirect success")
})
it("should allow post bodies", async () => {
e.use(bodyParser.json({ strict: false }))
e.post("/wsup", (req, res) => {
res.json(req.body)
})
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(proxyPath, {
method: "post",
body: JSON.stringify("coder is the best"),
headers: {
"Content-Type": "application/json",
},
})
expect(resp.status).toBe(200)
expect(await resp.json()).toBe("coder is the best")
})
})

View File

@@ -1,5 +1,5 @@
import * as httpserver from "../../../utils/httpserver"
import * as integration from "../../../utils/integration"
import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration"
describe("health", () => {
let codeServer: httpserver.HttpServer | undefined

View File

@@ -1,6 +1,6 @@
import { RateLimiter } from "../../../../src/node/routes/login"
import * as httpserver from "../../../utils/httpserver"
import * as integration from "../../../utils/integration"
import { RateLimiter } from "../../../src/node/routes/login"
import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration"
describe("login", () => {
describe("RateLimiter", () => {

View File

@@ -1,8 +1,8 @@
import { promises as fs } from "fs"
import * as path from "path"
import { tmpdir } from "../../../utils/helpers"
import * as httpserver from "../../../utils/httpserver"
import * as integration from "../../../utils/integration"
import { tmpdir } from "../../utils/helpers"
import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration"
describe("/static", () => {
let _codeServer: httpserver.HttpServer | undefined

View File

@@ -3,10 +3,10 @@ import { promises as fs } from "fs"
import * as net from "net"
import * as path from "path"
import * as tls from "tls"
import { Emitter } from "../../../src/common/emitter"
import { tmpdir } from "../../../src/node/constants"
import { SocketProxyProvider } from "../../../src/node/socket"
import { generateCertificate } from "../../../src/node/util"
import { Emitter } from "../../src/common/emitter"
import { tmpdir } from "../../src/node/constants"
import { SocketProxyProvider } from "../../src/node/socket"
import { generateCertificate } from "../../src/node/util"
describe("SocketProxyProvider", () => {
const provider = new SocketProxyProvider()

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -44,7 +44,7 @@
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
"paths": {
"code-server": ["../../../../typings/pluginapi"]
"code-server": ["../../../typings/pluginapi"]
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */

View File

@@ -1,9 +1,9 @@
import { promises as fs } from "fs"
import * as http from "http"
import * as path from "path"
import { tmpdir } from "../../../src/node/constants"
import { SettingsProvider, UpdateSettings } from "../../../src/node/settings"
import { LatestResponse, UpdateProvider } from "../../../src/node/update"
import { tmpdir } from "../../src/node/constants"
import { SettingsProvider, UpdateSettings } from "../../src/node/settings"
import { LatestResponse, UpdateProvider } from "../../src/node/update"
describe("update", () => {
let version = "1.0.0"

View File

@@ -1,6 +1,6 @@
import { JSDOM } from "jsdom"
import * as util from "../../../src/common/util"
import { createLoggerMock } from "../../utils/helpers"
import * as util from "../../src/common/util"
import { createLoggerMock } from "../utils/helpers"
const dom = new JSDOM()
global.document = dom.window.document

View File

@@ -1,7 +1,6 @@
import { promises as fs } from "fs"
import * as os from "os"
import * as path from "path"
import * as net from "net"
/**
* Return a mock of @coder/logger.
@@ -38,47 +37,3 @@ export async function tmpdir(testName: string): Promise<string> {
return await fs.mkdtemp(path.join(dir, `${testName}-`), { encoding: "utf8" })
}
/**
* @description Helper function to use an environment variable.
*
* @returns an array (similar to useState in React) with a function
* to set the value and reset the value
*/
export function useEnv(key: string): [(nextValue: string | undefined) => string | undefined, () => void] {
const initialValue = process.env[key]
const setValue = (nextValue: string | undefined) => (process.env[key] = nextValue)
// Node automatically converts undefined to string 'undefined'
// when assigning an environment variable.
// which is why we need to delete it if it's supposed to be undefined
// Source: https://stackoverflow.com/a/60147167
const resetValue = () => {
if (initialValue !== undefined) {
process.env[key] = initialValue
} else {
delete process.env[key]
}
}
return [setValue, resetValue]
}
/**
* Helper function to get a random port.
*
* Source: https://github.com/sindresorhus/get-port/blob/main/index.js#L23-L33
*/
export const getAvailablePort = (options?: net.ListenOptions): Promise<number> =>
new Promise((resolve, reject) => {
const server = net.createServer()
server.unref()
server.on("error", reject)
server.listen(options, () => {
// NOTE@jsjoeio: not a huge fan of the type assertion
// but it works for now.
const { port } = server.address() as net.AddressInfo
server.close(() => {
resolve(port)
})
})
})

View File

@@ -4392,10 +4392,10 @@ symbol-tree@^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==
tar@^6.1.0, tar@^6.1.3:
version "6.1.6"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.6.tgz#c23d797b0a1efe5d479b1490805c5443f3560c5d"
integrity sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==
tar@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"

277
yarn.lock
View File

@@ -206,10 +206,10 @@
resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.16.tgz#ee5b1b188f680733f35c11b065bbd139d618c1e1"
integrity sha512-X6VB1++IkosYY6amRAiMvuvCf12NA4+ooX+gOuu5bJIkdjmh4Lz7QpJcWRdgxesvo1msriDDr9E/sDbIWf6vsQ==
"@eslint/eslintrc@^0.4.3":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
"@eslint/eslintrc@^0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"
integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
@@ -442,9 +442,9 @@
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
"@types/node@*", "@types/node@^14.17.1":
version "14.17.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.6.tgz#cc61c8361c89e70c468cda464d1fa3dd7e5ebd62"
integrity sha512-iBxsxU7eswQDGhlr3AiamBxOssaYxbM+NKXVil8jg9yFXvrfEFbDumLD/2dMTB+zYyg7w+Xjt8yuxfdbUHAtcQ==
version "14.17.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.5.tgz#b59daf6a7ffa461b5648456ca59050ba8e40ed54"
integrity sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@@ -486,9 +486,9 @@
integrity sha512-1ri+LJhh0gRxIa37IpGytdaW7yDEHeJniBSMD1BmitS07R1j63brcYCzry+l0WJvGdEKQNQ7DYXO2epgborWPw==
"@types/semver@^7.1.0":
version "7.3.8"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.8.tgz#508a27995498d7586dcecd77c25e289bfaf90c59"
integrity sha512-D/2EJvAlCEtYFEYmmlGwbGXuK886HzyCc3nZX/tkFTQdEU8jZDAgiv08P162yB17y4ZXZoq7yFAnW4GDBb9Now==
version "7.3.7"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.7.tgz#b9eb89d7dfa70d5d1ce525bc1411a35347f533a3"
integrity sha512-4g1jrL98mdOIwSOUh6LTlB0Cs9I0dQPwINUhBg7C6pN4HLr8GS8xsksJxilW6S6dQHVi2K/o+lQuQcg7LroCnw==
"@types/serve-static@*":
version "1.13.9"
@@ -526,79 +526,113 @@
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
"@types/ws@^7.2.6":
version "7.4.7"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702"
integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==
version "7.4.6"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.6.tgz#c4320845e43d45a7129bb32905e28781c71c1fff"
integrity sha512-ijZ1vzRawI7QoWnTNL8KpHixd2b2XVb9I9HAqI3triPsh1EC0xH0Eg6w2O3TKbDCgiNNlJqfrof6j4T2I+l9vw==
dependencies:
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^4.7.0":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz#8197f1473e7da8218c6a37ff308d695707835684"
integrity sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.3.tgz#36cdcd9ca6f9e5cb49b9f61b970b1976708d084b"
integrity sha512-jW8sEFu1ZeaV8xzwsfi6Vgtty2jf7/lJmQmDkDruBjYAbx5DA8JtbcMnP0rNPUG+oH5GoQBTSp+9613BzuIpYg==
dependencies:
"@typescript-eslint/experimental-utils" "4.28.5"
"@typescript-eslint/scope-manager" "4.28.5"
"@typescript-eslint/experimental-utils" "4.28.3"
"@typescript-eslint/scope-manager" "4.28.3"
debug "^4.3.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.1.0"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/experimental-utils@4.28.5":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz#66c28bef115b417cf9d80812a713e0e46bb42a64"
integrity sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==
"@typescript-eslint/experimental-utils@4.28.3":
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.3.tgz#976f8c1191b37105fd06658ed57ddfee4be361ca"
integrity sha512-zZYl9TnrxwEPi3FbyeX0ZnE8Hp7j3OCR+ELoUfbwGHGxWnHg9+OqSmkw2MoCVpZksPCZYpQzC559Ee9pJNHTQw==
dependencies:
"@types/json-schema" "^7.0.7"
"@typescript-eslint/scope-manager" "4.28.5"
"@typescript-eslint/types" "4.28.5"
"@typescript-eslint/typescript-estree" "4.28.5"
"@typescript-eslint/scope-manager" "4.28.3"
"@typescript-eslint/types" "4.28.3"
"@typescript-eslint/typescript-estree" "4.28.3"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/parser@^4.7.0":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.5.tgz#9c971668f86d1b5c552266c47788a87488a47d1c"
integrity sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.3.tgz#95f1d475c08268edffdcb2779993c488b6434b44"
integrity sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ==
dependencies:
"@typescript-eslint/scope-manager" "4.28.5"
"@typescript-eslint/types" "4.28.5"
"@typescript-eslint/typescript-estree" "4.28.5"
"@typescript-eslint/scope-manager" "4.28.3"
"@typescript-eslint/types" "4.28.3"
"@typescript-eslint/typescript-estree" "4.28.3"
debug "^4.3.1"
"@typescript-eslint/scope-manager@4.28.5":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz#3a1b70c50c1535ac33322786ea99ebe403d3b923"
integrity sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==
"@typescript-eslint/scope-manager@4.28.2":
version "4.28.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz#451dce90303a3ce283750111495d34c9c204e510"
integrity sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==
dependencies:
"@typescript-eslint/types" "4.28.5"
"@typescript-eslint/visitor-keys" "4.28.5"
"@typescript-eslint/types" "4.28.2"
"@typescript-eslint/visitor-keys" "4.28.2"
"@typescript-eslint/types@4.28.5":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.5.tgz#d33edf8e429f0c0930a7c3d44e9b010354c422e9"
integrity sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==
"@typescript-eslint/typescript-estree@4.28.5":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz#4906d343de693cf3d8dcc301383ed638e0441cd1"
integrity sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==
"@typescript-eslint/scope-manager@4.28.3":
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz#c32ad4491b3726db1ba34030b59ea922c214e371"
integrity sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ==
dependencies:
"@typescript-eslint/types" "4.28.5"
"@typescript-eslint/visitor-keys" "4.28.5"
"@typescript-eslint/types" "4.28.3"
"@typescript-eslint/visitor-keys" "4.28.3"
"@typescript-eslint/types@4.28.2":
version "4.28.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.2.tgz#e6b9e234e0e9a66c4d25bab881661e91478223b5"
integrity sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==
"@typescript-eslint/types@4.28.3":
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.3.tgz#8fffd436a3bada422c2c1da56060a0566a9506c7"
integrity sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA==
"@typescript-eslint/typescript-estree@4.28.2":
version "4.28.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz#680129b2a285289a15e7c6108c84739adf3a798c"
integrity sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==
dependencies:
"@typescript-eslint/types" "4.28.2"
"@typescript-eslint/visitor-keys" "4.28.2"
debug "^4.3.1"
globby "^11.0.3"
is-glob "^4.0.1"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@4.28.5":
version "4.28.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz#ffee2c602762ed6893405ee7c1144d9cc0a29675"
integrity sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==
"@typescript-eslint/typescript-estree@4.28.3":
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz#253d7088100b2a38aefe3c8dd7bd1f8232ec46fb"
integrity sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w==
dependencies:
"@typescript-eslint/types" "4.28.5"
"@typescript-eslint/types" "4.28.3"
"@typescript-eslint/visitor-keys" "4.28.3"
debug "^4.3.1"
globby "^11.0.3"
is-glob "^4.0.1"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/visitor-keys@4.28.2":
version "4.28.2"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz#bf56a400857bb68b59b311e6d0a5fbef5c3b5130"
integrity sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==
dependencies:
"@typescript-eslint/types" "4.28.2"
eslint-visitor-keys "^2.0.0"
"@typescript-eslint/visitor-keys@4.28.3":
version "4.28.3"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz#26ac91e84b23529968361045829da80a4e5251c4"
integrity sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg==
dependencies:
"@typescript-eslint/types" "4.28.3"
eslint-visitor-keys "^2.0.0"
JSONStream@^1.0.3, JSONStream@^1.3.5:
@@ -1256,16 +1290,16 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codecov@^3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.3.tgz#9c3e364b8a700c597346ae98418d09880a3fdbe7"
integrity sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==
codecov@^3.8.1:
version "3.8.2"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.2.tgz#ab24f18783998c39e809ea210af899f8dbcc790e"
integrity sha512-6w/kt/xvmPsWMfDFPE/T054txA9RTgcJEw36PNa6MYX+YV29jCHCRFXwbQ3QZBTOgnex1J2WP8bo2AT8TWWz9g==
dependencies:
argv "0.0.2"
ignore-walk "3.0.4"
ignore-walk "3.0.3"
js-yaml "3.14.1"
teeny-request "7.1.1"
urlgrey "1.0.0"
teeny-request "7.0.1"
urlgrey "0.4.4"
collapse-white-space@^1.0.2:
version "1.0.6"
@@ -1559,15 +1593,14 @@ defined@^1.0.0:
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
degenerator@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-3.0.1.tgz#7ef78ec0c8577a544477308ddf1d2d6e88d51f5b"
integrity sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==
degenerator@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-2.2.0.tgz#49e98c11fa0293c5b26edfbb52f15729afcdb254"
integrity sha512-aiQcQowF01RxFI4ZLFMpzyotbQonhNpBao6dkI8JPk5a+hmSjR5ErHp2CQySmQe8os3VBqLCIh87nDBgZXvsmg==
dependencies:
ast-types "^0.13.2"
escodegen "^1.8.1"
esprima "^4.0.0"
vm2 "^3.9.3"
delegates@^1.0.0:
version "1.0.0"
@@ -1974,12 +2007,12 @@ eslint-visitor-keys@^2.0.0:
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint@^7.7.0:
version "7.31.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.31.0.tgz#f972b539424bf2604907a970860732c5d99d3aca"
integrity sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==
version "7.30.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.30.0.tgz#6d34ab51aaa56112fd97166226c9a97f505474f8"
integrity sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==
dependencies:
"@babel/code-frame" "7.12.11"
"@eslint/eslintrc" "^0.4.3"
"@eslint/eslintrc" "^0.4.2"
"@humanwhocodes/config-array" "^0.5.0"
ajv "^6.10.0"
chalk "^4.0.0"
@@ -2184,13 +2217,6 @@ fast-safe-stringify@^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==
fast-url-parser@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=
dependencies:
punycode "^1.3.2"
fastest-levenshtein@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2"
@@ -2659,10 +2685,10 @@ ieee754@^1.1.13, ieee754@^1.1.4:
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
ignore-walk@3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335"
integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==
ignore-walk@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
dependencies:
minimatch "^3.0.4"
@@ -3643,10 +3669,10 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
pac-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz#b718f76475a6a5415c2efbe256c1c971c84f635e"
integrity sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==
pac-proxy-agent@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-4.1.0.tgz#66883eeabadc915fc5e95457324cb0f0ac78defb"
integrity sha512-ejNgYm2HTXSIYX9eFlkvqFp8hyJ374uDf0Zq5YUAifiSh1D6fo+iBivQZirGvVv8dCYUsLhmLBRhlAYvBKI5+Q==
dependencies:
"@tootallnate/once" "1"
agent-base "6"
@@ -3654,16 +3680,16 @@ pac-proxy-agent@^5.0.0:
get-uri "3"
http-proxy-agent "^4.0.1"
https-proxy-agent "5"
pac-resolver "^5.0.0"
pac-resolver "^4.1.0"
raw-body "^2.2.0"
socks-proxy-agent "5"
pac-resolver@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-5.0.0.tgz#1d717a127b3d7a9407a16d6e1b012b13b9ba8dc0"
integrity sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==
pac-resolver@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-4.2.0.tgz#b82bcb9992d48166920bc83c7542abb454bd9bdd"
integrity sha512-rPACZdUyuxT5Io/gFKUeeZFfE5T7ve7cAkE5TUZRRfuKP0u5Hocwe48X7ZEm6mYB+bTB0Qf+xlVlA/RM/i6RCQ==
dependencies:
degenerator "^3.0.1"
degenerator "^2.2.0"
ip "^1.1.5"
netmask "^2.0.1"
@@ -3978,17 +4004,17 @@ proxy-addr@~2.0.5:
forwarded "~0.1.2"
ipaddr.js "1.9.1"
proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-5.0.0.tgz#d31405c10d6e8431fde96cba7a0c027ce01d633b"
integrity sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==
proxy-agent@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-4.0.1.tgz#326c3250776c7044cd19655ccbfadf2e065a045c"
integrity sha512-ODnQnW2jc/FUVwHHuaZEfN5otg/fMbvMxz9nMSUQfJ9JU7q2SZvSULSsjLloVgJOiv9yhc8GlNMKc4GkFmcVEA==
dependencies:
agent-base "^6.0.0"
debug "4"
http-proxy-agent "^4.0.0"
https-proxy-agent "^5.0.0"
lru-cache "^5.1.1"
pac-proxy-agent "^5.0.0"
pac-proxy-agent "^4.1.0"
proxy-from-env "^1.0.0"
socks-proxy-agent "^5.0.0"
@@ -4032,13 +4058,6 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@6.10.1:
version "6.10.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a"
integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==
dependencies:
side-channel "^1.0.4"
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
@@ -4452,15 +4471,6 @@ shellcheck@^1.0.0:
resolved "https://registry.yarnpkg.com/shellcheck/-/shellcheck-1.0.0.tgz#263479d92c3708d63d98883f896481461cf17cd0"
integrity sha512-CdKbWXOknBwE1wNQzAnwfLf7QNOu/yqyLSGBKoq2WuChEqfg7dnZJ1pHR2P463PbVpBRz3KGkYnXJCoQrPwtYA==
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
dependencies:
call-bind "^1.0.0"
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -4882,10 +4892,10 @@ tar-stream@^2.1.4:
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^6.1.0, tar@^6.1.3:
version "6.1.6"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.6.tgz#c23d797b0a1efe5d479b1490805c5443f3560c5d"
integrity sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==
tar@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
@@ -4894,10 +4904,10 @@ tar@^6.1.0, tar@^6.1.3:
mkdirp "^1.0.3"
yallist "^4.0.0"
teeny-request@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.1.1.tgz#2b0d156f4a8ad81de44303302ba8d7f1f05e20e6"
integrity sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg==
teeny-request@7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c"
integrity sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==
dependencies:
http-proxy-agent "^4.0.0"
https-proxy-agent "^5.0.0"
@@ -5222,12 +5232,10 @@ url@~0.11.0:
punycode "1.3.2"
querystring "0.2.0"
urlgrey@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-1.0.0.tgz#72d2f904482d0b602e3c7fa599343d699bbe1017"
integrity sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==
dependencies:
fast-url-parser "^1.1.3"
urlgrey@0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f"
integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
@@ -5319,11 +5327,6 @@ vm-browserify@^1.0.0:
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
vm2@^3.9.3:
version "3.9.3"
resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.3.tgz#29917f6cc081cc43a3f580c26c5b553fd3c91f40"
integrity sha512-smLS+18RjXYMl9joyJxMNI9l4w7biW8ilSDaVRvFBDwOH8P0BK1ognFQTpg0wyQ6wIKLTblHJvROW692L/E53Q==
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
@@ -5403,10 +5406,10 @@ write-file-atomic@^3.0.3:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
ws@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.0.0.tgz#550605d13dfc1437c9ec1396975709c6d7ffc57d"
integrity sha512-6AcSIXpBlS0QvCVKk+3cWnWElLsA6SzC0lkQ43ciEglgXJXiCWK3/CGFEJ+Ybgp006CMibamAsqOlxE9s4AvYA==
ws@^7.2.0:
version "7.5.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74"
integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==
x-is-string@^0.1.0:
version "0.1.0"
@@ -5479,9 +5482,9 @@ yargs@^15.0.0:
yargs-parser "^18.1.2"
yarn@^1.22.4:
version "1.22.11"
resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.11.tgz#d0104043e7349046e0e2aec977c24be106925ed6"
integrity sha512-AWje4bzqO9RUn3sdnM5N8n4ZJ0BqCc/kqFJvpOI5/EVkINXui0yuvU7NDCEF//+WaxHuNay2uOHxA4+tq1P3cg==
version "1.22.10"
resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c"
integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA==
yn@3.1.1:
version "3.1.1"