mirror of
https://github.com/coder/code-server.git
synced 2026-04-14 06:24:32 -05:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7a2b4936a | ||
|
|
c2d79d94f9 | ||
|
|
9fec2d7cad | ||
|
|
80dfb2b2a9 | ||
|
|
27e7b931e7 | ||
|
|
db9f678477 | ||
|
|
c095c26dbc | ||
|
|
262f66abf6 | ||
|
|
8ee45686b0 | ||
|
|
512d97f22f | ||
|
|
897e0ae1da | ||
|
|
f4bf492051 | ||
|
|
2eba7af117 | ||
|
|
0dc59c0da2 | ||
|
|
6275520348 | ||
|
|
2bb51a25a9 | ||
|
|
7a213161f2 | ||
|
|
a1131fadf2 | ||
|
|
468cf5c6ce | ||
|
|
800bf364d6 | ||
|
|
5428442628 | ||
|
|
020f280458 | ||
|
|
58f6e24a07 | ||
|
|
7868f4db23 | ||
|
|
acc50a5d36 | ||
|
|
47ee7ae670 | ||
|
|
70d0c603cc | ||
|
|
2e29c233ea | ||
|
|
331a017309 | ||
|
|
f915d1e2c8 | ||
|
|
95bcf101d7 | ||
|
|
d80568df20 | ||
|
|
03dc8cd808 | ||
|
|
3e1c00e017 | ||
|
|
a76e5241b6 | ||
|
|
913fc30866 | ||
|
|
eb498b0d6d | ||
|
|
eb8099ff89 | ||
|
|
56d3548fa2 | ||
|
|
2d335bd1ea | ||
|
|
291682e1c0 | ||
|
|
97aeb77abe | ||
|
|
76fd2389e4 | ||
|
|
3cb92edc76 | ||
|
|
94ef3776ad | ||
|
|
a82f1ceaa5 | ||
|
|
25254214fb | ||
|
|
feb5e6770c | ||
|
|
e37b35278d | ||
|
|
2ffbcfdfcb | ||
|
|
74da5167a2 | ||
|
|
daac46b3cf | ||
|
|
ea3c79ffd1 | ||
|
|
93e60f7b0e | ||
|
|
7926647058 | ||
|
|
d27cd43dce | ||
|
|
1befd37310 | ||
|
|
2b3b5e7051 | ||
|
|
788da5d495 | ||
|
|
070a5a3179 | ||
|
|
7cbb6a8b09 | ||
|
|
7fb54073db | ||
|
|
e72e8bb6b5 | ||
|
|
411846528b | ||
|
|
7f024eda6e | ||
|
|
2617623ed6 | ||
|
|
70aa1b7722 | ||
|
|
90a4147381 | ||
|
|
5c19962930 | ||
|
|
56d10d82bf | ||
|
|
cef2aa22dc | ||
|
|
b5a9ef80e7 | ||
|
|
5d3c9edce4 |
6
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
6
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -75,10 +75,10 @@ body:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you accessing code-server over HTTPS?
|
||||
description: code-server relies on service workers for many features. Double-check that you are using HTTPS.
|
||||
label: Are you accessing code-server over a secure context?
|
||||
description: code-server relies on service workers (which only work in secure contexts) for many features. Double-check that you are using a secure context like HTTPS or localhost.
|
||||
options:
|
||||
- label: I am using HTTPS.
|
||||
- label: I am using a secure context.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
63
.github/workflows/build.yaml
vendored
63
.github/workflows/build.yaml
vendored
@@ -28,10 +28,10 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run prettier with actionsx/prettier
|
||||
uses: actionsx/prettier@v2
|
||||
uses: actionsx/prettier@v3
|
||||
with:
|
||||
args: --check --loglevel=warn .
|
||||
|
||||
@@ -41,20 +41,20 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v36
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
docs/**
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
cache: "yarn"
|
||||
|
||||
- name: Install doctoc
|
||||
@@ -70,13 +70,13 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v36
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
ci/helm-chart/**
|
||||
@@ -101,13 +101,13 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v36
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
**/*.ts
|
||||
@@ -115,11 +115,11 @@ jobs:
|
||||
files_ignore: |
|
||||
lib/vscode/**
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
@@ -144,7 +144,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Check workflow files
|
||||
run: |
|
||||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/7fdc9630cc360ea1a469eed64ac6d78caeda1234/scripts/download-actionlint.bash)
|
||||
@@ -157,24 +157,24 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v36
|
||||
uses: tj-actions/changed-files@v39
|
||||
with:
|
||||
files: |
|
||||
**/*.ts
|
||||
files_ignore: |
|
||||
lib/vscode/**
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
@@ -203,15 +203,18 @@ jobs:
|
||||
build:
|
||||
name: Build code-server
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install quilt
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
@@ -221,10 +224,10 @@ jobs:
|
||||
- name: Patch Code
|
||||
run: quilt push -a
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
@@ -290,12 +293,15 @@ jobs:
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
@@ -346,12 +352,15 @@ jobs:
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
|
||||
6
.github/workflows/installer.yaml
vendored
6
.github/workflows/installer.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
container: "alpine:3.17"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install curl
|
||||
run: apk add curl
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
|
||||
16
.github/workflows/publish.yaml
vendored
16
.github/workflows/publish.yaml
vendored
@@ -27,12 +27,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
cache: "yarn"
|
||||
|
||||
- name: Download npm package from release artifacts
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
@@ -101,13 +101,13 @@ jobs:
|
||||
steps:
|
||||
# We need to checkout code-server so we can get the version
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: "./code-server"
|
||||
|
||||
- name: Checkout code-server-aur repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "cdrci/code-server-aur"
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
@@ -155,13 +155,13 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
|
||||
105
.github/workflows/release.yaml
vendored
105
.github/workflows/release.yaml
vendored
@@ -27,25 +27,25 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
container: "centos:7"
|
||||
container: "centos:8"
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18.15.0"
|
||||
|
||||
- name: Install development tools
|
||||
run: |
|
||||
yum install -y epel-release centos-release-scl make
|
||||
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync python3
|
||||
# for keytar
|
||||
yum install -y libsecret-devel
|
||||
cd /etc/yum.repos.d/
|
||||
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
|
||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
|
||||
yum install -y gcc-c++ make jq rsync python3 libsecret-devel krb5-devel
|
||||
|
||||
- name: Install nfpm and envsubst
|
||||
run: |
|
||||
@@ -67,10 +67,8 @@ jobs:
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
# NOTE: && here is deliberate - GitHub puts each line in its own `.sh`
|
||||
# file when running inside a docker container.
|
||||
- name: Build standalone release
|
||||
run: source scl_source enable devtoolset-9 && npm run release:standalone
|
||||
run: npm run release:standalone
|
||||
|
||||
- name: Install test dependencies
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
@@ -102,54 +100,60 @@ jobs:
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./release-packages/*
|
||||
|
||||
# NOTE@oxy:
|
||||
# We use Ubuntu 16.04 here, so that our build is more compatible
|
||||
# with older libc versions. We used to (Q1'20) use CentOS 7 here,
|
||||
# but it has a full update EOL of Q4'20 and a 'critical security'
|
||||
# update EOL of 2024. We're dropping full support a few years before
|
||||
# the final EOL, but I don't believe CentOS 7 has a large arm64 userbase.
|
||||
# It is not feasible to cross-compile with CentOS.
|
||||
|
||||
# Cross-compile notes: To compile native dependencies for arm64,
|
||||
# we install the aarch64/armv7l cross toolchain and then set it as the default
|
||||
# compiler/linker/etc. with the AR/CC/CXX/LINK environment variables.
|
||||
# qemu-user-static on ubuntu-16.04 currently doesn't run Node correctly,
|
||||
# so we just build with "native"/x86_64 node, then download arm64/armv7l node
|
||||
# and then put it in our release. We can't smoke test the cross build this way,
|
||||
# but this means we don't need to maintain a self-hosted runner!
|
||||
|
||||
# NOTE@jsjoeio:
|
||||
# We used to use 18.04 until GitHub browned it out on December 15, 2022
|
||||
# See here: https://github.com/actions/runner-images/issues/6002
|
||||
package-linux-cross:
|
||||
name: Linux cross-compile builds
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
container: "debian:buster"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- prefix: aarch64-linux-gnu
|
||||
arch: arm64
|
||||
npm_arch: arm64
|
||||
apt_arch: arm64
|
||||
- prefix: arm-linux-gnueabihf
|
||||
arch: armv7l
|
||||
npm_arch: armv7l
|
||||
apt_arch: armhf
|
||||
|
||||
env:
|
||||
AR: ${{ format('{0}-ar', matrix.prefix) }}
|
||||
AS: ${{ format('{0}-as', matrix.prefix) }}
|
||||
CC: ${{ format('{0}-gcc', matrix.prefix) }}
|
||||
CPP: ${{ format('{0}-cpp', matrix.prefix) }}
|
||||
CXX: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
LINK: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
NPM_CONFIG_ARCH: ${{ matrix.arch }}
|
||||
NODE_VERSION: v16.13.0
|
||||
FC: ${{ format('{0}-gfortran', matrix.prefix) }}
|
||||
LD: ${{ format('{0}-ld', matrix.prefix) }}
|
||||
STRIP: ${{ format('{0}-strip', matrix.prefix) }}
|
||||
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
|
||||
TARGET_ARCH: ${{ matrix.apt_arch }}
|
||||
npm_config_arch: ${{ matrix.npm_arch }}
|
||||
NODE_VERSION: v18.15.0
|
||||
# Not building from source results in an x86_64 argon2, as if
|
||||
# npm_config_arch is being ignored.
|
||||
npm_config_build_from_source: true
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18.15.0"
|
||||
|
||||
- name: Install cross-compiler and system dependencies
|
||||
run: |
|
||||
dpkg --add-architecture $TARGET_ARCH
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
crossbuild-essential-$TARGET_ARCH \
|
||||
libx11-dev:$TARGET_ARCH \
|
||||
libx11-xcb-dev:$TARGET_ARCH \
|
||||
libxkbfile-dev:$TARGET_ARCH \
|
||||
libsecret-1-dev:$TARGET_ARCH \
|
||||
libkrb5-dev:$TARGET_ARCH \
|
||||
ca-certificates \
|
||||
curl wget rsync gettext-base
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
@@ -157,11 +161,6 @@ jobs:
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Install cross-compiler
|
||||
run: sudo apt update && sudo apt install $PACKAGE
|
||||
env:
|
||||
PACKAGE: ${{ format('g++-{0}', matrix.prefix) }}
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
@@ -170,15 +169,13 @@ jobs:
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
# NOTE@jsjoeio - npm fails here
|
||||
# so use yarn
|
||||
- name: Build standalone release
|
||||
run: yarn release:standalone
|
||||
run: npm run release:standalone
|
||||
|
||||
- name: Replace node with cross-compile equivalent
|
||||
run: |
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}.tar.xz
|
||||
tar -xf node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}.tar.xz node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}/bin/node --strip-components=2
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-${npm_config_arch}.tar.xz
|
||||
tar -xf node-${NODE_VERSION}-linux-${npm_config_arch}.tar.xz node-${NODE_VERSION}-linux-${npm_config_arch}/bin/node --strip-components=2
|
||||
mv ./node ./release-standalone/lib/node
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
@@ -191,7 +188,7 @@ jobs:
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: yarn package ${NPM_CONFIG_ARCH}
|
||||
run: npm run package ${npm_config_arch}
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
@@ -206,12 +203,12 @@ jobs:
|
||||
needs: npm-version
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18.15.0"
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
@@ -305,7 +302,7 @@ jobs:
|
||||
npm version --prefix release "$VERSION"
|
||||
|
||||
echo "Updating version in lib/vscode/product.json"
|
||||
tmp=$(mktemp)
|
||||
tmp=$(mktemp)
|
||||
jq ".codeServerVersion = \"$VERSION\"" release/lib/vscode/product.json > "$tmp" && mv "$tmp" release/lib/vscode/product.json
|
||||
# Ensure it has the same permissions as before
|
||||
chmod 644 release/lib/vscode/product.json
|
||||
|
||||
4
.github/workflows/scripts.yaml
vendored
4
.github/workflows/scripts.yaml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
container: "alpine:3.17"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install test utilities
|
||||
run: apk add bats checkbashisms
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install lint utilities
|
||||
run: sudo apt install shellcheck
|
||||
|
||||
31
.github/workflows/security.yaml
vendored
31
.github/workflows/security.yaml
vendored
@@ -25,30 +25,21 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v16
|
||||
- name: Install Node.js v18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
node-version: "18"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
- name: Audit yarn for vulnerabilities
|
||||
run: yarn audit
|
||||
if: success()
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
|
||||
- name: Audit for vulnerabilities
|
||||
run: yarn _audit
|
||||
- name: Audit npm for vulnerabilities
|
||||
run: npm shrinkwrap && npm audit
|
||||
if: success()
|
||||
|
||||
trivy-scan-repo:
|
||||
@@ -59,12 +50,12 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@e5f43133f6e8736992c9f3c1b3296e24b37e17f2
|
||||
uses: aquasecurity/trivy-action@fbd16365eb88e12433951383f5e99bd901fc618f
|
||||
with:
|
||||
scan-type: "fs"
|
||||
scan-ref: "."
|
||||
@@ -89,7 +80,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
4
.github/workflows/trivy-docker.yaml
vendored
4
.github/workflows/trivy-docker.yaml
vendored
@@ -48,10 +48,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner in image mode
|
||||
uses: aquasecurity/trivy-action@e5f43133f6e8736992c9f3c1b3296e24b37e17f2
|
||||
uses: aquasecurity/trivy-action@fbd16365eb88e12433951383f5e99bd901fc618f
|
||||
with:
|
||||
image-ref: "docker.io/codercom/code-server:latest"
|
||||
ignore-unfixed: true
|
||||
|
||||
@@ -1 +1 @@
|
||||
16
|
||||
18
|
||||
|
||||
102
CHANGELOG.md
102
CHANGELOG.md
@@ -22,7 +22,105 @@ Code v99.99.999
|
||||
|
||||
## Unreleased
|
||||
|
||||
Code v1.78.2
|
||||
## [4.17.1](https://github.com/coder/code-server/releases/tag/v4.17.1) - 2023-09-29
|
||||
|
||||
Code v1.82.2
|
||||
|
||||
### Fixed
|
||||
|
||||
- Make secret storage persistent. For example, logging in with GitHub should
|
||||
persist between browser refreshes and code-server restarts.
|
||||
- Issues with argon2 on arm builds should be fixed now.
|
||||
|
||||
## [4.17.0](https://github.com/coder/code-server/releases/tag/v4.17.0) - 2023-09-22
|
||||
|
||||
Code v1.82.2
|
||||
|
||||
### Added
|
||||
|
||||
- Japanese locale.
|
||||
- `CODE_SERVER_HOST` environment variable.
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.82.2. This includes an update to Node 18, which also means
|
||||
that the minimum glibc is now 2.28. If you need to maintain a lower glibc then
|
||||
you can take a version of Node 18 that is compiled with a lower glibc and use
|
||||
that to build code-server (or at a minimum rebuild the native modules).
|
||||
- Display paths to config files in full rather than abbreviated. If you have
|
||||
trouble with the password not working please update and make sure the
|
||||
displayed config paths are what you expect.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix some dependency issues for the standalone arm64 and armv7l releases. If
|
||||
you had issues with missing or failing modules please try these new builds.
|
||||
|
||||
## [4.16.1](https://github.com/coder/code-server/releases/tag/v4.16.1) - 2023-07-31
|
||||
|
||||
Code v1.80.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.80.2.
|
||||
|
||||
## [4.16.0](https://github.com/coder/code-server/releases/tag/v4.16.0) - 2023-07-28
|
||||
|
||||
Code v1.80.1
|
||||
|
||||
### Added
|
||||
|
||||
- `--disable-proxy` flag. This disables the domain and path proxies but it does
|
||||
not disable the ports panel in Code. That can be disabled by using
|
||||
`remote.autoForwardPorts=false` in your settings.
|
||||
|
||||
## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21
|
||||
|
||||
Code v1.80.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.80.1.
|
||||
|
||||
### Added
|
||||
|
||||
- `--trusted-origin` flag for specifying origins that you trust but do not
|
||||
control (for example a reverse proxy).
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
### Security
|
||||
|
||||
- Remove extra write permissions on the Node binary bundled with the linux-amd64
|
||||
tarball. If you extract the tar without a umask this could mean the Node
|
||||
binary would be unexpectedly writable.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Inability to launch multiple instances of code-server for different users.
|
||||
|
||||
### Added
|
||||
|
||||
- `--session-socket` CLI flag to configure the location of the session socket.
|
||||
By default it will be placed in `<user data dir>/code-server-ipc.sock`.
|
||||
|
||||
## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
### Added
|
||||
|
||||
- `--domain-proxy` now supports `{{port}}` and `{{host}}` template variables.
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.79.2
|
||||
- Files opened from an external terminal will now open in the most closely
|
||||
related window rather than in the last opened window.
|
||||
|
||||
## [4.13.0](https://github.com/coder/code-server/releases/tag/v4.13.0) - 2023-05-19
|
||||
|
||||
@@ -210,7 +308,7 @@ Code v1.71.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstsall.sh` which ensures installing with npm works correctly
|
||||
- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstall.sh` which ensures installing with npm works correctly
|
||||
|
||||
## [4.6.1](https://github.com/coder/code-server/releases/tag/v4.6.1) - 2022-09-31
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ main() {
|
||||
release_archive() {
|
||||
local release_name="code-server-$VERSION-$OS-$ARCH"
|
||||
if [[ $OS == "linux" ]]; then
|
||||
tar -czf "release-packages/$release_name.tar.gz" --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
|
||||
tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
|
||||
else
|
||||
tar -czf "release-packages/$release_name.tar.gz" -s "/^release-standalone/$release_name/" release-standalone
|
||||
fi
|
||||
|
||||
@@ -56,7 +56,6 @@ bundle_code_server() {
|
||||
}
|
||||
EOF
|
||||
) > "$RELEASE_PATH/package.json"
|
||||
rsync yarn.lock "$RELEASE_PATH"
|
||||
mv npm-shrinkwrap.json "$RELEASE_PATH"
|
||||
|
||||
rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
|
||||
@@ -95,12 +94,10 @@ bundle_vscode() {
|
||||
"$VSCODE_SRC_PATH/remote/package.json" \
|
||||
"$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
|
||||
|
||||
rsync "$VSCODE_SRC_PATH/remote/yarn.lock" "$VSCODE_OUT_PATH/yarn.lock"
|
||||
mv "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"
|
||||
|
||||
# Include global extension dependencies as well.
|
||||
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock"
|
||||
mv "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
@@ -13,17 +9,19 @@ main() {
|
||||
rsync "$RELEASE_PATH/" "$RELEASE_PATH-standalone"
|
||||
RELEASE_PATH+=-standalone
|
||||
|
||||
# We cannot find the path to node from $PATH because yarn shims a script to ensure
|
||||
# we use the same version it's using so we instead run a script with yarn that
|
||||
# will print the path to node.
|
||||
# We cannot get the path to Node from $PATH (for example via `which node`)
|
||||
# because Yarn shims a script called `node` and we would end up just copying
|
||||
# that script. Instead we run Node and have it print its actual path.
|
||||
local node_path
|
||||
node_path="$(yarn -s node <<< 'console.info(process.execPath)')"
|
||||
node_path="$(node <<< 'console.info(process.execPath)')"
|
||||
|
||||
mkdir -p "$RELEASE_PATH/bin"
|
||||
mkdir -p "$RELEASE_PATH/lib"
|
||||
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
||||
rsync "$node_path" "$RELEASE_PATH/lib/node"
|
||||
|
||||
chmod 755 "$RELEASE_PATH/lib/node"
|
||||
|
||||
pushd "$RELEASE_PATH"
|
||||
npm install --unsafe-perm --omit=dev
|
||||
popd
|
||||
|
||||
@@ -40,6 +40,16 @@ main() {
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
# Set the commit Code will embed into the product.json. We need to do this
|
||||
# since Code tries to get the commit from the `.git` directory which will fail
|
||||
# as it is a submodule.
|
||||
#
|
||||
# Also, we use code-server's commit rather than VS Code's otherwise it would
|
||||
# not update when only our patch files change, and that will cause caching
|
||||
# issues where the browser keeps using outdated code.
|
||||
export BUILD_SOURCEVERSION
|
||||
BUILD_SOURCEVERSION=$(git rev-parse HEAD)
|
||||
|
||||
pushd lib/vscode
|
||||
|
||||
if [[ ! ${VERSION-} ]]; then
|
||||
@@ -48,14 +58,11 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set the commit Code will embed into the product.json. We need to do this
|
||||
# since Code tries to get the commit from the `.git` directory which will fail
|
||||
# as it is a submodule.
|
||||
export BUILD_SOURCEVERSION
|
||||
BUILD_SOURCEVERSION=$(git rev-parse HEAD)
|
||||
|
||||
# Add the date, our name, links, and enable telemetry (this just makes
|
||||
# telemetry available; telemetry can still be disabled by flag or setting).
|
||||
# Add the date, our name, links, enable telemetry (this just makes telemetry
|
||||
# available; telemetry can still be disabled by flag or setting), and
|
||||
# configure trusted extensions (since some, like github.copilot-chat, never
|
||||
# ask to be trusted and this is the only way to get auth working).
|
||||
#
|
||||
# This needs to be done before building as Code will read this file and embed
|
||||
# it into the client-side code.
|
||||
git checkout product.json # Reset in case the script exited early.
|
||||
@@ -89,6 +96,11 @@ main() {
|
||||
"linkProtectionTrustedDomains": [
|
||||
"https://open-vsx.org"
|
||||
],
|
||||
"trustedExtensionAuthAccess": [
|
||||
"vscode.git", "vscode.github",
|
||||
"github.vscode-pull-request-github",
|
||||
"github.copilot", "github.copilot-chat"
|
||||
],
|
||||
"aiConfig": {
|
||||
"ariaKey": "code-server"
|
||||
}
|
||||
|
||||
@@ -53,10 +53,6 @@ symlink_bin_script() {
|
||||
|
||||
OS="$(os)"
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
# Grabs the major version of node from $npm_config_user_agent which looks like
|
||||
# yarn/1.21.1 npm/? node/v14.2.0 darwin x64
|
||||
@@ -68,8 +64,8 @@ main() {
|
||||
echo "USE AT YOUR OWN RISK!"
|
||||
fi
|
||||
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-16}" ]; then
|
||||
echo "ERROR: code-server currently requires node v16."
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-18}" ]; then
|
||||
echo "ERROR: code-server currently requires node v18."
|
||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||
fi
|
||||
@@ -113,29 +109,40 @@ install_with_yarn_or_npm() {
|
||||
# HACK: NPM's use of semver doesn't like resolving some peerDependencies that vscode (upstream) brings in the form of pre-releases.
|
||||
# The legacy behavior doesn't complain about pre-releases being used, falling back to that for now.
|
||||
# See https://github.com//pull/5071
|
||||
npm install --unsafe-perm --legacy-peer-deps --omit=dev
|
||||
if ! npm install --unsafe-perm --legacy-peer-deps --omit=dev; then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
yarn*)
|
||||
yarn --production --frozen-lockfile --no-default-rc
|
||||
if ! yarn --production --frozen-lockfile --no-default-rc; then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Could not determine which package manager is being used to install code-server"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
vscode_install() {
|
||||
echo 'Installing Code dependencies...'
|
||||
cd lib/vscode
|
||||
install_with_yarn_or_npm
|
||||
if ! install_with_yarn_or_npm; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
symlink_asar
|
||||
symlink_bin_script remote-cli code code-server
|
||||
symlink_bin_script helpers browser browser .sh
|
||||
|
||||
cd extensions
|
||||
install_with_yarn_or_npm
|
||||
if ! install_with_yarn_or_npm; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -15,9 +15,9 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 3.9.0
|
||||
version: 3.13.1
|
||||
|
||||
# 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: 4.13.0
|
||||
appVersion: 4.17.1
|
||||
|
||||
@@ -20,6 +20,9 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
annotations: {{- toYaml .Values.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }}
|
||||
{{- if .Values.hostnameOverride }}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{{- if not .Values.existingSecret }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
@@ -11,8 +12,9 @@ metadata:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{ if .Values.password }}
|
||||
{{- if .Values.password }}
|
||||
password: "{{ .Values.password | b64enc }}"
|
||||
{{ else }}
|
||||
{{- else }}
|
||||
password: "{{ randAlphaNum 24 | b64enc }}"
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: codercom/code-server
|
||||
tag: '4.13.0'
|
||||
tag: '4.17.1'
|
||||
pullPolicy: Always
|
||||
|
||||
# Specifies one or more secrets to be used when pulling images from a
|
||||
|
||||
@@ -37,7 +37,7 @@ for [VS
|
||||
Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
Here is what is needed:
|
||||
|
||||
- `node` v16.x
|
||||
- `node` v18.x
|
||||
- `git` v2.x or greater
|
||||
- [`git-lfs`](https://git-lfs.github.com)
|
||||
- [`yarn`](https://classic.yarnpkg.com/en/)
|
||||
@@ -63,7 +63,7 @@ Here is what is needed:
|
||||
If you're developing code-server on Linux, make sure you have installed or install the following dependencies:
|
||||
|
||||
```shell
|
||||
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev python-is-python3
|
||||
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev libkrb5-dev python-is-python3
|
||||
```
|
||||
|
||||
These are required by Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for more information.
|
||||
|
||||
35
docs/FAQ.md
35
docs/FAQ.md
@@ -14,6 +14,7 @@
|
||||
- [How do I install an extension manually?](#how-do-i-install-an-extension-manually)
|
||||
- [How do I use my own extensions marketplace?](#how-do-i-use-my-own-extensions-marketplace)
|
||||
- [Where are extensions stored?](#where-are-extensions-stored)
|
||||
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
|
||||
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
||||
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
||||
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
||||
@@ -34,6 +35,7 @@
|
||||
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
|
||||
- [How do I change the port?](#how-do-i-change-the-port)
|
||||
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
|
||||
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
||||
- [How do I disable file download?](#how-do-i-disable-file-download)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
@@ -175,10 +177,10 @@ If you own a marketplace that implements the VS Code Extension Gallery API, you
|
||||
can point code-server to it by setting `$EXTENSIONS_GALLERY`.
|
||||
This corresponds directly with the `extensionsGallery` entry in in VS Code's `product.json`.
|
||||
|
||||
For example, to use the legacy Coder extensions marketplace:
|
||||
For example:
|
||||
|
||||
```bash
|
||||
export EXTENSIONS_GALLERY='{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
export EXTENSIONS_GALLERY='{"serviceUrl": "https://my-extensions/api"}'
|
||||
```
|
||||
|
||||
Though you can technically use Microsoft's marketplace in this manner, we
|
||||
@@ -191,10 +193,20 @@ docs](https://github.com/VSCodium/vscodium/blob/master/DOCS.md#extensions--marke
|
||||
|
||||
## Where are extensions stored?
|
||||
|
||||
Extensions are store, by default, to `~/.local/share/code-server/extensions`.
|
||||
Extensions are stored in `~/.local/share/code-server/extensions` by default.
|
||||
|
||||
If you set the `XDG_DATA_HOME` environment variable, the data directory will be
|
||||
`$XDG_DATA_HOME/code-server/extensions`. In general, we try to follow the XDG directory spec.
|
||||
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the
|
||||
extensions directory will be `$XDG_DATA_HOME/code-server/extensions`. In
|
||||
general, we try to follow the XDG directory spec.
|
||||
|
||||
## Where is VS Code configuration stored?
|
||||
|
||||
VS Code configuration such as settings and keybindings are stored in
|
||||
`~/.local/share/code-server` by default.
|
||||
|
||||
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the data
|
||||
directory will be `$XDG_DATA_HOME/code-server`. In general, we try to follow the
|
||||
XDG directory spec.
|
||||
|
||||
## How can I reuse my VS Code configuration?
|
||||
|
||||
@@ -453,6 +465,19 @@ You can pass the flag `--disable-getting-started-override` to `code-server` or
|
||||
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
|
||||
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
|
||||
|
||||
## How do I disable the proxy?
|
||||
|
||||
You can pass the flag `--disable-proxy` to `code-server` or
|
||||
you can set the environment variable `CS_DISABLE_PROXY=1` or
|
||||
`CS_DISABLE_PROXY=true`.
|
||||
|
||||
Note, this option currently only disables the proxy routes to forwarded ports, including
|
||||
the domain and path proxy routes over HTTP and WebSocket; however, it does not
|
||||
disable the automatic port forwarding in the VS Code workbench itself. In other words,
|
||||
user will still see the Ports tab and notifications, but will not be able to actually
|
||||
use access the ports. It is recommended to set `remote.autoForwardPorts` to `false`
|
||||
when using the option.
|
||||
|
||||
## How do I disable file download?
|
||||
|
||||
You can pass the flag `--disable-file-downloads` to `code-server`
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
|
||||
access it in the browser.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Highlights
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
```
|
||||
|
||||
6. Exit the terminal using `exit` and then reopen the terminal
|
||||
7. Install and use Node.js 16:
|
||||
7. Install and use Node.js 18:
|
||||
|
||||
```shell
|
||||
nvm install 16
|
||||
nvm use 16
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
```
|
||||
|
||||
8. Install code-server globally on device with: `npm install --global code-server --unsafe-perm`
|
||||
|
||||
BIN
docs/assets/screenshot-1.png
Normal file
BIN
docs/assets/screenshot-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
BIN
docs/assets/screenshot-2.png
Normal file
BIN
docs/assets/screenshot-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 267 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 357 KiB |
@@ -19,6 +19,7 @@
|
||||
- [Proxying to create a React app](#proxying-to-create-a-react-app)
|
||||
- [Proxying to a Vue app](#proxying-to-a-vue-app)
|
||||
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
||||
- [Proxying to a Svelte app](#proxying-to-a-svelte-app)
|
||||
- [SSH into code-server on VS Code](#ssh-into-code-server-on-vs-code)
|
||||
- [Option 1: cloudflared tunnel](#option-1-cloudflared-tunnel)
|
||||
- [Option 2: ngrok tunnel](#option-2-ngrok-tunnel)
|
||||
@@ -138,9 +139,9 @@ sudo apt install caddy
|
||||
1. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this:
|
||||
|
||||
```text
|
||||
mydomain.com
|
||||
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
mydomain.com {
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
```
|
||||
|
||||
If you want to serve code-server from a sub-path, you can do so as follows:
|
||||
@@ -190,7 +191,7 @@ At this point, you should be able to access code-server via
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection upgrade;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
@@ -414,6 +415,27 @@ In order to use code-server's built-in proxy with Angular, you need to make the
|
||||
|
||||
For additional context, see [this GitHub Discussion](https://github.com/coder/code-server/discussions/5439#discussioncomment-3371983).
|
||||
|
||||
### Proxying to a Svelte app
|
||||
|
||||
In order to use code-server's built-in proxy with Svelte, you need to make the following changes in your app:
|
||||
|
||||
1. Add `svelte.config.js` if you don't already have one
|
||||
2. Update the values to match this (you can use any free port):
|
||||
|
||||
```js
|
||||
const config = {
|
||||
kit: {
|
||||
paths: {
|
||||
base: "/absproxy/5173",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
3. Access app at `<code-server-root>/absproxy/5173/` e.g. `http://localhost:8080/absproxy/5173/
|
||||
|
||||
For additional context, see [this Github Issue](https://github.com/sveltejs/kit/issues/2958)
|
||||
|
||||
## SSH into code-server on VS Code
|
||||
|
||||
[](https://ohmyz.sh/) [](https://img.shields.io/badge/Terminal-2E2E2E?style=for-the-badge&logo=Windows+Terminal&logoColor=ffffff) [](vscode:extension/ms-vscode-remote.remote-ssh)
|
||||
|
||||
@@ -103,10 +103,9 @@ _exact_ same commands presented in the rest of this document.
|
||||
We recommend installing with `npm` when:
|
||||
|
||||
1. You aren't using a machine with `amd64` or `arm64`.
|
||||
1. You are installing code-server on Windows
|
||||
1. You're on Linux with `glibc` < v2.17, `glibcxx` < v3.4.18 on `amd64`, `glibc`
|
||||
< v2.23, or `glibcxx` < v3.4.21 on `arm64`.
|
||||
1. You're running Alpine Linux or are using a non-glibc libc. See
|
||||
2. You are installing code-server on Windows.
|
||||
3. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
||||
4. You're running Alpine Linux or are using a non-glibc libc. See
|
||||
[#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
|
||||
for more information.
|
||||
|
||||
@@ -123,8 +122,8 @@ node binary and node modules.
|
||||
We create the standalone releases using the [npm package](#npm), and we
|
||||
then create the remaining releases using the standalone version.
|
||||
|
||||
The only requirement to use the standalone release is `glibc` >= 2.17 and
|
||||
`glibcxx` >= v3.4.18 on Linux (for macOS, there is no minimum system
|
||||
The only requirement to use the standalone release is `glibc` >= 2.28 and
|
||||
`glibcxx` >= v3.4.21 on Linux (for macOS, there is no minimum system
|
||||
requirement).
|
||||
|
||||
To use a standalone release:
|
||||
@@ -280,6 +279,7 @@ brew services start code-server
|
||||
# outside the container.
|
||||
mkdir -p ~/.config
|
||||
docker run -it --name code-server -p 127.0.0.1:8080:8080 \
|
||||
-v "$HOME/.local:/home/coder/.local" \
|
||||
-v "$HOME/.config:/home/coder/.config" \
|
||||
-v "$PWD:/home/coder/project" \
|
||||
-u "$(id -u):$(id -g)" \
|
||||
|
||||
@@ -30,7 +30,7 @@ includes installing instructions based on your operating system.
|
||||
## Node.js version
|
||||
|
||||
We use the same major version of Node.js shipped with Code's remote, which is
|
||||
currently `16.x`. VS Code also [lists Node.js
|
||||
currently `18.x`. VS Code also [lists Node.js
|
||||
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
|
||||
Using other versions of Node.js [may lead to unexpected
|
||||
@@ -79,7 +79,7 @@ Proceed to [installing](#installing)
|
||||
## FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install -y git python npm-node16 pkgconf
|
||||
pkg install -y git python npm-node18 pkgconf
|
||||
pkg install -y libinotify
|
||||
```
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ npm config set python python3
|
||||
node -v
|
||||
```
|
||||
|
||||
you will get node version `v16.15.0`
|
||||
you will get Node version `v18`
|
||||
|
||||
5. Now install code-server following our guide on [installing with npm](./npm.md)
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
flake-utils.lib.eachDefaultSystem
|
||||
(system:
|
||||
let pkgs = nixpkgs.legacyPackages.${system};
|
||||
nodejs = pkgs.nodejs-16_x;
|
||||
nodejs = pkgs.nodejs-18_x;
|
||||
yarn' = pkgs.yarn.override { inherit nodejs; };
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
nodejs yarn' python3 pkg-config git rsync jq moreutils quilt bats
|
||||
nodejs yarn' python3 pkg-config git rsync jq moreutils quilt bats openssl
|
||||
];
|
||||
buildInputs = with pkgs; (lib.optionals (!stdenv.isDarwin) [ libsecret ]
|
||||
buildInputs = with pkgs; (lib.optionals (!stdenv.isDarwin) [ libsecret libkrb5 ]
|
||||
++ (with xorg; [ libX11 libxkbfile ])
|
||||
++ lib.optionals stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [
|
||||
AppKit Cocoa CoreServices Security xcbuild
|
||||
|
||||
@@ -441,7 +441,7 @@ install_npm() {
|
||||
return
|
||||
fi
|
||||
echoerr "Please install npm to install code-server!"
|
||||
echoerr "You will need at least node v12 and a few C dependencies."
|
||||
echoerr "You will need at least node v18 and a few C dependencies."
|
||||
echoerr "See the docs https://coder.com/docs/code-server/latest/install#npm"
|
||||
|
||||
exit 1
|
||||
|
||||
Submodule lib/vscode updated: 695af097c7...f1b07bd25d
105
package.json
105
package.json
@@ -38,75 +38,62 @@
|
||||
},
|
||||
"main": "out/node/entry.js",
|
||||
"devDependencies": {
|
||||
"@schemastore/package": "^0.0.6",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
"@types/js-yaml": "^4.0.0",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/pem": "^1.9.5",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/compression": "^1.7.3",
|
||||
"@types/cookie-parser": "^1.4.4",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/http-proxy": "1.17.7",
|
||||
"@types/js-yaml": "^4.0.6",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/pem": "^1.14.1",
|
||||
"@types/proxy-from-env": "^1.0.1",
|
||||
"@types/safe-compare": "^1.1.0",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/trusted-types": "^2.0.2",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"audit-ci": "^6.0.0",
|
||||
"doctoc": "2.2.1",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"prettier": "2.8.0",
|
||||
"prettier-plugin-sh": "^0.12.8",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"ansi-regex": "^5.0.1",
|
||||
"normalize-package-data": "^5.0.0",
|
||||
"doctoc/underscore": "^1.13.1",
|
||||
"doctoc/**/trim": "^1.0.0",
|
||||
"postcss": "^8.2.1",
|
||||
"browserslist": "^4.16.5",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"vfile-message": "^2.0.2",
|
||||
"tar": "^6.1.9",
|
||||
"path-parse": "^1.0.7",
|
||||
"vm2": "^3.9.11",
|
||||
"follow-redirects": "^1.14.8",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nanoid": "^3.1.31",
|
||||
"minimist": "npm:minimist-lite@2.2.1",
|
||||
"glob-parent": "^6.0.1",
|
||||
"@types/node": "^16.0.0",
|
||||
"qs": "^6.7.3"
|
||||
"@types/semver": "^7.5.2",
|
||||
"@types/trusted-types": "^2.0.4",
|
||||
"@types/ws": "^8.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.2",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
"audit-ci": "^6.6.1",
|
||||
"doctoc": "^2.2.1",
|
||||
"eslint": "^8.49.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-sh": "^0.13.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "^3.0.0",
|
||||
"argon2": "0.30.3",
|
||||
"@coder/logger": "^3.0.1",
|
||||
"argon2": "^0.31.1",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"env-paths": "^2.2.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"env-paths": "^2.2.1",
|
||||
"express": "5.0.0-alpha.8",
|
||||
"http-proxy": "^1.18.0",
|
||||
"http-proxy": "^1.18.1",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"i18next": "^22.4.6",
|
||||
"js-yaml": "^4.0.0",
|
||||
"i18next": "^23.5.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"limiter": "^2.1.0",
|
||||
"pem": "^1.14.2",
|
||||
"proxy-agent": "^6.2.1",
|
||||
"qs": "6.11.0",
|
||||
"rotating-file-stream": "^3.0.0",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"pem": "^1.14.8",
|
||||
"proxy-agent": "^6.3.1",
|
||||
"qs": "6.9.7",
|
||||
"rotating-file-stream": "^3.1.1",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"safe-compare": "^1.1.4",
|
||||
"semver": "^7.1.3",
|
||||
"ws": "^8.0.0",
|
||||
"semver": "^7.5.4",
|
||||
"ws": "^8.14.2",
|
||||
"xdg-basedir": "^4.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "^18.0.0",
|
||||
"qs": "6.9.7"
|
||||
},
|
||||
"overrides": {
|
||||
"qs": "6.9.7"
|
||||
},
|
||||
"bin": {
|
||||
"code-server": "out/node/entry.js"
|
||||
},
|
||||
@@ -120,7 +107,7 @@
|
||||
"remote-development"
|
||||
],
|
||||
"engines": {
|
||||
"node": "16"
|
||||
"node": "18"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
@@ -167,7 +167,9 @@ class RemoteAuthoritiesImpl {
|
||||
@@ -168,7 +168,9 @@ class RemoteAuthoritiesImpl {
|
||||
return URI.from({
|
||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||
authority: `${host}:${port}`,
|
||||
@@ -111,7 +111,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -267,12 +267,11 @@ export class WebClientServer {
|
||||
@@ -269,16 +269,15 @@ export class WebClientServer {
|
||||
return void res.end();
|
||||
}
|
||||
|
||||
@@ -120,16 +120,20 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
- return Array.isArray(val) ? val[0] : val;
|
||||
- };
|
||||
-
|
||||
- const remoteAuthority = getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host;
|
||||
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
|
||||
+ // For now we are getting the remote authority from the client to avoid
|
||||
+ // needing specific configuration for reverse proxies to work. Set this to
|
||||
+ // something invalid to make sure we catch code that is using this value
|
||||
+ // from the backend when it should not.
|
||||
+ const remoteAuthority = 'remote';
|
||||
const remoteAuthority = (
|
||||
useTestResolver
|
||||
? 'test+test'
|
||||
- : (getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host)
|
||||
+ : 'remote'
|
||||
);
|
||||
if (!remoteAuthority) {
|
||||
return serveError(req, res, 400, `Bad request.`);
|
||||
}
|
||||
@@ -298,8 +297,12 @@ export class WebClientServer {
|
||||
@@ -305,8 +304,12 @@ export class WebClientServer {
|
||||
scopes: [['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
|
||||
@@ -142,7 +146,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -334,11 +337,12 @@ export class WebClientServer {
|
||||
@@ -341,8 +344,10 @@ export class WebClientServer {
|
||||
const values: { [key: string]: string } = {
|
||||
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
|
||||
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
||||
@@ -154,20 +158,17 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+ VS_BASE: vscodeBase,
|
||||
};
|
||||
|
||||
-
|
||||
let data;
|
||||
try {
|
||||
const workbenchTemplate = (await fsp.readFile(filePath)).toString();
|
||||
@@ -352,7 +356,7 @@ export class WebClientServer {
|
||||
if (useTestResolver) {
|
||||
@@ -367,7 +372,7 @@ export class WebClientServer {
|
||||
'default-src \'self\';',
|
||||
'img-src \'self\' https: data: blob:;',
|
||||
'media-src \'self\';',
|
||||
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' http://${remoteAuthority};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=';`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' ${useTestResolver ? '' : ''};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
'child-src \'self\';',
|
||||
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
||||
'worker-src \'self\' data: blob:;',
|
||||
@@ -425,3 +429,70 @@ export class WebClientServer {
|
||||
@@ -440,3 +445,70 @@ export class WebClientServer {
|
||||
return void res.end(data);
|
||||
}
|
||||
}
|
||||
@@ -254,23 +255,45 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -484,6 +484,7 @@ function doCreateUri(path: string, query
|
||||
});
|
||||
@@ -304,7 +304,8 @@ class LocalStorageURLCallbackProvider ex
|
||||
this.startListening();
|
||||
}
|
||||
|
||||
- return URI.parse(window.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
|
||||
+ const path = (window.location.pathname + "/" + this._callbackRoute).replace(/\/\/+/g, "/");
|
||||
+ return URI.parse(window.location.href).with({ path: path, query: queryParams.join('&') });
|
||||
}
|
||||
|
||||
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
return URI.parse(window.location.href).with({ path, query });
|
||||
private startListening(): void {
|
||||
@@ -550,17 +551,6 @@ class WorkspaceProvider implements IWork
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +496,7 @@ function doCreateUri(path: string, query
|
||||
-function readCookie(name: string): string | undefined {
|
||||
- const cookies = document.cookie.split('; ');
|
||||
- for (const cookie of cookies) {
|
||||
- if (cookie.startsWith(name + '=')) {
|
||||
- return cookie.substring(name.length + 1);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return undefined;
|
||||
-}
|
||||
-
|
||||
(function () {
|
||||
|
||||
// Find config by checking for DOM
|
||||
@@ -569,8 +559,8 @@ function readCookie(name: string): strin
|
||||
if (!configElement || !configElementAttribute) {
|
||||
throw new Error('Missing web configuration element');
|
||||
}
|
||||
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
|
||||
- const secretStorageKeyPath = readCookie('vscode-secret-key-path');
|
||||
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
|
||||
+ const secretStorageKeyPath = (window.location.pathname + "/mint-key").replace(/\/\/+/g, "/");
|
||||
const secretStorageCrypto = secretStorageKeyPath && ServerKeyedAESCrypto.supported()
|
||||
? new ServerKeyedAESCrypto(secretStorageKeyPath) : new TransparentCrypto();
|
||||
|
||||
// Create workbench
|
||||
create(document.body, {
|
||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
|
||||
@@ -17,7 +17,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
@@ -97,10 +97,14 @@ class RemoteTerminalBackend extends Base
|
||||
@@ -104,10 +104,14 @@ class RemoteTerminalBackend extends Base
|
||||
}
|
||||
const reqId = e.reqId;
|
||||
const commandId = e.commandId;
|
||||
|
||||
@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
@@ -243,6 +243,10 @@ export class Extension implements IExten
|
||||
@@ -244,6 +244,10 @@ export class Extension implements IExten
|
||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -16,6 +16,7 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
@@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -94,6 +95,7 @@ export interface ServerParsedArgs {
|
||||
@@ -97,6 +98,7 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
@@ -78,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -325,6 +325,7 @@ export class WebClientServer {
|
||||
@@ -332,6 +332,7 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
@@ -94,9 +94,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -105,7 +105,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
@@ -80,7 +80,7 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -79,7 +79,7 @@ export class WorkbenchContextKeysHandler
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@@ -114,7 +114,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
|
||||
@@ -210,6 +210,9 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -209,6 +209,9 @@ export class WorkbenchContextKeysHandler
|
||||
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
|
||||
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
|
||||
|
||||
@@ -165,7 +165,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -35,6 +35,8 @@ export const HasWebFileSystemAccess = ne
|
||||
@@ -38,6 +38,8 @@ export const HasWebFileSystemAccess = ne
|
||||
|
||||
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
|
||||
|
||||
|
||||
@@ -21,15 +21,24 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -234,6 +234,9 @@ export async function setupServerService
|
||||
@@ -11,7 +11,7 @@ import * as path from 'vs/base/common/pa
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { getMachineId } from 'vs/base/node/id';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ProtocolConstants } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
@@ -227,6 +227,9 @@ export async function setupServerService
|
||||
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
||||
socketServer.registerChannel('extensions', channel);
|
||||
|
||||
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService));
|
||||
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables);
|
||||
+ socketServer.registerChannel('languagePacks', languagePackChannel);
|
||||
+
|
||||
const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
|
||||
socketServer.registerChannel('encryption', encryptionChannel);
|
||||
// clean up extensions folder
|
||||
remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp());
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
===================================================================
|
||||
@@ -89,10 +98,10 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
@@ -46,15 +49,26 @@
|
||||
// Set up nls if the user is not using the default language (English)
|
||||
const nlsConfig = {};
|
||||
const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language;
|
||||
@@ -48,15 +51,26 @@
|
||||
// Normalize locale to lowercase because translationServiceUrl is case-sensitive.
|
||||
// ref: https://github.com/microsoft/vscode/issues/187795
|
||||
const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language.toLowerCase();
|
||||
- if (!locale.startsWith('en')) {
|
||||
- nlsConfig['vs/nls'] = {
|
||||
- availableLanguages: {
|
||||
@@ -203,15 +212,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
@@ -27,6 +27,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
import { streamToBuffer } from 'vs/base/common/buffer';
|
||||
import { IProductConfiguration } from 'vs/base/common/product';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
+import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
@@ -337,6 +338,8 @@ export class WebClientServer {
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -344,6 +345,8 @@ export class WebClientServer {
|
||||
callbackRoute: this._callbackRoute
|
||||
};
|
||||
|
||||
@@ -220,19 +229,19 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
const nlsBaseUrl = this._productService.extensionsGallery?.nlsBaseUrl;
|
||||
const values: { [key: string]: string } = {
|
||||
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
|
||||
@@ -345,6 +348,7 @@ export class WebClientServer {
|
||||
@@ -352,6 +355,7 @@ export class WebClientServer {
|
||||
WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''),
|
||||
BASE: base,
|
||||
VS_BASE: vscodeBase,
|
||||
+ NLS_CONFIGURATION: asJSON(nlsConfiguration),
|
||||
};
|
||||
|
||||
let data;
|
||||
if (useTestResolver) {
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -17,6 +17,7 @@ export const serverOptions: OptionDescri
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
@@ -240,7 +249,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -96,6 +97,7 @@ export interface ServerParsedArgs {
|
||||
@@ -99,6 +100,7 @@ export interface ServerParsedArgs {
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
'disable-file-downloads'?: boolean;
|
||||
@@ -252,7 +261,7 @@ Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
@@ -52,7 +52,7 @@ import 'vs/workbench/services/dialogs/br
|
||||
@@ -50,7 +50,7 @@ import 'vs/workbench/services/dialogs/br
|
||||
import 'vs/workbench/services/host/browser/browserHostService';
|
||||
import 'vs/workbench/services/lifecycle/browser/lifecycleService';
|
||||
import 'vs/workbench/services/clipboard/browser/clipboardService';
|
||||
@@ -261,7 +270,7 @@ Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
import 'vs/workbench/services/path/browser/pathService';
|
||||
import 'vs/workbench/services/themes/browser/browserHostColorSchemeService';
|
||||
import 'vs/workbench/services/encryption/browser/encryptionService';
|
||||
@@ -116,8 +116,9 @@ registerSingleton(ILanguagePackService,
|
||||
@@ -115,8 +115,9 @@ registerSingleton(ILanguagePackService,
|
||||
// Logs
|
||||
import 'vs/workbench/contrib/logs/browser/logs.contribution';
|
||||
|
||||
@@ -339,7 +348,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
@@ -335,9 +335,6 @@ export abstract class AbstractInstallAct
|
||||
@@ -321,9 +321,6 @@ export class InstallAction extends Exten
|
||||
if (this.extension.isBuiltin) {
|
||||
return;
|
||||
}
|
||||
@@ -349,7 +358,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
if (this.extension.state === ExtensionState.Uninstalled && await this.extensionsWorkbenchService.canInstall(this.extension)) {
|
||||
this.enabled = this.options.installPreReleaseVersion ? this.extension.hasPreReleaseVersion : this.extension.hasReleaseVersion;
|
||||
this.updateLabel();
|
||||
@@ -715,7 +712,7 @@ export abstract class InstallInOtherServ
|
||||
@@ -591,7 +588,7 @@ export abstract class InstallInOtherServ
|
||||
}
|
||||
|
||||
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
||||
@@ -358,7 +367,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
}
|
||||
|
||||
// Prefers to run on UI
|
||||
@@ -1803,17 +1800,6 @@ export class SetLanguageAction extends E
|
||||
@@ -1683,17 +1680,6 @@ export class SetLanguageAction extends E
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
this.class = SetLanguageAction.DisabledClass;
|
||||
@@ -376,7 +385,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
@@ -1830,7 +1816,6 @@ export class ClearLanguageAction extends
|
||||
@@ -1710,7 +1696,6 @@ export class ClearLanguageAction extends
|
||||
private static readonly DisabledClass = `${ClearLanguageAction.EnabledClass} disabled`;
|
||||
|
||||
constructor(
|
||||
@@ -384,7 +393,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
@ILocaleService private readonly localeService: ILocaleService,
|
||||
) {
|
||||
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
||||
@@ -1840,17 +1825,6 @@ export class ClearLanguageAction extends
|
||||
@@ -1720,17 +1705,6 @@ export class ClearLanguageAction extends
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
this.class = ClearLanguageAction.DisabledClass;
|
||||
|
||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
import { OpenFolderAction, OpenFileFolderAction, OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
|
||||
import { Toggle } from 'vs/base/browser/ui/toggle/toggle';
|
||||
@@ -770,6 +770,72 @@ export class GettingStartedPage extends
|
||||
@@ -783,6 +783,72 @@ export class GettingStartedPage extends
|
||||
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
|
||||
);
|
||||
|
||||
@@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
const leftColumn = $('.categories-column.categories-column-left', {},);
|
||||
const rightColumn = $('.categories-column.categories-column-right', {},);
|
||||
|
||||
@@ -819,6 +885,9 @@ export class GettingStartedPage extends
|
||||
@@ -832,6 +898,9 @@ export class GettingStartedPage extends
|
||||
recentList.setLimit(5);
|
||||
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||
}
|
||||
@@ -181,7 +181,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -16,6 +16,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri
|
||||
'auth': { type: 'string' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
'locale': { type: 'string' },
|
||||
@@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -98,6 +99,7 @@ export interface ServerParsedArgs {
|
||||
@@ -101,6 +102,7 @@ export interface ServerParsedArgs {
|
||||
'auth'?: string
|
||||
'disable-file-downloads'?: boolean;
|
||||
'locale'?: string
|
||||
@@ -201,7 +201,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -328,6 +328,7 @@ export class WebClientServer {
|
||||
@@ -335,6 +335,7 @@ export class WebClientServer {
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
@@ -217,12 +217,12 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, IsEnabledCoderGettingStarted, ActiveEditorCanToggleReadonlyContext } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, IsEnabledCoderGettingStarted, ActiveEditorCanToggleReadonlyContext, applyAvailableEditorIds } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
@@ -212,6 +212,7 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -211,6 +211,7 @@ export class WorkbenchContextKeysHandler
|
||||
|
||||
// code-server
|
||||
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||
@@ -234,7 +234,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -36,6 +36,7 @@ export const HasWebFileSystemAccess = ne
|
||||
@@ -39,6 +39,7 @@ export const HasWebFileSystemAccess = ne
|
||||
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
|
||||
|
||||
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
Add the ability to provide a GitHub token
|
||||
|
||||
To test install the GitHub PR extension and start code-server with GITHUB_TOKEN
|
||||
or set github-auth in the config file. The extension should be authenticated.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
@@ -5,9 +5,18 @@
|
||||
|
||||
import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
-import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
+import { IServerEnvironmentService } from 'vs/server/node/serverEnvironmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService';
|
||||
+import { generateUuid } from 'vs/base/common/uuid';
|
||||
+import { equals as arrayEquals } from 'vs/base/common/arrays';
|
||||
+
|
||||
+interface IToken {
|
||||
+ accessToken: string
|
||||
+ account?: { label: string }
|
||||
+ id: string
|
||||
+ scopes: string[]
|
||||
+}
|
||||
|
||||
export class CredentialsWebMainService extends BaseCredentialsMainService {
|
||||
// Since we fallback to the in-memory credentials provider, we do not need to surface any Keytar load errors
|
||||
@@ -16,10 +25,15 @@ export class CredentialsWebMainService e
|
||||
|
||||
constructor(
|
||||
@ILogService logService: ILogService,
|
||||
- @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService,
|
||||
+ @IServerEnvironmentService private readonly environmentMainService: IServerEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
) {
|
||||
super(logService);
|
||||
+ if (this.environmentMainService.args["github-auth"]) {
|
||||
+ this.storeGitHubToken(this.environmentMainService.args["github-auth"]).catch((error) => {
|
||||
+ this.logService.error('Failed to store provided GitHub token', error)
|
||||
+ })
|
||||
+ }
|
||||
}
|
||||
|
||||
// If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the
|
||||
@@ -48,4 +62,59 @@ export class CredentialsWebMainService e
|
||||
}
|
||||
return this._keytarCache;
|
||||
}
|
||||
+
|
||||
+ private async storeGitHubToken(githubToken: string): Promise<void> {
|
||||
+ const extensionId = 'vscode.github-authentication';
|
||||
+ const service = `${await this.getSecretStoragePrefix()}${extensionId}`;
|
||||
+ const account = 'github.auth';
|
||||
+ const scopes = [['read:user', 'user:email', 'repo']]
|
||||
+
|
||||
+ // Oddly the scopes need to match exactly so we cannot just have one token
|
||||
+ // with all the scopes, instead we have to duplicate the token for each
|
||||
+ // expected set of scopes.
|
||||
+ const tokens: IToken[] = scopes.map((scopes) => ({
|
||||
+ id: generateUuid(),
|
||||
+ scopes: scopes.sort(), // Sort for comparing later.
|
||||
+ accessToken: githubToken,
|
||||
+ }));
|
||||
+
|
||||
+ const raw = await this.getPassword(service, account)
|
||||
+
|
||||
+ let existing: {
|
||||
+ content: IToken[]
|
||||
+ } | undefined;
|
||||
+
|
||||
+ if (raw) {
|
||||
+ try {
|
||||
+ const json = JSON.parse(raw);
|
||||
+ json.content = JSON.parse(json.content);
|
||||
+ existing = json;
|
||||
+ } catch (error) {
|
||||
+ this.logService.error('Failed to parse existing GitHub credentials', error)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Keep tokens for account and scope combinations we do not have in case
|
||||
+ // there is an extension that uses scopes we have not accounted for (in
|
||||
+ // these cases the user will need to manually authenticate the extension
|
||||
+ // through the UI) or the user has tokens for other accounts.
|
||||
+ if (existing?.content) {
|
||||
+ existing.content = existing.content.filter((existingToken) => {
|
||||
+ const scopes = existingToken.scopes.sort();
|
||||
+ return !(tokens.find((token) => {
|
||||
+ return arrayEquals(scopes, token.scopes)
|
||||
+ && token.account?.label === existingToken.account?.label;
|
||||
+ }))
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return this.setPassword(service, account, JSON.stringify({
|
||||
+ extensionId,
|
||||
+ ...(existing || {}),
|
||||
+ content: JSON.stringify([
|
||||
+ ...tokens,
|
||||
+ ...(existing?.content || []),
|
||||
+ ])
|
||||
+ }));
|
||||
+ }
|
||||
}
|
||||
@@ -176,15 +176,15 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -67,6 +67,7 @@ import { IndexedDB } from 'vs/base/brows
|
||||
import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService';
|
||||
@@ -65,6 +65,7 @@ import { mixin, safeStringify } from 'vs
|
||||
import { IndexedDB } from 'vs/base/browser/indexedDB';
|
||||
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
|
||||
+import { CodeServerClient } from 'vs/workbench/browser/client';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel';
|
||||
@@ -127,6 +128,9 @@ export class BrowserMain extends Disposa
|
||||
@@ -130,6 +131,9 @@ export class BrowserMain extends Disposa
|
||||
// Startup
|
||||
const instantiationService = workbench.startup();
|
||||
|
||||
@@ -264,7 +264,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -299,6 +299,7 @@ export class WebClientServer {
|
||||
@@ -306,6 +306,7 @@ export class WebClientServer {
|
||||
} : undefined;
|
||||
|
||||
const productConfiguration = <Partial<IProductConfiguration>>{
|
||||
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -320,6 +320,7 @@ export class WebClientServer {
|
||||
@@ -327,6 +327,7 @@ export class WebClientServer {
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -13,6 +13,7 @@ import { IEnvironmentService, INativeEnv
|
||||
@@ -15,6 +15,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -92,6 +93,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -95,6 +96,7 @@ export const serverOptions: OptionDescri
|
||||
export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -304,6 +304,7 @@ export class WebClientServer {
|
||||
@@ -311,6 +311,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
|
||||
@@ -12,7 +12,7 @@ in-between and has web extensions install directly from the marketplace.
|
||||
|
||||
This can be tested by setting EXTENSIONS_GALLERY set to:
|
||||
|
||||
'{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
'{"serviceUrl": "https://my-extensions/api"}'
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -111,7 +111,7 @@ export class WebClientServer {
|
||||
@@ -113,7 +113,7 @@ export class WebClientServer {
|
||||
const serverRootPath = getRemoteServerRootPath(_productService);
|
||||
this._staticRoute = `${serverRootPath}/static`;
|
||||
this._callbackRoute = `${serverRootPath}/callback`;
|
||||
@@ -49,7 +49,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,14 +304,7 @@ export class WebClientServer {
|
||||
@@ -311,14 +311,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
@@ -260,10 +260,7 @@ function extensionDescriptionArrayToMap(
|
||||
@@ -282,10 +282,7 @@ function extensionDescriptionArrayToMap(
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
|
||||
@@ -71,7 +71,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -305,6 +305,7 @@ export class WebClientServer {
|
||||
@@ -312,6 +312,7 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
@@ -83,7 +83,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalE
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
@@ -384,7 +384,7 @@ export async function createTerminalEnvi
|
||||
@@ -271,7 +271,7 @@ export async function createTerminalEnvi
|
||||
|
||||
// Sanitize the environment, removing any undesirable VS Code and Electron environment
|
||||
// variables
|
||||
@@ -96,20 +96,18 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -21,6 +21,7 @@ import type { ICredentialsProvider } fro
|
||||
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
|
||||
@@ -19,6 +19,7 @@ import { isFolderToOpen, isWorkspaceToOp
|
||||
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
|
||||
import { AuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
|
||||
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
|
||||
import { create } from 'vs/workbench/workbench.web.main';
|
||||
|
||||
interface ICredential {
|
||||
service: string;
|
||||
@@ -505,6 +506,39 @@ function doCreateUri(path: string, query
|
||||
@@ -571,6 +572,39 @@ class WorkspaceProvider implements IWork
|
||||
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
||||
workspaceProvider: WorkspaceProvider.create(config),
|
||||
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
||||
- credentialsProvider: config.remoteAuthority ? undefined /* with a remote, we don't use a local credentials provider */ : new LocalStorageCredentialsProvider()
|
||||
+ credentialsProvider: config.remoteAuthority ? undefined /* with a remote, we don't use a local credentials provider */ : new LocalStorageCredentialsProvider(),
|
||||
+ resolveExternalUri: (uri: URI): Promise<URI> => {
|
||||
+ let resolvedUri = uri
|
||||
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(resolvedUri)
|
||||
@@ -142,19 +140,20 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ }
|
||||
});
|
||||
})();
|
||||
+ },
|
||||
secretStorageProvider: config.remoteAuthority && !secretStorageKeyPath
|
||||
? undefined /* with a remote without embedder-preferred storage, store on the remote */
|
||||
: new LocalStorageSecretStorageProvider(secretStorageCrypto),
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
|
||||
@@ -76,7 +76,7 @@ export class ForwardedPortsView extends
|
||||
this.contextKeyListener = undefined;
|
||||
}
|
||||
|
||||
- const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
|
||||
+ const viewEnabled: boolean = true;
|
||||
|
||||
if (this.environmentService.remoteAuthority && viewEnabled) {
|
||||
if (viewEnabled) {
|
||||
const viewContainer = await this.getViewContainer();
|
||||
|
||||
82
patches/safari.diff
Normal file
82
patches/safari.diff
Normal file
@@ -0,0 +1,82 @@
|
||||
Revert back to es2020
|
||||
|
||||
es2022 outputs static blocks when using static properties that are not
|
||||
compatible with Safari, or at least not older versions of Safari.
|
||||
|
||||
Index: code-server/lib/vscode/src/tsconfig.base.json
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/tsconfig.base.json
|
||||
+++ code-server/lib/vscode/src/tsconfig.base.json
|
||||
@@ -17,9 +17,30 @@
|
||||
"./vs/*"
|
||||
]
|
||||
},
|
||||
- "target": "es2022",
|
||||
- "useDefineForClassFields": false,
|
||||
+ "target": "es2020",
|
||||
"lib": [
|
||||
+ "ES2016",
|
||||
+ "ES2017.Object",
|
||||
+ "ES2017.String",
|
||||
+ "ES2017.Intl",
|
||||
+ "ES2017.TypedArrays",
|
||||
+ "ES2018.AsyncIterable",
|
||||
+ "ES2018.AsyncGenerator",
|
||||
+ "ES2018.Promise",
|
||||
+ "ES2018.Regexp",
|
||||
+ "ES2018.Intl",
|
||||
+ "ES2019.Array",
|
||||
+ "ES2019.Object",
|
||||
+ "ES2019.String",
|
||||
+ "ES2019.Symbol",
|
||||
+ "ES2020.BigInt",
|
||||
+ "ES2020.Promise",
|
||||
+ "ES2020.String",
|
||||
+ "ES2020.Symbol.WellKnown",
|
||||
+ "ES2020.Intl",
|
||||
+ "ES2021.Promise",
|
||||
+ "ES2021.String",
|
||||
+ "ES2021.WeakRef",
|
||||
"ES2022",
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
Index: code-server/lib/vscode/build/lib/tsb/transpiler.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/tsb/transpiler.js
|
||||
+++ code-server/lib/vscode/build/lib/tsb/transpiler.js
|
||||
@@ -293,7 +293,7 @@ class SwcTranspiler {
|
||||
tsx: false,
|
||||
decorators: true
|
||||
},
|
||||
- target: 'es2022',
|
||||
+ target: 'es2020',
|
||||
loose: false,
|
||||
minify: {
|
||||
compress: false,
|
||||
Index: code-server/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
+++ code-server/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
@@ -376,7 +376,7 @@ export class SwcTranspiler implements IT
|
||||
tsx: false,
|
||||
decorators: true
|
||||
},
|
||||
- target: 'es2022',
|
||||
+ target: 'es2020',
|
||||
loose: false,
|
||||
minify: {
|
||||
compress: false,
|
||||
Index: code-server/lib/vscode/src/vs/base/common/tfIdf.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/tfIdf.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/tfIdf.ts
|
||||
@@ -88,8 +88,7 @@ export class TfIdfCalculator {
|
||||
for (const [word] of input.matchAll(/\b\p{Letter}[\p{Letter}\d]{2,}\b/gu)) {
|
||||
yield normalize(word);
|
||||
|
||||
- // eslint-disable-next-line local/code-no-look-behind-regex
|
||||
- const camelParts = word.split(/(?<=[a-z])(?=[A-Z])/g);
|
||||
+ const camelParts = word.split(/(?=[A-Z])/g);
|
||||
if (camelParts.length > 1) {
|
||||
for (const part of camelParts) {
|
||||
// Require at least 3 letters in the parts of a camel case word
|
||||
@@ -9,7 +9,6 @@ update-check.diff
|
||||
logout.diff
|
||||
store-socket.diff
|
||||
proxy-uri.diff
|
||||
github-auth.diff
|
||||
unique-db.diff
|
||||
local-storage.diff
|
||||
service-worker.diff
|
||||
@@ -19,3 +18,4 @@ telemetry.diff
|
||||
display-language.diff
|
||||
cli-window-open.diff
|
||||
getting-started.diff
|
||||
safari.diff
|
||||
|
||||
@@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -306,6 +306,10 @@ export class WebClientServer {
|
||||
@@ -313,6 +313,10 @@ export class WebClientServer {
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
||||
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
||||
@@ -199,8 +199,7 @@ function packageTask(type, platform, arc
|
||||
@@ -238,8 +238,7 @@ function packageTask(type, platform, arc
|
||||
|
||||
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||
const isUIExtension = (manifest) => {
|
||||
@@ -239,9 +238,9 @@ function packageTask(type, platform, arc
|
||||
@@ -278,9 +277,9 @@ function packageTask(type, platform, arc
|
||||
.map(name => `.build/extensions/${name}/**`);
|
||||
|
||||
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
||||
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
let version = packageJson.version;
|
||||
const quality = product.quality;
|
||||
@@ -387,7 +386,7 @@ function tweakProductForServerWeb(produc
|
||||
@@ -427,7 +426,7 @@ function tweakProductForServerWeb(produc
|
||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||
optimizeTask,
|
||||
util.rimraf(`out-vscode-${type}-min`),
|
||||
|
||||
@@ -15,18 +15,16 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
@@ -2,7 +2,9 @@
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
-
|
||||
+import * as os from 'os';
|
||||
+import * as _http from 'http';
|
||||
+import * as path from 'vs/base/common/path';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
|
||||
@@ -17,6 +19,7 @@ import { ExtensionRuntime } from 'vs/wor
|
||||
@@ -17,6 +17,7 @@ import { ExtensionRuntime } from 'vs/wor
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
import { realpathSync } from 'vs/base/node/extpath';
|
||||
import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder';
|
||||
@@ -34,13 +32,14 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
||||
import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider';
|
||||
|
||||
class NodeModuleRequireInterceptor extends RequireInterceptor {
|
||||
@@ -83,6 +86,52 @@ export class ExtHostExtensionService ext
|
||||
@@ -83,6 +84,52 @@ export class ExtHostExtensionService ext
|
||||
await interceptor.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
+ (async () => {
|
||||
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
|
||||
+ if (!socketPath) {
|
||||
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
|
||||
+ if (!socketPath || !codeServerSocketPath) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const workspace = this._instaService.invokeFunction((accessor) => {
|
||||
@@ -52,7 +51,6 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
||||
+ socketPath
|
||||
+ };
|
||||
+ const message = JSON.stringify({entry});
|
||||
+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock');
|
||||
+ await new Promise<void>((resolve, reject) => {
|
||||
+ const opts: _http.RequestOptions = {
|
||||
+ path: '/add-session',
|
||||
@@ -91,17 +89,15 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
@@ -3,6 +3,9 @@
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
+import * as os from 'os';
|
||||
+import * as _http from 'http';
|
||||
+import * as path from 'vs/base/common/path';
|
||||
import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as net from 'net';
|
||||
import * as minimist from 'minimist';
|
||||
@@ -400,7 +403,28 @@ async function startExtensionHostProcess
|
||||
@@ -400,7 +401,28 @@ async function startExtensionHostProcess
|
||||
);
|
||||
|
||||
// rewrite onTerminate-function to be a proper shutdown
|
||||
@@ -110,11 +106,11 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
+ extensionHostMain.terminate(reason);
|
||||
+
|
||||
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
|
||||
+ if (!socketPath) {
|
||||
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
|
||||
+ if (!socketPath || !codeServerSocketPath) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const message = JSON.stringify({socketPath});
|
||||
+ const codeServerSocketPath = path.join(os.tmpdir(), 'code-server-ipc.sock');
|
||||
+ const opts: _http.RequestOptions = {
|
||||
+ path: '/delete-session',
|
||||
+ socketPath: codeServerSocketPath,
|
||||
|
||||
@@ -12,30 +12,26 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -69,6 +69,7 @@ import { IExtensionsScannerService } fro
|
||||
@@ -65,6 +65,7 @@ import { IExtensionsScannerService } fro
|
||||
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
|
||||
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
|
||||
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
+import { TelemetryClient } from "vs/server/node/telemetryClient";
|
||||
+import { TelemetryClient } from 'vs/server/node/telemetryClient';
|
||||
import { NullPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
@@ -151,10 +152,13 @@ export async function setupServerService
|
||||
@@ -148,7 +149,10 @@ export async function setupServerService
|
||||
let oneDsAppender: ITelemetryAppender = NullAppender;
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
- if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
- if (!isLoggingOnly(productService, environmentService) && productService.aiConfig?.ariaKey) {
|
||||
+ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track";
|
||||
+ if (telemetryEndpoint) {
|
||||
+ oneDsAppender = new OneDataSystemAppender(false, eventPrefix, null, () => new TelemetryClient(telemetryEndpoint));
|
||||
+ } else if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
oneDsAppender = new OneDataSystemAppender(isInternal, eventPrefix, null, productService.aiConfig.ariaKey);
|
||||
- disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
+ oneDsAppender = new OneDataSystemAppender(requestService, false, eventPrefix, null, () => new TelemetryClient(telemetryEndpoint));
|
||||
+ } else if (!isLoggingOnly(productService, environmentService) && productService.aiConfig?.ariaKey) {
|
||||
oneDsAppender = new OneDataSystemAppender(requestService, isInternal, eventPrefix, null, productService.aiConfig.ariaKey);
|
||||
disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
}
|
||||
+ disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appenders: [oneDsAppender],
|
||||
Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
@@ -94,7 +90,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -310,6 +310,7 @@ export class WebClientServer {
|
||||
@@ -317,6 +317,7 @@ export class WebClientServer {
|
||||
scope: vscodeBase + '/',
|
||||
path: base + '/_static/out/browser/serviceWorker.js',
|
||||
},
|
||||
|
||||
@@ -105,7 +105,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -303,6 +303,7 @@ export class WebClientServer {
|
||||
@@ -310,6 +310,7 @@ export class WebClientServer {
|
||||
const productConfiguration = <Partial<IProductConfiguration>>{
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
@@ -117,8 +117,8 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -11,6 +11,8 @@ import { refineServiceDecorator } from '
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
@@ -13,6 +13,8 @@ import { memoize } from 'vs/base/common/
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
+ /* ----- code-server ----- */
|
||||
@@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -88,6 +90,8 @@ export const serverOptions: OptionDescri
|
||||
@@ -91,6 +93,8 @@ export const serverOptions: OptionDescri
|
||||
};
|
||||
|
||||
export interface ServerParsedArgs {
|
||||
|
||||
@@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -316,6 +316,7 @@ export class WebClientServer {
|
||||
@@ -323,6 +323,7 @@ export class WebClientServer {
|
||||
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
@@ -70,12 +70,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
- content="default-src 'none'; script-src 'sha256-N4YFn5ze5crjPqMK/opogKs7bSGWtf3lmjV/3LfbSOs=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
+ content="default-src 'none'; script-src 'sha256-B5FRTRmagxqZ2yiS/ip5EgFZJPHAF0G0O3NgwgN6hhg=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
- content="default-src 'none'; script-src 'sha256-QA1gXilHYAUFCvp7MpjgcmyBCFzSKV0SpiecMU8aUVc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
+ content="default-src 'none'; script-src 'sha256-5X5RiKYn8NTJVx919WStPrAmsV80rIIBbePhKquPcAQ=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
@@ -334,6 +334,12 @@
|
||||
@@ -335,6 +335,12 @@
|
||||
|
||||
const hostname = location.hostname;
|
||||
|
||||
@@ -92,7 +92,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
||||
@@ -333,6 +333,12 @@
|
||||
@@ -334,6 +334,12 @@
|
||||
|
||||
const hostname = location.hostname;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
@@ -46,7 +46,9 @@ button {
|
||||
.card-box {
|
||||
background-color: rgb(250, 253, 258);
|
||||
border-radius: 5px;
|
||||
box-shadow: rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px, rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
||||
box-shadow:
|
||||
rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px,
|
||||
rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
||||
max-width: 650px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
@@ -14,7 +14,11 @@ export enum HttpCode {
|
||||
* used in the HTTP response.
|
||||
*/
|
||||
export class HttpError extends Error {
|
||||
public constructor(message: string, public readonly statusCode: HttpCode, public readonly details?: object) {
|
||||
public constructor(
|
||||
message: string,
|
||||
public readonly statusCode: HttpCode,
|
||||
public readonly details?: object,
|
||||
) {
|
||||
super(message)
|
||||
this.name = this.constructor.name
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as util from "../common/util"
|
||||
import { DefaultedArgs } from "./cli"
|
||||
import { disposer } from "./http"
|
||||
import { isNodeJSErrnoException } from "./util"
|
||||
import { DEFAULT_SOCKET_PATH, EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket"
|
||||
import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket"
|
||||
import { handleUpgrade } from "./wsRouter"
|
||||
|
||||
type SocketOptions = { socket: string; "socket-mode"?: string }
|
||||
@@ -88,7 +88,7 @@ export const createApp = async (args: DefaultedArgs): Promise<App> => {
|
||||
handleUpgrade(wsRouter, server)
|
||||
|
||||
const editorSessionManager = new EditorSessionManager()
|
||||
const editorSessionManagerServer = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, editorSessionManager)
|
||||
const editorSessionManagerServer = await makeEditorSessionManagerServer(args["session-socket"], editorSessionManager)
|
||||
const disposeEditorSessionManagerServer = disposer(editorSessionManagerServer)
|
||||
|
||||
const dispose = async () => {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { field, Level, logger } from "@coder/logger"
|
||||
import { promises as fs } from "fs"
|
||||
import { load } from "js-yaml"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { generateCertificate, generatePassword, humanPath, paths, splitOnFirstEquals } from "./util"
|
||||
import { DEFAULT_SOCKET_PATH, EditorSessionManagerClient } from "./vscodeSocket"
|
||||
import { generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
|
||||
import { EditorSessionManagerClient } from "./vscodeSocket"
|
||||
|
||||
export enum Feature {
|
||||
// No current experimental features!
|
||||
@@ -51,6 +50,8 @@ export interface UserProvidedCodeArgs {
|
||||
"disable-file-downloads"?: boolean
|
||||
"disable-workspace-trust"?: boolean
|
||||
"disable-getting-started-override"?: boolean
|
||||
"disable-proxy"?: boolean
|
||||
"session-socket"?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,6 +79,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
"bind-addr"?: string
|
||||
socket?: string
|
||||
"socket-mode"?: string
|
||||
"trusted-origins"?: string[]
|
||||
version?: boolean
|
||||
"proxy-domain"?: string[]
|
||||
"reuse-window"?: boolean
|
||||
@@ -160,6 +162,9 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
|
||||
"then notifies you once every week that a new release is available.",
|
||||
},
|
||||
"session-socket": {
|
||||
type: "string",
|
||||
},
|
||||
"disable-file-downloads": {
|
||||
type: "boolean",
|
||||
description:
|
||||
@@ -173,6 +178,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
type: "boolean",
|
||||
description: "Disable the coder/coder override in the Help: Getting Started page.",
|
||||
},
|
||||
"disable-proxy": {
|
||||
type: "boolean",
|
||||
description: "Disable domain and path proxy routes.",
|
||||
},
|
||||
// --enable can be used to enable experimental features. These features
|
||||
// provide no guarantees.
|
||||
enable: { type: "string[]" },
|
||||
@@ -204,6 +213,11 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
|
||||
socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
|
||||
"socket-mode": { type: "string", description: "File mode of the socket." },
|
||||
"trusted-origins": {
|
||||
type: "string[]",
|
||||
description:
|
||||
"Disables authenticate origin check for trusted origin. Useful if not able to access reverse proxy configuration.",
|
||||
},
|
||||
version: { type: "boolean", short: "v", description: "Display version information." },
|
||||
_: { type: "string[]" },
|
||||
|
||||
@@ -459,6 +473,7 @@ export interface DefaultedArgs extends ConfigArgs {
|
||||
usingEnvHashedPassword: boolean
|
||||
"extensions-dir": string
|
||||
"user-data-dir": string
|
||||
"session-socket": string
|
||||
/* Positional arguments. */
|
||||
_: string[]
|
||||
}
|
||||
@@ -479,6 +494,11 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args["extensions-dir"] = path.join(args["user-data-dir"], "extensions")
|
||||
}
|
||||
|
||||
if (!args["session-socket"]) {
|
||||
args["session-socket"] = path.join(args["user-data-dir"], "code-server-ipc.sock")
|
||||
}
|
||||
process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"]
|
||||
|
||||
// --verbose takes priority over --log and --log takes priority over the
|
||||
// environment variable.
|
||||
if (args.verbose) {
|
||||
@@ -548,6 +568,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args["disable-getting-started-override"] = true
|
||||
}
|
||||
|
||||
if (process.env.CS_DISABLE_PROXY?.match(/^(1|true)$/)) {
|
||||
args["disable-proxy"] = true
|
||||
}
|
||||
|
||||
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
|
||||
if (process.env.HASHED_PASSWORD) {
|
||||
args["hashed-password"] = process.env.HASHED_PASSWORD
|
||||
@@ -638,7 +662,7 @@ export async function readConfigFile(configPath?: string): Promise<ConfigArgs> {
|
||||
await fs.writeFile(configPath, defaultConfigFile(generatedPassword), {
|
||||
flag: "wx", // wx means to fail if the path exists.
|
||||
})
|
||||
logger.info(`Wrote default config file to ${humanPath(os.homedir(), configPath)}`)
|
||||
logger.info(`Wrote default config file to ${configPath}`)
|
||||
} catch (error: any) {
|
||||
// EEXIST is fine; we don't want to overwrite existing configurations.
|
||||
if (error.code !== "EEXIST") {
|
||||
@@ -708,6 +732,9 @@ export function bindAddrFromArgs(addr: Addr, args: UserProvidedArgs): Addr {
|
||||
if (args["bind-addr"]) {
|
||||
addr = parseBindAddr(args["bind-addr"])
|
||||
}
|
||||
if (process.env.CODE_SERVER_HOST) {
|
||||
addr.host = process.env.CODE_SERVER_HOST
|
||||
}
|
||||
if (args.host) {
|
||||
addr.host = args.host
|
||||
}
|
||||
@@ -739,7 +766,10 @@ function bindAddrFromAllSources(...argsConfig: UserProvidedArgs[]): Addr {
|
||||
* existing instance. The arguments here should be the arguments the user
|
||||
* explicitly passed on the command line, *NOT DEFAULTS* or the configuration.
|
||||
*/
|
||||
export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Promise<string | undefined> => {
|
||||
export const shouldOpenInExistingInstance = async (
|
||||
args: UserProvidedArgs,
|
||||
sessionSocket: string,
|
||||
): Promise<string | undefined> => {
|
||||
// Always use the existing instance if we're running from VS Code's terminal.
|
||||
if (process.env.VSCODE_IPC_HOOK_CLI) {
|
||||
logger.debug("Found VSCODE_IPC_HOOK_CLI")
|
||||
@@ -747,21 +777,22 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom
|
||||
}
|
||||
|
||||
const paths = getResolvedPathsFromArgs(args)
|
||||
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
|
||||
|
||||
// If we can't connect to the socket then there's no existing instance.
|
||||
if (!(await client.canConnect())) {
|
||||
return undefined
|
||||
}
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
|
||||
// If these flags are set then assume the user is trying to open in an
|
||||
// existing instance since these flags have no effect otherwise.
|
||||
// existing instance since these flags have no effect otherwise. That means
|
||||
// if there is no existing instance we should error rather than falling back
|
||||
// to spawning code-server normally.
|
||||
const openInFlagCount = ["reuse-window", "new-window"].reduce((prev, cur) => {
|
||||
return args[cur as keyof UserProvidedArgs] ? prev + 1 : prev
|
||||
}, 0)
|
||||
if (openInFlagCount > 0) {
|
||||
logger.debug("Found --reuse-window or --new-window")
|
||||
return await client.getConnectedSocketPath(paths[0])
|
||||
const socketPath = await client.getConnectedSocketPath(paths[0])
|
||||
if (!socketPath) {
|
||||
throw new Error(`No opened code-server instances found to handle ${paths[0]}`)
|
||||
}
|
||||
return socketPath
|
||||
}
|
||||
|
||||
// It's possible the user is trying to spawn another instance of code-server.
|
||||
@@ -769,7 +800,11 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom
|
||||
// code-server is invoked exactly like this: `code-server my-file`).
|
||||
// 2. That a file or directory was passed.
|
||||
// 3. That the socket is active.
|
||||
// 4. That an instance exists to handle the path (implied by #3).
|
||||
if (Object.keys(args).length === 1 && typeof args._ !== "undefined" && args._.length > 0) {
|
||||
if (!(await client.canConnect())) {
|
||||
return undefined
|
||||
}
|
||||
const socketPath = await client.getConnectedSocketPath(paths[0])
|
||||
if (socketPath) {
|
||||
logger.debug("Found existing code-server socket")
|
||||
|
||||
@@ -51,7 +51,7 @@ async function entry(): Promise<void> {
|
||||
return runCodeCli(args)
|
||||
}
|
||||
|
||||
const socketPath = await shouldOpenInExistingInstance(cliArgs)
|
||||
const socketPath = await shouldOpenInExistingInstance(cliArgs, args["session-socket"])
|
||||
if (socketPath) {
|
||||
logger.debug("Trying to open in existing instance")
|
||||
return openInExistingInstance(args, socketPath)
|
||||
|
||||
@@ -9,7 +9,10 @@ export class Heart {
|
||||
private heartbeatInterval = 60000
|
||||
public lastHeartbeat = 0
|
||||
|
||||
public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {
|
||||
public constructor(
|
||||
private readonly heartbeatPath: string,
|
||||
private readonly isActive: () => Promise<boolean>,
|
||||
) {
|
||||
this.beat = this.beat.bind(this)
|
||||
this.alive = this.alive.bind(this)
|
||||
}
|
||||
|
||||
@@ -75,6 +75,25 @@ export const replaceTemplates = <T extends object>(
|
||||
.replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if proxy is not enabled. Call `next` if provided.
|
||||
*/
|
||||
export const ensureProxyEnabled = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
|
||||
if (!proxyEnabled(req)) {
|
||||
throw new HttpError("Forbidden", HttpCode.Forbidden)
|
||||
}
|
||||
if (next) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if proxy is enabled.
|
||||
*/
|
||||
export const proxyEnabled = (req: express.Request): boolean => {
|
||||
return !req.args["disable-proxy"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if not authorized. Call `next` if provided.
|
||||
*/
|
||||
@@ -355,6 +374,11 @@ export function authenticateOrigin(req: express.Request): void {
|
||||
throw new Error(`unable to parse malformed origin "${originRaw}"`)
|
||||
}
|
||||
|
||||
const trustedOrigins = req.args["trusted-origins"] || []
|
||||
if (trustedOrigins.includes(origin) || trustedOrigins.includes("*")) {
|
||||
return
|
||||
}
|
||||
|
||||
const host = getHost(req)
|
||||
if (typeof host === "undefined") {
|
||||
// A missing host likely means the reverse proxy has not been configured to
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import i18next, { init } from "i18next"
|
||||
import * as en from "./locales/en.json"
|
||||
import * as zhCn from "./locales/zh-cn.json"
|
||||
import * as ja from "./locales/ja.json"
|
||||
import * as th from "./locales/th.json"
|
||||
import * as ur from "./locales/ur.json"
|
||||
import * as zhCn from "./locales/zh-cn.json"
|
||||
|
||||
init({
|
||||
lng: "en",
|
||||
fallbackLng: "en", // language to use if translations in user language are not available.
|
||||
@@ -18,6 +21,12 @@ init({
|
||||
th: {
|
||||
translation: th,
|
||||
},
|
||||
ja: {
|
||||
translation: ja,
|
||||
},
|
||||
ur: {
|
||||
translation: ur,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
13
src/node/i18n/locales/ja.json
Normal file
13
src/node/i18n/locales/ja.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"LOGIN_TITLE": "{{app}} ログイン",
|
||||
"LOGIN_BELOW": "以下によりログインしてください。",
|
||||
"WELCOME": "ようこそ {{app}} へ!",
|
||||
"LOGIN_PASSWORD": "パスワードは設定ファイル( {{configFile}} )を確認してください。",
|
||||
"LOGIN_USING_ENV_PASSWORD": "パスワードは環境変数 $PASSWORD で設定されています。",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "パスワードは環境変数 $HASHED_PASSWORD で設定されています。",
|
||||
"SUBMIT": "実行",
|
||||
"PASSWORD_PLACEHOLDER": "パスワード",
|
||||
"LOGIN_RATE_LIMIT": "ログイン制限を超えました!",
|
||||
"MISS_PASSWORD": "パスワードを入力してください。",
|
||||
"INCORRECT_PASSWORD": "パスワードが間違っています。"
|
||||
}
|
||||
13
src/node/i18n/locales/ur.json
Normal file
13
src/node/i18n/locales/ur.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"LOGIN_TITLE": "{{app}} لاگ ان کریں",
|
||||
"LOGIN_BELOW": "براہ کرم نیچے لاگ ان کریں۔",
|
||||
"WELCOME": "میں خوش آمدید {{app}}",
|
||||
"LOGIN_PASSWORD": "پاس ورڈ کے لیے {{configFile}} پر کنفگ فائل چیک کریں۔",
|
||||
"LOGIN_USING_ENV_PASSWORD": "پاس ورڈ $PASSWORD سے سیٹ کیا گیا تھا۔",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "پاس ورڈ $HASHED_PASSWORD سے سیٹ کیا گیا تھا۔",
|
||||
"SUBMIT": "جمع کرائیں",
|
||||
"PASSWORD_PLACEHOLDER": "پاس ورڈ",
|
||||
"LOGIN_RATE_LIMIT": "لاگ ان کی شرح محدود!",
|
||||
"MISS_PASSWORD": "پاس ورڈ غائب ہے۔",
|
||||
"INCORRECT_PASSWORD": "غلط پاس ورڈ"
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
import { field, logger } from "@coder/logger"
|
||||
import http from "http"
|
||||
import * as os from "os"
|
||||
import { Disposable } from "../common/emitter"
|
||||
import { plural } from "../common/util"
|
||||
import { createApp, ensureAddress } from "./app"
|
||||
import { AuthType, DefaultedArgs, Feature, SpawnCodeCli, toCodeArgs, UserProvidedArgs } from "./cli"
|
||||
import { commit, version } from "./constants"
|
||||
import { register } from "./routes"
|
||||
import { humanPath, isDirectory, loadAMDModule, open } from "./util"
|
||||
import { isDirectory, loadAMDModule, open } from "./util"
|
||||
|
||||
/**
|
||||
* Return true if the user passed an extension-related VS Code flag.
|
||||
@@ -109,8 +108,8 @@ export const runCodeServer = async (
|
||||
): Promise<{ dispose: Disposable["dispose"]; server: http.Server }> => {
|
||||
logger.info(`code-server ${version} ${commit}`)
|
||||
|
||||
logger.info(`Using user-data-dir ${humanPath(os.homedir(), args["user-data-dir"])}`)
|
||||
logger.trace(`Using extensions-dir ${humanPath(os.homedir(), args["extensions-dir"])}`)
|
||||
logger.info(`Using user-data-dir ${args["user-data-dir"]}`)
|
||||
logger.trace(`Using extensions-dir ${args["extensions-dir"]}`)
|
||||
|
||||
if (args.auth === AuthType.Password && !args.password && !args["hashed-password"]) {
|
||||
throw new Error(
|
||||
@@ -121,13 +120,10 @@ export const runCodeServer = async (
|
||||
const app = await createApp(args)
|
||||
const protocol = args.cert ? "https" : "http"
|
||||
const serverAddress = ensureAddress(app.server, protocol)
|
||||
const sessionServerAddress = app.editorSessionManagerServer.address()
|
||||
const disposeRoutes = await register(app, args)
|
||||
|
||||
logger.info(`Using config file ${humanPath(os.homedir(), args.config)}`)
|
||||
logger.info(`Using config file ${args.config}`)
|
||||
logger.info(`${protocol.toUpperCase()} server listening on ${serverAddress.toString()}`)
|
||||
logger.info(`Session server listening on ${sessionServerAddress?.toString()}`)
|
||||
|
||||
if (args.auth === AuthType.Password) {
|
||||
logger.info(" - Authentication is enabled")
|
||||
if (args.usingEnvPassword) {
|
||||
@@ -135,19 +131,21 @@ export const runCodeServer = async (
|
||||
} else if (args.usingEnvHashedPassword) {
|
||||
logger.info(" - Using password from $HASHED_PASSWORD")
|
||||
} else {
|
||||
logger.info(` - Using password from ${humanPath(os.homedir(), args.config)}`)
|
||||
logger.info(` - Using password from ${args.config}`)
|
||||
}
|
||||
} else {
|
||||
logger.info(" - Authentication is disabled")
|
||||
}
|
||||
|
||||
if (args.cert) {
|
||||
logger.info(` - Using certificate for HTTPS: ${humanPath(os.homedir(), args.cert.value)}`)
|
||||
logger.info(` - Using certificate for HTTPS: ${args.cert.value}`)
|
||||
} else {
|
||||
logger.info(" - Not serving HTTPS")
|
||||
}
|
||||
|
||||
if (args["proxy-domain"].length > 0) {
|
||||
if (args["disable-proxy"]) {
|
||||
logger.info(" - Proxy disabled")
|
||||
} else if (args["proxy-domain"].length > 0) {
|
||||
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
|
||||
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
|
||||
}
|
||||
@@ -155,6 +153,11 @@ export const runCodeServer = async (
|
||||
logger.info(`Using proxy URI in PORTS tab: ${process.env.VSCODE_PROXY_URI}`)
|
||||
}
|
||||
|
||||
const sessionServerAddress = app.editorSessionManagerServer.address()
|
||||
if (sessionServerAddress) {
|
||||
logger.info(`Session server listening on ${sessionServerAddress.toString()}`)
|
||||
}
|
||||
|
||||
if (args.enable && args.enable.length > 0) {
|
||||
logger.info("Enabling the following experimental features:")
|
||||
args.enable.forEach((feature) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Router } from "express"
|
||||
import { HttpCode, HttpError } from "../../common/http"
|
||||
import { getHost, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||
import { getHost, ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||
import { proxy } from "../proxy"
|
||||
import { Router as WsRouter } from "../wsRouter"
|
||||
|
||||
@@ -59,6 +59,8 @@ router.all("*", async (req, res, next) => {
|
||||
return next()
|
||||
}
|
||||
|
||||
ensureProxyEnabled(req)
|
||||
|
||||
// Must be authenticated to use the proxy.
|
||||
const isAuthenticated = await authenticated(req)
|
||||
if (!isAuthenticated) {
|
||||
@@ -100,6 +102,8 @@ wsRouter.ws("*", async (req, _, next) => {
|
||||
if (!port) {
|
||||
return next()
|
||||
}
|
||||
|
||||
ensureProxyEnabled(req)
|
||||
ensureOrigin(req)
|
||||
await ensureAuthenticated(req)
|
||||
proxy.ws(req, req.ws, req.head, {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Router, Request } from "express"
|
||||
import { promises as fs } from "fs"
|
||||
import { RateLimiter as Limiter } from "limiter"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { CookieKeys } from "../../common/http"
|
||||
import { rootPath } from "../constants"
|
||||
import { authenticated, getCookieOptions, redirect, replaceTemplates } from "../http"
|
||||
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString, escapeHtml } from "../util"
|
||||
import i18n from "../i18n"
|
||||
import { getPasswordMethod, handlePasswordValidation, sanitizeString, escapeHtml } from "../util"
|
||||
|
||||
// RateLimiter wraps around the limiter library for logins.
|
||||
// It allows 2 logins every minute plus 12 logins every hour.
|
||||
@@ -33,7 +32,7 @@ const getRoot = async (req: Request, error?: Error): Promise<string> => {
|
||||
i18n.changeLanguage(locale)
|
||||
const appName = req.args["app-name"] || "code-server"
|
||||
const welcomeText = req.args["welcome-text"] || (i18n.t("WELCOME", { app: appName }) as string)
|
||||
let passwordMsg = i18n.t("LOGIN_PASSWORD", { configFile: humanPath(os.homedir(), req.args.config) })
|
||||
let passwordMsg = i18n.t("LOGIN_PASSWORD", { configFile: req.args.config })
|
||||
if (req.args.usingEnvPassword) {
|
||||
passwordMsg = i18n.t("LOGIN_USING_ENV_PASSWORD")
|
||||
} else if (req.args.usingEnvHashedPassword) {
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as path from "path"
|
||||
import * as qs from "qs"
|
||||
import * as pluginapi from "../../../typings/pluginapi"
|
||||
import { HttpCode, HttpError } from "../../common/http"
|
||||
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||
import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||
import { proxy as _proxy } from "../proxy"
|
||||
|
||||
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
||||
@@ -21,6 +21,8 @@ export async function proxy(
|
||||
passthroughPath?: boolean
|
||||
},
|
||||
): Promise<void> {
|
||||
ensureProxyEnabled(req)
|
||||
|
||||
if (!(await authenticated(req))) {
|
||||
// If visiting the root (/:port only) redirect to the login page.
|
||||
if (!req.params[0] || req.params[0] === "/") {
|
||||
@@ -50,6 +52,7 @@ export async function wsProxy(
|
||||
passthroughPath?: boolean
|
||||
},
|
||||
): Promise<void> {
|
||||
ensureProxyEnabled(req)
|
||||
ensureOrigin(req)
|
||||
await ensureAuthenticated(req)
|
||||
_proxy.ws(req, req.ws, req.head, {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import * as crypto from "crypto"
|
||||
import * as express from "express"
|
||||
import { promises as fs } from "fs"
|
||||
import * as http from "http"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
@@ -32,6 +34,7 @@ export class CodeServerRouteWrapper {
|
||||
private _wsRouterWrapper = WsRouter()
|
||||
private _socketProxyProvider = new SocketProxyProvider()
|
||||
public router = express.Router()
|
||||
private mintKeyPromise: Promise<Buffer> | undefined
|
||||
|
||||
public get wsRouter() {
|
||||
return this._wsRouterWrapper.router
|
||||
@@ -52,6 +55,7 @@ export class CodeServerRouteWrapper {
|
||||
short_name: appName,
|
||||
start_url: ".",
|
||||
display: "fullscreen",
|
||||
display_override: ["window-controls-overlay"],
|
||||
description: "Run Code on a remote server.",
|
||||
icons: [192, 512].map((size) => ({
|
||||
src: `{{BASE}}/_static/src/browser/media/pwa-icon-${size}.png`,
|
||||
@@ -66,6 +70,33 @@ export class CodeServerRouteWrapper {
|
||||
)
|
||||
}
|
||||
|
||||
private mintKey: express.Handler = async (req, res, next) => {
|
||||
if (!this.mintKeyPromise) {
|
||||
this.mintKeyPromise = new Promise(async (resolve) => {
|
||||
const keyPath = path.join(req.args["user-data-dir"], "serve-web-key-half")
|
||||
logger.debug(`Reading server web key half from ${keyPath}`)
|
||||
try {
|
||||
resolve(await fs.readFile(keyPath))
|
||||
return
|
||||
} catch (error: any) {
|
||||
if (error.code !== "ENOENT") {
|
||||
logError(logger, `read ${keyPath}`, error)
|
||||
}
|
||||
}
|
||||
// VS Code wants 256 bits.
|
||||
const key = crypto.randomBytes(32)
|
||||
try {
|
||||
await fs.writeFile(keyPath, key)
|
||||
} catch (error: any) {
|
||||
logError(logger, `write ${keyPath}`, error)
|
||||
}
|
||||
resolve(key)
|
||||
})
|
||||
}
|
||||
const key = await this.mintKeyPromise
|
||||
res.end(key)
|
||||
}
|
||||
|
||||
private $root: express.Handler = async (req, res, next) => {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
const NO_FOLDER_OR_WORKSPACE_QUERY = !req.query.folder && !req.query.workspace
|
||||
@@ -173,6 +204,7 @@ export class CodeServerRouteWrapper {
|
||||
constructor() {
|
||||
this.router.get("/", this.ensureCodeServerLoaded, this.$root)
|
||||
this.router.get("/manifest.json", this.manifest)
|
||||
this.router.post("/mint-key", this.mintKey)
|
||||
this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
|
||||
this._wsRouterWrapper.ws("*", ensureOrigin, ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
|
||||
}
|
||||
|
||||
@@ -87,20 +87,6 @@ export function getEnvPaths(platform = process.platform): Paths {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* humanPath replaces the home directory in path with ~.
|
||||
* Makes it more readable.
|
||||
*
|
||||
* @param homedir - the home directory(i.e. `os.homedir()`)
|
||||
* @param path - a file path
|
||||
*/
|
||||
export function humanPath(homedir: string, path?: string): string {
|
||||
if (!path) {
|
||||
return ""
|
||||
}
|
||||
return path.replace(homedir, "~")
|
||||
}
|
||||
|
||||
export const generateCertificate = async (hostname: string): Promise<{ cert: string; certKey: string }> => {
|
||||
const certPath = path.join(paths.data, `${hostname.replace(/\./g, "_")}.crt`)
|
||||
const certKeyPath = path.join(paths.data, `${hostname.replace(/\./g, "_")}.key`)
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import express from "express"
|
||||
import * as http from "http"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { HttpCode } from "../common/http"
|
||||
import { listen } from "./app"
|
||||
import { canConnect } from "./util"
|
||||
|
||||
// Socket path of the daemonized code-server instance.
|
||||
export const DEFAULT_SOCKET_PATH = path.join(os.tmpdir(), "code-server-ipc.sock")
|
||||
|
||||
export interface EditorSessionEntry {
|
||||
workspace: {
|
||||
id: string
|
||||
@@ -78,7 +74,11 @@ export async function makeEditorSessionManagerServer(
|
||||
})
|
||||
|
||||
const server = http.createServer(router)
|
||||
await listen(server, { socket: codeServerSocketPath })
|
||||
try {
|
||||
await listen(server, { socket: codeServerSocketPath })
|
||||
} catch (e) {
|
||||
logger.warn(`Could not create socket at ${codeServerSocketPath}`)
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,10 @@ type ChildMessage = RelaunchMessage | ChildHandshakeMessage
|
||||
type ParentMessage = ParentHandshakeMessage
|
||||
|
||||
class ProcessError extends Error {
|
||||
public constructor(message: string, public readonly code: number | undefined) {
|
||||
public constructor(
|
||||
message: string,
|
||||
public readonly code: number | undefined,
|
||||
) {
|
||||
super(message)
|
||||
this.name = this.constructor.name
|
||||
Error.captureStackTrace(this, this.constructor)
|
||||
|
||||
@@ -117,40 +117,26 @@ export class CodeServer {
|
||||
* directories.
|
||||
*/
|
||||
private async spawn(): Promise<CodeServerProcess> {
|
||||
// This will be used both as the workspace and data directory to ensure
|
||||
// instances don't bleed into each other.
|
||||
const dir = await this.createWorkspace()
|
||||
|
||||
const args = await this.argsWithDefaults([
|
||||
"--auth",
|
||||
"none",
|
||||
// The workspace to open.
|
||||
...(this.args.includes("--ignore-last-opened") ? [] : [dir]),
|
||||
...this.args,
|
||||
// Using port zero will spawn on a random port.
|
||||
"--bind-addr",
|
||||
"127.0.0.1:0",
|
||||
])
|
||||
return new Promise((resolve, reject) => {
|
||||
const args = [
|
||||
this.entry,
|
||||
"--extensions-dir",
|
||||
path.join(dir, "extensions"),
|
||||
"--auth",
|
||||
"none",
|
||||
// The workspace to open.
|
||||
...(this.args.includes("--ignore-last-opened") ? [] : [dir]),
|
||||
...this.args,
|
||||
// Using port zero will spawn on a random port.
|
||||
"--bind-addr",
|
||||
"127.0.0.1:0",
|
||||
// Setting the XDG variables would be easier and more thorough but the
|
||||
// modules we import ignores those variables for non-Linux operating
|
||||
// systems so use these flags instead.
|
||||
"--config",
|
||||
path.join(dir, "config.yaml"),
|
||||
"--user-data-dir",
|
||||
dir,
|
||||
]
|
||||
this.logger.debug("spawning `node " + args.join(" ") + "`")
|
||||
const proc = cp.spawn("node", args, {
|
||||
cwd: path.join(__dirname, "../../.."),
|
||||
env: {
|
||||
...process.env,
|
||||
...this.env,
|
||||
// Set to empty string to prevent code-server from
|
||||
// using the existing instance when running the e2e tests
|
||||
// from an integrated terminal.
|
||||
// Prevent code-server from using the existing instance when running
|
||||
// the e2e tests from an integrated terminal.
|
||||
VSCODE_IPC_HOOK_CLI: "",
|
||||
PASSWORD,
|
||||
},
|
||||
@@ -173,11 +159,15 @@ export class CodeServer {
|
||||
reject(error)
|
||||
})
|
||||
|
||||
// Tracks when the HTTP and session servers are ready.
|
||||
let httpAddress: string | undefined
|
||||
let sessionAddress: string | undefined
|
||||
|
||||
let resolved = false
|
||||
proc.stdout.setEncoding("utf8")
|
||||
onLine(proc, (line) => {
|
||||
// As long as we are actively getting input reset the timer. If we stop
|
||||
// getting input and still have not found the address the timer will
|
||||
// getting input and still have not found the addresses the timer will
|
||||
// reject.
|
||||
timer.reset()
|
||||
|
||||
@@ -186,20 +176,69 @@ export class CodeServer {
|
||||
if (resolved) {
|
||||
return
|
||||
}
|
||||
const match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/)
|
||||
|
||||
let match = line.trim().match(/HTTPS? server listening on (https?:\/\/[.:\d]+)\/?$/)
|
||||
if (match) {
|
||||
// Cookies don't seem to work on IP address so swap to localhost.
|
||||
// Cookies don't seem to work on IP addresses so swap to localhost.
|
||||
// TODO: Investigate whether this is a bug with code-server.
|
||||
const address = match[1].replace("127.0.0.1", "localhost")
|
||||
this.logger.debug(`spawned on ${address}`)
|
||||
httpAddress = match[1].replace("127.0.0.1", "localhost")
|
||||
}
|
||||
|
||||
match = line.trim().match(/Session server listening on (.+)$/)
|
||||
if (match) {
|
||||
sessionAddress = match[1]
|
||||
}
|
||||
|
||||
if (typeof httpAddress !== "undefined" && typeof sessionAddress !== "undefined") {
|
||||
resolved = true
|
||||
timer.dispose()
|
||||
resolve({ process: proc, address })
|
||||
this.logger.debug(`code-server is ready: ${httpAddress} ${sessionAddress}`)
|
||||
resolve({ process: proc, address: httpAddress })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a short-lived command.
|
||||
*/
|
||||
async run(args: string[]): Promise<void> {
|
||||
args = await this.argsWithDefaults(args)
|
||||
this.logger.debug("executing `node " + args.join(" ") + "`")
|
||||
await util.promisify(cp.exec)("node " + args.join(" "), {
|
||||
cwd: path.join(__dirname, "../../.."),
|
||||
env: {
|
||||
...process.env,
|
||||
...this.env,
|
||||
// Prevent code-server from using the existing instance when running
|
||||
// the e2e tests from an integrated terminal.
|
||||
VSCODE_IPC_HOOK_CLI: "",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine arguments with defaults.
|
||||
*/
|
||||
private async argsWithDefaults(args: string[]): Promise<string[]> {
|
||||
// This will be used both as the workspace and data directory to ensure
|
||||
// instances don't bleed into each other.
|
||||
const dir = await this.workspaceDir
|
||||
return [
|
||||
this.entry,
|
||||
"--extensions-dir",
|
||||
path.join(dir, "extensions"),
|
||||
...args,
|
||||
// Setting the XDG variables would be easier and more thorough but the
|
||||
// modules we import ignores those variables for non-Linux operating
|
||||
// systems so use these flags instead.
|
||||
"--config",
|
||||
path.join(dir, "config.yaml"),
|
||||
"--user-data-dir",
|
||||
dir,
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the code-server process.
|
||||
*/
|
||||
@@ -230,7 +269,10 @@ export class CodeServer {
|
||||
export class CodeServerPage {
|
||||
private readonly editorSelector = "div.monaco-workbench"
|
||||
|
||||
constructor(private readonly codeServer: CodeServer, public readonly page: Page) {
|
||||
constructor(
|
||||
private readonly codeServer: CodeServer,
|
||||
public readonly page: Page,
|
||||
) {
|
||||
this.page.on("console", (message) => {
|
||||
this.codeServer.logger.debug(message.text())
|
||||
})
|
||||
@@ -364,6 +406,13 @@ export class CodeServerPage {
|
||||
await this.waitForTab(file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a file through an external command.
|
||||
*/
|
||||
async openFileExternally(file: string) {
|
||||
await this.codeServer.run(["--reuse-window", file])
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a tab to open for the specified file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, test, expect } from "./baseFixture"
|
||||
import { clean, getMaybeProxiedPathname } from "../utils/helpers"
|
||||
import { describe, test, expect } from "./baseFixture"
|
||||
|
||||
const routes = ["/", "/vscode", "/vscode/"]
|
||||
|
||||
@@ -103,7 +103,7 @@ describe("VS Code Routes with no workspace or folder", ["--disable-workspace-tru
|
||||
|
||||
// Closing the folder should stop the redirecting.
|
||||
await codeServerPage.navigate("/?ew=true")
|
||||
let url = new URL(codeServerPage.page.url())
|
||||
const url = new URL(codeServerPage.page.url())
|
||||
const pathname = getMaybeProxiedPathname(url)
|
||||
expect(pathname).toBe("/")
|
||||
expect(url.search).toBe("?ew=true")
|
||||
|
||||
@@ -35,13 +35,19 @@ describe("Integrated Terminal", ["--disable-workspace-trust"], {}, () => {
|
||||
const tmpFolderPath = await tmpdir(testName)
|
||||
const tmpFile = path.join(tmpFolderPath, "test-file")
|
||||
await fs.writeFile(tmpFile, "test")
|
||||
const fileName = path.basename(tmpFile)
|
||||
|
||||
await codeServerPage.focusTerminal()
|
||||
|
||||
await codeServerPage.page.keyboard.type(`code-server ${tmpFile}`)
|
||||
await codeServerPage.page.keyboard.press("Enter")
|
||||
|
||||
await codeServerPage.waitForTab(fileName)
|
||||
await codeServerPage.waitForTab(path.basename(tmpFile))
|
||||
|
||||
const externalTmpFile = path.join(tmpFolderPath, "test-external-file")
|
||||
await fs.writeFile(externalTmpFile, "foobar")
|
||||
|
||||
await codeServerPage.openFileExternally(externalTmpFile)
|
||||
|
||||
await codeServerPage.waitForTab(path.basename(externalTmpFile))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("createApp", () => {
|
||||
app.dispose()
|
||||
}
|
||||
|
||||
expect(() => masterBall()).rejects.toThrow(`listen EACCES: permission denied 127.0.0.1:${port}`)
|
||||
expect(() => masterBall()).rejects.toThrow("listen EACCES: permission denied")
|
||||
})
|
||||
|
||||
it("should unlink a socket before listening on the socket", async () => {
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import { shouldSpawnCliProcess } from "../../../src/node/main"
|
||||
import { generatePassword, paths } from "../../../src/node/util"
|
||||
import {
|
||||
DEFAULT_SOCKET_PATH,
|
||||
EditorSessionManager,
|
||||
EditorSessionManagerClient,
|
||||
makeEditorSessionManagerServer,
|
||||
@@ -37,6 +36,7 @@ const defaults = {
|
||||
usingEnvHashedPassword: false,
|
||||
"extensions-dir": path.join(paths.data, "extensions"),
|
||||
"user-data-dir": paths.data,
|
||||
"session-socket": path.join(paths.data, "code-server-ipc.sock"),
|
||||
_: [],
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ describe("parser", () => {
|
||||
delete process.env.CS_DISABLE_FILE_DOWNLOADS
|
||||
delete process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE
|
||||
delete process.env.VSCODE_PROXY_URI
|
||||
delete process.env.CS_DISABLE_PROXY
|
||||
console.log = jest.fn()
|
||||
})
|
||||
|
||||
@@ -103,6 +104,10 @@ describe("parser", () => {
|
||||
|
||||
"--disable-getting-started-override",
|
||||
|
||||
"--disable-proxy",
|
||||
|
||||
["--session-socket", "/tmp/override-code-server-ipc-socket"],
|
||||
|
||||
["--host", "0.0.0.0"],
|
||||
"4",
|
||||
"--",
|
||||
@@ -121,6 +126,7 @@ describe("parser", () => {
|
||||
},
|
||||
"disable-file-downloads": true,
|
||||
"disable-getting-started-override": true,
|
||||
"disable-proxy": true,
|
||||
enable: ["feature1", "feature2"],
|
||||
help: true,
|
||||
host: "0.0.0.0",
|
||||
@@ -136,6 +142,7 @@ describe("parser", () => {
|
||||
"welcome-text": "welcome to code",
|
||||
version: true,
|
||||
"bind-addr": "192.169.0.1:8080",
|
||||
"session-socket": "/tmp/override-code-server-ipc-socket",
|
||||
})
|
||||
})
|
||||
|
||||
@@ -389,6 +396,30 @@ describe("parser", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("should use env var CS_DISABLE_PROXY", async () => {
|
||||
process.env.CS_DISABLE_PROXY = "1"
|
||||
const args = parse([])
|
||||
expect(args).toEqual({})
|
||||
|
||||
const defaultArgs = await setDefaults(args)
|
||||
expect(defaultArgs).toEqual({
|
||||
...defaults,
|
||||
"disable-proxy": true,
|
||||
})
|
||||
})
|
||||
|
||||
it("should use env var CS_DISABLE_PROXY set to true", async () => {
|
||||
process.env.CS_DISABLE_PROXY = "true"
|
||||
const args = parse([])
|
||||
expect(args).toEqual({})
|
||||
|
||||
const defaultArgs = await setDefaults(args)
|
||||
expect(defaultArgs).toEqual({
|
||||
...defaults,
|
||||
"disable-proxy": true,
|
||||
})
|
||||
})
|
||||
|
||||
it("should error if password passed in", () => {
|
||||
expect(() => parse(["--password", "supersecret123"])).toThrowError(
|
||||
"--password can only be set in the config file or passed in via $PASSWORD",
|
||||
@@ -504,22 +535,23 @@ describe("cli", () => {
|
||||
it("should use existing if inside code-server", async () => {
|
||||
process.env.VSCODE_IPC_HOOK_CLI = "test"
|
||||
const args: UserProvidedArgs = {}
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test")
|
||||
expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test")
|
||||
|
||||
args.port = 8081
|
||||
args._ = ["./file"]
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual("test")
|
||||
expect(await shouldOpenInExistingInstance(args, "")).toStrictEqual("test")
|
||||
})
|
||||
|
||||
it("should use existing if --reuse-window is set", async () => {
|
||||
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
|
||||
const sessionSocket = path.join(tmpDirPath, "session-socket")
|
||||
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
|
||||
|
||||
const args: UserProvidedArgs = {}
|
||||
args["reuse-window"] = true
|
||||
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined)
|
||||
await expect(shouldOpenInExistingInstance(args, sessionSocket)).rejects.toThrow()
|
||||
|
||||
const socketPath = path.join(tmpDirPath, "socket")
|
||||
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
await client.addSession({
|
||||
entry: {
|
||||
workspace: {
|
||||
@@ -537,24 +569,25 @@ describe("cli", () => {
|
||||
})
|
||||
const vscodeSockets = listenOn(socketPath)
|
||||
|
||||
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath)
|
||||
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath)
|
||||
|
||||
args.port = 8081
|
||||
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(socketPath)
|
||||
await expect(shouldOpenInExistingInstance(args, sessionSocket)).resolves.toStrictEqual(socketPath)
|
||||
|
||||
server.close()
|
||||
vscodeSockets.close()
|
||||
})
|
||||
|
||||
it("should use existing if --new-window is set", async () => {
|
||||
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
|
||||
const sessionSocket = path.join(tmpDirPath, "session-socket")
|
||||
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
|
||||
|
||||
const args: UserProvidedArgs = {}
|
||||
args["new-window"] = true
|
||||
await expect(shouldOpenInExistingInstance(args)).resolves.toStrictEqual(undefined)
|
||||
await expect(shouldOpenInExistingInstance(args, sessionSocket)).rejects.toThrow()
|
||||
|
||||
const socketPath = path.join(tmpDirPath, "socket")
|
||||
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
await client.addSession({
|
||||
entry: {
|
||||
workspace: {
|
||||
@@ -572,25 +605,26 @@ describe("cli", () => {
|
||||
})
|
||||
const vscodeSockets = listenOn(socketPath)
|
||||
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
|
||||
|
||||
args.port = 8081
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
|
||||
|
||||
server.close()
|
||||
vscodeSockets.close()
|
||||
})
|
||||
|
||||
it("should use existing if no unrelated flags are set, has positional, and socket is active", async () => {
|
||||
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
|
||||
const sessionSocket = path.join(tmpDirPath, "session-socket")
|
||||
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
|
||||
|
||||
const args: UserProvidedArgs = {}
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
|
||||
|
||||
args._ = ["./file"]
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
|
||||
|
||||
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
const socketPath = path.join(tmpDirPath, "socket")
|
||||
await client.addSession({
|
||||
entry: {
|
||||
@@ -609,18 +643,19 @@ describe("cli", () => {
|
||||
})
|
||||
const vscodeSockets = listenOn(socketPath)
|
||||
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(socketPath)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(socketPath)
|
||||
|
||||
args.port = 8081
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(undefined)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(undefined)
|
||||
|
||||
server.close()
|
||||
vscodeSockets.close()
|
||||
})
|
||||
|
||||
it("should prefer matching sessions for only the first path", async () => {
|
||||
const server = await makeEditorSessionManagerServer(DEFAULT_SOCKET_PATH, new EditorSessionManager())
|
||||
const client = new EditorSessionManagerClient(DEFAULT_SOCKET_PATH)
|
||||
const sessionSocket = path.join(tmpDirPath, "session-socket")
|
||||
const server = await makeEditorSessionManagerServer(sessionSocket, new EditorSessionManager())
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
await client.addSession({
|
||||
entry: {
|
||||
workspace: {
|
||||
@@ -655,7 +690,7 @@ describe("cli", () => {
|
||||
|
||||
const args: UserProvidedArgs = {}
|
||||
args._ = ["/aaa/file", "/bbb/file"]
|
||||
expect(await shouldOpenInExistingInstance(args)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.sock`)
|
||||
expect(await shouldOpenInExistingInstance(args, sessionSocket)).toStrictEqual(`${tmpDirPath}/vscode-ipc-aaa.sock`)
|
||||
|
||||
server.close()
|
||||
})
|
||||
@@ -754,6 +789,50 @@ describe("bindAddrFromArgs", () => {
|
||||
expect(actual).toStrictEqual(expected)
|
||||
})
|
||||
|
||||
it("should use process.env.CODE_SERVER_HOST if set", () => {
|
||||
const [setValue, resetValue] = useEnv("CODE_SERVER_HOST")
|
||||
setValue("coder")
|
||||
|
||||
const args: UserProvidedArgs = {}
|
||||
|
||||
const addr = {
|
||||
host: "localhost",
|
||||
port: 8080,
|
||||
}
|
||||
|
||||
const actual = bindAddrFromArgs(addr, args)
|
||||
const expected = {
|
||||
host: "coder",
|
||||
port: 8080,
|
||||
}
|
||||
|
||||
expect(actual).toStrictEqual(expected)
|
||||
resetValue()
|
||||
})
|
||||
|
||||
it("should use the args.host over process.env.CODE_SERVER_HOST if both set", () => {
|
||||
const [setValue, resetValue] = useEnv("CODE_SERVER_HOST")
|
||||
setValue("coder")
|
||||
|
||||
const args: UserProvidedArgs = {
|
||||
host: "123.123.123.123",
|
||||
}
|
||||
|
||||
const addr = {
|
||||
host: "localhost",
|
||||
port: 8080,
|
||||
}
|
||||
|
||||
const actual = bindAddrFromArgs(addr, args)
|
||||
const expected = {
|
||||
host: "123.123.123.123",
|
||||
port: 8080,
|
||||
}
|
||||
|
||||
expect(actual).toStrictEqual(expected)
|
||||
resetValue()
|
||||
})
|
||||
|
||||
it("should use process.env.PORT if set", () => {
|
||||
const [setValue, resetValue] = useEnv("PORT")
|
||||
setValue("8000")
|
||||
|
||||
@@ -70,6 +70,7 @@ describe("http", () => {
|
||||
origin: test.origin,
|
||||
[key]: value,
|
||||
},
|
||||
args: {},
|
||||
})
|
||||
if (typeof test.expected === "string") {
|
||||
expect(() => http.authenticateOrigin(req)).toThrow(test.expected)
|
||||
|
||||
@@ -43,6 +43,7 @@ describe("plugin", () => {
|
||||
usingEnvHashedPassword: false,
|
||||
"extensions-dir": "",
|
||||
"user-data-dir": "",
|
||||
"session-socket": "",
|
||||
}
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as bodyParser from "body-parser"
|
||||
import * as express from "express"
|
||||
import * as http from "http"
|
||||
import nodeFetch from "node-fetch"
|
||||
@@ -45,6 +44,17 @@ describe("proxy", () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should return 403 Forbidden if proxy is disabled", async () => {
|
||||
e.get("/wsup", (req, res) => {
|
||||
res.json("you cannot see this")
|
||||
})
|
||||
codeServer = await integration.setup(["--auth=none", "--disable-proxy"], "")
|
||||
const resp = await codeServer.fetch(proxyPath)
|
||||
expect(resp.status).toBe(403)
|
||||
const json = await resp.json()
|
||||
expect(json).toEqual({ error: "Forbidden" })
|
||||
})
|
||||
|
||||
it("should rewrite the base path", async () => {
|
||||
e.get("/wsup", (req, res) => {
|
||||
res.json("asher is the best")
|
||||
@@ -99,7 +109,7 @@ describe("proxy", () => {
|
||||
})
|
||||
|
||||
it("should allow post bodies", async () => {
|
||||
e.use(bodyParser.json({ strict: false }))
|
||||
e.use(express.json({ strict: false }))
|
||||
e.post("/wsup", (req, res) => {
|
||||
res.json(req.body)
|
||||
})
|
||||
@@ -116,7 +126,7 @@ describe("proxy", () => {
|
||||
})
|
||||
|
||||
it("should handle bad requests", async () => {
|
||||
e.use(bodyParser.json({ strict: false }))
|
||||
e.use(express.json({ strict: false }))
|
||||
e.post("/wsup", (req, res) => {
|
||||
res.json(req.body)
|
||||
})
|
||||
@@ -143,7 +153,7 @@ describe("proxy", () => {
|
||||
})
|
||||
|
||||
it("should handle errors", async () => {
|
||||
e.use(bodyParser.json({ strict: false }))
|
||||
e.use(express.json({ strict: false }))
|
||||
e.post("/wsup", (req, res) => {
|
||||
throw new Error("BROKEN")
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { mockLogger } from "../../../utils/helpers"
|
||||
import * as httpserver from "../../../utils/httpserver"
|
||||
import * as integration from "../../../utils/integration"
|
||||
import { mockLogger } from "../../../utils/helpers"
|
||||
|
||||
describe("vscode", () => {
|
||||
let codeServer: httpserver.HttpServer | undefined
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import * as http from "http"
|
||||
import { AddressInfo } from "net"
|
||||
import * as path from "path"
|
||||
import { ensureAddress } from "../../../src/node/app"
|
||||
import { SettingsProvider, UpdateSettings } from "../../../src/node/settings"
|
||||
import { LatestResponse, UpdateProvider } from "../../../src/node/update"
|
||||
import { clean, isAddressInfo, mockLogger, tmpdir } from "../../utils/helpers"
|
||||
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
|
||||
|
||||
describe("update", () => {
|
||||
let version = "1.0.0"
|
||||
@@ -79,7 +79,6 @@ describe("update", () => {
|
||||
}
|
||||
|
||||
let _provider: UpdateProvider | undefined
|
||||
let _address: string | AddressInfo | null
|
||||
const provider = (): UpdateProvider => {
|
||||
if (!_provider) {
|
||||
throw new Error("Update provider has not been created")
|
||||
@@ -87,6 +86,7 @@ describe("update", () => {
|
||||
return _provider
|
||||
}
|
||||
|
||||
let address = new URL("http://localhost")
|
||||
beforeAll(async () => {
|
||||
mockLogger()
|
||||
|
||||
@@ -105,12 +105,13 @@ describe("update", () => {
|
||||
})
|
||||
})
|
||||
|
||||
_address = server.address()
|
||||
if (!isAddressInfo(_address)) {
|
||||
throw new Error("unexpected address")
|
||||
const addr = ensureAddress(server, "http")
|
||||
if (typeof addr === "string") {
|
||||
throw new Error("unable to run update tests with unix sockets")
|
||||
}
|
||||
|
||||
_provider = new UpdateProvider(`http://${_address?.address}:${_address?.port}/latest`, _settings)
|
||||
address = addr
|
||||
address.pathname = "/latest"
|
||||
_provider = new UpdateProvider(address.toString(), _settings)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
@@ -220,59 +221,51 @@ describe("update", () => {
|
||||
})
|
||||
|
||||
it("should reject if response has status code 500", async () => {
|
||||
if (isAddressInfo(_address)) {
|
||||
const mockURL = `http://${_address.address}:${_address.port}/reject-status-code`
|
||||
const provider = new UpdateProvider(mockURL, settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
address.pathname = "/reject-status-code"
|
||||
const provider = new UpdateProvider(address.toString(), settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `${mockURL}: 500`,
|
||||
})
|
||||
}
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `${address.toString()}: 500`,
|
||||
})
|
||||
})
|
||||
|
||||
it("should reject if no location header provided", async () => {
|
||||
if (isAddressInfo(_address)) {
|
||||
const mockURL = `http://${_address.address}:${_address.port}/no-location-header`
|
||||
const provider = new UpdateProvider(mockURL, settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
address.pathname = "/no-location-header"
|
||||
const provider = new UpdateProvider(address.toString(), settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `received redirect with no location header`,
|
||||
})
|
||||
}
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `received redirect with no location header`,
|
||||
})
|
||||
})
|
||||
|
||||
it("should resolve the request with response.headers.location", async () => {
|
||||
version = "4.1.1"
|
||||
if (isAddressInfo(_address)) {
|
||||
const mockURL = `http://${_address.address}:${_address.port}/with-location-header`
|
||||
const provider = new UpdateProvider(mockURL, settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
address.pathname = "/with-location-header"
|
||||
const provider = new UpdateProvider(address.toString(), settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
|
||||
expect(logger.error).not.toHaveBeenCalled()
|
||||
expect(update.version).toBe("4.1.1")
|
||||
}
|
||||
expect(logger.error).not.toHaveBeenCalled()
|
||||
expect(update.version).toBe("4.1.1")
|
||||
})
|
||||
|
||||
it("should reject if more than 10 redirects", async () => {
|
||||
if (isAddressInfo(_address)) {
|
||||
const mockURL = `http://${_address.address}:${_address.port}/redirect/11`
|
||||
const provider = new UpdateProvider(mockURL, settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
address.pathname = "/redirect/11"
|
||||
const provider = new UpdateProvider(address.toString(), settings())
|
||||
const update = await provider.getUpdate(true)
|
||||
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `reached max redirects`,
|
||||
})
|
||||
}
|
||||
expect(update.version).toBe("unknown")
|
||||
expect(logger.error).toHaveBeenCalled()
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to get latest version", {
|
||||
identifier: "error",
|
||||
value: `reached max redirects`,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -491,22 +491,6 @@ describe("isDirectory", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("humanPath", () => {
|
||||
it("should return an empty string if no path provided", () => {
|
||||
const mockHomedir = "/home/coder"
|
||||
const actual = util.humanPath(mockHomedir)
|
||||
const expected = ""
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
it("should replace the homedir with ~", () => {
|
||||
const mockHomedir = "/home/coder"
|
||||
const path = `${mockHomedir}/code-server`
|
||||
const actual = util.humanPath(mockHomedir, path)
|
||||
const expected = "~/code-server"
|
||||
expect(actual).toBe(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe("isWsl", () => {
|
||||
const testName = "wsl"
|
||||
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
import { EditorSessionManager } from "../../../src/node/vscodeSocket"
|
||||
import { clean, tmpdir, listenOn } from "../../utils/helpers"
|
||||
import { logger } from "@coder/logger"
|
||||
import * as app from "../../../src/node/app"
|
||||
import { EditorSessionManager, makeEditorSessionManagerServer } from "../../../src/node/vscodeSocket"
|
||||
import { clean, tmpdir, listenOn, mockLogger } from "../../utils/helpers"
|
||||
|
||||
describe("makeEditorSessionManagerServer", () => {
|
||||
let tmpDirPath: string
|
||||
|
||||
const testName = "mesms"
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
mockLogger()
|
||||
await clean(testName)
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDirPath = await tmpdir(testName)
|
||||
})
|
||||
|
||||
it("warns if socket cannot be created", async () => {
|
||||
jest.spyOn(app, "listen").mockImplementation(() => {
|
||||
throw new Error()
|
||||
})
|
||||
const server = await makeEditorSessionManagerServer(
|
||||
`${tmpDirPath}/code-server-ipc.sock`,
|
||||
new EditorSessionManager(),
|
||||
)
|
||||
expect(logger.warn).toHaveBeenCalledWith(`Could not create socket at ${tmpDirPath}/code-server-ipc.sock`)
|
||||
server.close()
|
||||
})
|
||||
})
|
||||
|
||||
describe("EditorSessionManager", () => {
|
||||
let tmpDirPath: string
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { promises as fs } from "fs"
|
||||
import * as path from "path"
|
||||
import { workspaceDir } from "./constants"
|
||||
import { clean, tmpdir } from "./helpers"
|
||||
import * as wtfnode from "./wtfnode"
|
||||
import * as path from "path"
|
||||
import { promises as fs } from "fs"
|
||||
|
||||
/**
|
||||
* Perform workspace cleanup and authenticate. This should be ran before e2e
|
||||
|
||||
@@ -108,20 +108,6 @@ export function idleTimer(message: string, reject: (error: Error) => void, delay
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function which returns a boolean indicating whether
|
||||
* the given address is AddressInfo and has .address
|
||||
* and a .port property.
|
||||
*/
|
||||
export function isAddressInfo(address: unknown): address is net.AddressInfo {
|
||||
return (
|
||||
address !== null &&
|
||||
typeof address !== "string" &&
|
||||
(address as net.AddressInfo).port !== undefined &&
|
||||
(address as net.AddressInfo).address !== undefined
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* If using a proxy, return the address of the proxy.
|
||||
*
|
||||
|
||||
@@ -35,7 +35,7 @@ export class HttpServer {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.hs.on("error", reject)
|
||||
|
||||
this.hs.listen(0, "localhost", () => {
|
||||
this.hs.listen(0, "127.0.0.1", () => {
|
||||
this.hs.off("error", reject)
|
||||
resolve()
|
||||
|
||||
|
||||
@@ -2856,6 +2856,11 @@ qs@^6.10.1:
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
querystringify@^2.1.1:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
|
||||
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
|
||||
|
||||
react-is@^17.0.1:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
@@ -2875,6 +2880,11 @@ require-directory@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
|
||||
|
||||
requires-port@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
|
||||
|
||||
resolve-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||
@@ -2936,16 +2946,16 @@ saxes@^5.0.1:
|
||||
xmlchars "^2.2.0"
|
||||
|
||||
semver@7.x, semver@^7.3.2, semver@^7.3.5:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^6.0.0, semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -3222,13 +3232,14 @@ to-regex-range@^5.0.1:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tough-cookie@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
|
||||
integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
|
||||
integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
|
||||
dependencies:
|
||||
psl "^1.1.33"
|
||||
punycode "^2.1.1"
|
||||
universalify "^0.1.2"
|
||||
universalify "^0.2.0"
|
||||
url-parse "^1.5.3"
|
||||
|
||||
tr46@^2.1.0:
|
||||
version "2.1.0"
|
||||
@@ -3280,10 +3291,18 @@ typedarray-to-buffer@^3.1.5:
|
||||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
universalify@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
|
||||
universalify@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
|
||||
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
|
||||
|
||||
url-parse@^1.5.3:
|
||||
version "1.5.10"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
|
||||
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
|
||||
dependencies:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
@@ -3379,9 +3398,9 @@ wide-align@^1.1.2:
|
||||
string-width "^1.0.2 || 2 || 3 || 4"
|
||||
|
||||
word-wrap@~1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
|
||||
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
|
||||
Reference in New Issue
Block a user