Compare commits

..

1 Commits

Author SHA1 Message Date
Nick Vigilante
299e566813 docs: fix 7 broken relative links in CONTRIBUTING.md
Relative paths like ../test/unit resolve correctly on GitHub but produce
404s when the page is rendered at coder.com/docs/code-server/CONTRIBUTING.
Replace all 7 with absolute github.com/coder/code-server/tree/main/... URLs.

Closes https://linear.app/codercom/issue/DOCS-244

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 19:00:17 -04:00
71 changed files with 798 additions and 1324 deletions

View File

@@ -6,8 +6,6 @@ updates:
interval: "monthly"
time: "06:00"
timezone: "America/Chicago"
cooldown:
default-days: 7
labels: []
commit-message:
prefix: "chore"
@@ -18,8 +16,8 @@ updates:
interval: "monthly"
time: "06:00"
timezone: "America/Chicago"
cooldown:
default-days: 7
commit-message:
prefix: "chore"
labels: []
ignore:
# Ignore patch updates for all dependencies

View File

@@ -21,13 +21,12 @@ jobs:
outputs:
ci: ${{ steps.filter.outputs.ci }}
code: ${{ steps.filter.outputs.code }}
npm: ${{ steps.filter.outputs.npm }}
vscode: ${{ steps.filter.outputs.vscode }}
deps: ${{ steps.filter.outputs.deps }}
docs: ${{ steps.filter.outputs.docs }}
helm: ${{ steps.filter.outputs.helm }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
id: filter
with:
filters: |
@@ -43,12 +42,11 @@ jobs:
code:
- "src/**"
- "test/**"
npm:
- "package-lock.json"
- "test/package-lock.json"
vscode:
deps:
- "lib/**"
- "patches/**"
- "package-lock.json"
- "test/package-lock.json"
- id: debug
run: |
echo "${{ toJSON(steps.filter )}}"
@@ -57,8 +55,8 @@ jobs:
name: Run prettier check
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -74,8 +72,8 @@ jobs:
needs: changes
if: needs.changes.outputs.docs == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -91,11 +89,13 @@ jobs:
needs: changes
if: needs.changes.outputs.helm == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: bmuschko/setup-kubeconform@e5d264ec1eafe2314e750c429a9da7639dd5a003 # v1.1.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with:
kubeconform-version: "0.8.0"
- run: kubeconform ci/helm-chart
token: ${{ secrets.GITHUB_TOKEN }}
version: "v3.19.2"
- run: helm plugin install https://github.com/instrumenta/helm-kubeval
- run: helm kubeval ci/helm-chart
lint-ts:
name: Lint TypeScript files
@@ -103,8 +103,8 @@ jobs:
needs: changes
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -121,7 +121,7 @@ jobs:
if: needs.changes.outputs.ci == 'true'
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
@@ -132,10 +132,10 @@ jobs:
name: Run unit tests
runs-on: ubuntu-22.04
needs: changes
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -144,7 +144,7 @@ jobs:
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run test:unit
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
- uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
if: success()
with:
token: ${{ secrets.CODECOV_TOKEN }}
@@ -163,16 +163,16 @@ jobs:
steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
- uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with:
packages: quilt
version: 1.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -191,7 +191,7 @@ jobs:
# embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
- name: Fetch prebuilt linux-x64 Code package from cache
id: cache-vscode
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: lib/vscode-reh-web-linux-x64
key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
@@ -216,11 +216,11 @@ jobs:
env:
LOG_LEVEL: debug
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -252,11 +252,11 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LOG_LEVEL: debug
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true'
steps:
- name: Cache Caddy
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
id: caddy-cache
with:
path: |
@@ -269,8 +269,8 @@ jobs:
mkdir -p ~/.cache/caddy
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm

View File

@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install code-server
run: ./install.sh
@@ -44,7 +44,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install curl
run: apk add curl
@@ -67,7 +67,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install code-server
run: ./install.sh

View File

@@ -33,8 +33,8 @@ jobs:
run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
@@ -64,7 +64,7 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Checkout code-server-aur repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
repository: "cdrci/code-server-aur"
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
@@ -93,9 +93,9 @@ jobs:
run: |
git checkout -b update-version-${{ env.VERSION }}
git add .
git commit -m "Update to ${{ env.VERSION }}"
git commit -m "chore: updating version to ${{ env.VERSION }}"
git push -u origin $(git branch --show)
gh pr create --repo coder/code-server-aur --title "Update to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
docker:
runs-on: ubuntu-latest
@@ -108,15 +108,15 @@ jobs:
run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
@@ -149,7 +149,7 @@ jobs:
run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: ./ci/build/update-repo.sh
@@ -159,9 +159,9 @@ jobs:
git config --global user.email opensource@coder.com
git checkout -b "helm/$VERSION"
git add .
git commit -m "Update Helm chart and changelog with $VERSION"
git commit -m "Update to $VERSION"
git push -u origin "$(git branch --show)"
gh pr create \
--repo coder/code-server \
--body-file .cache/checklist \
--title "Update Helm chart and changelog with $VERSION"
--title "Update to $VERSION"

View File

@@ -39,6 +39,9 @@ jobs:
- npm_arch: arm64
vscode_arch: arm64
package_arch: arm64
- npm_arch: arm
vscode_arch: armhf
package_arch: armv7l
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -59,7 +62,7 @@ jobs:
steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
- uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with:
packages: quilt
version: 1.0
@@ -69,18 +72,16 @@ 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: Strip update/ and v from tag and set major version
- name: Strip update/ and v from tag
run: |
version=${TAG#update/}
version=${version#v}
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
echo "VERSION=${version#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -110,7 +111,7 @@ jobs:
- run: |
sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes
if: ${{ matrix.vscode_arch == 'x64' }}
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
if: ${{ matrix.vscode_arch == 'x64' }}
with:
draft: true
@@ -123,7 +124,7 @@ jobs:
# Platform-specific release.
- run: KEEP_MODULES=1 npm run release
- run: npm run package
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with:
draft: true
discussion_category_name: "📣 Announcements"
@@ -147,7 +148,7 @@ jobs:
env:
VSCODE_TARGET: ${{ matrix.vscode_target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
TAG: ${{ inputs.version || github.ref_name }}
# Ensure native modules are built from source to avoid prebuilds.
npm_config_build_from_source: true
@@ -163,18 +164,16 @@ 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: Strip update/ and v from tag and set major version
- name: Strip update/ and v from tag
run: |
version=${TAG#update/}
version=${version#v}
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
echo "VERSION=${version#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
cache: npm
@@ -189,7 +188,7 @@ jobs:
- run: npm run test:native
- run: npm run package
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with:
draft: true
discussion_category_name: "📣 Announcements"

View File

@@ -41,7 +41,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install test utilities
run: apk add bats checkbashisms
@@ -58,7 +58,7 @@ jobs:
timeout-minutes: 5
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Install lint utilities
run: sudo apt install shellcheck

View File

@@ -25,12 +25,12 @@ jobs:
timeout-minutes: 15
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version-file: .node-version
@@ -46,7 +46,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
@@ -62,7 +62,7 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
sarif_file: "trivy-repo-results.sarif"
@@ -76,17 +76,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
config-file: ./.github/codeql-config.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4

View File

@@ -46,7 +46,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@314ff8b43182423b84c50b1670b0e10f858f2d98 # latest
@@ -58,6 +58,6 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4
with:
sarif_file: "trivy-image-results.sarif"

View File

@@ -28,7 +28,7 @@ jobs:
run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
submodules: true
@@ -47,7 +47,7 @@ jobs:
echo done=false >> $GITHUB_OUTPUT
fi
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
- uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
if: steps.check.outputs.done == 'false'
with:
packages: quilt

View File

@@ -1 +1 @@
24.18.1
22.22.1

View File

@@ -22,167 +22,6 @@ Code v99.99.999
## Unreleased
## [4.135.0](https://github.com/coder/code-server/releases/tag/v4.135.0) - 2026-08-27
Code v1.135.0
### Changed
- Update to Code 1.135.0
## [4.134.0](https://github.com/coder/code-server/releases/tag/v4.134.0) - 2026-08-24
Code v1.134.0
### Added
- New `--socket-fd` flag that can be used to listen on a file descriptor. In
particular, this allows using code-server with systemd's socket activation.
- New `--vscode-option` repeatable flag that can be used to pass through options
to VS Code. It requires `flag=value` or simply `flag` for booleans. For
example: `--vscode-option enable-sandbox --vscode-option agents=true`. The
`VSCODE_OPTIONS` environment variable may also be used. For example:
`VSCODE_OPTIONS="enable-sandbox agents=true"`. Note that code-server simply
splits this variable on spaces and is not aware of quoting.
### Changed
- Update to Code 1.134.0
- Remove `--unsafe-perm` from installation scripts. This flag results in an
error when used with npm since v12 and has been a no-op since v7. If you are
installing with a version of npm older than v7 as root, installation may not
work correctly.
## [4.133.0](https://github.com/coder/code-server/releases/tag/v4.133.0) - 2026-08-17
Code v1.133.0
### Changed
- Update to Code 1.133.0
## [4.132.0](https://github.com/coder/code-server/releases/tag/v4.132.0) - 2026-08-10
Code v1.132.0
### Changed
- Update to Code 1.132.0
### Fixed
- When proxying, cookies were being decoded and re-encoded, which could cause
issues for applications that encode differently. Cookies are now passed
through unchanged (aside from stripping out code-server's session token).
## [4.131.0](https://github.com/coder/code-server/releases/tag/v4.131.0) - 2026-07-30
Code v1.131.0
### Changed
- Update to Code 1.131.0
## [4.130.0](https://github.com/coder/code-server/releases/tag/v4.130.0) - 2026-07-24
Code v1.130.0
### Changed
- Update to Code 1.130.0
## [4.129.0](https://github.com/coder/code-server/releases/tag/v4.129.0) - 2026-07-17
Code v1.129.0
### Changed
- Update to Code 1.129.0
## [4.128.0](https://github.com/coder/code-server/releases/tag/v4.128.0) - 2026-07-11
Code v1.128.0
### Changed
- Update to Code 1.128.0
## [4.127.0](https://github.com/coder/code-server/releases/tag/v4.127.0) - 2026-07-02
Code v1.127.0
### Changed
- Update to Code 1.127.0
## [4.126.0](https://github.com/coder/code-server/releases/tag/v4.126.0) - 2026-06-24
Code v1.126.0
### Changed
- Update to Code 1.126.0
## [4.125.0](https://github.com/coder/code-server/releases/tag/v4.125.0) - 2026-06-18
Code v1.125.0
### Changed
- Update to Code 1.125.0
## [4.124.2](https://github.com/coder/code-server/releases/tag/v4.124.2) - 2026-06-16
Code v1.124.2
### Security
- Strip code-server's session token from the cookie before proxying to a local
port. Previously, when you used built-in password authentication, the cookie
would be sent to the local proxied port, which meant if the service was
malicious and not already running as your code-server user it could use the
cookie to log into code-server and execute commands as your code-server user.
### Changed
- Update to Code 1.124.2
## [4.123.0](https://github.com/coder/code-server/releases/tag/v4.123.0) - 2026-06-03
Code v1.123.0
### Changed
- Update to Code 1.123.0
- Microsoft dropped support for armhf remotes so there will no longer be any
builds for armhf.
## [4.122.1](https://github.com/coder/code-server/releases/tag/v4.122.1) - 2026-06-02
Code v1.122.1
### Changed
- Update to Code 1.122.1
## [4.122.0](https://github.com/coder/code-server/releases/tag/v4.122.0) - 2026-05-29
Code v1.122.0
### Changed
- Update to Code 1.122.0
### Fixed
- `--app-name` will now affect window titles within the editor (it is now used
as the value for `${appName}` in the title template) as well as some other
places like the help > about dialog.
### Added
- App name can now be set with the `CODE_SERVER_APP_NAME` environment variable.
## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
Code v1.121.0

View File

@@ -128,9 +128,7 @@ bundle_vscode() {
# Merge the package.json for the web/remote server so we can include
# dependencies, since we want to ship this via NPM.
# Also override the name to prevent vulnerability scanners from
# misidentifying this package as VS Code (see #7071).
jq --slurp '.[0] * .[1] | .name = "code-oss"' \
jq --slurp '.[0] * .[1]' \
"$VSCODE_SRC_PATH/remote/package.json" \
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"

View File

@@ -65,8 +65,8 @@ main() {
echo "USE AT YOUR OWN RISK!"
fi
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-24}" ]; then
echo "ERROR: code-server currently requires node v24."
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
echo "ERROR: code-server currently requires node v22."
if [ -n "$FORCE_NODE_VERSION" ]; then
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
fi
@@ -76,6 +76,20 @@ main() {
exit 1
fi
# Under npm, if we are running as root, we need --unsafe-perm otherwise
# post-install scripts will not have sufficient permissions to do their thing.
if is_root; then
case "${npm_config_user_agent-}" in npm*)
if [ "${npm_config_unsafe_perm-}" != "true" ]; then
echo "Please pass --unsafe-perm to npm to install code-server"
echo "Otherwise post-install scripts will not have permissions to run"
echo "See https://docs.npmjs.com/misc/config#unsafe-perm"
echo "See https://stackoverflow.com/questions/49084929/npm-sudo-global-installation-unsafe-perm"
exit 1
fi
;;
esac
fi
if ! vscode_install; then
echo "You may not have the required dependencies to build the native modules."
@@ -96,7 +110,7 @@ install_with_yarn_or_npm() {
# end-user we want to keep using whatever package manager is in use.
case "${npm_config_user_agent-}" in
npm*)
if ! npm install --omit=dev; then
if ! npm install --unsafe-perm --omit=dev; then
return 1
fi
;;

View File

@@ -2,65 +2,16 @@
set -Eeuo pipefail
# Given versions $1 and $2 figure out the first component that is different
# (major, minor, patch).
function find_version_diff() {
# shellcheck disable=SC2206
local a=( ${1//./ } )
# shellcheck disable=SC2206
local b=( ${2//./ } )
if [[ ${a[0]} != "${b[0]}" ]] ; then
echo major
elif [[ ${a[1]} != "${b[1]}" ]] ; then
echo minor
else
echo patch
fi
}
# Bump $1 by the bump type (major, minor, patch) in $2.
function bump_version() {
# shellcheck disable=SC2206
local a=( ${1//./ } )
case $2 in
major)
((a[0]++))
a[1]=0
a[2]=0
;;
minor)
((a[1]++))
a[2]=0
;;
*)
((a[2]++))
;;
esac
echo "${a[0]}.${a[1]}.${a[2]}"
}
function update_helm() {
local chart_version
chart_version=$(yq .version ci/helm-chart/Chart.yaml)
local app_version
app_version=$(yq .appVersion ci/helm-chart/Chart.yaml)
local image_version
image_version=$(yq .image.tag ci/helm-chart/values.yaml)
local current
current=$(yq .version ci/helm-chart/Chart.yaml)
local next
next=$(semver "$current" -i minor)
echo "Bumping version from $current to $next..."
sed -i.bak "s/^version: $current\$/version: $next/" ci/helm-chart/Chart.yaml
local bump_type
bump_type=$(find_version_diff "$app_version" "$version")
local chart_version_bump
chart_version_bump=$(bump_version "$chart_version" "$bump_type")
# Use sed to replace because yq will reformat.
echo "Bumping version from $chart_version to $chart_version_bump..."
sed -i.bak "s/^version: $chart_version\$/version: $chart_version_bump/" ci/helm-chart/Chart.yaml
echo "Bumping app version from $app_version to $version..."
echo "Setting app version and image to $version..."
sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml
echo "Bumping image version from $image_version to $version..."
sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
}
@@ -86,8 +37,7 @@ function main() {
"Update changelog" "update_changelog"
)
# Even if a step failed, still output the last checkmark.
run-steps "${steps[@]}" || true
run-steps "${steps[@]}"
# This step is always manual.
echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist

View File

@@ -4,7 +4,7 @@ set -Eeuo pipefail
function unapply_patches() {
local -i exit_code=0
quiet quilt pop -af 2>&1 || exit_code=$?
quiet quilt pop -af || exit_code=$?
case $exit_code in
# Sucessfully unapplied.
0) ;;
@@ -15,19 +15,6 @@ function unapply_patches() {
esac
}
function apply_patches() {
local -i exit_code=0
quiet quilt push -a 2>&1 || exit_code=$?
case $exit_code in
# Sucessfully applied.
0) ;;
# No more patches to apply.
2) ;;
# Some error.
*) return $exit_code ;;
esac
}
function update_vscode() {
pushd lib/vscode
if ! git checkout 2>&1 "$target_vscode_version" ; then
@@ -41,8 +28,8 @@ function update_vscode() {
function refresh_patches() {
local -i exit_code=0
while quiet quilt push 2>&1 ; ! (( exit_code=$? )) ; do
quilt refresh 2>&1
while quiet quilt push ; ! (( exit_code=$? )) ; do
quilt refresh
done
case $exit_code in
# No more patches to apply.
@@ -55,8 +42,6 @@ function refresh_patches() {
function update_node() {
local node_version
node_version=$(cat .node-version)
local target_node_version
target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"')
if [[ $node_version == "$target_node_version" ]] ; then
echo "Already set to $target_node_version"
else
@@ -69,41 +54,50 @@ function get-webview-script-hash() {
local html
html=$(<"$1")
local start_tag='<script async type="module">'
if [[ $file == */webWorkerExtensionHostIframe.html ]] ; then
start_tag='<script>'
fi
local end_tag="</script>"
html=${html##*"$start_tag"}
html=${html%%"$end_tag"*}
echo -n "$html" | openssl sha256 -binary | openssl base64
}
function delete_csp() {
quilt delete csp-hashes.diff || true
}
function update_csp() {
apply_patches
local files=(
./lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
./lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
)
quilt new csp-hashes.diff
local file
for file in "${files[@]}" ; do
quilt add "$file"
local current
current=$(quilt top 2>/dev/null || echo "")
local patch_action=""
echo "Currently at ${current:-base}"
if [[ $current != */webview.diff ]] ; then
echo "Moving to patches/webview.diff..."
local -i exit_code=0
if quilt applied 2>/dev/null | grep --quiet webview.diff ; then
quiet quilt pop webview || exit_code=$?
patch_action=pop
else
quiet quilt push webview || exit_code=$?
patch_action=push
fi
case $exit_code in
# Successfully moved.
0) ;;
# Some error.
*) return $exit_code ;;
esac
fi
local file=lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
local hash
hash=$(get-webview-script-hash "$file")
echo "Calculated hash as $hash"
# Use octothorpe as a delimiter since the hash may contain a slash.
sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file"
done
sed -i.bak "s#script-src 'sha256-[^']\+'#script-src 'sha256-$hash'#" "$file"
quilt refresh
if [[ $patch_action != "" ]] ; then
echo "Moving back to ${current:-base}..."
case $patch_action in
pop) quiet quilt push "$current" ;;
push) quiet quilt pop "${current:--a}" ;;
esac
fi
}
function add_changelog() {
@@ -122,10 +116,10 @@ function main() {
source ./ci/lib.sh
declare -a steps
local target_node_version
target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"')
# Hashes are always regenerated to avoid having to resolve conflicts..
steps+=("Revert CSP hashes" "delete_csp")
declare -a steps
# If version is not set, assume we are already at the target version and the
# user is just trying to resolve conflics.
@@ -147,13 +141,12 @@ function main() {
fi
steps+=(
"Update Node version" "update_node"
"Regenerate CSP hashes" "update_csp"
"Set Node version to $target_node_version" "update_node"
"Update CSP webview hash" "update_csp"
"Add changelog note" "add_changelog"
)
# Even if a step failed, still output the last checkmark.
run-steps "${steps[@]}" || true
run-steps "${steps[@]}"
# This step is always manual.
echo "- [ ] Verify changelog" >> .cache/checklist

View File

@@ -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.50.0
version: 3.36.0
# 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.135.0
appVersion: 4.121.0

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.135.0'
tag: '4.121.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@@ -34,10 +34,6 @@ serviceAccount:
# Specifies annotations for deployment
annotations: {}
# code-server.labels -- The Deployment labels. See:
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
labels: {}
podAnnotations: {}
podSecurityContext: {}

View File

@@ -85,20 +85,18 @@ run-steps() {
while (( $# )) ; do
local name=$1 ; shift
local fn=$1 ; shift
echo "$name..."
# Only run if an earlier step has not failed.
# For all failed steps, write out an empty checkbox.
if [[ $failed == 0 ]] ; then
echo "$name..."
if $fn | indent ; then
echo "- [X] $name" >> .cache/checklist
else
((failed++))
echo "- [ ] $name" >> .cache/checklist
echo "Failed" | indent
fi
else
fi
# For all failed steps, write out an empty checkbox.
if [[ $failed != 0 ]] ; then
echo "- [ ] $name" >> .cache/checklist
echo "Skipped" | indent
fi
done
if [[ $failed != 0 ]] ; then

View File

@@ -31,7 +31,7 @@ The prerequisites for contributing to code-server are almost the same as those
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Here is what is needed:
- `node` v24.x
- `node` v22.x
- `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com)
- [`npm`](https://www.npmjs.com/)
@@ -201,7 +201,7 @@ There are four kinds of tests in code-server:
Our unit tests are written in TypeScript and run using
[Jest](https://jestjs.io/), the testing framework].
These live under [test/unit](../test/unit).
These live under [test/unit](https://github.com/coder/code-server/tree/main/test/unit).
We use unit tests for functions and things that can be tested in isolation. The
file structure is modeled closely after `/src` so it's easy for people to know
@@ -230,7 +230,7 @@ testing the CLI requires us to build and package code-server.
The end-to-end (e2e) tests are written in TypeScript and run using
[Playwright](https://playwright.dev/).
These live under [test/e2e](../test/e2e).
These live under [test/e2e](https://github.com/coder/code-server/tree/main/test/e2e).
Before the e2e tests run, we run `globalSetup`, which eliminates the need to log
in before each test by preserving the authentication state.
@@ -246,15 +246,15 @@ We also have a model where you can create helpers to use within tests. See
code-server essentially serves as an HTTP API for logging in and starting a
remote Code process.
The CLI code is in [src/node](../src/node) and the HTTP routes are implemented
in [src/node/routes](../src/node/routes).
The CLI code is in [src/node](https://github.com/coder/code-server/tree/main/src/node) and the HTTP routes are implemented
in [src/node/routes](https://github.com/coder/code-server/tree/main/src/node/routes).
Most of the meaty parts are in the Code portion of the codebase under
[lib/vscode](../lib/vscode), which we describe next.
[lib/vscode](https://github.com/coder/code-server/tree/main/lib/vscode), which we describe next.
### Modifications to Code
Our modifications to Code can be found in the [patches](../patches) directory.
Our modifications to Code can be found in the [patches](https://github.com/coder/code-server/tree/main/patches) directory.
We pull in Code as a submodule pointing to an upstream release branch.
In v1 of code-server, we had Code as a submodule and used a single massive patch
@@ -277,7 +277,7 @@ requires us to ensure that our changes are still applied correctly and work as
intended. In the future, we'd like to run Code unit tests against our builds to
ensure that features work as expected.
> We have [extension docs](../ci/README.md) on the CI and build system.
> We have [extension docs](https://github.com/coder/code-server/tree/main/ci) on the CI and build system.
If the functionality you're working on does NOT depend on code from Code, please
move it out and into code-server.

View File

@@ -17,7 +17,6 @@
- [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)
- [Can I open a file at a specific line from a URL?](#can-i-open-a-file-at-a-specific-line-from-a-url)
- [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)
- [How do I direct server-side requests through a proxy?](#how-do-i-direct-server-side-requests-through-a-proxy)
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
@@ -41,7 +40,6 @@
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
- [How do I disable file download?](#how-do-i-disable-file-download)
- [Why do web views not work?](#why-do-web-views-not-work)
- [Can I run code-server with systemd socket activation?](#can-i-run-code-server-with-systemd-socket-activation)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
@@ -232,39 +230,6 @@ code-server tries the following in this order:
3. The workspace or directory passed via the command line
4. The last opened workspace or directory
## Can I open a file at a specific line from a URL?
Yes. In addition to `workspace` and `folder`, code-server supports VS Code's
`payload` query parameter, which can open a specific file — optionally at a
line and column — once the workbench loads.
`payload` is a URL-encoded JSON array of `[key, value]` string pairs. The
`openFile` key takes a `vscode-remote://<host>/<absolute path>` URI, where
`<host>` is the host you use to reach code-server. Add
`["gotoLineMode","true"]` to have a trailing `:line[:column]` suffix on the
path interpreted as a cursor position:
```text
https://code.example.com/?folder=/home/coder/project&payload=[["gotoLineMode","true"],["openFile","vscode-remote://code.example.com/home/coder/project/src/app.py:10:5"]]
```
(with the `payload` value URL-encoded). Notes:
- Paths must be absolute; there is no form relative to `folder`.
- This is upstream VS Code web behavior (the same mechanism vscode.dev uses),
so it works without any code-server-specific configuration.
For example, to generate links from a shell:
```sh
#!/bin/sh
# usage: code-link <absolute-file> [line[:column]]
HOST=code.example.com
payload="[[\"gotoLineMode\",\"true\"],[\"openFile\",\"vscode-remote://$HOST$1${2:+:$2}\"]]"
printf 'https://%s/?folder=%s&payload=%s\n' "$HOST" "$(dirname "$1")" \
"$(printf '%s' "$payload" | jq -sRr @uri)"
```
## How do I access my Documents/Downloads/Desktop folders in code-server on macOS?
Newer versions of macOS require permission through a non-UNIX mechanism for
@@ -561,41 +526,3 @@ To fix this, you must either:
create and trust a certificate manually).
- Disable security if your browser allows it. For example, in Chromium see
`chrome://flags/#unsafely-treat-insecure-origin-as-secure`
## Can I run code-server with systemd socket activation?
Yes. Pass the inherited socket to code-server with `--socket-fd`. systemd
passes the first listening socket as file descriptor `3`.
Create a socket unit, `~/.config/systemd/user/code-server.socket`:
```ini
[Socket]
ListenStream=8080
[Install]
WantedBy=sockets.target
```
And a matching service unit, `~/.config/systemd/user/code-server.service`:
```ini
[Service]
ExecStart=/usr/bin/code-server --socket-fd 3
```
Then enable and start the socket:
```bash
systemctl --user enable --now code-server.socket
```
code-server will start on the first connection and listen on the socket
systemd created. `--socket-fd` takes precedence over `--socket` and
`--bind-addr`/`--port`/`--host`, and `--socket-mode` is ignored because
systemd owns the socket's permissions.
Socket activation only changes how code-server binds; your usual
authentication still applies (it keeps prompting for the configured password
unless you set `--auth none`), so keep authentication enabled when exposing the
server.

View File

@@ -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 24:
7. Install and use Node.js 22:
```shell
nvm install 24
nvm use 24
nvm install 22
nvm use 22
```
8. Install code-server globally on device with: `npm install --global code-server`

View File

@@ -105,7 +105,7 @@ $ helm upgrade --install code-server \
--set persistence.enabled=false
```
The above command sets the persistence storage to false.
The above command sets the the persistence storage to false.
Alternatively, a YAML file that specifies the values for the above parameters
can be provided while installing the chart. For example,

View File

@@ -101,8 +101,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`.
2. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
3. 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.
@@ -295,7 +296,8 @@ You can install code-server using the [Helm package manager](https://coder.com/d
## Windows
We currently [do not publish Windows
releases](https://github.com/coder/code-server/issues/1397).
releases](https://github.com/coder/code-server/issues/1397). We recommend
installing code-server onto Windows with [`npm`](#npm).
## Raspberry Pi

View File

@@ -29,7 +29,8 @@ includes installing instructions based on your operating system.
## Node.js version
We use Node.js `24.x`. VS Code also [lists Node.js
We use the same major version of Node.js shipped with Code's remote, which is
currently `22.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
@@ -77,7 +78,7 @@ Proceed to [installing](#installing)
## FreeBSD
```sh
pkg install -y git python npm-node24 pkgconf
pkg install -y git python npm-node22 pkgconf
pkg install -y libinotify
```

View File

@@ -57,7 +57,7 @@ npm config set python python3
node -v
```
you will get Node version `v24`
you will get Node version `v22`
5. Now install code-server following our guide on [installing with npm](./npm.md)

View File

@@ -436,7 +436,7 @@ install_npm() {
fi
echoh "Installing with npm."
echoh
"$sh_c" "$NPM_PATH" install -g "code-server@$VERSION"
"$sh_c" "$NPM_PATH" install -g "code-server@$VERSION" --unsafe-perm
NPM_BIN_DIR="\$($NPM_PATH bin -g)" echo_npm_postinstall
return
fi

544
package-lock.json generated
View File

@@ -13,14 +13,13 @@
"@coder/logger": "^3.0.1",
"argon2": "^0.44.0",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
"env-paths": "^2.2.1",
"express": "^5.0.1",
"http-proxy": "^1.18.1",
"httpolyglot": "^0.1.2",
"i18next": "^26.3.1",
"js-yaml": "^5.2.3",
"i18next": "^25.8.3",
"js-yaml": "^4.1.0",
"limiter": "^2.1.0",
"pem": "^1.14.8",
"proxy-agent": "^6.3.1",
@@ -38,13 +37,14 @@
"@eslint/compat": "^1.2.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.12.0",
"@schemastore/package": "^0.0.10",
"@types/compression": "^1.7.3",
"@types/cookie-parser": "^1.4.4",
"@types/eslint__js": "^8.42.3",
"@types/express": "^5.0.0",
"@types/http-proxy": "1.17.7",
"@types/js-yaml": "^4.0.6",
"@types/node": "24.x",
"@types/node": "22.x",
"@types/pem": "^1.14.1",
"@types/proxy-from-env": "^1.0.1",
"@types/safe-compare": "^1.1.0",
@@ -57,15 +57,24 @@
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0",
"prettier": "3.9.4",
"globals": "^16.1.0",
"prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
"typescript-eslint": "^8.8.0"
},
"engines": {
"node": "24"
"node": "22"
}
},
"node_modules/@babel/runtime": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
"integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@coder/logger": {
@@ -268,29 +277,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/eslintrc/node_modules/js-yaml": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz",
"integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/@eslint/js": {
"version": "9.39.3",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz",
@@ -460,29 +446,35 @@
"dev": true,
"license": "MIT"
},
"node_modules/@schemastore/package": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/@schemastore/package/-/package-0.0.10.tgz",
"integrity": "sha512-D3LxMCnkgsb4LO5sDKf6E+yahM2SqpEHmkqMPDSJis5Cy/j2MgWo/g/iq0lECK0mrPWfx3hqKm2ZJlqxwbRJQA==",
"dev": true,
"license": "MIT"
},
"node_modules/@textlint/ast-node-types": {
"version": "15.7.1",
"resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz",
"integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==",
"version": "12.6.1",
"resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz",
"integrity": "sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA==",
"dev": true,
"license": "MIT"
},
"node_modules/@textlint/markdown-to-ast": {
"version": "15.7.1",
"resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-15.7.1.tgz",
"integrity": "sha512-9DLSah7g6mYNHvO6pssLdFvFPAl3HHyEIm4RE5of/1QN9FXJXDgdOcVV3YpQmbYT/YntuIvOQiqOndCSPWTW2A==",
"version": "12.6.1",
"resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz",
"integrity": "sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@textlint/ast-node-types": "15.7.1",
"debug": "^4.4.3",
"@textlint/ast-node-types": "^12.6.1",
"debug": "^4.3.4",
"mdast-util-gfm-autolink-literal": "^0.1.3",
"neotraverse": "^0.6.18",
"remark-footnotes": "^3.0.0",
"remark-frontmatter": "^3.0.0",
"remark-gfm": "^1.0.0",
"remark-parse": "^9.0.0",
"structured-source": "^4.0.0",
"traverse": "^0.6.7",
"unified": "^9.2.2"
}
},
@@ -675,13 +667,13 @@
}
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"version": "22.19.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz",
"integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
"undici-types": "~6.21.0"
}
},
"node_modules/@types/pem": {
@@ -778,20 +770,20 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz",
"integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz",
"integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.61.1",
"@typescript-eslint/type-utils": "8.61.1",
"@typescript-eslint/utils": "8.61.1",
"@typescript-eslint/visitor-keys": "8.61.1",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/type-utils": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -801,9 +793,9 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.61.1",
"@typescript-eslint/parser": "^8.56.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
@@ -817,16 +809,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz",
"integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz",
"integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.61.1",
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/typescript-estree": "8.61.1",
"@typescript-eslint/visitor-keys": "8.61.1",
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3"
},
"engines": {
@@ -838,18 +830,18 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz",
"integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz",
"integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.61.1",
"@typescript-eslint/types": "^8.61.1",
"@typescript-eslint/tsconfig-utils": "^8.56.1",
"@typescript-eslint/types": "^8.56.1",
"debug": "^4.4.3"
},
"engines": {
@@ -860,18 +852,18 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz",
"integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz",
"integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/visitor-keys": "8.61.1"
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -882,9 +874,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz",
"integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz",
"integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -895,21 +887,21 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz",
"integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz",
"integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/typescript-estree": "8.61.1",
"@typescript-eslint/utils": "8.61.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -920,13 +912,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz",
"integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz",
"integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -938,21 +930,21 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz",
"integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz",
"integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.61.1",
"@typescript-eslint/tsconfig-utils": "8.61.1",
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/visitor-keys": "8.61.1",
"@typescript-eslint/project-service": "8.56.1",
"@typescript-eslint/tsconfig-utils": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.5.0"
"ts-api-utils": "^2.4.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -962,7 +954,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
@@ -976,26 +968,26 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "20 || >=22"
"node": "18 || 20 || >=22"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "10.2.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.5"
"brace-expansion": "^5.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
@@ -1005,16 +997,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz",
"integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz",
"integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.61.1",
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/typescript-estree": "8.61.1"
"@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1025,17 +1017,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz",
"integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz",
"integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.61.1",
"@typescript-eslint/types": "8.56.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -1413,9 +1405,9 @@
}
},
"node_modules/anchor-markdown-header": {
"version": "0.8.4",
"resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.4.tgz",
"integrity": "sha512-20eMBMpts7k5rXAAj67geSqc/tsexHZOZJDWQD214YcDuNtyizDa7Q77sYa5rkao2FwsQP1WKRt2X6mphwmhbg==",
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.2.tgz",
"integrity": "sha512-ix0Hx6ARkHOsQRmt1++ZmjURq4Pr5MGXQJjh0lQ/l5jTpTURn4aqhbZ+AJMpZ/Sd3JiyNwi7KaeiF64OsMGCPg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1647,29 +1639,29 @@
"license": "MIT"
},
"node_modules/basic-ftp": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/body-parser": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz",
"integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==",
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
"integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^2.0.0",
"content-type": "^1.0.5",
"debug": "^4.4.3",
"http-errors": "^2.0.1",
"iconv-lite": "^0.7.2",
"http-errors": "^2.0.0",
"iconv-lite": "^0.7.0",
"on-finished": "^2.4.1",
"qs": "^6.15.2",
"raw-body": "^3.0.2",
"type-is": "^2.1.0"
"qs": "^6.14.1",
"raw-body": "^3.0.1",
"type-is": "^2.0.1"
},
"engines": {
"node": ">=18"
@@ -1679,30 +1671,10 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/content-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
"integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/boundary": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz",
"integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==",
"dev": true,
"license": "BSD-2-Clause"
},
"node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1964,16 +1936,12 @@
}
},
"node_modules/cookie": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
"node": ">= 0.6"
}
},
"node_modules/cookie-parser": {
@@ -1989,15 +1957,6 @@
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -2208,17 +2167,18 @@
}
},
"node_modules/doctoc": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.5.0.tgz",
"integrity": "sha512-xWb2P8mQw9x+T9xPYToytRP0/bA68oexdsY0anMG72RdhZGTVPx6oHJfI57gbZe9LsOSfQUNNLwxSspdoTlJIQ==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.3.0.tgz",
"integrity": "sha512-duuDNVnRHE5mFGYlI+oDf1vguML8PIhKnbUCs7iKPHIEdzYhkCldk6MQeX3ZeXQStRtZxGspSHImtgOMQPIS4A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@textlint/markdown-to-ast": "^15.6.0",
"anchor-markdown-header": "^0.8.4",
"@textlint/markdown-to-ast": "^12.1.1",
"anchor-markdown-header": "^0.8.2",
"htmlparser2": "^7.2.0",
"loglevel": "^1.9.2",
"minimist": "^1.2.6"
"minimist": "^1.2.6",
"underscore": "^1.13.2",
"update-section": "^0.3.3"
},
"bin": {
"doctoc": "doctoc.js"
@@ -2993,15 +2953,6 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/express/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express/node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
@@ -3359,9 +3310,9 @@
}
},
"node_modules/globals": {
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
"version": "16.5.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
"integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3581,26 +3532,29 @@
}
},
"node_modules/i18next": {
"version": "26.3.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz",
"integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==",
"version": "25.8.13",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz",
"integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==",
"funding": [
{
"type": "individual",
"url": "https://www.locize.com/i18next"
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
},
{
"type": "individual",
"url": "https://www.locize.com"
}
],
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4"
},
"peerDependencies": {
"typescript": "^5 || ^6"
"typescript": "^5"
},
"peerDependenciesMeta": {
"typescript": {
@@ -3683,9 +3637,9 @@
}
},
"node_modules/ip-address": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz",
"integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==",
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
"license": "MIT",
"engines": {
"node": ">= 12"
@@ -4176,25 +4130,15 @@
"license": "ISC"
},
"node_modules/js-yaml": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.3.tgz",
"integrity": "sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.mjs"
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-buffer": {
@@ -4293,20 +4237,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/loglevel": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz",
"integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
},
"funding": {
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/loglevel"
}
},
"node_modules/longest-streak": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
@@ -4780,16 +4710,6 @@
"node": ">= 0.6"
}
},
"node_modules/neotraverse": {
"version": "0.6.18",
"resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz",
"integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10"
}
},
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
@@ -5180,9 +5100,9 @@
}
},
"node_modules/prettier": {
"version": "3.9.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.4.tgz",
"integrity": "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg==",
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -5277,9 +5197,9 @@
}
},
"node_modules/qs": {
"version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -5419,9 +5339,9 @@
}
},
"node_modules/remove-markdown": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.4.tgz",
"integrity": "sha512-BompiLClzjfh46irZmzv+1Q61jZYlKN3iq/hzae9EOUwf7ctr/5wpD4qwgn/FWDAYE18RORO7z/yr+HXZJCY8Q==",
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.3.tgz",
"integrity": "sha512-Qvp2p0Q1irE7AaJO7QemJe04HdObHylJrG+q4hszvPlYp7q4EvfINpEIaIEFdB+3XTDp1h6fiyT60ae00gmRow==",
"dev": true,
"license": "MIT"
},
@@ -5984,16 +5904,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/structured-source": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz",
"integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"boundary": "^2.0.0"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -6062,6 +5972,24 @@
"node": ">=0.6"
}
},
"node_modules/traverse": {
"version": "0.6.11",
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.11.tgz",
"integrity": "sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==",
"dev": true,
"license": "MIT",
"dependencies": {
"gopd": "^1.2.0",
"typedarray.prototype.slice": "^1.0.5",
"which-typed-array": "^1.1.18"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/trough": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
@@ -6074,9 +6002,9 @@
}
},
"node_modules/ts-api-utils": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
"integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -6163,34 +6091,17 @@
}
},
"node_modules/type-is": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz",
"integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"license": "MIT",
"dependencies": {
"content-type": "^2.0.0",
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/type-is/node_modules/content-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
"integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
"node": ">= 0.6"
}
},
"node_modules/typed-array-buffer": {
@@ -6271,6 +6182,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/typedarray.prototype.slice": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz",
"integrity": "sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
"es-abstract": "^1.23.9",
"es-errors": "^1.3.0",
"get-proto": "^1.0.1",
"math-intrinsics": "^1.1.0",
"typed-array-buffer": "^1.0.3",
"typed-array-byte-offset": "^1.0.4"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/typescript": {
"version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@@ -6286,16 +6220,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.61.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.1.tgz",
"integrity": "sha512-V7PayAfJokV3pEHgN7/v03D1SpujhRfQtYLbLIiBfDDncdg4PAiRBfoS4cnCANK4jmAPncczi59QO3afiXUlNw==",
"version": "8.56.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz",
"integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.61.1",
"@typescript-eslint/parser": "8.61.1",
"@typescript-eslint/typescript-estree": "8.61.1",
"@typescript-eslint/utils": "8.61.1"
"@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.56.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6306,7 +6240,7 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/unbox-primitive": {
@@ -6328,10 +6262,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/underscore": {
"version": "1.13.8",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz",
"integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==",
"dev": true,
"license": "MIT"
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
},
@@ -6462,6 +6403,13 @@
"@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
}
},
"node_modules/update-section": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz",
"integrity": "sha512-BpRZMZpgXLuTiKeiu7kK0nIPwGdyrqrs6EDSaXtjD/aQ2T+qVo9a5hRC3HN3iJjCMxNT/VxoLGQ7E/OzE5ucnw==",
"dev": true,
"license": "MIT"
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -6665,9 +6613,9 @@
"license": "ISC"
},
"node_modules/ws": {
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
"version": "8.20.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
"integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"

View File

@@ -39,13 +39,14 @@
"@eslint/compat": "^1.2.0",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.12.0",
"@schemastore/package": "^0.0.10",
"@types/compression": "^1.7.3",
"@types/cookie-parser": "^1.4.4",
"@types/eslint__js": "^8.42.3",
"@types/express": "^5.0.0",
"@types/http-proxy": "1.17.7",
"@types/js-yaml": "^4.0.6",
"@types/node": "24.x",
"@types/node": "22.x",
"@types/pem": "^1.14.1",
"@types/proxy-from-env": "^1.0.1",
"@types/safe-compare": "^1.1.0",
@@ -58,8 +59,8 @@
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0",
"prettier": "3.9.4",
"globals": "^16.1.0",
"prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
@@ -69,14 +70,13 @@
"@coder/logger": "^3.0.1",
"argon2": "^0.44.0",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
"env-paths": "^2.2.1",
"express": "^5.0.1",
"http-proxy": "^1.18.1",
"httpolyglot": "^0.1.2",
"i18next": "^26.3.1",
"js-yaml": "^5.2.3",
"i18next": "^25.8.3",
"js-yaml": "^4.1.0",
"limiter": "^2.1.0",
"pem": "^1.14.8",
"proxy-agent": "^6.3.1",
@@ -88,7 +88,7 @@
"xdg-basedir": "^4.0.0"
},
"resolutions": {
"@types/node": "24.x"
"@types/node": "22.x"
},
"bin": {
"code-server": "out/node/entry.js"
@@ -103,7 +103,7 @@
"remote-development"
],
"engines": {
"node": "24"
"node": "22"
},
"jest": {
"transform": {

View File

@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -124,6 +125,7 @@ export interface ServerParsedArgs {
@@ -120,6 +121,7 @@ export interface ServerParsedArgs {
'disable-getting-started-override'?: boolean,
'locale'?: string
'link-protection-trusted-domains'?: string[],
@@ -32,7 +32,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
@@ -362,8 +362,11 @@ export class WebClientServer {
@@ -366,8 +366,11 @@ export class WebClientServer {
linkProtectionTrustedDomains.push(...this._productService.linkProtectionTrustedDomains);
}

View File

@@ -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
@@ -251,7 +251,9 @@ class RemoteAuthoritiesImpl {
@@ -245,7 +245,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
@@ -263,7 +263,9 @@ export class WebClientServer {
@@ -265,7 +265,9 @@ export class WebClientServer {
};
// Prefix routes with basePath for clients
@@ -120,9 +120,9 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+ const vscodeBase = relativePath(getOriginalUrl(req))
+ const basePath = vscodeBase || getFirstHeader('x-forwarded-prefix') || this._basePath;
const queryConnectionTokens = parsedUrl.searchParams.getAll(connectionTokenQueryName);
if (queryConnectionTokens.length === 1) {
@@ -300,10 +302,14 @@ export class WebClientServer {
const queryConnectionToken = parsedUrl.query[connectionTokenQueryName];
if (typeof queryConnectionToken === 'string') {
@@ -304,10 +306,14 @@ export class WebClientServer {
};
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
@@ -138,15 +138,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
);
if (!remoteAuthority) {
return serveError(req, res, 400, `Bad request.`);
@@ -350,6 +356,7 @@ export class WebClientServer {
@@ -354,6 +360,7 @@ export class WebClientServer {
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
codeServerVersion: this._productService.codeServerVersion,
+ rootEndpoint: rootBase,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
@@ -399,7 +406,9 @@ export class WebClientServer {
...this._productService.extensionsGallery,
@@ -407,7 +414,9 @@ export class WebClientServer {
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
WORKBENCH_WEB_BASE_URL: staticRoute,
WORKBENCH_NLS_URL,
@@ -157,7 +157,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
};
// DEV ---------------------------------------------------------------------------------------
@@ -436,7 +445,7 @@ export class WebClientServer {
@@ -444,7 +453,7 @@ export class WebClientServer {
'default-src \'self\';',
'img-src \'self\' https: data: blob:;',
'media-src \'self\';',
@@ -166,7 +166,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
'child-src \'self\';',
`frame-src 'self' https://*.vscode-cdn.net data:;`,
'worker-src \'self\' data: blob:;',
@@ -509,3 +518,70 @@ export class WebClientServer {
@@ -517,3 +526,70 @@ export class WebClientServer {
return void res.end(data);
}
}
@@ -241,7 +241,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -98,6 +98,7 @@ export interface IDictationRuntimeProduc
@@ -66,6 +66,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration {
readonly codeServerVersion?: string
@@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
}
private startListening(): void {
@@ -590,17 +591,6 @@ class WorkspaceProvider implements IWork
@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
}
}
@@ -281,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
(function () {
// Find config by checking for DOM
@@ -610,8 +600,8 @@ function readCookie(name: string): strin
@@ -604,8 +594,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}

View File

@@ -78,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
@@ -147,6 +147,7 @@ export interface NativeParsedArgs {
@@ -146,6 +146,7 @@ export interface NativeParsedArgs {
'disable-chromium-sandbox'?: boolean;
sandbox?: boolean;
'enable-coi'?: boolean;
@@ -102,7 +102,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
@@ -78,6 +78,7 @@ const isSupportedForPipe = (optionId: ke
@@ -77,6 +77,7 @@ const isSupportedForPipe = (optionId: ke
case 'verbose':
case 'remote':
case 'locate-shell-integration-path':
@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
return true;
default:
return false;
@@ -307,6 +308,22 @@ export async function main(desc: Product
@@ -300,6 +301,22 @@ export async function main(desc: Product
}
}
} else {

View File

@@ -2,8 +2,8 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
+++ code-server/lib/vscode/build/gulpfile.extensions.ts
@@ -291,6 +291,29 @@ export const compileCopilotExtensionBuil
task.task(compileCopilotExtensionBuildTask);
@@ -294,6 +294,29 @@ export const compileCopilotExtensionBuil
gulp.task(compileCopilotExtensionBuildTask);
/**
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering
@@ -26,7 +26,7 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
+ return Promise.resolve();
+ })
+));
+task.task(compileCopilotExtensionFullBuildTask);
+gulp.task(compileCopilotExtensionFullBuildTask);
+
+/**
* Compiles the extensions for the build.
@@ -36,15 +36,15 @@ Index: code-server/lib/vscode/build/lib/extensions.ts
===================================================================
--- code-server.orig/lib/vscode/build/lib/extensions.ts
+++ code-server/lib/vscode/build/lib/extensions.ts
@@ -21,6 +21,7 @@ import { getProductionDependencies } fro
@@ -24,6 +24,7 @@ import { getProductionDependencies } fro
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
import { fetchUrls, fetchGithub } from './fetch.ts';
import { createTsgoStream, spawnTsgo } from './tsgo.ts';
+import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts';
import watcher from './watch/index.ts';
import vzip from 'gulp-vinyl-zip';
import { createRequire } from 'module';
@@ -491,6 +492,116 @@ export function packageCopilotExtensionS
@@ -492,6 +493,116 @@ export function packageCopilotExtensionS
).pipe(util2.setExecutableBit(['**/*.sh']));
}

View File

@@ -1,26 +0,0 @@
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -5,7 +5,7 @@
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-FFQoOVVa2tOE3uqUvirwaMNT20TZmrHcL2aaOjJ8BUo=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-24QqbpzqcqSyIGvg/ZwFRy5pPlhmVBa8CkUREEIUnBw=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
@@ -4,7 +4,7 @@
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
- script-src 'self' 'unsafe-eval' 'sha256-daEgfo2VIXpx2Np71KqCCbkeQwv+68vPrx54XRcbdcs=' https: http://localhost:* blob:;
+ script-src 'self' 'unsafe-eval' 'sha256-gfjiOVjAlxqrivZAfTq2d83mOaz0fnAxbGaFpj5IjD8=' https: http://localhost:* blob:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>

View File

@@ -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
@@ -343,6 +343,10 @@ export class Extension implements IExten
@@ -342,6 +342,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) {
return false;
}

View File

@@ -9,16 +9,16 @@ 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
@@ -13,7 +13,7 @@ import { IURITransformer } from '../../b
import { generateUuid } from '../../base/common/uuid.js';
@@ -12,7 +12,7 @@ import * as path from '../../base/common
import { IURITransformer } from '../../base/common/uriIpc.js';
import { getMachineId, getSqmMachineId, getDevDeviceId } from '../../base/node/id.js';
import { Promises } from '../../base/node/pfs.js';
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
import { createRandomIPCHandle } from '../../base/parts/ipc/node/ipc.net.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
@@ -417,6 +417,9 @@ export async function setupServerService
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
@@ -358,6 +358,9 @@ export async function setupServerService
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));
@@ -153,7 +153,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
@@ -24,6 +24,7 @@ import { URI } from '../../base/common/u
@@ -25,6 +25,7 @@ import { URI } from '../../base/common/u
import { streamToBuffer } from '../../base/common/buffer.js';
import { IProductConfiguration } from '../../base/common/product.js';
import { isString, Mutable } from '../../base/common/types.js';
@@ -161,7 +161,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
import { CharCode } from '../../base/common/charCode.js';
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
@@ -397,14 +398,22 @@ export class WebClientServer {
@@ -405,14 +406,22 @@ export class WebClientServer {
};
const cookies = cookie.parse(req.headers.cookie || '');
@@ -272,7 +272,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
@@ -475,9 +475,6 @@ export class InstallAction extends Exten
@@ -474,9 +474,6 @@ export class InstallAction extends Exten
if (this.extension.isBuiltin) {
return;
}
@@ -282,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
if (this.extension.state !== ExtensionState.Uninstalled) {
return;
}
@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ
@@ -781,7 +778,7 @@ export abstract class InstallInOtherServ
}
if (isLanguagePackExtension(this.extension.local.manifest)) {
@@ -291,7 +291,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
// Prefers to run on UI
@@ -2281,17 +2278,6 @@ export class SetLanguageAction extends E
@@ -2284,17 +2281,6 @@ export class SetLanguageAction extends E
update(): void {
this.enabled = false;
this.class = SetLanguageAction.DisabledClass;
@@ -309,7 +309,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
override async run(): Promise<any> {
@@ -2308,7 +2294,6 @@ export class ClearLanguageAction extends
@@ -2311,7 +2297,6 @@ export class ClearLanguageAction extends
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
constructor(
@@ -317,7 +317,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);
@@ -2318,17 +2303,6 @@ export class ClearLanguageAction extends
@@ -2321,17 +2306,6 @@ export class ClearLanguageAction extends
update(): void {
this.enabled = false;
this.class = ClearLanguageAction.DisabledClass;

View File

@@ -27,7 +27,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -319,6 +319,16 @@ export interface IWorkbenchConstructionO
@@ -312,6 +312,16 @@ export interface IWorkbenchConstructionO
*/
readonly userDataPath?: string
@@ -112,7 +112,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
@@ -380,6 +380,8 @@ export class WebClientServer {
@@ -389,6 +389,8 @@ export class WebClientServer {
serverBasePath: basePath,
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
userDataPath: this._environmentService.userDataPath,
@@ -129,8 +129,8 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
import { Disposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
-import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
@@ -138,7 +138,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
@@ -70,7 +70,7 @@ export class WorkbenchContextKeysHandler
@@ -69,7 +69,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@@ -147,7 +147,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@IProductService private readonly productService: IProductService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IEditorService private readonly editorService: IEditorService,
@@ -205,6 +205,10 @@ export class WorkbenchContextKeysHandler
@@ -201,6 +201,10 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
@@ -166,12 +166,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
import { AutoSaveAfterShortDelayContext } from '../../../services/filesConfiguration/common/filesConfigurationService.js';
import { WorkbenchListDoubleSelection } from '../../../../platform/list/browser/listService.js';
import { Schemas } from '../../../../base/common/network.js';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ActiveEditorDirtyContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ActiveEditorDirtyContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
import { IsWebContext } from '../../../../platform/contextkey/common/contextkeys.js';
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
@@ -573,13 +573,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
@@ -571,13 +571,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},
@@ -195,7 +195,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
)
}));
@@ -591,6 +594,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
@@ -589,6 +592,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
title: UPLOAD_LABEL,
},
when: ContextKeyExpr.and(
@@ -207,7 +207,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
@@ -42,6 +42,9 @@ export const EmbedderIdentifierContext =
@@ -40,6 +40,9 @@ export const EmbedderIdentifierContext =
export const InAutomationContext = new RawContextKey<boolean>('inAutomation', false, localize('inAutomation', "Whether VS Code is running under automation/smoke test"));
@@ -230,7 +230,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.js';
@@ -152,7 +152,7 @@ export class SimpleFileDialog extends Di
@@ -161,7 +161,7 @@ export class SimpleFileDialog extends Di
@IFileDialogService private readonly fileDialogService: IFileDialogService,
@IModelService private readonly modelService: IModelService,
@ILanguageService private readonly languageService: ILanguageService,
@@ -239,7 +239,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@IPathService protected readonly pathService: IPathService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@@ -362,21 +362,23 @@ export class SimpleFileDialog extends Di
@@ -392,21 +392,23 @@ export class SimpleFileDialog extends Di
this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
this.filePickBox.ok = true;
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;

View File

@@ -135,7 +135,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -329,6 +329,11 @@ export interface IWorkbenchConstructionO
@@ -322,6 +322,11 @@ export interface IWorkbenchConstructionO
*/
readonly isEnabledFileUploads?: boolean
@@ -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
@@ -384,6 +384,7 @@ export class WebClientServer {
@@ -393,6 +393,7 @@ export class WebClientServer {
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
@@ -217,12 +217,12 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
import { Disposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
-import { IsEnabledFileDownloads, IsEnabledFileUploads, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
@@ -208,6 +208,7 @@ export class WorkbenchContextKeysHandler
@@ -204,6 +204,7 @@ export class WorkbenchContextKeysHandler
// code-server
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? 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
@@ -44,6 +44,7 @@ export const InAutomationContext = new R
@@ -42,6 +42,7 @@ export const InAutomationContext = new R
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);

View File

@@ -164,7 +164,7 @@ 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
@@ -64,6 +64,7 @@ import { IOpenerService } from '../../pl
@@ -65,6 +65,7 @@ import { IOpenerService } from '../../pl
import { mixin, safeStringify } from '../../base/common/objects.js';
import { IndexedDB } from '../../base/browser/indexedDB.js';
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
@@ -186,8 +186,8 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -97,6 +97,8 @@ export interface IDictationRuntimeProduc
}
@@ -65,6 +65,8 @@ export type ExtensionVirtualWorkspaceSup
};
export interface IProductConfiguration {
+ readonly codeServerVersion?: string
@@ -251,19 +251,19 @@ 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
@@ -349,6 +349,7 @@ export class WebClientServer {
@@ -353,6 +353,7 @@ export class WebClientServer {
} : undefined;
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
+ codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
...this._productService.extensionsGallery,
Index: code-server/lib/vscode/src/server-main.ts
===================================================================
--- code-server.orig/lib/vscode/src/server-main.ts
+++ code-server/lib/vscode/src/server-main.ts
@@ -23,6 +23,9 @@ import { IServerAPI } from './vs/server/
@@ -22,6 +22,9 @@ import { IServerAPI } from './vs/server/
perf.mark('code/server/start');
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
@@ -273,16 +273,7 @@ Index: code-server/lib/vscode/src/server-main.ts
// Do a quick parse to determine if a server or the cli needs to be started
const parsedArgs = minimist(process.argv.slice(2), {
boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'],
@@ -50,7 +53,7 @@ if (shouldSpawnCli) {
mod.spawnCli();
});
} else {
- installServerProcessExitDiagnostics();
+ installServerProcessExitDiagnostics(parsedArgs);
let _remoteExtensionHostAgentServer: IServerAPI | null = null;
let _remoteExtensionHostAgentServerPromise: Promise<IServerAPI> | null = null;
@@ -153,6 +156,7 @@ if (shouldSpawnCli) {
@@ -150,6 +153,7 @@ if (shouldSpawnCli) {
}
});
}
@@ -290,16 +281,7 @@ Index: code-server/lib/vscode/src/server-main.ts
function sanitizeStringArg(val: unknown): string | undefined {
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
@@ -173,7 +177,7 @@ function sanitizeStringArg(val: unknown)
* provided) so they survive process teardown (an async stdio write from an
* `exit` handler does not).
*/
-function installServerProcessExitDiagnostics(): void {
+function installServerProcessExitDiagnostics(parsedArgs: minimist.ParsedArgs): void {
if (!process.env['VSCODE_SERVER_EXIT_DIAGNOSTICS']) {
return;
}
@@ -406,3 +410,22 @@ function prompt(question: string): Promi
@@ -283,3 +287,22 @@ function prompt(question: string): Promi
});
});
}
@@ -326,7 +308,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
@@ -54,8 +54,11 @@ export function createWorkbenchDialogOpt
@@ -47,8 +47,11 @@ export function createWorkbenchDialogOpt
export function createBrowserAboutDialogDetails(productService: IProductService): { title: string; details: string; detailsToCopy: string } {
const detailString = (useAgo: boolean): string => {

View File

@@ -18,7 +18,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
@@ -375,6 +375,7 @@ export class WebClientServer {
@@ -384,6 +384,7 @@ export class WebClientServer {
remoteAuthority,
serverBasePath: basePath,
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
@@ -30,7 +30,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -314,6 +314,11 @@ export interface IWorkbenchConstructionO
@@ -307,6 +307,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, unknown>;

View File

@@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -100,6 +100,7 @@ export interface IProductConfiguration {
@@ -68,6 +68,7 @@ export interface IProductConfiguration {
readonly codeServerVersion?: string
readonly rootEndpoint?: string
readonly updateEndpoint?: string
@@ -40,14 +40,14 @@ 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
@@ -357,6 +357,7 @@ export class WebClientServer {
@@ -361,6 +361,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
};
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts

View File

@@ -19,9 +19,9 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
@@ -65,6 +65,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
Object.assign(product, { copilotVersions: { runtime, sdk } });
}
@@ -49,6 +49,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
version: pkg.version
});
}
+
+ Object.assign(product, {
@@ -41,7 +41,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
@@ -342,7 +342,6 @@ export class WebClientServer {
@@ -346,7 +346,6 @@ export class WebClientServer {
const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH);
const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH);
@@ -49,10 +49,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority });
@@ -359,14 +358,7 @@ export class WebClientServer {
@@ -362,14 +361,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
- ...this._productService.extensionsGallery,
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
@@ -64,7 +64,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+ extensionsGallery: this._productService.extensionsGallery,
};
if (!this._environmentService.isBuilt) {
const proposedApi = this._environmentService.args['enable-proposed-api'];
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts

View File

@@ -10,17 +10,18 @@ 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
@@ -324,6 +324,10 @@ function extensionDescriptionArrayToMap(
@@ -321,10 +321,7 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
+ return true;
+}
+
+export function _isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
if (!extension.enabledApiProposals) {
return false;
- if (!extension.enabledApiProposals) {
- return false;
- }
- return true;// extension.enabledApiProposals.includes(proposal);
+ return true
}
export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts

View File

@@ -30,7 +30,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -101,6 +101,7 @@ export interface IProductConfiguration {
@@ -69,6 +69,7 @@ export interface IProductConfiguration {
readonly rootEndpoint?: string
readonly updateEndpoint?: string
readonly logoutEndpoint?: string
@@ -71,14 +71,14 @@ 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
@@ -358,6 +358,7 @@ export class WebClientServer {
@@ -362,6 +362,7 @@ export class WebClientServer {
rootEndpoint: rootBase,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
};
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js';
@@ -612,6 +613,39 @@ class WorkspaceProvider implements IWork
@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
@@ -148,7 +148,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
===================================================================
--- 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
@@ -99,8 +99,8 @@ export class ForwardedPortsView extends
@@ -83,8 +83,8 @@ export class ForwardedPortsView extends
private async enableForwardedPortsFeatures() {
this.contextKeyListener.clear();

View File

@@ -24,4 +24,3 @@ trusted-domains.diff
signature-verification.diff
copilot.diff
app-name.diff
csp-hashes.diff

View File

@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -102,6 +102,10 @@ export interface IProductConfiguration {
@@ -70,6 +70,10 @@ export interface IProductConfiguration {
readonly updateEndpoint?: string
readonly logoutEndpoint?: string
readonly proxyEndpointTemplate?: string
@@ -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
@@ -359,6 +359,10 @@ export class WebClientServer {
@@ -363,6 +363,10 @@ export class WebClientServer {
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
@@ -63,5 +63,5 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
+ },
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
};

View File

@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.ts
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.ts
+++ code-server/lib/vscode/build/gulpfile.reh.ts
@@ -344,10 +344,15 @@ function packageTask(type: string, platf
@@ -261,10 +261,15 @@ function packageTask(type: string, platf
const destination = path.join(BUILD_ROOT, destinationFolderName);
return () => {

View File

@@ -12,7 +12,15 @@ 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
@@ -68,6 +68,7 @@ import { IExtensionsScannerService } fro
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { hostname, release } from 'os';
+import { promises as fs } from 'fs';
import { Emitter, Event } from '../../base/common/event.js';
import { DisposableStore, toDisposable } from '../../base/common/lifecycle.js';
import { Schemas } from '../../base/common/network.js';
@@ -65,6 +66,7 @@ import { IExtensionsScannerService } fro
import { ExtensionsScannerService } from './extensionsScannerService.js';
import { IExtensionsProfileScannerService } from '../../platform/extensionManagement/common/extensionsProfileScannerService.js';
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';
@@ -20,18 +28,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
import { NullPolicyService } from '../../platform/policy/common/policy.js';
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
import { LoggerService } from '../../platform/log/node/loggerService.js';
@@ -179,11 +180,23 @@ export async function setupServerService
@@ -176,11 +178,23 @@ export async function setupServerService
const requestService = new RequestService('remote', configurationService, environmentService, logService);
services.set(IRequestService, requestService);
+ let isContainer = undefined;
+ try {
+ await fs.promises.stat('/run/.containerenv');
+ await fs.stat('/run/.containerenv');
+ isContainer = true;
+ } catch (error) { /* Does not exist, probably. */ }
+ if (!isContainer) {
+ try {
+ const content = await fs.promises.readFile('/proc/self/cgroup', 'utf8')
+ const content = await fs.readFile('/proc/self/cgroup', 'utf8')
+ isContainer = content.includes('docker');
+ } catch (error) { /* Permission denied, probably. */ }
+ }
@@ -126,20 +134,20 @@ 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
@@ -363,6 +363,8 @@ export class WebClientServer {
@@ -367,6 +367,8 @@ export class WebClientServer {
scope: vscodeBase + '/',
path: rootBase + '/_static/out/browser/serviceWorker.js',
},
+ enableTelemetry: this._productService.enableTelemetry,
+ telemetryEndpoint: this._productService.telemetryEndpoint,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
};
Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -106,6 +106,7 @@ export interface IProductConfiguration {
@@ -74,6 +74,7 @@ export interface IProductConfiguration {
readonly path: string;
readonly scope: string;
}
@@ -151,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
@@ -74,7 +74,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
@@ -58,7 +58,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
controlUrl: "",
recommendationsUrl: "",

View File

@@ -24,7 +24,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
@@ -354,6 +354,14 @@ export class WebClientServer {
@@ -358,6 +358,14 @@ export class WebClientServer {
scopes: [['user:email'], ['repo']]
} : undefined;
@@ -39,11 +39,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
@@ -369,6 +377,7 @@ export class WebClientServer {
@@ -372,6 +380,7 @@ export class WebClientServer {
telemetryEndpoint: this._productService.telemetryEndpoint,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
+ linkProtectionTrustedDomains,
};
if (!this._environmentService.isBuilt) {
const proposedApi = this._environmentService.args['enable-proposed-api'];

View File

@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
export class BrowserStorageService extends AbstractStorageService {
@@ -354,7 +355,11 @@ export class IndexedDBStorageDatabase ex
@@ -328,7 +329,11 @@ export class IndexedDBStorageDatabase ex
}
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {

View File

@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -99,6 +99,7 @@ export interface IDictationRuntimeProduc
@@ -67,6 +67,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration {
readonly codeServerVersion?: string
readonly rootEndpoint?: string
@@ -101,26 +101,26 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
readonly version: string;
readonly date?: string;
@@ -151,6 +152,7 @@ export interface IProductConfiguration {
@@ -119,6 +120,7 @@ export interface IProductConfiguration {
readonly resourceUrlTemplate: string;
readonly nlsBaseUrl: string;
readonly accessSKUs?: string[];
+ readonly authorizationHeaderToken?: string;
};
readonly agentSdks?: { readonly [packageId: string]: IAgentSdkProductConfig };
readonly mcpGallery?: {
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
@@ -356,6 +356,7 @@ export class WebClientServer {
@@ -360,6 +360,7 @@ export class WebClientServer {
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
embedderIdentifier: 'server-distro',
voiceWsUrl: this._productService.voiceWsUrl,
extensionsGallery: this._productService.extensionsGallery,
};
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts

View File

@@ -3,6 +3,9 @@ Serve webviews from the same origin
Normally webviews are served from vscode-webview.net but we would rather them be
self-hosted.
When doing this CSP will block resources (for example when viewing images) so
add 'self' to the CSP to fix that.
Additionally the service worker defaults to handling *all* requests made to the
current host but when self-hosting the webview this will end up including the
webview HTML itself which means these requests will fail since the communication
@@ -17,6 +20,16 @@ webview host is separate by default but we serve on the same host).
To test, open a few types of webviews (images, markdown, extension details, etc).
Make sure to update the hash. To do so:
1. run code-server
2. open any webview (i.e. preview Markdown)
3. see error in console and copy hash
That will test the hash change in pre/index.html
Double-check the console to make sure there are no console errors for the webWorkerExtensionHostIframe
which also requires a hash change.
parentOriginHash changes
This fixes webviews from not working properly due to a change upstream.
@@ -28,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -234,7 +234,7 @@ export class BrowserWorkbenchEnvironment
@@ -223,7 +223,7 @@ export class BrowserWorkbenchEnvironment
@memoize
get webviewExternalEndpoint(): string {
@@ -41,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
@@ -371,6 +371,7 @@ export class WebClientServer {
@@ -380,6 +380,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
serverBasePath: basePath,
@@ -53,10 +66,19 @@ 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.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -5,7 +5,7 @@
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-q+WTr+fBXpLLE3++yWNaxT6BTWQtsKscoeIlynBRk4E=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-m1DlJtsIJd46QuWYNcsaYIG1xI+9FyjKQu+cfp+zq5Q=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -253,7 +253,7 @@
}
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}&platform=${searchParams.get('platform')}`);
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);
- navigator.serviceWorker.register(swPath, { type: 'module', updateViaCache: 'none' })
+ navigator.serviceWorker.register(swPath)
.then(async registration => {
@@ -79,8 +101,17 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
@@ -34,6 +34,13 @@
}
@@ -4,7 +4,7 @@
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
- script-src 'self' 'unsafe-eval' 'sha256-cl8ijlOzEe+0GRCQNJQu2k6nUQ0fAYNYIuuKEm72JDs=' https: http://localhost:* blob:;
+ script-src 'self' 'unsafe-eval' 'sha256-yhZXuB8LS6t73dvNg6rtLX8y4PHLnqRm5+6DdOGkOcw=' https: http://localhost:* blob:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>
@@ -25,6 +25,13 @@
// validation not requested
return start();
}
+

View File

@@ -13,8 +13,7 @@ import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSo
import { handleUpgrade } from "./wsRouter"
type SocketOptions = { socket: string; "socket-mode"?: string }
type FdOptions = { "socket-fd": number }
type ListenOptions = DefaultedArgs | SocketOptions | FdOptions
type ListenOptions = DefaultedArgs | SocketOptions
export interface App extends Disposable {
/** Handles regular HTTP requests. */
@@ -31,12 +30,8 @@ const isSocketOpts = (opts: ListenOptions): opts is SocketOptions => {
return !!(opts as SocketOptions).socket || !(opts as DefaultedArgs).host
}
export const isFdOpts = (opts: ListenOptions): opts is FdOptions => {
return typeof (opts as FdOptions)["socket-fd"] === "number"
}
export const listen = async (server: http.Server, opts: ListenOptions) => {
if (!isFdOpts(opts) && isSocketOpts(opts)) {
if (isSocketOpts(opts)) {
try {
await fs.unlink(opts.socket)
} catch (error: any) {
@@ -51,9 +46,7 @@ export const listen = async (server: http.Server, opts: ListenOptions) => {
server.on("error", (err) => util.logError(logger, "http server error", err))
resolve()
}
if (isFdOpts(opts)) {
server.listen({ fd: opts["socket-fd"] }, onListen)
} else if (isSocketOpts(opts)) {
if (isSocketOpts(opts)) {
server.listen(opts.socket, onListen)
} else {
// [] is the correct format when using :: but Node errors with them.
@@ -63,7 +56,7 @@ export const listen = async (server: http.Server, opts: ListenOptions) => {
// NOTE@jsjoeio: we need to chmod after the server is finished
// listening. Otherwise, the socket may not have been created yet.
if (!isFdOpts(opts) && isSocketOpts(opts)) {
if (isSocketOpts(opts)) {
if (opts["socket-mode"]) {
await fs.chmod(opts.socket, opts["socket-mode"])
}

View File

@@ -83,7 +83,6 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
open?: boolean
"bind-addr"?: string
socket?: string
"socket-fd"?: number
"socket-mode"?: string
"trusted-origins"?: string[]
version?: boolean
@@ -98,7 +97,6 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
"abs-proxy-base-path"?: string
i18n?: string
"idle-timeout-seconds"?: number
"vscode-option"?: string[]
/* Positional arguments. */
_?: string[]
}
@@ -237,10 +235,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
port: { type: "number", description: "" },
socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
"socket-fd": {
type: "number",
description: "File descriptor of a pre-bound, listening socket to use (for systemd socket activation).",
},
"socket-mode": { type: "string", description: "File mode of the socket." },
"trusted-origins": {
type: "string[]",
@@ -328,13 +322,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
"Override the reconnection grace time in seconds. Clients who disconnect for longer than this duration will need to \n" +
"reload the window. Defaults to 10800 (3 hours).",
},
"vscode-option": {
type: "string[]",
description:
"Pass an option straight through to the VS Code server as flag=value, or as a bare flag for a \n" +
"boolean. Repeatable; repeating the same flag builds an array. Use this to reach VS Code options \n" +
"code-server does not model itself, e.g. --vscode-option enable-sandbox --vscode-option agents=true.",
},
}
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
@@ -656,15 +643,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["reconnection-grace-time"] = process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
}
// Space-separated, like NODE_OPTIONS. Appended to any flags rather than
// replacing them so the two can be combined.
if (process.env.VSCODE_OPTIONS) {
args["vscode-option"] = [
...(args["vscode-option"] ?? []),
...process.env.VSCODE_OPTIONS.split(/\s+/).filter((option) => option),
]
}
if (process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) {
if (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
@@ -931,58 +909,17 @@ export interface CodeArgs extends UserProvidedCodeArgs {
log?: string[]
}
/**
* Expand --vscode-option entries into VS Code server arguments.
*
* An entry is `flag=value`, or a bare `flag` meaning true. A leading `--` on
* the flag is optional, so both spellings people reach for work. Repeating a
* flag collects the values into an array, since several VS Code options take
* one.
*
* `true` and `false` become booleans rather than strings. VS Code tests these
* flags for truthiness and the string "false" is truthy, so passing it along
* verbatim would quietly do the opposite of what was asked.
*/
export const parseVscodeOptions = (entries: string[]): Record<string, string | boolean | string[]> => {
const parsed: Record<string, string | boolean | string[]> = {}
for (const entry of entries) {
const [flag, rawValue] = splitOnFirstEquals(entry.replace(/^--/, ""))
if (!flag) {
throw new Error(`--vscode-option requires a flag name (got "${entry}")`)
}
const value: string | boolean =
typeof rawValue === "undefined" || rawValue === "true" ? true : rawValue === "false" ? false : rawValue
const existing = parsed[flag]
if (typeof existing === "undefined") {
parsed[flag] = value
} else if (Array.isArray(existing)) {
existing.push(String(value))
} else {
parsed[flag] = [String(existing), String(value)]
}
}
return parsed
}
/**
* Convert our arguments to equivalent VS Code server arguments.
* Does not add any extra arguments.
*/
export const toCodeArgs = async (args: DefaultedArgs): Promise<CodeArgs> => {
// The passthrough option is ours; VS Code has no idea what it is.
const { "vscode-option": vscodeOptions, ...rest } = args
return {
...rest,
...args,
/** Type casting. */
help: !!args.help,
version: !!args.version,
port: args.port?.toString(),
log: args.log ? [args.log] : undefined,
// Last, so that reaching an option code-server does model still works.
...parseVscodeOptions(vscodeOptions ?? []),
} as CodeArgs
}
}

View File

@@ -1,13 +1,9 @@
import { logger } from "@coder/logger"
import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
import * as os from "os"
import * as path from "path"
type PackageJson = {
version: string
commit: string
}
export function getPackageJson(relativePath: string): PackageJson {
export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
let pkg = {}
try {
pkg = require(relativePath)
@@ -15,7 +11,7 @@ export function getPackageJson(relativePath: string): PackageJson {
logger.warn(error.message)
}
return pkg as PackageJson
return pkg
}
export const rootPath = path.resolve(__dirname, "../..")

View File

@@ -54,6 +54,7 @@ init({
lowerCaseLng: true,
debug: process.env.NODE_ENV === "development",
resources: defaultResources,
showSupportNotice: false,
})
export default i18next

View File

@@ -1,7 +1,5 @@
import * as cookie from "cookie"
import type { Request } from "express"
import proxyServer from "http-proxy"
import { getCookieSessionName, HttpCode } from "../common/http"
import { HttpCode } from "../common/http"
export const proxy = proxyServer.createProxyServer({})
@@ -20,33 +18,6 @@ proxy.on("error", (error, _, res) => {
}
})
function identity<T>(val: T): T {
return val
}
// Strip the code-server cookie if it exists to avoid transmitting the cookie
// to potentially malicious local ports.
proxy.on("proxyReq", (preq, req) => {
if (req.headers.cookie) {
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
// Encoding and decoding are no-ops; we just want to remove the token
// without changing anything else about the cookies because not all
// applications encode/decode the same way `cookie` here does.
preq.setHeader(
"Cookie",
cookie.stringifyCookie(
{
...cookie.parseCookie(req.headers.cookie, { decode: identity }),
[cookieSessionName]: undefined,
},
{
encode: identity,
},
),
)
}
})
// Intercept the response to rewrite absolute redirects against the base path.
// Is disabled when the request has no base path which means /absproxy is in use.
proxy.on("proxyRes", (res, req) => {

View File

@@ -210,7 +210,7 @@ router.get("/manifest.json", async (req, res) => {
})
let mintKeyPromise: Promise<Buffer> | undefined
router.post("/mint-key", ensureAuthenticated, async (req, res) => {
router.post("/mint-key", async (req, res) => {
if (!mintKeyPromise) {
mintKeyPromise = new Promise(async (resolve) => {
const keyPath = path.join(req.args["user-data-dir"], "serve-web-key-half")

View File

@@ -32,7 +32,7 @@ describe("code-server", ["--disable-workspace-trust"], {}, () => {
test("should show the Integrated Terminal", async ({ codeServerPage }) => {
await codeServerPage.focusTerminal()
await expect(codeServerPage.page.locator("#terminal")).toBeVisible()
expect(await codeServerPage.page.isVisible("#terminal")).toBe(true)
})
test("should open a file", async ({ codeServerPage }) => {

View File

@@ -18,7 +18,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
// Action
await codeServerPage.openContextMenu("text=unique-file.txt")
await expect(codeServerPage.page.locator("text=Download...")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true)
})
test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => {
@@ -37,7 +37,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
await codeServerPage.page.keyboard.type("Making some edits.")
await codeServerPage.navigateMenus(["File", "Save As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
@@ -46,14 +46,14 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
await codeServerPage.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
})
@@ -72,7 +72,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
// Action
await codeServerPage.openContextMenu("text=unique-file.txt")
await expect(codeServerPage.page.locator("text=Download...")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false)
})
test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => {
@@ -87,7 +87,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
await codeServerPage.openFile(fileName)
await codeServerPage.page.click(".tab")
await codeServerPage.navigateMenus(["File", "Save As..."])
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
test("should not see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
@@ -96,13 +96,13 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
await codeServerPage.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
})

View File

@@ -13,7 +13,7 @@ function runTestExtensionTests() {
// Remove end slash in address.
const normalizedAddress = address.replace(/\/+$/, "")
await expect(codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)).toBeVisible()
await codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)
})
}

View File

@@ -12,7 +12,7 @@ if (process.env.GITHUB_TOKEN) {
await codeServerPage.page.click("text=Allow")
// It should ask to select an account, one of which will be the one we
// pre-injected.
await expect(codeServerPage.page.locator("text=Select an account")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Select an account")).toBe(false)
})
})
@@ -26,7 +26,7 @@ if (process.env.GITHUB_TOKEN) {
await codeServerPage.page.click("text=Allow")
// Since there is no account it will ask directly for the token (because
// we are on localhost; otherwise it would initiate the oauth flow).
await expect(codeServerPage.page.locator("text=GitHub Personal Access Token")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=GitHub Personal Access Token")).toBe(false)
})
})
} else {

View File

@@ -24,8 +24,8 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
// Skip entering password
// Click the submit button and login
await codeServerPage.page.click(".submit")
// The required input blocks empty submits, so the server-side error can't render.
await expect(codeServerPage.page.locator("input.password:invalid")).toBeVisible()
await codeServerPage.page.waitForLoadState("networkidle")
expect(await codeServerPage.page.isVisible("text=Missing password"))
})
test("should see an error message for incorrect password", async ({ codeServerPage }) => {
@@ -34,29 +34,28 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
// Click the submit button and login
await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle")
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
})
test("should hit the rate limiter for too many unsuccessful logins", async ({ codeServerPage }) => {
test.slow()
// Type in password
await codeServerPage.page.fill(".password", "password123")
// Click the submit button and login
// The current RateLimiter allows 2 logins per minute plus
// 12 logins per hour for a total of 14
// See: src/node/routes/login.ts
for (let i = 1; i <= 14; i++) {
await codeServerPage.page.fill(".password", "password123")
await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle")
// We double-check that the correct error message shows
// which should be for incorrect password
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
}
// The 15th should fail for a different reason:
// login rate
await codeServerPage.page.fill(".password", "password123")
await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle")
await expect(codeServerPage.page.locator("text=Login rate limited!")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Login rate limited!"))
})
})

View File

@@ -18,14 +18,14 @@ describe("Uploads (enabled)", ["--disable-workspace-trust"], {}, () => {
// Action
await codeServerPage.openContextMenu('span:has-text("test-directory")')
await expect(codeServerPage.page.locator("text=Upload...")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(true)
})
test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
})
})
@@ -44,13 +44,13 @@ describe("Uploads (disabled)", ["--disable-workspace-trust", "--disable-file-upl
// Action
await codeServerPage.openContextMenu('span:has-text("test-directory")')
await expect(codeServerPage.page.locator("text=Upload...")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(false)
})
test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action
await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget")
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
})
})

109
test/package-lock.json generated
View File

@@ -7,7 +7,7 @@
"license": "MIT",
"devDependencies": {
"@jest-mock/express": "^1.4.5",
"@playwright/test": "^1.61.0",
"@playwright/test": "^1.56.1",
"@types/jest": "^27.0.2",
"@types/jsdom": "^16.2.13",
"@types/node-fetch": "^2.5.8",
@@ -18,7 +18,7 @@
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0",
"node-fetch": "^2.6.7",
"playwright": "^1.61.0",
"playwright": "^1.59.1",
"ts-jest": "^27.0.7",
"wtfnode": "^0.9.1"
}
@@ -998,13 +998,13 @@
}
},
"node_modules/@playwright/test": {
"version": "1.61.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.0.tgz",
"integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==",
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.61.0"
"playwright": "1.56.1"
},
"bin": {
"playwright": "cli.js"
@@ -1013,6 +1013,53 @@
"node": ">=18"
}
},
"node_modules/@playwright/test/node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/@playwright/test/node_modules/playwright": {
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.56.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/@playwright/test/node_modules/playwright-core": {
"version": "1.56.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sinonjs/commons": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
@@ -1498,9 +1545,9 @@
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2289,17 +2336,17 @@
}
},
"node_modules/form-data": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4",
"mime-types": "^2.1.35"
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
@@ -2514,9 +2561,9 @@
}
},
"node_modules/hasown": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3555,16 +3602,16 @@
}
},
"node_modules/jsdom/node_modules/form-data": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz",
"integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz",
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4",
"hasown": "^2.0.2",
"mime-types": "^2.1.35"
},
"engines": {
@@ -4067,13 +4114,13 @@
}
},
"node_modules/playwright": {
"version": "1.61.0",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.0.tgz",
"integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==",
"version": "1.59.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
"integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.61.0"
"playwright-core": "1.59.1"
},
"bin": {
"playwright": "cli.js"
@@ -4086,9 +4133,9 @@
}
},
"node_modules/playwright-core": {
"version": "1.61.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz",
"integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==",
"version": "1.59.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
"integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4937,9 +4984,9 @@
}
},
"node_modules/ws": {
"version": "7.5.13",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz",
"integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==",
"version": "7.5.10",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"dev": true,
"license": "MIT",
"engines": {

View File

@@ -3,7 +3,7 @@
"#": "We must put jest in a sub-directory otherwise VS Code somehow picks up the types and generates conflicts with mocha.",
"devDependencies": {
"@jest-mock/express": "^1.4.5",
"@playwright/test": "^1.61.0",
"@playwright/test": "^1.56.1",
"@types/jest": "^27.0.2",
"@types/jsdom": "^16.2.13",
"@types/node-fetch": "^2.5.8",
@@ -14,7 +14,7 @@
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0",
"node-fetch": "^2.6.7",
"playwright": "^1.61.0",
"playwright": "^1.59.1",
"ts-jest": "^27.0.7",
"wtfnode": "^0.9.1"
},

View File

@@ -3,7 +3,7 @@ import { promises } from "fs"
import * as http from "http"
import * as https from "https"
import * as path from "path"
import { createApp, ensureAddress, handleArgsSocketCatchError, isFdOpts, listen } from "../../../src/node/app"
import { createApp, ensureAddress, handleArgsSocketCatchError, listen } from "../../../src/node/app"
import { OptionalString, setDefaults } from "../../../src/node/cli"
import { generateCertificate } from "../../../src/node/util"
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
@@ -261,47 +261,3 @@ describe("listen", () => {
}
})
})
describe("listen (socket-fd)", () => {
// Wrap a bound-but-not-yet-listening TCP socket so we get a real file
// descriptor that listen({ fd }) can adopt, mirroring the systemd socket
// activation case where the process inherits an fd and calls listen(2) on it.
// Using a live net.Server's fd instead fails with EEXIST because the socket
// is already listening in-process.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { TCP, constants: TCPConstants } = (process as any).binding("tcp_wrap")
let inherited: any
let httpServer: http.Server
let unlinkSpy: jest.SpyInstance
beforeEach(async () => {
mockLogger()
unlinkSpy = jest.spyOn(promises, "unlink")
inherited = new TCP(TCPConstants.SERVER)
inherited.bind("127.0.0.1", 0)
httpServer = http.createServer()
})
afterEach(() => {
httpServer.close()
try {
inherited.close()
} catch {
// The fd is adopted by httpServer.close() above; ignore double-close.
}
jest.clearAllMocks()
})
it("isFdOpts detects a numeric socket-fd", () => {
expect(isFdOpts({ "socket-fd": 3 })).toBe(true)
expect(isFdOpts({ socket: "/tmp/x.sock" } as any)).toBe(false)
})
it("listens on an inherited fd without unlinking", async () => {
const fd = inherited.fd as number
await listen(httpServer, { "socket-fd": fd })
expect(httpServer.address()).not.toBeNull()
expect(unlinkSpy).not.toHaveBeenCalled()
})
})

View File

@@ -51,7 +51,6 @@ describe("parser", () => {
delete process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
delete process.env.VSCODE_PROXY_URI
delete process.env.CS_DISABLE_PROXY
delete process.env.VSCODE_OPTIONS
console.log = jest.fn()
})
@@ -414,17 +413,6 @@ describe("parser", () => {
})
})
it("should use env var VSCODE_OPTIONS", async () => {
process.env.VSCODE_OPTIONS = "--enable-sandbox agents=true"
const args = parse(["--vscode-option", "verbose-logging"])
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"vscode-option": ["verbose-logging", "--enable-sandbox", "agents=true"],
})
})
it("should use env var CS_DISABLE_GETTING_STARTED_OVERRIDE", async () => {
process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE = "1"
const args = parse([])
@@ -1018,44 +1006,6 @@ describe("toCodeArgs", () => {
_: [file],
})
})
it("should pass through --vscode-option", async () => {
const args = parse([
"--vscode-option",
"enable-sandbox",
"--vscode-option",
"agents=true",
"--vscode-option",
"enable-smoke-test-driver=false",
])
expect(await toCodeArgs(await setDefaults(args))).toStrictEqual({
...vscodeDefaults,
"enable-sandbox": true,
agents: true,
"enable-smoke-test-driver": false,
})
})
it("should collect a repeated --vscode-option into an array", async () => {
const args = parse([
"--vscode-option",
"locate-extension=a",
"--vscode-option",
"locate-extension=b",
"--vscode-option",
"locate-extension=c",
])
expect(await toCodeArgs(await setDefaults(args))).toStrictEqual({
...vscodeDefaults,
"locate-extension": ["a", "b", "c"],
})
})
it("should error if --vscode-option has no flag", async () => {
await expect(toCodeArgs(await setDefaults(parse(["--vscode-option", "=nothing"])))).rejects.toThrow(
"--vscode-option requires a flag name",
)
})
})
describe("optionDescriptions", () => {

View File

@@ -1,9 +1,10 @@
import { logger } from "@coder/logger"
import { readFile, writeFile, stat, utimes } from "fs/promises"
import { setImmediate } from "timers"
import { Heart } from "../../../src/node/heart"
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
describe("Heart", () => {
const testName = "heartTests"
let testDir = ""
@@ -14,15 +15,12 @@ describe("Heart", () => {
await clean(testName)
testDir = await tmpdir(testName)
})
beforeEach(() => {
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
})
afterAll(() => {
jest.restoreAllMocks()
})
beforeEach(() => {
heart = new Heart(`${testDir}/shutdown.txt`, jest.fn().mockResolvedValue(true))
})
afterEach(() => {
jest.resetAllMocks()
jest.useRealTimers()
@@ -30,7 +28,6 @@ describe("Heart", () => {
heart.dispose()
}
})
it("should write to a file when given a valid file path", async () => {
// Set up heartbeat file with contents
const text = "test"
@@ -45,7 +42,7 @@ describe("Heart", () => {
expect(fileContents).toBe(text)
heart = new Heart(pathToFile, jest.fn().mockResolvedValue(true))
heart = new Heart(pathToFile, mockIsActive(true))
await heart.beat()
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
@@ -54,30 +51,31 @@ describe("Heart", () => {
const fileStatusAfterEdit = await stat(pathToFile)
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
})
it("should log a warning when given an invalid file path", async () => {
heart = new Heart(`fakeDir/fake.txt`, jest.fn().mockResolvedValue(false))
heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false))
await heart.beat()
expect(logger.warn).toHaveBeenCalled()
})
it("should be active after calling beat", async () => {
await heart.beat()
const isAlive = heart.alive()
expect(isAlive).toBe(true)
})
it("should not be active after dispose is called", () => {
heart.dispose()
const isAlive = heart.alive()
expect(isAlive).toBe(false)
})
it("should beat twice without warnings", async () => {
heart = new Heart(`${testDir}/hello.txt`, jest.fn().mockResolvedValue(true))
// Use fake timers so we can speed up setTimeout
jest.useFakeTimers()
heart = new Heart(`${testDir}/hello.txt`, mockIsActive(true))
await heart.beat()
// we need to speed up clocks, timeouts
// call heartbeat again (and it won't be alive I think)
// then assert no warnings were called
jest.runAllTimers()
expect(logger.warn).not.toHaveBeenCalled()
})
@@ -86,48 +84,40 @@ describe("Heart", () => {
describe("heartbeatTimer", () => {
const testName = "heartbeatTimer"
let testDir = ""
beforeAll(async () => {
await clean(testName)
testDir = await tmpdir(testName)
mockLogger()
})
afterAll(() => {
jest.restoreAllMocks()
})
beforeEach(() => {
jest.useFakeTimers()
})
afterEach(() => {
jest.resetAllMocks()
jest.clearAllTimers()
jest.useRealTimers()
})
it("should call isActive when timeout expires", async () => {
const mockIsActive = jest.fn().mockResolvedValue(true)
const isActive = true
const mockIsActive = jest.fn().mockResolvedValue(isActive)
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat()
jest.advanceTimersByTime(60 * 1000)
expect(mockIsActive).toHaveBeenCalled()
})
it("should log a warning when isActive rejects", async () => {
const error = new Error("oh no")
const errorMsg = "oh no"
const error = new Error(errorMsg)
const mockIsActive = jest.fn().mockRejectedValue(error)
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat()
jest.advanceTimersByTime(60 * 1000)
expect(mockIsActive).toHaveBeenCalled()
// The timer callback waits on mockIsActive, so we need to yield to let the
// callback finish.
await new Promise((resolve) => setImmediate(resolve))
expect(logger.warn).toHaveBeenCalledWith(error.message)
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
})
})
@@ -135,54 +125,38 @@ describe("stateChange", () => {
const testName = "stateChange"
let testDir = ""
let heart: Heart
beforeAll(async () => {
await clean(testName)
testDir = await tmpdir(testName)
mockLogger()
})
afterAll(() => {
jest.restoreAllMocks()
})
beforeEach(() => {
jest.useFakeTimers()
})
afterEach(() => {
jest.resetAllMocks()
jest.useRealTimers()
if (heart) {
heart.dispose()
}
})
it("should change to alive after a beat", async () => {
const mockIsActive = jest.fn().mockResolvedValue(true)
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
const mockOnChange = jest.fn()
heart.onChange(mockOnChange)
await heart.beat()
expect(mockOnChange.mock.calls[0][0]).toBe("alive")
})
it("should change to expired when not active", async () => {
const mockIsActive = jest.fn().mockResolvedValue(false)
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
it.only("should change to expired when not active", async () => {
jest.useFakeTimers()
heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false)))
const mockOnChange = jest.fn()
heart.onChange(mockOnChange)
await heart.beat()
jest.advanceTimersByTime(60 * 1000)
expect(mockIsActive).toHaveBeenCalled()
// The timer callback waits on the isActive promise, so we need to yield to
// let the callback finish.
await new Promise((resolve) => setImmediate(resolve))
await jest.advanceTimersByTime(60 * 1000)
expect(mockOnChange.mock.calls[1][0]).toBe("expired")
jest.clearAllTimers()
jest.useRealTimers()
})
})

View File

@@ -1,12 +1,15 @@
import * as express from "express"
import * as http from "http"
import nodeFetch from "node-fetch"
import { HttpCode } from "../../../src/common/http"
import { proxy } from "../../../src/node/proxy"
import { wss, Router as WsRouter } from "../../../src/node/wsRouter"
import { mockLogger } from "../../utils/helpers"
import { getAvailablePort, mockLogger } from "../../utils/helpers"
import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration"
describe("proxy", () => {
const proxyTarget = new httpserver.HttpServer()
const nhooyrDevServer = new httpserver.HttpServer()
const wsApp = express.default()
const wsRouter = WsRouter()
let codeServer: httpserver.HttpServer | undefined
@@ -16,22 +19,21 @@ describe("proxy", () => {
beforeAll(async () => {
wsApp.use("/", wsRouter.router)
await proxyTarget.listen((req, res) => {
await nhooyrDevServer.listen((req, res) => {
e(req, res)
})
proxyTarget.listenUpgrade(wsApp)
proxyPath = `/proxy/${proxyTarget.port()}/wsup`
nhooyrDevServer.listenUpgrade(wsApp)
proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
})
afterAll(async () => {
await proxyTarget.dispose()
await nhooyrDevServer.dispose()
})
beforeEach(() => {
e = express.default()
mockLogger()
delete process.env.PASSWORD
})
afterEach(async () => {
@@ -281,61 +283,65 @@ describe("proxy", () => {
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
expect(resp.status).toBe(200)
})
})
it("should return a 500 when no target is running ", async () => {
const target = new httpserver.HttpServer()
await target.listen(() => {})
const port = target.port()
target.dispose()
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch(`/proxy/${port}/wsup`)
expect(resp.status).toBe(HttpCode.ServerError)
expect(resp.statusText).toBe("Internal Server Error")
// NOTE@jsjoeio
// Both this test suite and the one above it are very similar
// The main difference is this one uses http and node-fetch
// and specifically tests the proxy in isolation vs. using
// the httpserver abstraction we've built.
//
// Leaving this as a separate test suite for now because
// we may consider refactoring the httpserver abstraction
// in the future.
//
// If you're writing a test specifically for code in
// src/node/proxy.ts, you should probably add it to
// this test suite.
describe("proxy (standalone)", () => {
let URL = ""
let PROXY_URL = ""
let testServer: http.Server
let proxyTarget: http.Server
beforeEach(async () => {
const PORT = await getAvailablePort()
const PROXY_PORT = await getAvailablePort()
URL = `http://localhost:${PORT}`
PROXY_URL = `http://localhost:${PROXY_PORT}`
// Define server and a proxy server
testServer = http.createServer((req, res) => {
proxy.web(req, res, {
target: PROXY_URL,
})
})
it("should strip token cookie", async () => {
const token = "my-super-secure-token"
process.env.HASHED_PASSWORD = token
codeServer = await integration.setup(["--auth=password"])
e.get("/wsup/cookies", (req, res) => {
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" })
res.end(req.headers.cookie)
proxyTarget = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" })
res.end()
})
const cookies = [
"cookie2=hello",
// Cookies should pass through unchanged, neither encoded nor decoded.
`cookie1=${encodeURIComponent("hello=there")}`,
"cookie3=foo|bar",
`cookie4=${encodeURIComponent("foo|bar")}`,
`cookie5=${encodeURIComponent("bar;baz")}`,
]
// Test each slot to ensure the token is found anywhere.
for (let i = 0; i <= cookies.length; ++i) {
const left = cookies.slice(0, i)
const right = cookies.slice(i)
const resp = await codeServer.fetch(proxyPath + "/cookies", {
headers: {
cookie: [...left, `code-server-session=${token}`, ...right].join("; "),
},
// Start both servers
proxyTarget.listen(PROXY_PORT)
testServer.listen(PORT)
})
afterEach(async () => {
testServer.close()
proxyTarget.close()
})
it("should return a 500 when proxy target errors ", async () => {
// Close the proxy target so that proxy errors
proxyTarget.close()
const errorResp = await nodeFetch(`${URL}/error`)
expect(errorResp.status).toBe(HttpCode.ServerError)
expect(errorResp.statusText).toBe("Internal Server Error")
})
it("should proxy correctly", async () => {
const resp = await nodeFetch(`${URL}/route`)
expect(resp.status).toBe(200)
expect(await resp.text()).toBe(cookies.join("; "))
}
})
it("should proxy when no cookies", async () => {
codeServer = await integration.setup(["--auth=none"])
e.get("/wsup/cookies", (req, res) => {
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" })
res.end(req.headers.cookie || "no cookies")
})
const resp = await codeServer.fetch(proxyPath + "/cookies")
expect(resp.status).toBe(200)
expect(await resp.text()).toBe("no cookies")
expect(resp.statusText).toBe("OK")
})
})

View File

@@ -4,19 +4,11 @@ import * as integration from "../../../utils/integration"
describe("vscode", () => {
let codeServer: httpserver.HttpServer | undefined
// TODO: Support setting this as an argument for tests.
const previousEnvPassword = process.env.PASSWORD
beforeEach(() => {
process.env.PASSWORD = "test"
mockLogger()
})
afterEach(async () => {
if (typeof previousEnvPassword !== "undefined") {
process.env.PASSWORD = previousEnvPassword
} else {
delete process.env.PASSWORD
}
if (codeServer) {
await codeServer.dispose()
codeServer = undefined
@@ -35,10 +27,4 @@ describe("vscode", () => {
})
}).rejects.toThrow()
})
it("should require auth", async () => {
codeServer = await integration.setup(["--auth=password"], "")
const resp = await codeServer.fetch("/mint-key", { method: "POST" })
expect(resp.status).toBe(401)
})
})