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
47 changed files with 507 additions and 592 deletions

View File

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

View File

@@ -25,8 +25,8 @@ jobs:
docs: ${{ steps.filter.outputs.docs }} docs: ${{ steps.filter.outputs.docs }}
helm: ${{ steps.filter.outputs.helm }} helm: ${{ steps.filter.outputs.helm }}
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
id: filter id: filter
with: with:
filters: | filters: |
@@ -55,7 +55,7 @@ jobs:
name: Run prettier check name: Run prettier check
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -72,7 +72,7 @@ jobs:
needs: changes needs: changes
if: needs.changes.outputs.docs == 'true' if: needs.changes.outputs.docs == 'true'
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -89,7 +89,7 @@ jobs:
needs: changes needs: changes
if: needs.changes.outputs.helm == 'true' if: needs.changes.outputs.helm == 'true'
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0 - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@@ -103,7 +103,7 @@ jobs:
needs: changes needs: changes
if: needs.changes.outputs.code == 'true' if: needs.changes.outputs.code == 'true'
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -121,7 +121,7 @@ jobs:
if: needs.changes.outputs.ci == 'true' if: needs.changes.outputs.ci == 'true'
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check workflow files - name: Check workflow files
run: | run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9 bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
@@ -134,7 +134,7 @@ jobs:
needs: changes needs: changes
if: needs.changes.outputs.code == 'true' if: needs.changes.outputs.code == 'true'
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -144,7 +144,7 @@ jobs:
test/package-lock.json test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci - run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run test:unit - run: npm run test:unit
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 - uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
if: success() if: success()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
@@ -163,12 +163,12 @@ jobs:
steps: steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev - run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # latest - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with: with:
packages: quilt packages: quilt
version: 1.0 version: 1.0
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
submodules: true submodules: true
- run: quilt push -a - run: quilt push -a
@@ -191,7 +191,7 @@ jobs:
# embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild. # embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
- name: Fetch prebuilt linux-x64 Code package from cache - name: Fetch prebuilt linux-x64 Code package from cache
id: cache-vscode id: cache-vscode
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: lib/vscode-reh-web-linux-x64 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') }} key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
@@ -219,7 +219,7 @@ jobs:
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true' if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true'
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -256,7 +256,7 @@ jobs:
steps: steps:
- name: Cache Caddy - name: Cache Caddy
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
id: caddy-cache id: caddy-cache
with: with:
path: | path: |
@@ -269,7 +269,7 @@ jobs:
mkdir -p ~/.cache/caddy mkdir -p ~/.cache/caddy
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version

View File

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

View File

@@ -33,7 +33,7 @@ jobs:
run: | run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with: with:
node-version-file: .node-version node-version-file: .node-version
@@ -64,7 +64,7 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Checkout code-server-aur repo - name: Checkout code-server-aur repo
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
repository: "cdrci/code-server-aur" repository: "cdrci/code-server-aur"
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }} token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
@@ -93,7 +93,7 @@ jobs:
run: | run: |
git checkout -b update-version-${{ env.VERSION }} git checkout -b update-version-${{ env.VERSION }}
git add . 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) git push -u origin $(git branch --show)
gh pr create --repo coder/code-server-aur --title "chore: bump version 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
@@ -108,15 +108,15 @@ jobs:
run: | run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -149,7 +149,7 @@ jobs:
run: | run: |
echo "VERSION=${TAG#v}" >> $GITHUB_ENV echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: ./ci/build/update-repo.sh - run: ./ci/build/update-repo.sh
@@ -159,7 +159,7 @@ jobs:
git config --global user.email opensource@coder.com git config --global user.email opensource@coder.com
git checkout -b "helm/$VERSION" git checkout -b "helm/$VERSION"
git add . 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)" git push -u origin "$(git branch --show)"
gh pr create \ gh pr create \
--repo coder/code-server \ --repo coder/code-server \

View File

@@ -39,6 +39,9 @@ jobs:
- npm_arch: arm64 - npm_arch: arm64
vscode_arch: arm64 vscode_arch: arm64
package_arch: arm64 package_arch: arm64
- npm_arch: arm
vscode_arch: armhf
package_arch: armv7l
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -59,7 +62,7 @@ jobs:
steps: steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev - run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # latest - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with: with:
packages: quilt packages: quilt
version: 1.0 version: 1.0
@@ -69,14 +72,12 @@ 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 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 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: | run: |
version=${TAG#update/} version=${TAG#update/}
version=${version#v} echo "VERSION=${version#v}" >> $GITHUB_ENV
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
submodules: true submodules: true
- run: quilt push -a - run: quilt push -a
@@ -110,7 +111,7 @@ jobs:
- run: | - run: |
sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes
if: ${{ matrix.vscode_arch == 'x64' }} if: ${{ matrix.vscode_arch == 'x64' }}
- uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
if: ${{ matrix.vscode_arch == 'x64' }} if: ${{ matrix.vscode_arch == 'x64' }}
with: with:
draft: true draft: true
@@ -123,7 +124,7 @@ jobs:
# Platform-specific release. # Platform-specific release.
- run: KEEP_MODULES=1 npm run release - run: KEEP_MODULES=1 npm run release
- run: npm run package - run: npm run package
- uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with: with:
draft: true draft: true
discussion_category_name: "📣 Announcements" discussion_category_name: "📣 Announcements"
@@ -147,7 +148,7 @@ jobs:
env: env:
VSCODE_TARGET: ${{ matrix.vscode_target }} VSCODE_TARGET: ${{ matrix.vscode_target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 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. # Ensure native modules are built from source to avoid prebuilds.
npm_config_build_from_source: true npm_config_build_from_source: true
@@ -163,14 +164,12 @@ 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 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 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: | run: |
version=${TAG#update/} version=${TAG#update/}
version=${version#v} echo "VERSION=${version#v}" >> $GITHUB_ENV
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
submodules: true submodules: true
- run: quilt push -a - run: quilt push -a
@@ -189,7 +188,7 @@ jobs:
- run: npm run test:native - run: npm run test:native
- run: npm run package - run: npm run package
- uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
with: with:
draft: true draft: true
discussion_category_name: "📣 Announcements" discussion_category_name: "📣 Announcements"

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
24.15.0 22.22.1

View File

@@ -22,64 +22,6 @@ Code v99.99.999
## Unreleased ## Unreleased
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 ## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
Code v1.121.0 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 # Merge the package.json for the web/remote server so we can include
# dependencies, since we want to ship this via NPM. # dependencies, since we want to ship this via NPM.
# Also override the name to prevent vulnerability scanners from jq --slurp '.[0] * .[1]' \
# misidentifying this package as VS Code (see #7071).
jq --slurp '.[0] * .[1] | .name = "code-oss"' \
"$VSCODE_SRC_PATH/remote/package.json" \ "$VSCODE_SRC_PATH/remote/package.json" \
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json" mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"

View File

@@ -2,65 +2,16 @@
set -Eeuo pipefail 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() { function update_helm() {
local chart_version local current
chart_version=$(yq .version ci/helm-chart/Chart.yaml) current=$(yq .version ci/helm-chart/Chart.yaml)
local app_version local next
app_version=$(yq .appVersion ci/helm-chart/Chart.yaml) next=$(semver "$current" -i minor)
local image_version echo "Bumping version from $current to $next..."
image_version=$(yq .image.tag ci/helm-chart/values.yaml) sed -i.bak "s/^version: $current\$/version: $next/" ci/helm-chart/Chart.yaml
local bump_type echo "Setting app version and image to $version..."
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..."
sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml 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 sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
} }
@@ -86,8 +37,7 @@ function main() {
"Update changelog" "update_changelog" "Update changelog" "update_changelog"
) )
# Even if a step failed, still output the last checkmark. run-steps "${steps[@]}"
run-steps "${steps[@]}" || true
# This step is always manual. # This step is always manual.
echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist

View File

@@ -146,8 +146,7 @@ function main() {
"Add changelog note" "add_changelog" "Add changelog note" "add_changelog"
) )
# Even if a step failed, still output the last checkmark. run-steps "${steps[@]}"
run-steps "${steps[@]}" || true
# This step is always manual. # This step is always manual.
echo "- [ ] Verify changelog" >> .cache/checklist 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 # 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. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.39.0 version: 3.36.0
# This is the version number of the application being deployed. This version number should be # 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 # 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. # follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.124.2 appVersion: 4.121.0

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image: image:
repository: codercom/code-server repository: codercom/code-server
tag: '4.124.2' tag: '4.121.0'
pullPolicy: Always pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a # Specifies one or more secrets to be used when pulling images from a

View File

@@ -201,7 +201,7 @@ There are four kinds of tests in code-server:
Our unit tests are written in TypeScript and run using Our unit tests are written in TypeScript and run using
[Jest](https://jestjs.io/), the testing framework]. [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 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 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 The end-to-end (e2e) tests are written in TypeScript and run using
[Playwright](https://playwright.dev/). [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 Before the e2e tests run, we run `globalSetup`, which eliminates the need to log
in before each test by preserving the authentication state. 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 code-server essentially serves as an HTTP API for logging in and starting a
remote Code process. remote Code process.
The CLI code is in [src/node](../src/node) and the HTTP routes are implemented 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](../src/node/routes). 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 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 ### 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. 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 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 intended. In the future, we'd like to run Code unit tests against our builds to
ensure that features work as expected. 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 If the functionality you're working on does NOT depend on code from Code, please
move it out and into code-server. move it out and into code-server.

View File

@@ -101,8 +101,9 @@ _exact_ same commands presented in the rest of this document.
We recommend installing with `npm` when: We recommend installing with `npm` when:
1. You aren't using a machine with `amd64` or `arm64`. 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. 2. You are installing code-server on Windows.
3. You're running Alpine Linux or are using a non-glibc libc. See 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) [#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
for more information. for more information.
@@ -295,7 +296,8 @@ You can install code-server using the [Helm package manager](https://coder.com/d
## Windows ## Windows
We currently [do not publish 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 ## Raspberry Pi

417
package-lock.json generated
View File

@@ -13,13 +13,12 @@
"@coder/logger": "^3.0.1", "@coder/logger": "^3.0.1",
"argon2": "^0.44.0", "argon2": "^0.44.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"env-paths": "^2.2.1", "env-paths": "^2.2.1",
"express": "^5.0.1", "express": "^5.0.1",
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
"httpolyglot": "^0.1.2", "httpolyglot": "^0.1.2",
"i18next": "^26.3.1", "i18next": "^25.8.3",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"limiter": "^2.1.0", "limiter": "^2.1.0",
"pem": "^1.14.8", "pem": "^1.14.8",
@@ -58,7 +57,7 @@
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0", "globals": "^16.1.0",
"prettier": "3.8.3", "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0", "prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
@@ -69,6 +68,15 @@
"node": "22" "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": { "node_modules/@coder/logger": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@coder/logger/-/logger-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@coder/logger/-/logger-3.0.1.tgz",
@@ -446,28 +454,27 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@textlint/ast-node-types": { "node_modules/@textlint/ast-node-types": {
"version": "15.7.1", "version": "12.6.1",
"resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz",
"integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==", "integrity": "sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@textlint/markdown-to-ast": { "node_modules/@textlint/markdown-to-ast": {
"version": "15.7.1", "version": "12.6.1",
"resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-15.7.1.tgz", "resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz",
"integrity": "sha512-9DLSah7g6mYNHvO6pssLdFvFPAl3HHyEIm4RE5of/1QN9FXJXDgdOcVV3YpQmbYT/YntuIvOQiqOndCSPWTW2A==", "integrity": "sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@textlint/ast-node-types": "15.7.1", "@textlint/ast-node-types": "^12.6.1",
"debug": "^4.4.3", "debug": "^4.3.4",
"mdast-util-gfm-autolink-literal": "^0.1.3", "mdast-util-gfm-autolink-literal": "^0.1.3",
"neotraverse": "^0.6.18",
"remark-footnotes": "^3.0.0", "remark-footnotes": "^3.0.0",
"remark-frontmatter": "^3.0.0", "remark-frontmatter": "^3.0.0",
"remark-gfm": "^1.0.0", "remark-gfm": "^1.0.0",
"remark-parse": "^9.0.0", "remark-parse": "^9.0.0",
"structured-source": "^4.0.0", "traverse": "^0.6.7",
"unified": "^9.2.2" "unified": "^9.2.2"
} }
}, },
@@ -763,20 +770,20 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz",
"integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==", "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.12.2", "@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/type-utils": "8.61.1", "@typescript-eslint/type-utils": "8.56.1",
"@typescript-eslint/utils": "8.61.1", "@typescript-eslint/utils": "8.56.1",
"@typescript-eslint/visitor-keys": "8.61.1", "@typescript-eslint/visitor-keys": "8.56.1",
"ignore": "^7.0.5", "ignore": "^7.0.5",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.4.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -786,9 +793,9 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.61.1", "@typescript-eslint/parser": "^8.56.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "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": { "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
@@ -802,16 +809,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz",
"integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==", "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/visitor-keys": "8.61.1", "@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -823,18 +830,18 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "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": { "node_modules/@typescript-eslint/project-service": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz",
"integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==", "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.61.1", "@typescript-eslint/tsconfig-utils": "^8.56.1",
"@typescript-eslint/types": "^8.61.1", "@typescript-eslint/types": "^8.56.1",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -845,18 +852,18 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=4.8.4 <6.1.0" "typescript": ">=4.8.4 <6.0.0"
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz",
"integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==", "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.61.1" "@typescript-eslint/visitor-keys": "8.56.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -867,9 +874,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz",
"integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==", "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -880,21 +887,21 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=4.8.4 <6.1.0" "typescript": ">=4.8.4 <6.0.0"
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz",
"integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==", "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.61.1", "@typescript-eslint/utils": "8.56.1",
"debug": "^4.4.3", "debug": "^4.4.3",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.4.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -905,13 +912,13 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "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": { "node_modules/@typescript-eslint/types": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz",
"integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==", "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -923,21 +930,21 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz",
"integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==", "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.61.1", "@typescript-eslint/project-service": "8.56.1",
"@typescript-eslint/tsconfig-utils": "8.61.1", "@typescript-eslint/tsconfig-utils": "8.56.1",
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"@typescript-eslint/visitor-keys": "8.61.1", "@typescript-eslint/visitor-keys": "8.56.1",
"debug": "^4.4.3", "debug": "^4.4.3",
"minimatch": "^10.2.2", "minimatch": "^10.2.2",
"semver": "^7.7.3", "semver": "^7.7.3",
"tinyglobby": "^0.2.15", "tinyglobby": "^0.2.15",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.4.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -947,7 +954,7 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "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": { "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
@@ -961,9 +968,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.6", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -974,13 +981,13 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "10.2.5", "version": "10.2.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
"dev": true, "dev": true,
"license": "BlueOak-1.0.0", "license": "BlueOak-1.0.0",
"dependencies": { "dependencies": {
"brace-expansion": "^5.0.5" "brace-expansion": "^5.0.2"
}, },
"engines": { "engines": {
"node": "18 || 20 || >=22" "node": "18 || 20 || >=22"
@@ -990,16 +997,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz",
"integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==", "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.9.1", "@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"@typescript-eslint/typescript-estree": "8.61.1" "@typescript-eslint/typescript-estree": "8.56.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1010,17 +1017,17 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "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": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz",
"integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==", "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.61.1", "@typescript-eslint/types": "8.56.1",
"eslint-visitor-keys": "^5.0.0" "eslint-visitor-keys": "^5.0.0"
}, },
"engines": { "engines": {
@@ -1398,9 +1405,9 @@
} }
}, },
"node_modules/anchor-markdown-header": { "node_modules/anchor-markdown-header": {
"version": "0.8.4", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.4.tgz", "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.2.tgz",
"integrity": "sha512-20eMBMpts7k5rXAAj67geSqc/tsexHZOZJDWQD214YcDuNtyizDa7Q77sYa5rkao2FwsQP1WKRt2X6mphwmhbg==", "integrity": "sha512-ix0Hx6ARkHOsQRmt1++ZmjURq4Pr5MGXQJjh0lQ/l5jTpTURn4aqhbZ+AJMpZ/Sd3JiyNwi7KaeiF64OsMGCPg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1632,9 +1639,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/basic-ftp": { "node_modules/basic-ftp": {
"version": "5.3.1", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
@@ -1664,13 +1671,6 @@
"url": "https://opencollective.com/express" "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": { "node_modules/brace-expansion": {
"version": "1.1.14", "version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
@@ -1936,16 +1936,12 @@
} }
}, },
"node_modules/cookie": { "node_modules/cookie": {
"version": "1.1.1", "version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">= 0.6"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
} }
}, },
"node_modules/cookie-parser": { "node_modules/cookie-parser": {
@@ -1961,15 +1957,6 @@
"node": ">= 0.8.0" "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": { "node_modules/cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -2180,17 +2167,18 @@
} }
}, },
"node_modules/doctoc": { "node_modules/doctoc": {
"version": "2.5.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.5.0.tgz", "resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.3.0.tgz",
"integrity": "sha512-xWb2P8mQw9x+T9xPYToytRP0/bA68oexdsY0anMG72RdhZGTVPx6oHJfI57gbZe9LsOSfQUNNLwxSspdoTlJIQ==", "integrity": "sha512-duuDNVnRHE5mFGYlI+oDf1vguML8PIhKnbUCs7iKPHIEdzYhkCldk6MQeX3ZeXQStRtZxGspSHImtgOMQPIS4A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@textlint/markdown-to-ast": "^15.6.0", "@textlint/markdown-to-ast": "^12.1.1",
"anchor-markdown-header": "^0.8.4", "anchor-markdown-header": "^0.8.2",
"htmlparser2": "^7.2.0", "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": { "bin": {
"doctoc": "doctoc.js" "doctoc": "doctoc.js"
@@ -2965,15 +2953,6 @@
"url": "https://opencollective.com/express" "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": { "node_modules/express/node_modules/cookie-signature": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
@@ -3331,9 +3310,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "17.6.0", "version": "16.5.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -3553,26 +3532,29 @@
} }
}, },
"node_modules/i18next": { "node_modules/i18next": {
"version": "26.3.1", "version": "25.8.13",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz",
"integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==", "integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
"url": "https://www.locize.com/i18next" "url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
}, },
{ {
"type": "individual", "type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" "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", "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.28.4"
},
"peerDependencies": { "peerDependencies": {
"typescript": "^5 || ^6" "typescript": "^5"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"typescript": { "typescript": {
@@ -3655,9 +3637,9 @@
} }
}, },
"node_modules/ip-address": { "node_modules/ip-address": {
"version": "10.2.0", "version": "10.1.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 12" "node": ">= 12"
@@ -4148,19 +4130,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.2.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
@@ -4265,20 +4237,6 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/longest-streak": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz",
@@ -4752,16 +4710,6 @@
"node": ">= 0.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": { "node_modules/netmask": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
@@ -5249,9 +5197,9 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.15.2", "version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.1.0" "side-channel": "^1.1.0"
@@ -5391,9 +5339,9 @@
} }
}, },
"node_modules/remove-markdown": { "node_modules/remove-markdown": {
"version": "0.6.4", "version": "0.6.3",
"resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.4.tgz", "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.3.tgz",
"integrity": "sha512-BompiLClzjfh46irZmzv+1Q61jZYlKN3iq/hzae9EOUwf7ctr/5wpD4qwgn/FWDAYE18RORO7z/yr+HXZJCY8Q==", "integrity": "sha512-Qvp2p0Q1irE7AaJO7QemJe04HdObHylJrG+q4hszvPlYp7q4EvfINpEIaIEFdB+3XTDp1h6fiyT60ae00gmRow==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -5956,16 +5904,6 @@
"url": "https://github.com/sponsors/sindresorhus" "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": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -6034,6 +5972,24 @@
"node": ">=0.6" "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": { "node_modules/trough": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz",
@@ -6046,9 +6002,9 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "2.5.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
"integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -6226,6 +6182,29 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/typescript": {
"version": "5.9.3", "version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@@ -6241,16 +6220,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.61.1", "version": "8.56.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.1.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz",
"integrity": "sha512-V7PayAfJokV3pEHgN7/v03D1SpujhRfQtYLbLIiBfDDncdg4PAiRBfoS4cnCANK4jmAPncczi59QO3afiXUlNw==", "integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.61.1", "@typescript-eslint/eslint-plugin": "8.56.1",
"@typescript-eslint/parser": "8.61.1", "@typescript-eslint/parser": "8.56.1",
"@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/typescript-estree": "8.56.1",
"@typescript-eslint/utils": "8.61.1" "@typescript-eslint/utils": "8.56.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6261,7 +6240,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "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": { "node_modules/unbox-primitive": {
@@ -6283,6 +6262,13 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/undici-types": {
"version": "6.21.0", "version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
@@ -6417,6 +6403,13 @@
"@unrs/resolver-binding-win32-x64-msvc": "1.11.1" "@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": { "node_modules/uri-js": {
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -6620,9 +6613,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.21.0", "version": "8.20.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"

View File

@@ -59,7 +59,7 @@
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0", "globals": "^16.1.0",
"prettier": "3.8.3", "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0", "prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
@@ -70,13 +70,12 @@
"@coder/logger": "^3.0.1", "@coder/logger": "^3.0.1",
"argon2": "^0.44.0", "argon2": "^0.44.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"env-paths": "^2.2.1", "env-paths": "^2.2.1",
"express": "^5.0.1", "express": "^5.0.1",
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
"httpolyglot": "^0.1.2", "httpolyglot": "^0.1.2",
"i18next": "^26.3.1", "i18next": "^25.8.3",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"limiter": "^2.1.0", "limiter": "^2.1.0",
"pem": "^1.14.8", "pem": "^1.14.8",

View File

@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -124,6 +125,7 @@ export interface ServerParsedArgs { @@ -120,6 +121,7 @@ export interface ServerParsedArgs {
'disable-getting-started-override'?: boolean, 'disable-getting-started-override'?: boolean,
'locale'?: string 'locale'?: string
'link-protection-trusted-domains'?: string[], 'link-protection-trusted-domains'?: string[],

View File

@@ -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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -85,6 +85,7 @@ export interface IAgentSdkProductConfig @@ -66,6 +66,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration { export interface IProductConfiguration {
readonly codeServerVersion?: string readonly codeServerVersion?: string
@@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
} }
private startListening(): void { 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 () { (function () {
// Find config by checking for DOM // 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) { if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element'); throw new Error('Missing web configuration element');
} }

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.orig/lib/vscode/build/gulpfile.extensions.ts
+++ code-server/lib/vscode/build/gulpfile.extensions.ts +++ code-server/lib/vscode/build/gulpfile.extensions.ts
@@ -291,6 +291,29 @@ export const compileCopilotExtensionBuil @@ -294,6 +294,29 @@ export const compileCopilotExtensionBuil
task.task(compileCopilotExtensionBuildTask); gulp.task(compileCopilotExtensionBuildTask);
/** /**
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering + * 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(); + return Promise.resolve();
+ }) + })
+)); +));
+task.task(compileCopilotExtensionFullBuildTask); +gulp.task(compileCopilotExtensionFullBuildTask);
+ +
+/** +/**
* Compiles the extensions for the build. * 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.orig/lib/vscode/build/lib/extensions.ts
+++ code-server/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 { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
import { fetchUrls, fetchGithub } from './fetch.ts'; import { fetchUrls, fetchGithub } from './fetch.ts';
import { createTsgoStream, spawnTsgo } from './tsgo.ts'; import { createTsgoStream, spawnTsgo } from './tsgo.ts';
+import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts'; +import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts';
import watcher from './watch/index.ts'; import vzip from 'gulp-vinyl-zip';
import { createRequire } from 'module'; import { createRequire } from 'module';
@@ -483,6 +484,116 @@ export function packageCopilotExtensionS @@ -492,6 +493,116 @@ export function packageCopilotExtensionS
).pipe(util2.setExecutableBit(['**/*.sh'])); ).pipe(util2.setExecutableBit(['**/*.sh']));
} }

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.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/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())) { if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) {
return false; return false;
} }

View File

@@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js'; import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js'; import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
@@ -359,6 +359,9 @@ export async function setupServerService @@ -358,6 +358,9 @@ export async function setupServerService
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority))); socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));

View File

@@ -230,7 +230,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js'; import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js'; import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.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, @IFileDialogService private readonly fileDialogService: IFileDialogService,
@IModelService private readonly modelService: IModelService, @IModelService private readonly modelService: IModelService,
@ILanguageService private readonly languageService: ILanguageService, @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, @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@IPathService protected readonly pathService: IPathService, @IPathService protected readonly pathService: IPathService,
@IKeybindingService private readonly keybindingService: IKeybindingService, @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.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
this.filePickBox.ok = true; this.filePickBox.ok = true;
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic; this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;

View File

@@ -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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -84,6 +84,8 @@ export interface IAgentSdkProductConfig @@ -65,6 +65,8 @@ export type ExtensionVirtualWorkspaceSup
} };
export interface IProductConfiguration { export interface IProductConfiguration {
+ readonly codeServerVersion?: string + readonly codeServerVersion?: string

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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -87,6 +87,7 @@ export interface IProductConfiguration { @@ -68,6 +68,7 @@ export interface IProductConfiguration {
readonly codeServerVersion?: string readonly codeServerVersion?: string
readonly rootEndpoint?: string readonly rootEndpoint?: string
readonly updateEndpoint?: string readonly updateEndpoint?: string

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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -88,6 +88,7 @@ export interface IProductConfiguration { @@ -69,6 +69,7 @@ export interface IProductConfiguration {
readonly rootEndpoint?: string readonly rootEndpoint?: string
readonly updateEndpoint?: string readonly updateEndpoint?: string
readonly logoutEndpoint?: string readonly logoutEndpoint?: string
@@ -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 type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.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, settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config), workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute), urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),

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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -89,6 +89,10 @@ export interface IProductConfiguration { @@ -70,6 +70,10 @@ export interface IProductConfiguration {
readonly updateEndpoint?: string readonly updateEndpoint?: string
readonly logoutEndpoint?: string readonly logoutEndpoint?: string
readonly proxyEndpointTemplate?: string readonly proxyEndpointTemplate?: string

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

View File

@@ -147,7 +147,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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -93,6 +93,7 @@ export interface IProductConfiguration { @@ -74,6 +74,7 @@ export interface IProductConfiguration {
readonly path: string; readonly path: string;
readonly scope: string; readonly scope: string;
} }

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.orig/lib/vscode/src/vs/base/common/product.ts
+++ code-server/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts
@@ -86,6 +86,7 @@ export interface IAgentSdkProductConfig @@ -67,6 +67,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration { export interface IProductConfiguration {
readonly codeServerVersion?: string readonly codeServerVersion?: string
readonly rootEndpoint?: string readonly rootEndpoint?: string
@@ -101,14 +101,14 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
readonly version: string; readonly version: string;
readonly date?: string; readonly date?: string;
@@ -138,6 +139,7 @@ export interface IProductConfiguration { @@ -119,6 +120,7 @@ export interface IProductConfiguration {
readonly resourceUrlTemplate: string; readonly resourceUrlTemplate: string;
readonly nlsBaseUrl: string; readonly nlsBaseUrl: string;
readonly accessSKUs?: string[]; readonly accessSKUs?: string[];
+ readonly authorizationHeaderToken?: string; + readonly authorizationHeaderToken?: string;
}; };
readonly agentSdks?: { readonly [packageId: string]: IAgentSdkProductConfig }; readonly mcpGallery?: {
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts

View File

@@ -41,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.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -226,7 +226,7 @@ export class BrowserWorkbenchEnvironment @@ -223,7 +223,7 @@ export class BrowserWorkbenchEnvironment
@memoize @memoize
get webviewExternalEndpoint(): string { get webviewExternalEndpoint(): string {
@@ -70,8 +70,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" <meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-nXjtuhBilO++r8hfxl5VjEScSmdm07wDAk6jw228DgM=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> - 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-A6/szVNdTzyi4hDa+9OLbzS8tSd2iUV4CqimLNWex2Y=' '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 --> <!-- Disable pinch zooming -->
<meta name="viewport" <meta name="viewport"

View File

@@ -54,6 +54,7 @@ init({
lowerCaseLng: true, lowerCaseLng: true,
debug: process.env.NODE_ENV === "development", debug: process.env.NODE_ENV === "development",
resources: defaultResources, resources: defaultResources,
showSupportNotice: false,
}) })
export default i18next 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 proxyServer from "http-proxy"
import { getCookieSessionName, HttpCode } from "../common/http" import { HttpCode } from "../common/http"
export const proxy = proxyServer.createProxyServer({}) export const proxy = proxyServer.createProxyServer({})
@@ -20,19 +18,6 @@ proxy.on("error", (error, _, res) => {
} }
}) })
// Strip the code-server cookie if it exists to avoid transmitting the cookie
// to potentially malicious local ports.
proxy.on("proxyReq", (preq, req) => {
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
preq.setHeader(
"Cookie",
cookie.stringifyCookie({
...(req as Request).cookies,
[cookieSessionName]: undefined,
}),
)
})
// Intercept the response to rewrite absolute redirects against the base path. // 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. // Is disabled when the request has no base path which means /absproxy is in use.
proxy.on("proxyRes", (res, req) => { proxy.on("proxyRes", (res, req) => {

View File

@@ -32,7 +32,7 @@ describe("code-server", ["--disable-workspace-trust"], {}, () => {
test("should show the Integrated Terminal", async ({ codeServerPage }) => { test("should show the Integrated Terminal", async ({ codeServerPage }) => {
await codeServerPage.focusTerminal() 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 }) => { test("should open a file", async ({ codeServerPage }) => {

View File

@@ -18,7 +18,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
// Action // Action
await codeServerPage.openContextMenu("text=unique-file.txt") 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 }) => { 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.page.keyboard.type("Making some edits.")
await codeServerPage.navigateMenus(["File", "Save As..."]) await codeServerPage.navigateMenus(["File", "Save As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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 }) => { 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.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"]) await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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 }) => { test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action // Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."]) await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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 // Action
await codeServerPage.openContextMenu("text=unique-file.txt") 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 }) => { 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.openFile(fileName)
await codeServerPage.page.click(".tab") await codeServerPage.page.click(".tab")
await codeServerPage.navigateMenus(["File", "Save As..."]) 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 }) => { 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.waitForTab("Untitled-1")
await codeServerPage.navigateMenus(["File", "Save"]) await codeServerPage.navigateMenus(["File", "Save"])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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 }) => { test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
// Action // Action
await codeServerPage.navigateMenus(["File", "Save Workspace As..."]) await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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. // Remove end slash in address.
const normalizedAddress = address.replace(/\/+$/, "") 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") await codeServerPage.page.click("text=Allow")
// It should ask to select an account, one of which will be the one we // It should ask to select an account, one of which will be the one we
// pre-injected. // 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") await codeServerPage.page.click("text=Allow")
// Since there is no account it will ask directly for the token (because // Since there is no account it will ask directly for the token (because
// we are on localhost; otherwise it would initiate the oauth flow). // 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 { } else {

View File

@@ -24,8 +24,8 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
// Skip entering password // Skip entering password
// Click the submit button and login // Click the submit button and login
await codeServerPage.page.click(".submit") await codeServerPage.page.click(".submit")
// The required input blocks empty submits, so the server-side error can't render. await codeServerPage.page.waitForLoadState("networkidle")
await expect(codeServerPage.page.locator("input.password:invalid")).toBeVisible() expect(await codeServerPage.page.isVisible("text=Missing password"))
}) })
test("should see an error message for incorrect password", async ({ codeServerPage }) => { 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 // Click the submit button and login
await codeServerPage.page.click(".submit") await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle") 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("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 // Click the submit button and login
// The current RateLimiter allows 2 logins per minute plus // The current RateLimiter allows 2 logins per minute plus
// 12 logins per hour for a total of 14 // 12 logins per hour for a total of 14
// See: src/node/routes/login.ts // See: src/node/routes/login.ts
for (let i = 1; i <= 14; i++) { for (let i = 1; i <= 14; i++) {
await codeServerPage.page.fill(".password", "password123")
await codeServerPage.page.click(".submit") await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle") await codeServerPage.page.waitForLoadState("networkidle")
// We double-check that the correct error message shows // We double-check that the correct error message shows
// which should be for incorrect password // 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: // The 15th should fail for a different reason:
// login rate // login rate
await codeServerPage.page.fill(".password", "password123")
await codeServerPage.page.click(".submit") await codeServerPage.page.click(".submit")
await codeServerPage.page.waitForLoadState("networkidle") 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 // Action
await codeServerPage.openContextMenu('span:has-text("test-directory")') 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 }) => { test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action // Action
await codeServerPage.navigateMenus(["File", "Open File..."]) await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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 // Action
await codeServerPage.openContextMenu('span:has-text("test-directory")') 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 }) => { test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
// Action // Action
await codeServerPage.navigateMenus(["File", "Open File..."]) await codeServerPage.navigateMenus(["File", "Open File..."])
await codeServerPage.page.waitForSelector(".quick-input-widget") 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)
}) })
}) })

97
test/package-lock.json generated
View File

@@ -7,7 +7,7 @@
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@jest-mock/express": "^1.4.5", "@jest-mock/express": "^1.4.5",
"@playwright/test": "^1.61.0", "@playwright/test": "^1.56.1",
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/jsdom": "^16.2.13", "@types/jsdom": "^16.2.13",
"@types/node-fetch": "^2.5.8", "@types/node-fetch": "^2.5.8",
@@ -18,7 +18,7 @@
"jest-fetch-mock": "^3.0.3", "jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0", "jsdom": "^16.4.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.7",
"playwright": "^1.61.0", "playwright": "^1.59.1",
"ts-jest": "^27.0.7", "ts-jest": "^27.0.7",
"wtfnode": "^0.9.1" "wtfnode": "^0.9.1"
} }
@@ -998,13 +998,13 @@
} }
}, },
"node_modules/@playwright/test": { "node_modules/@playwright/test": {
"version": "1.61.0", "version": "1.56.1",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.0.tgz", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
"integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==", "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright": "1.61.0" "playwright": "1.56.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -1013,6 +1013,53 @@
"node": ">=18" "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": { "node_modules/@sinonjs/commons": {
"version": "1.8.6", "version": "1.8.6",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
@@ -2289,17 +2336,17 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.6", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4", "hasown": "^2.0.2",
"mime-types": "^2.1.35" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
@@ -2514,9 +2561,9 @@
} }
}, },
"node_modules/hasown": { "node_modules/hasown": {
"version": "2.0.4", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -3555,16 +3602,16 @@
} }
}, },
"node_modules/jsdom/node_modules/form-data": { "node_modules/jsdom/node_modules/form-data": {
"version": "3.0.5", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz",
"integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4", "hasown": "^2.0.2",
"mime-types": "^2.1.35" "mime-types": "^2.1.35"
}, },
"engines": { "engines": {
@@ -4067,13 +4114,13 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.61.0", "version": "1.59.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.0.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
"integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==", "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.61.0" "playwright-core": "1.59.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -4086,9 +4133,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.61.0", "version": "1.59.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
"integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==", "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

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

View File

@@ -1,9 +1,10 @@
import { logger } from "@coder/logger" import { logger } from "@coder/logger"
import { readFile, writeFile, stat, utimes } from "fs/promises" import { readFile, writeFile, stat, utimes } from "fs/promises"
import { setImmediate } from "timers"
import { Heart } from "../../../src/node/heart" import { Heart } from "../../../src/node/heart"
import { clean, mockLogger, tmpdir } from "../../utils/helpers" import { clean, mockLogger, tmpdir } from "../../utils/helpers"
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
describe("Heart", () => { describe("Heart", () => {
const testName = "heartTests" const testName = "heartTests"
let testDir = "" let testDir = ""
@@ -14,15 +15,12 @@ describe("Heart", () => {
await clean(testName) await clean(testName)
testDir = await tmpdir(testName) testDir = await tmpdir(testName)
}) })
beforeEach(() => {
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
})
afterAll(() => { afterAll(() => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
beforeEach(() => {
heart = new Heart(`${testDir}/shutdown.txt`, jest.fn().mockResolvedValue(true))
})
afterEach(() => { afterEach(() => {
jest.resetAllMocks() jest.resetAllMocks()
jest.useRealTimers() jest.useRealTimers()
@@ -30,7 +28,6 @@ describe("Heart", () => {
heart.dispose() heart.dispose()
} }
}) })
it("should write to a file when given a valid file path", async () => { it("should write to a file when given a valid file path", async () => {
// Set up heartbeat file with contents // Set up heartbeat file with contents
const text = "test" const text = "test"
@@ -45,7 +42,7 @@ describe("Heart", () => {
expect(fileContents).toBe(text) expect(fileContents).toBe(text)
heart = new Heart(pathToFile, jest.fn().mockResolvedValue(true)) heart = new Heart(pathToFile, mockIsActive(true))
await heart.beat() await heart.beat()
// Check that the heart wrote to the heartbeatFilePath and overwrote our text // Check that the heart wrote to the heartbeatFilePath and overwrote our text
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" }) const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
@@ -54,30 +51,31 @@ describe("Heart", () => {
const fileStatusAfterEdit = await stat(pathToFile) const fileStatusAfterEdit = await stat(pathToFile)
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0) expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
}) })
it("should log a warning when given an invalid file path", async () => { 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() await heart.beat()
expect(logger.warn).toHaveBeenCalled() expect(logger.warn).toHaveBeenCalled()
}) })
it("should be active after calling beat", async () => { it("should be active after calling beat", async () => {
await heart.beat() await heart.beat()
const isAlive = heart.alive() const isAlive = heart.alive()
expect(isAlive).toBe(true) expect(isAlive).toBe(true)
}) })
it("should not be active after dispose is called", () => { it("should not be active after dispose is called", () => {
heart.dispose() heart.dispose()
const isAlive = heart.alive() const isAlive = heart.alive()
expect(isAlive).toBe(false) expect(isAlive).toBe(false)
}) })
it("should beat twice without warnings", async () => { 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() 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() jest.runAllTimers()
expect(logger.warn).not.toHaveBeenCalled() expect(logger.warn).not.toHaveBeenCalled()
}) })
@@ -86,48 +84,40 @@ describe("Heart", () => {
describe("heartbeatTimer", () => { describe("heartbeatTimer", () => {
const testName = "heartbeatTimer" const testName = "heartbeatTimer"
let testDir = "" let testDir = ""
beforeAll(async () => { beforeAll(async () => {
await clean(testName) await clean(testName)
testDir = await tmpdir(testName) testDir = await tmpdir(testName)
mockLogger() mockLogger()
}) })
afterAll(() => { afterAll(() => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
beforeEach(() => { beforeEach(() => {
jest.useFakeTimers() jest.useFakeTimers()
}) })
afterEach(() => { afterEach(() => {
jest.resetAllMocks() jest.resetAllMocks()
jest.clearAllTimers() jest.clearAllTimers()
jest.useRealTimers() jest.useRealTimers()
}) })
it("should call isActive when timeout expires", async () => { 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) const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat() await heart.beat()
jest.advanceTimersByTime(60 * 1000) jest.advanceTimersByTime(60 * 1000)
expect(mockIsActive).toHaveBeenCalled() expect(mockIsActive).toHaveBeenCalled()
}) })
it("should log a warning when isActive rejects", async () => { 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 mockIsActive = jest.fn().mockRejectedValue(error)
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive) const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
await heart.beat() await heart.beat()
jest.advanceTimersByTime(60 * 1000) jest.advanceTimersByTime(60 * 1000)
expect(mockIsActive).toHaveBeenCalled() expect(mockIsActive).toHaveBeenCalled()
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
// 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)
}) })
}) })
@@ -135,54 +125,38 @@ describe("stateChange", () => {
const testName = "stateChange" const testName = "stateChange"
let testDir = "" let testDir = ""
let heart: Heart let heart: Heart
beforeAll(async () => { beforeAll(async () => {
await clean(testName) await clean(testName)
testDir = await tmpdir(testName) testDir = await tmpdir(testName)
mockLogger() mockLogger()
}) })
afterAll(() => { afterAll(() => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
beforeEach(() => {
jest.useFakeTimers()
})
afterEach(() => { afterEach(() => {
jest.resetAllMocks() jest.resetAllMocks()
jest.useRealTimers()
if (heart) { if (heart) {
heart.dispose() heart.dispose()
} }
}) })
it("should change to alive after a beat", async () => { it("should change to alive after a beat", async () => {
const mockIsActive = jest.fn().mockResolvedValue(true) heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
const mockOnChange = jest.fn() const mockOnChange = jest.fn()
heart.onChange(mockOnChange) heart.onChange(mockOnChange)
await heart.beat() await heart.beat()
expect(mockOnChange.mock.calls[0][0]).toBe("alive") expect(mockOnChange.mock.calls[0][0]).toBe("alive")
}) })
it.only("should change to expired when not active", async () => {
it("should change to expired when not active", async () => { jest.useFakeTimers()
const mockIsActive = jest.fn().mockResolvedValue(false) heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false)))
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
const mockOnChange = jest.fn() const mockOnChange = jest.fn()
heart.onChange(mockOnChange) heart.onChange(mockOnChange)
await heart.beat() 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") 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 express from "express"
import * as http from "http"
import nodeFetch from "node-fetch"
import { HttpCode } from "../../../src/common/http" import { HttpCode } from "../../../src/common/http"
import { proxy } from "../../../src/node/proxy"
import { wss, Router as WsRouter } from "../../../src/node/wsRouter" 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 httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration" import * as integration from "../../utils/integration"
describe("proxy", () => { describe("proxy", () => {
const proxyTarget = new httpserver.HttpServer() const nhooyrDevServer = new httpserver.HttpServer()
const wsApp = express.default() const wsApp = express.default()
const wsRouter = WsRouter() const wsRouter = WsRouter()
let codeServer: httpserver.HttpServer | undefined let codeServer: httpserver.HttpServer | undefined
@@ -16,22 +19,21 @@ describe("proxy", () => {
beforeAll(async () => { beforeAll(async () => {
wsApp.use("/", wsRouter.router) wsApp.use("/", wsRouter.router)
await proxyTarget.listen((req, res) => { await nhooyrDevServer.listen((req, res) => {
e(req, res) e(req, res)
}) })
proxyTarget.listenUpgrade(wsApp) nhooyrDevServer.listenUpgrade(wsApp)
proxyPath = `/proxy/${proxyTarget.port()}/wsup` proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/") absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
}) })
afterAll(async () => { afterAll(async () => {
await proxyTarget.dispose() await nhooyrDevServer.dispose()
}) })
beforeEach(() => { beforeEach(() => {
e = express.default() e = express.default()
mockLogger() mockLogger()
delete process.env.PASSWORD
}) })
afterEach(async () => { afterEach(async () => {
@@ -281,42 +283,65 @@ describe("proxy", () => {
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" }) const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
expect(resp.status).toBe(200) expect(resp.status).toBe(200)
}) })
})
it("should return a 500 when no target is running ", async () => { // NOTE@jsjoeio
const target = new httpserver.HttpServer() // Both this test suite and the one above it are very similar
await target.listen(() => {}) // The main difference is this one uses http and node-fetch
const port = target.port() // and specifically tests the proxy in isolation vs. using
target.dispose() // the httpserver abstraction we've built.
codeServer = await integration.setup(["--auth=none"], "") //
const resp = await codeServer.fetch(`/proxy/${port}/wsup`) // Leaving this as a separate test suite for now because
expect(resp.status).toBe(HttpCode.ServerError) // we may consider refactoring the httpserver abstraction
expect(resp.statusText).toBe("Internal Server Error") // in the future.
//
// If you're writing a test specifically for code in
// src/node/proxy.ts, you should probably add it to
// this test suite.
describe("proxy (standalone)", () => {
let URL = ""
let PROXY_URL = ""
let testServer: http.Server
let proxyTarget: http.Server
beforeEach(async () => {
const PORT = await getAvailablePort()
const PROXY_PORT = await getAvailablePort()
URL = `http://localhost:${PORT}`
PROXY_URL = `http://localhost:${PROXY_PORT}`
// Define server and a proxy server
testServer = http.createServer((req, res) => {
proxy.web(req, res, {
target: PROXY_URL,
})
})
proxyTarget = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" })
res.end()
})
// Start both servers
proxyTarget.listen(PROXY_PORT)
testServer.listen(PORT)
}) })
it("should strip token cookie", async () => { afterEach(async () => {
const token = "my-super-secure-token" testServer.close()
process.env.HASHED_PASSWORD = token proxyTarget.close()
codeServer = await integration.setup(["--auth=password"]) })
// Set up a listener that just prints the cookies it got. it("should return a 500 when proxy target errors ", async () => {
e.get("/wsup/cookies", (req, res) => { // Close the proxy target so that proxy errors
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" }) proxyTarget.close()
res.end(req.headers.cookie) const errorResp = await nodeFetch(`${URL}/error`)
}) expect(errorResp.status).toBe(HttpCode.ServerError)
expect(errorResp.statusText).toBe("Internal Server Error")
})
// Send the token along with other cookies which should be preserved. it("should proxy correctly", async () => {
// Encode one to make sure they are being re-encoded properly. const resp = await nodeFetch(`${URL}/route`)
const value = "hello=there"
const encodedValue = encodeURIComponent(value)
const resp = await codeServer.fetch(proxyPath + "/cookies", {
headers: {
cookie: `cookie1=${encodedValue}; code-server-session=${token}; cookie2=hello;`,
},
})
// The proxied listener should not have printed the code-server token.
expect(resp.status).toBe(200) expect(resp.status).toBe(200)
const text = await resp.text() expect(resp.statusText).toBe("OK")
expect(text).toBe(`cookie1=${encodedValue}; cookie2=hello`)
}) })
}) })