diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 369040983858..b8f169a4b1fa 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -20,6 +20,8 @@ body: - **Remote OS**: Ubuntu - **Remote Architecture**: amd64 - **`code-server --version`**: 4.0.1 + + Please do not just put "latest" for the version. value: | - Web Browser: - Local OS: diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index f020ccde31ae..91e320087175 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -124,7 +124,7 @@ jobs: echo "VERSION=${TAG#v}" >> $GITHUB_ENV - name: Validate package - uses: heyhusen/archlinux-package-action@v2.2.1 + uses: heyhusen/archlinux-package-action@v2.4.0 env: VERSION: ${{ env.VERSION }} with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a4433c810937..a16fc6b90ac7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -73,6 +73,7 @@ jobs: - name: Install cross-compiler and system dependencies run: | + sed -i 's/deb\.debian\.org/archive.debian.org/g' /etc/apt/sources.list dpkg --add-architecture $TARGET_ARCH apt update && apt install -y --no-install-recommends \ crossbuild-essential-$TARGET_ARCH \ @@ -268,7 +269,7 @@ jobs: timeout-minutes: 15 steps: - name: Download artifacts - uses: dawidd6/action-download-artifact@v9 + uses: dawidd6/action-download-artifact@v11 id: download with: branch: ${{ github.ref }} diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml index 69a08a5a4e09..a14094d92e82 100644 --- a/.github/workflows/security.yaml +++ b/.github/workflows/security.yaml @@ -43,7 +43,7 @@ jobs: permissions: contents: read # for actions/checkout to fetch code security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout repo uses: actions/checkout@v4 @@ -51,7 +51,7 @@ jobs: fetch-depth: 0 - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 + uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 with: scan-type: "fs" scan-ref: "." @@ -72,7 +72,7 @@ jobs: contents: read # for actions/checkout to fetch code security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze with CodeQL - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout repository diff --git a/.github/workflows/trivy-docker.yaml b/.github/workflows/trivy-docker.yaml index a1e90306c7f4..06ca72ae6429 100644 --- a/.github/workflows/trivy-docker.yaml +++ b/.github/workflows/trivy-docker.yaml @@ -44,14 +44,14 @@ concurrency: jobs: trivy-scan-image: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v4 - name: Run Trivy vulnerability scanner in image mode - uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5 + uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 with: image-ref: "docker.io/codercom/code-server:latest" ignore-unfixed: true diff --git a/.node-version b/.node-version index 87bc4c77fe13..fc37597bccdb 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -20.18.3 +22.17.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index f89a3760aa50..1b3be79caf63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,142 @@ Code v99.99.999 ## Unreleased +## [4.103.0](https://github.com/coder/code-server/releases/tag/v4.103.0) - 2025-08-12 + +Code v1.103.0 + +### Changed + +- Update to Code 1.103.0. + +## [4.102.2](https://github.com/coder/code-server/releases/tag/v4.102.2) - 2025-07-24 + +Code v1.102.2 + +### Changed + +- Update to Code 1.102.2. + +## [4.102.1](https://github.com/coder/code-server/releases/tag/v4.102.1) - 2025-07-17 + +Code v1.102.1 + +### Changed + +- Update to Code 1.102.1. + +## [4.102.0](https://github.com/coder/code-server/releases/tag/v4.102.0) - 2025-07-16 + +Code v1.102.0 + +### Changed + +- Update to Code 1.102.0. + +### Added + +- Custom strings can be configured using the `--i18n` flag set to a JSON + file. This can be used for either translation (and can be used alongside + `--locale`) or for customizing the strings. See + [./src/node/i18n/locales/en.json](./src/node/i18n/locales/en.json) for the + available keys. + +## [4.101.2](https://github.com/coder/code-server/releases/tag/v4.101.2) - 2025-06-25 + +Code v1.101.2 + +### Changed + +- Update to Code 1.101.2. + +### Fixed + +- Fix web views not loading due to 401 when requesting the service worker. + +## [4.101.1](https://github.com/coder/code-server/releases/tag/v4.101.1) - 2025-06-20 + +Code v1.101.1 + +### Changed + +- Update to Code 1.101.1. + +## [4.101.0](https://github.com/coder/code-server/releases/tag/v4.101.0) - 2025-06-20 + +Code v1.101.0 + +### Changed + +- Update to Code 1.101.0. + +## [4.100.3](https://github.com/coder/code-server/releases/tag/v4.100.3) - 2025-06-03 + +Code v1.100.3 + +### Changed + +- Update to Code 1.100.3. + +## [4.100.2](https://github.com/coder/code-server/releases/tag/v4.100.2) - 2025-05-15 + +Code v1.100.2 + +### Changed + +- Update to Code 1.100.2. + +## [4.100.1](https://github.com/coder/code-server/releases/tag/v4.100.1) - 2025-05-13 + +Code v1.100.1 + +### Changed + +- Update to Code 1.100.1. + +## [4.100.0](https://github.com/coder/code-server/releases/tag/v4.100.0) - 2025-05-12 + +Code v1.100.0 + +### Added + +- Trusted domains for links can now be set at run-time by configuring + `linkProtectionTrustedDomains` in the `lib/vscode/product.json` file or via + the `--link-protection-trusted-domains` flag. + +### Changed + +- Update to Code 1.100.0. +- Disable extension signature verification, which previously was skipped by + default (the package used for verification is not available to OSS builds of + VS Code) but now reportedly throws hard errors making it impossible to install + extensions. + +### Fixed + +- Flags with repeatable options now work via the config file. + +## [4.99.4](https://github.com/coder/code-server/releases/tag/v4.99.4) - 2025-05-02 + +Code v1.99.3 + +### Security + +- Validate that ports in the path proxy are numbers, to prevent proxying to + arbitrary domains. + +## [4.99.3](https://github.com/coder/code-server/releases/tag/v4.99.3) - 2025-04-17 + +Code v1.99.3 + +### Added + +- Added `--skip-auth-preflight` flag to let preflight requests through the + proxy. + +### Changed + +- Update to Code 1.99.3. + ## [4.99.2](https://github.com/coder/code-server/releases/tag/v4.99.2) - 2025-04-10 Code v1.99.2 @@ -682,7 +818,6 @@ Code v1.68.1 would be accessible at `my.domain/proxy/8000/` without any authentication. If all of the following apply to you please update as soon as possible: - - You run code-server with the built-in password authentication. - You run unprotected HTTP services on ports accessible by code-server. diff --git a/ci/build/build-standalone-release.sh b/ci/build/build-standalone-release.sh index f4078557789b..b0833db810cb 100755 --- a/ci/build/build-standalone-release.sh +++ b/ci/build/build-standalone-release.sh @@ -16,7 +16,7 @@ main() { # Package managers may shim their own "node" wrapper into the PATH, so run # node and ask it for its true path. local node_path - node_path="$(node <<< 'console.info(process.execPath)')" + node_path="$(node -p process.execPath)" mkdir -p "$RELEASE_PATH/bin" mkdir -p "$RELEASE_PATH/lib" diff --git a/ci/build/build-vscode.sh b/ci/build/build-vscode.sh index e4a781a88b40..f037fac3a4c1 100755 --- a/ci/build/build-vscode.sh +++ b/ci/build/build-vscode.sh @@ -112,7 +112,9 @@ EOF # this because we have an NPM package that could be installed on any platform. # The correct platform dependencies and scripts will be installed as part of # the post-install during `npm install` or when building a standalone release. - npm run gulp "vscode-reh-web-linux-x64${MINIFY:+-min}" + node --max-old-space-size=16384 --optimize-for-size \ + ./node_modules/gulp/bin/gulp.js \ + "vscode-reh-web-linux-x64${MINIFY:+-min}" # Reset so if you develop after building you will not be stuck with the wrong # commit (the dev client will use `oss-dev` but the dev server will still use diff --git a/ci/build/npm-postinstall.sh b/ci/build/npm-postinstall.sh index fc82b2ffbe47..ee4c92237023 100755 --- a/ci/build/npm-postinstall.sh +++ b/ci/build/npm-postinstall.sh @@ -76,8 +76,8 @@ main() { echo "USE AT YOUR OWN RISK!" fi - if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-20}" ]; then - echo "ERROR: code-server currently requires node v20." + if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then + echo "ERROR: code-server currently requires node v22." if [ -n "$FORCE_NODE_VERSION" ]; then echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION." fi diff --git a/ci/dev/gen_icons.sh b/ci/dev/gen_icons.sh index 9d27486dcc57..39d509bc4f4b 100755 --- a/ci/dev/gen_icons.sh +++ b/ci/dev/gen_icons.sh @@ -1,44 +1,50 @@ #!/bin/sh set -eu +# Generate icons from a single favicon.svg. favicon.svg should have no fill +# colors set. main() { cd src/browser/media - # We need .ico for backwards compatibility. - # The other two are the only icon sizes required by Chrome and - # we use them for stuff like apple-touch-icon as well. - # https://web.dev/add-manifest/ + # We need .ico for backwards compatibility. The other two are the only icon + # sizes required by Chrome and we use them for stuff like apple-touch-icon as + # well. https://web.dev/add-manifest/ # # This should be enough and we can always add more if there are problems. - + # + # -quiet to avoid https://github.com/ImageMagick/ImageMagick/issues/884 # -background defaults to white but we want it transparent. + # -density somehow makes the image both sharper and smaller in file size. + # # https://imagemagick.org/script/command-line-options.php#background - convert -quiet -background transparent -resize 256x256 favicon.svg favicon.ico - # We do not generate the pwa-icon from the favicon as they are slightly different - # designs and sizes. - # See favicon.afdesign and #2401 for details on the differences. - convert -quiet -background transparent -resize 192x192 pwa-icon.png pwa-icon-192.png - convert -quiet -background transparent -resize 512x512 pwa-icon.png pwa-icon-512.png + convert -quiet -background transparent \ + -resize 256x256 -density 256x256 \ + favicon.svg favicon.ico - # We use -quiet above to avoid https://github.com/ImageMagick/ImageMagick/issues/884 + # Generate PWA icons. There should be enough padding to support masking. + convert -quiet -border 60x60 -bordercolor white -background white \ + -resize 192x192 -density 192x192 \ + favicon.svg pwa-icon-maskable-192.png + convert -quiet -border 160x160 -bordercolor white -background white \ + -resize 512x512 -density 512x512 \ + favicon.svg pwa-icon-maskable-512.png - # The following adds dark mode support for the favicon as favicon-dark-support.svg - # There is no similar capability for pwas or .ico so we can only add support to the svg. - favicon_dark_style="" - # See https://stackoverflow.com/a/22901380/4283659 - # This escapes all newlines so that sed will accept them. - favicon_dark_style="$(printf "%s\n" "$favicon_dark_style" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g')" - sed "$( - cat -n << EOF -s% favicon-dark-support.svg + # Generate non-maskable PWA icons. + magick pwa-icon-maskable-192.png \ + \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 50,50" \) \ + -channel-fx "| gray=>alpha" \ + pwa-icon-192.png + magick pwa-icon-maskable-512.png \ + \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 100,100" \) \ + -channel-fx "| gray=>alpha" \ + pwa-icon-512.png + + # The following adds dark mode support for the favicon as + # favicon-dark-support.svg There is no similar capability for pwas or .ico so + # we can only add support to the svg. + favicon_dark_style="" + cp favicon.svg favicon-dark-support.svg + sed "s% favicon-dark-support.svg } main "$@" diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml index 305f33d616ec..7950bea8ec74 100644 --- a/ci/helm-chart/Chart.yaml +++ b/ci/helm-chart/Chart.yaml @@ -15,9 +15,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 3.26.2 +version: 3.30.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 4.99.2 +appVersion: 4.103.0 diff --git a/ci/helm-chart/values.yaml b/ci/helm-chart/values.yaml index d2ded096cccf..53313b86a090 100644 --- a/ci/helm-chart/values.yaml +++ b/ci/helm-chart/values.yaml @@ -6,7 +6,7 @@ replicaCount: 1 image: repository: codercom/code-server - tag: '4.99.2' + tag: '4.103.0' pullPolicy: Always # Specifies one or more secrets to be used when pulling images from a @@ -75,8 +75,9 @@ extraArgs: [] extraVars: [] # - name: DISABLE_TELEMETRY # value: "true" +# if dind is desired: # - name: DOCKER_HOST -# value: "tcp://localhost:2375" +# value: "tcp://localhost:2376" ## ## Init containers parameters: @@ -139,25 +140,39 @@ lifecycle: # - -c # - curl -s -L SOME_SCRIPT | bash + # for dind, the following may be helpful + # postStart: + # exec: + # command: + # - /bin/sh + # - -c + # - | + # sudo apt-get update \ + # && sudo apt-get install -y docker.io + ## Enable an Specify container in extraContainers. ## This is meant to allow adding code-server dependencies, like docker-dind. extraContainers: | # If docker-dind is used, DOCKER_HOST env is mandatory to set in "extraVars" -#- name: docker-dind -# image: docker:19.03-dind -# imagePullPolicy: IfNotPresent -# resources: -# requests: -# cpu: 250m -# memory: 256M -# securityContext: -# privileged: true -# procMount: Default -# env: -# - name: DOCKER_TLS_CERTDIR -# value: "" -# - name: DOCKER_DRIVER -# value: "overlay2" +# - name: docker-dind +# image: docker:28.3.2-dind +# imagePullPolicy: IfNotPresent +# resources: +# requests: +# cpu: 1 +# ephemeral-storage: "50Gi" +# memory: 10Gi +# securityContext: +# privileged: true +# procMount: Default +# env: +# - name: DOCKER_TLS_CERTDIR +# value: "" # disable TLS setup +# command: +# - dockerd +# - --host=unix:///var/run/docker.sock +# - --host=tcp://0.0.0.0:2376 + extraInitContainers: | # - name: customization diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 9d6c413c4ff4..3a89005e32f6 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -32,7 +32,7 @@ The prerequisites for contributing to code-server are almost the same as those for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites). Here is what is needed: -- `node` v20.x +- `node` v22.x - `git` v2.x or greater - [`git-lfs`](https://git-lfs.github.com) - [`npm`](https://www.npmjs.com/) diff --git a/docs/FAQ.md b/docs/FAQ.md index c46c003b8800..2e01306cb2f2 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -383,6 +383,9 @@ mount into `/home/coder/myproject` from inside the `code-server` container. You need to make sure the Docker daemon's `/home/coder/myproject` is the same as the one mounted inside the `code-server` container, and the mount will work. +If you want Docker enabled when deploying on Kubernetes, look at the `values.yaml` +file for the 3 fields: `extraVars`, `lifecycle.postStart`, and `extraContainers`. + ## How do I disable telemetry? Use the `--disable-telemetry` flag to disable telemetry. diff --git a/docs/README.md b/docs/README.md index b56f267e4d3c..5724c804c087 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,7 +24,7 @@ on how to set up a Google VM on which you can install code-server. ## Getting started -There are four ways to get started: +There are five ways to get started: 1. Using the [install script](https://github.com/coder/code-server/blob/main/install.sh), which @@ -35,6 +35,9 @@ There are four ways to get started: 3. Deploy code-server to your team with [coder/coder](https://cdr.co/coder-github) 4. Using our one-click buttons and guides to [deploy code-server to a cloud provider](https://github.com/coder/deploy-code-server) ⚡ +5. Using the [code-server feature for + devcontainers](https://github.com/coder/devcontainer-features/blob/main/src/code-server/README.md), + if you already use devcontainers in your project. If you use the install script, you can preview what occurs during the install process: diff --git a/docs/android.md b/docs/android.md index 00909f975415..2659c44000b8 100644 --- a/docs/android.md +++ b/docs/android.md @@ -11,7 +11,7 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash ``` 6. Exit the terminal using `exit` and then reopen the terminal -7. Install and use Node.js 20: +7. Install and use Node.js 22: ```shell nvm install 18 diff --git a/docs/guide.md b/docs/guide.md index de1b50b495cf..0aa8901c36a1 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -21,6 +21,10 @@ - [Proxying to an Angular app](#proxying-to-an-angular-app) - [Proxying to a Svelte app](#proxying-to-a-svelte-app) - [Prefixing `/absproxy/` with a path](#prefixing-absproxyport-with-a-path) + - [Preflight requests](#preflight-requests) +- [Internationalization and customization](#internationalization-and-customization) + - [Available keys and placeholders](#available-keys-and-placeholders) + - [Legacy flag](#legacy-flag) @@ -119,22 +123,22 @@ access code-server on an iPad or do not want to use SSH port forwarding. 1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic. -1. You'll need a domain name (if you don't have one, you can purchase one from +2. You'll need a domain name (if you don't have one, you can purchase one from [Google Domains](https://domains.google.com) or the domain service of your choice). Once you have a domain name, add an A record to your domain that contains your instance's IP address. -1. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian): +3. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian): -```console -sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https -curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg -curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list -sudo apt update -sudo apt install caddy -``` + ```console + sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https + curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg + curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list + sudo apt update + sudo apt install caddy + ``` -1. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this: +4. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this: ```text mydomain.com { @@ -153,7 +157,7 @@ sudo apt install caddy Remember to replace `mydomain.com` with your domain name! -1. Reload Caddy: +5. Reload Caddy: ```console sudo systemctl reload caddy @@ -164,21 +168,22 @@ At this point, you should be able to access code-server via ### Using Let's Encrypt with NGINX -1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic. +1. This option requires that the remote machine be exposed to the internet. Make + sure that your instance allows HTTP/HTTPS traffic. -1. You'll need a domain name (if you don't have one, you can purchase one from +2. You'll need a domain name (if you don't have one, you can purchase one from [Google Domains](https://domains.google.com) or the domain service of your choice). Once you have a domain name, add an A record to your domain that contains your instance's IP address. -1. Install NGINX: +3. Install NGINX: ```bash sudo apt update sudo apt install -y nginx certbot python3-certbot-nginx ``` -1. Update `/etc/nginx/sites-available/code-server` using sudo with the following +4. Update `/etc/nginx/sites-available/code-server` using sudo with the following configuration: ```text @@ -199,13 +204,11 @@ At this point, you should be able to access code-server via Be sure to replace `mydomain.com` with your domain name! -1. Enable the config: - +5. Enable the config: ```console sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server sudo certbot --non-interactive --redirect --agree-tos --nginx -d mydomain.com -m me@example.com ``` - Be sure to replace `me@example.com` with your actual email. At this point, you should be able to access code-server via @@ -292,7 +295,9 @@ redirect all HTTP requests to HTTPS. > You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate > for free. -Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it will change the address displayed in the green section of code-server in the bottom left to show the correct address. +Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it +will change the address displayed in the green section of code-server in the +bottom left to show the correct address. ## Accessing web services @@ -378,14 +383,16 @@ PUBLIC_URL=/absproxy/3000 \ BROWSER=none yarn start ``` -You should then be able to visit `https://my-code-server-address.io/absproxy/3000` to see your app exposed through -code-server! +You should then be able to visit +`https://my-code-server-address.io/absproxy/3000` to see your app exposed +through code-server. > We highly recommend using the subdomain approach instead to avoid this class of issue. ### Proxying to a Vue app -Similar to the situation with React apps, you have to make a few modifications to proxy a Vue app. +Similar to the situation with React apps, you have to make a few modifications +to proxy a Vue app. 1. add `vue.config.js` 2. update the values to match this (you can use any free port): @@ -406,7 +413,8 @@ Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/# ### Proxying to an Angular app -In order to use code-server's built-in proxy with Angular, you need to make the following changes in your app: +In order to use code-server's built-in proxy with Angular, you need to make the +following changes in your app: 1. use `` in `src/index.html` 2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json` @@ -415,7 +423,8 @@ For additional context, see [this GitHub Discussion](https://github.com/coder/co ### Proxying to a Svelte app -In order to use code-server's built-in proxy with Svelte, you need to make the following changes in your app: +In order to use code-server's built-in proxy with Svelte, you need to make the +following changes in your app: 1. Add `svelte.config.js` if you don't already have one 2. Update the values to match this (you can use any free port): @@ -436,9 +445,68 @@ For additional context, see [this Github Issue](https://github.com/sveltejs/kit/ ### Prefixing `/absproxy/` with a path -This is a case where you need to serve an application via `absproxy` as explained above while serving `codeserver` itself from a path other than the root in your domain. +This is a case where you need to serve an application via `absproxy` as +explained above while serving code-server itself from a path other than the root +in your domain. -For example: `http://my-code-server.com/user/123/workspace/my-app`. To achieve this result: +For example: `http://my-code-server.com/user/123/workspace/my-app`. To achieve +this result: -1. Start code server with the switch `--abs-proxy-base-path=/user/123/workspace` +1. Start code-server with the switch `--abs-proxy-base-path=/user/123/workspace` 2. Follow one of the instructions above for your framework. + +### Preflight requests + +By default, if you have auth enabled, code-server will authenticate all proxied +requests including preflight requests. This can cause issues because preflight +requests do not typically include credentials. To allow all preflight requests +through the proxy without authentication, use `--skip-auth-preflight`. + +## Internationalization and customization + +code-server allows you to provide a JSON file to configure certain strings. This +can be used for both internationalization and customization. + +Create a JSON file with your custom strings: + +```json +{ + "WELCOME": "Welcome to {{app}}", + "LOGIN_TITLE": "{{app}} Access Portal", + "LOGIN_BELOW": "Please log in to continue", + "PASSWORD_PLACEHOLDER": "Enter Password" +} +``` + +Then reference the file: + +```shell +code-server --i18n /path/to/custom-strings.json +``` + +Or this can be done in the config file: + +```yaml +i18n: /path/to/custom-strings.json +``` + +You can combine this with the `--locale` flag to configure language support for +both code-server and VS Code in cases where code-server has no support but VS +Code does. If you are using this for internationalization, please consider +sending us a pull request to contribute it to `src/node/i18n/locales`. + +### Available keys and placeholders + +Refer to [../src/node/i18n/locales/en.json](../src/node/i18n/locales/en.json) +for a full list of the available keys for translations. Note that the only +placeholders supported for each key are the ones used in the default string. + +The `--app-name` flag controls the `{{app}}` placeholder in templates. If you +want to change the name, you can either: + +1. Set `--app-name` (potentially alongside `--i18n`) +2. Use `--i18n` and hardcode the name in your strings + +### Legacy flag + +The `--welcome-text` flag is now deprecated. Use the `WELCOME` key instead. diff --git a/docs/install.md b/docs/install.md index e2dd905f9401..30da4d415e77 100644 --- a/docs/install.md +++ b/docs/install.md @@ -82,13 +82,11 @@ _exact_ same commands presented in the rest of this document. - For Arch Linux, code-server will install the AUR package. - For any unrecognized Linux operating system, code-server will install the latest standalone release into `~/.local`. - - Ensure that you add `~/.local/bin` to your `$PATH` to run code-server. - For macOS, code-server will install the Homebrew package (if you don't have Homebrew installed, code-server will install the latest standalone release into `~/.local`). - - Ensure that you add `~/.local/bin` to your `$PATH` to run code-server. - For FreeBSD, code-server will install the [npm package](#npm) with `npm` diff --git a/docs/npm.md b/docs/npm.md index d300cfa5bd55..8d3afd0be06a 100644 --- a/docs/npm.md +++ b/docs/npm.md @@ -30,7 +30,7 @@ includes installing instructions based on your operating system. ## Node.js version We use the same major version of Node.js shipped with Code's remote, which is -currently `20.x`. VS Code also [lists Node.js +currently `22.x`. VS Code also [lists Node.js requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites). Using other versions of Node.js [may lead to unexpected @@ -78,7 +78,7 @@ Proceed to [installing](#installing) ## FreeBSD ```sh -pkg install -y git python npm-node20 pkgconf +pkg install -y git python npm-node22 pkgconf pkg install -y libinotify ``` diff --git a/docs/termux.md b/docs/termux.md index 84dcec0765e4..db81cb57d1e1 100644 --- a/docs/termux.md +++ b/docs/termux.md @@ -57,7 +57,7 @@ npm config set python python3 node -v ``` -you will get Node version `v20` +you will get Node version `v22` 5. Now install code-server following our guide on [installing with npm](./npm.md) diff --git a/flake.nix b/flake.nix index 2fee8f28b6fd..3a1f7efbc122 100644 --- a/flake.nix +++ b/flake.nix @@ -10,10 +10,11 @@ flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; - nodejs = pkgs.nodejs_20; + nodejs = pkgs.nodejs_22; in { devShells.default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ + imagemagick nodejs python3 pkg-config diff --git a/lib/vscode b/lib/vscode index 17baf841131a..360a4e4fd251 160000 --- a/lib/vscode +++ b/lib/vscode @@ -1 +1 @@ -Subproject commit 17baf841131aa23349f217ca7c570c76ee87b957 +Subproject commit 360a4e4fd251bfce169a4ddf857c7d25d1ad40da diff --git a/package-lock.json b/package-lock.json index 6c7f81cea9c6..2c98099e0bb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,14 +18,13 @@ "express": "^5.0.1", "http-proxy": "^1.18.1", "httpolyglot": "^0.1.2", - "i18next": "^23.5.1", + "i18next": "^25.3.0", "js-yaml": "^4.1.0", "limiter": "^2.1.0", "pem": "^1.14.8", "proxy-agent": "^6.3.1", - "qs": "6.13.0", + "qs": "6.14.0", "rotating-file-stream": "^3.1.1", - "safe-buffer": "^5.2.1", "safe-compare": "^1.1.4", "semver": "^7.5.4", "ws": "^8.14.2", @@ -45,7 +44,7 @@ "@types/express": "^5.0.0", "@types/http-proxy": "1.17.7", "@types/js-yaml": "^4.0.6", - "@types/node": "20.x", + "@types/node": "22.x", "@types/pem": "^1.14.1", "@types/proxy-from-env": "^1.0.1", "@types/safe-compare": "^1.1.0", @@ -55,28 +54,24 @@ "doctoc": "^2.2.1", "eslint": "^9.12.0", "eslint-config-prettier": "^9.0.0", - "eslint-import-resolver-typescript": "^3.6.0", + "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", - "globals": "^15.10.0", - "prettier": "3.4.2", + "globals": "^16.1.0", + "prettier": "3.6.2", "prettier-plugin-sh": "^0.14.0", "ts-node": "^10.9.1", "typescript": "^5.6.2", "typescript-eslint": "^8.8.0" }, "engines": { - "node": "20" + "node": "22" } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "engines": { "node": ">=6.9.0" } @@ -98,17 +93,55 @@ "node": ">=12" } }, + "node_modules/@emnapi/core": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.4.tgz", + "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz", + "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz", + "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } @@ -142,9 +175,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -157,9 +190,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", - "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -167,9 +200,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -217,13 +250,16 @@ } }, "node_modules/@eslint/js": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", - "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -237,13 +273,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.15.1", "levn": "^0.4.1" }, "engines": { @@ -359,6 +395,19 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -397,15 +446,6 @@ "node": ">= 8" } }, - "node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true, - "engines": { - "node": ">=12.4.0" - } - }, "node_modules/@phc/format": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", @@ -491,6 +531,17 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -502,12 +553,14 @@ } }, "node_modules/@types/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-AAQvK5pxMpaT+nDvhHrsBhLSYG5yQdtkaJE1WYieSNY2mVFKAgmU4ks65rkZD5oqnGCFLyQpUr1CqI4DmUMyDg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-g4vmPIwbTii9dX1HVioHbOolubEaf4re4vDxuzpKrzz9uI7uarBExi9begX0cXyIB85jXZ5X2A/v8rsHZxSAPw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/express": "*" + "@types/express": "*", + "@types/node": "*" } }, "node_modules/@types/connect": { @@ -632,13 +685,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.17.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.17.tgz", - "integrity": "sha512-/WndGO4kIfMicEQLTi/mDANUu/iVUhT7KboZPdEqqHQ4aTS+3qT3U5gIqWDFV+XouorjfgGqvKILJeHhuQgFYg==", + "version": "22.15.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.31.tgz", + "integrity": "sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.21.0" } }, "node_modules/@types/pem": { @@ -680,10 +733,11 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/send": { "version": "0.17.4", @@ -728,21 +782,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz", - "integrity": "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.0.tgz", + "integrity": "sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.29.0", - "@typescript-eslint/type-utils": "8.29.0", - "@typescript-eslint/utils": "8.29.0", - "@typescript-eslint/visitor-keys": "8.29.0", + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/type-utils": "8.33.0", + "@typescript-eslint/utils": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -752,22 +806,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.33.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz", - "integrity": "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz", + "integrity": "sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.29.0", - "@typescript-eslint/types": "8.29.0", - "@typescript-eslint/typescript-estree": "8.29.0", - "@typescript-eslint/visitor-keys": "8.29.0", + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/typescript-estree": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4" }, "engines": { @@ -782,15 +846,34 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.0.tgz", + "integrity": "sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.33.0", + "@typescript-eslint/types": "^8.33.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz", - "integrity": "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.0.tgz", + "integrity": "sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.0", - "@typescript-eslint/visitor-keys": "8.29.0" + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -800,17 +883,34 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz", + "integrity": "sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz", - "integrity": "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.0.tgz", + "integrity": "sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.29.0", - "@typescript-eslint/utils": "8.29.0", + "@typescript-eslint/typescript-estree": "8.33.0", + "@typescript-eslint/utils": "8.33.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -825,9 +925,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", - "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz", + "integrity": "sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==", "dev": true, "license": "MIT", "engines": { @@ -839,20 +939,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz", - "integrity": "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.0.tgz", + "integrity": "sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.0", - "@typescript-eslint/visitor-keys": "8.29.0", + "@typescript-eslint/project-service": "8.33.0", + "@typescript-eslint/tsconfig-utils": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/visitor-keys": "8.33.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -866,9 +968,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -892,16 +994,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz", - "integrity": "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.0.tgz", + "integrity": "sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.29.0", - "@typescript-eslint/types": "8.29.0", - "@typescript-eslint/typescript-estree": "8.29.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.33.0", + "@typescript-eslint/types": "8.33.0", + "@typescript-eslint/typescript-estree": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -916,13 +1018,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz", - "integrity": "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.0.tgz", + "integrity": "sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/types": "8.33.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -946,6 +1048,275 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -965,9 +1336,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -1280,7 +1651,7 @@ "http-errors": "^2.0.0", "iconv-lite": "^0.5.2", "on-finished": "^2.4.1", - "qs": "^6.14.0", + "qs": "6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" }, @@ -1288,25 +1659,10 @@ "node": ">=18" } }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -1522,16 +1878,16 @@ } }, "node_modules/compression": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", - "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -1710,9 +2066,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1937,19 +2293,6 @@ "node": ">= 0.8" } }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/entities": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", @@ -2147,20 +2490,20 @@ } }, "node_modules/eslint": { - "version": "9.23.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", - "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.23.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -2171,9 +2514,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2219,6 +2562,31 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-import-context": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/eslint-import-context/-/eslint-import-context-0.1.9.tgz", + "integrity": "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-tsconfig": "^4.10.1", + "stable-hash-x": "^0.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-context" + }, + "peerDependencies": { + "unrs-resolver": "^1.0.0" + }, + "peerDependenciesMeta": { + "unrs-resolver": { + "optional": true + } + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -2240,25 +2608,25 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.8.3.tgz", - "integrity": "sha512-A0bu4Ks2QqDWNpeEgTQMPTngaMhuDu4yv6xpftBMAf+1ziXnpx+eSR1WRfoPTe2BAiAjHFZ7kSNx1fvr5g5pmQ==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.4.4.tgz", + "integrity": "sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==", "dev": true, "license": "ISC", "dependencies": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "get-tsconfig": "^4.10.0", - "is-bun-module": "^1.0.2", - "stable-hash": "^0.0.4", - "tinyglobby": "^0.2.12" + "debug": "^4.4.1", + "eslint-import-context": "^0.1.8", + "get-tsconfig": "^4.10.1", + "is-bun-module": "^2.0.0", + "stable-hash-x": "^0.2.0", + "tinyglobby": "^0.2.14", + "unrs-resolver": "^1.7.11" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^16.17.0 || >=18.6.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", @@ -2394,9 +2762,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2423,9 +2791,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2436,15 +2804,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2454,9 +2822,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2618,6 +2986,21 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2974,9 +3357,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3033,10 +3416,11 @@ } }, "node_modules/globals": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", - "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.1.0.tgz", + "integrity": "sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -3072,12 +3456,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -3261,9 +3639,9 @@ } }, "node_modules/i18next": { - "version": "23.16.4", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.4.tgz", - "integrity": "sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg==", + "version": "25.3.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.3.0.tgz", + "integrity": "sha512-ZSQIiNGfqSG6yoLHaCvrkPp16UejHI8PCDxFYaNG/1qxtmqNmqEg4JlWKlxkrUmrin2sEjsy+Mjy1TRozBhOgw==", "funding": [ { "type": "individual", @@ -3279,7 +3657,15 @@ } ], "dependencies": { - "@babel/runtime": "^7.23.2" + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/iconv-lite": { @@ -3454,12 +3840,13 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-bun-module": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz", - "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, + "license": "MIT", "dependencies": { - "semver": "^7.6.3" + "semver": "^7.7.1" } }, "node_modules/is-callable": { @@ -4336,6 +4723,22 @@ "integrity": "sha512-kMbrH0EObaKmK3nVRKUIIya1dpASHIEusM13S4V1ViHFuxuNxCo+arxoa6j/dbV22YBGjl7UKJm9QQKJ2Crzhg==", "dev": true }, + "node_modules/napi-postinstall": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.0.tgz", + "integrity": "sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4519,9 +4922,10 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4770,9 +5174,9 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -4885,11 +5289,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -4968,11 +5373,6 @@ "node": ">= 6" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", @@ -5539,12 +5939,15 @@ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "license": "BSD-3-Clause" }, - "node_modules/stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "node_modules/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } }, "node_modules/statuses": { "version": "2.0.1", @@ -5703,15 +6106,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -5729,13 +6123,13 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { @@ -5746,9 +6140,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5761,9 +6155,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -6020,10 +6414,10 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "dev": true, + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -6034,15 +6428,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.29.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.0.tgz", - "integrity": "sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==", + "version": "8.33.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.33.0.tgz", + "integrity": "sha512-5YmNhF24ylCsvdNW2oJwMzTbaeO4bg90KeGtMjUw0AGtHksgEPLRTUil+coHwCfiu4QjVJFnjp94DmU6zV7DhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.29.0", - "@typescript-eslint/parser": "8.29.0", - "@typescript-eslint/utils": "8.29.0" + "@typescript-eslint/eslint-plugin": "8.33.0", + "@typescript-eslint/parser": "8.33.0", + "@typescript-eslint/utils": "8.33.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6078,10 +6472,11 @@ "dev": true }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" }, "node_modules/unified": { "version": "9.2.2", @@ -6170,6 +6565,41 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-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", diff --git a/package.json b/package.json index ffdfccafdede..8bd1c71b7caa 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/express": "^5.0.0", "@types/http-proxy": "1.17.7", "@types/js-yaml": "^4.0.6", - "@types/node": "20.x", + "@types/node": "22.x", "@types/pem": "^1.14.1", "@types/proxy-from-env": "^1.0.1", "@types/safe-compare": "^1.1.0", @@ -57,11 +57,11 @@ "doctoc": "^2.2.1", "eslint": "^9.12.0", "eslint-config-prettier": "^9.0.0", - "eslint-import-resolver-typescript": "^3.6.0", + "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", - "globals": "^15.10.0", - "prettier": "3.4.2", + "globals": "^16.1.0", + "prettier": "3.6.2", "prettier-plugin-sh": "^0.14.0", "ts-node": "^10.9.1", "typescript": "^5.6.2", @@ -76,21 +76,20 @@ "express": "^5.0.1", "http-proxy": "^1.18.1", "httpolyglot": "^0.1.2", - "i18next": "^23.5.1", + "i18next": "^25.3.0", "js-yaml": "^4.1.0", "limiter": "^2.1.0", "pem": "^1.14.8", "proxy-agent": "^6.3.1", - "qs": "6.13.0", + "qs": "6.14.0", "rotating-file-stream": "^3.1.1", - "safe-buffer": "^5.2.1", "safe-compare": "^1.1.4", "semver": "^7.5.4", "ws": "^8.14.2", "xdg-basedir": "^4.0.0" }, "resolutions": { - "@types/node": "20.x" + "@types/node": "22.x" }, "bin": { "code-server": "out/node/entry.js" @@ -105,7 +104,7 @@ "remote-development" ], "engines": { - "node": "20" + "node": "22" }, "jest": { "transform": { diff --git a/patches/base-path.diff b/patches/base-path.diff index 7d6bbc6999f0..09a967cb9ed4 100644 --- a/patches/base-path.diff +++ b/patches/base-path.diff @@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/network.ts +++ code-server/lib/vscode/src/vs/base/common/network.ts -@@ -220,7 +220,9 @@ class RemoteAuthoritiesImpl { +@@ -226,7 +226,9 @@ class RemoteAuthoritiesImpl { return URI.from({ scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource, authority: `${host}:${port}`, @@ -111,7 +111,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -246,7 +246,9 @@ export class WebClientServer { +@@ -245,7 +245,9 @@ export class WebClientServer { }; // Prefix routes with basePath for clients @@ -122,7 +122,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts const queryConnectionToken = parsedUrl.query[connectionTokenQueryName]; if (typeof queryConnectionToken === 'string') { -@@ -285,10 +287,14 @@ export class WebClientServer { +@@ -284,10 +286,14 @@ export class WebClientServer { }; const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']); @@ -138,15 +138,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts ); if (!remoteAuthority) { return serveError(req, res, 400, `Bad request.`); -@@ -335,6 +341,7 @@ export class WebClientServer { +@@ -334,6 +340,7 @@ export class WebClientServer { - const productConfiguration = { + const productConfiguration: Partial> = { codeServerVersion: this._productService.codeServerVersion, + rootEndpoint: rootBase, embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? { ...this._productService.extensionsGallery, -@@ -382,7 +389,9 @@ export class WebClientServer { +@@ -387,7 +394,9 @@ export class WebClientServer { WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '', WORKBENCH_WEB_BASE_URL: staticRoute, WORKBENCH_NLS_URL, @@ -157,7 +157,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts }; // DEV --------------------------------------------------------------------------------------- -@@ -419,7 +428,7 @@ export class WebClientServer { +@@ -424,7 +433,7 @@ export class WebClientServer { 'default-src \'self\';', 'img-src \'self\' https: data: blob:;', 'media-src \'self\';', @@ -166,7 +166,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts 'child-src \'self\';', `frame-src 'self' https://*.vscode-cdn.net data:;`, 'worker-src \'self\' data: blob:;', -@@ -492,3 +501,70 @@ export class WebClientServer { +@@ -497,3 +506,70 @@ export class WebClientServer { return void res.end(data); } } @@ -253,7 +253,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts -@@ -332,7 +332,8 @@ class LocalStorageURLCallbackProvider ex +@@ -338,7 +338,8 @@ class LocalStorageURLCallbackProvider ex this.startListening(); } @@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts } private startListening(): void { -@@ -579,17 +580,6 @@ class WorkspaceProvider implements IWork +@@ -583,17 +584,6 @@ class WorkspaceProvider implements IWork } } @@ -281,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts (function () { // Find config by checking for DOM -@@ -598,8 +588,8 @@ function readCookie(name: string): strin +@@ -602,8 +592,8 @@ function readCookie(name: string): strin if (!configElement || !configElementAttribute) { throw new Error('Missing web configuration element'); } diff --git a/patches/clipboard.diff b/patches/clipboard.diff index ffcafe5dddb0..02c7d54dfd93 100644 --- a/patches/clipboard.diff +++ b/patches/clipboard.diff @@ -78,19 +78,19 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts +++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts -@@ -122,6 +122,7 @@ export interface NativeParsedArgs { +@@ -135,6 +135,7 @@ export interface NativeParsedArgs { 'disable-chromium-sandbox'?: boolean; sandbox?: boolean; 'enable-coi'?: boolean; + 'stdin-to-clipboard'?: boolean; 'unresponsive-sample-interval'?: string; 'unresponsive-sample-period'?: string; - + 'enable-rdp-display-tracking'?: boolean; Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts +++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts -@@ -91,6 +91,7 @@ export const OPTIONS: OptionDescriptions +@@ -104,6 +104,7 @@ export const OPTIONS: OptionDescriptions 'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") }, 'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") }, 'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") }, diff --git a/patches/disable-builtin-ext-update.diff b/patches/disable-builtin-ext-update.diff index 6b222147a92d..5e71ed6770e7 100644 --- a/patches/disable-builtin-ext-update.diff +++ b/patches/disable-builtin-ext-update.diff @@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts -@@ -326,6 +326,10 @@ export class Extension implements IExten +@@ -341,6 +341,10 @@ export class Extension implements IExten if (this.type === ExtensionType.System && this.productService.quality === 'stable') { return false; } diff --git a/patches/display-language.diff b/patches/display-language.diff index b711a0cf414d..d6ecffcb35c6 100644 --- a/patches/display-language.diff +++ b/patches/display-language.diff @@ -18,9 +18,9 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; import { ConfigurationService } from '../../platform/configuration/common/configurationService.js'; -@@ -255,6 +255,9 @@ export async function setupServerService - const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)); - socketServer.registerChannel('extensions', channel); +@@ -269,6 +269,9 @@ export async function setupServerService + + socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority))); + const languagePackChannel = ProxyChannel.fromService(accessor.get(ILanguagePackService), disposables); + socketServer.registerChannel('languagePacks', languagePackChannel); @@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentServ =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts +++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts -@@ -101,7 +101,7 @@ export abstract class AbstractNativeEnvi +@@ -98,7 +98,7 @@ export abstract class AbstractNativeEnvi return URI.file(join(vscodePortable, 'argv.json')); } @@ -153,15 +153,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -26,6 +26,7 @@ import { URI } from '../../base/common/u +@@ -25,6 +25,7 @@ import { URI } from '../../base/common/u import { streamToBuffer } from '../../base/common/buffer.js'; import { IProductConfiguration } from '../../base/common/product.js'; - import { isString } from '../../base/common/types.js'; + import { isString, Mutable } from '../../base/common/types.js'; +import { getLocaleFromConfig, getBrowserNLSConfiguration } from './remoteLanguagePacks.js'; import { CharCode } from '../../base/common/charCode.js'; import { IExtensionManifest } from '../../platform/extensions/common/extensions.js'; import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js'; -@@ -380,14 +381,22 @@ export class WebClientServer { +@@ -385,14 +386,22 @@ export class WebClientServer { }; const cookies = cookie.parse(req.headers.cookie || ''); @@ -190,7 +190,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts -@@ -19,6 +19,7 @@ export const serverOptions: OptionDescri +@@ -21,6 +21,7 @@ export const serverOptions: OptionDescri 'disable-file-downloads': { type: 'boolean' }, 'disable-file-uploads': { type: 'boolean' }, 'disable-getting-started-override': { type: 'boolean' }, @@ -198,7 +198,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -106,6 +107,7 @@ export interface ServerParsedArgs { +@@ -110,6 +111,7 @@ export interface ServerParsedArgs { 'disable-file-downloads'?: boolean; 'disable-file-uploads'?: boolean; 'disable-getting-started-override'?: boolean, @@ -244,10 +244,10 @@ Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePack + return this.languagePackService.getInstalledLanguages() } } -Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts +Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts =================================================================== ---- code-server.orig/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts -+++ code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts +--- code-server.orig/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts ++++ code-server/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts @@ -51,7 +51,8 @@ class NativeLocaleService implements ILo @IProductService private readonly productService: IProductService ) { } @@ -272,7 +272,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts -@@ -445,9 +445,6 @@ export class InstallAction extends Exten +@@ -475,9 +475,6 @@ export class InstallAction extends Exten if (this.extension.isBuiltin) { return; } @@ -282,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens if (this.extension.state !== ExtensionState.Uninstalled) { return; } -@@ -752,7 +749,7 @@ export abstract class InstallInOtherServ +@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ } if (isLanguagePackExtension(this.extension.local.manifest)) { @@ -291,7 +291,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens } // Prefers to run on UI -@@ -2039,17 +2036,6 @@ export class SetLanguageAction extends E +@@ -2073,17 +2070,6 @@ export class SetLanguageAction extends E update(): void { this.enabled = false; this.class = SetLanguageAction.DisabledClass; @@ -309,7 +309,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens } override async run(): Promise { -@@ -2066,7 +2052,6 @@ export class ClearLanguageAction extends +@@ -2100,7 +2086,6 @@ export class ClearLanguageAction extends private static readonly DisabledClass = `${this.EnabledClass} disabled`; constructor( @@ -317,7 +317,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens @ILocaleService private readonly localeService: ILocaleService, ) { super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false); -@@ -2076,17 +2061,6 @@ export class ClearLanguageAction extends +@@ -2110,17 +2095,6 @@ export class ClearLanguageAction extends update(): void { this.enabled = false; this.class = ClearLanguageAction.DisabledClass; @@ -335,28 +335,16 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens } override async run(): Promise { -Index: code-server/lib/vscode/build/gulpfile.reh.js -=================================================================== ---- code-server.orig/lib/vscode/build/gulpfile.reh.js -+++ code-server/lib/vscode/build/gulpfile.reh.js -@@ -58,6 +58,7 @@ const serverResourceIncludes = [ - - // NLS - 'out-build/nls.messages.json', -+ 'out-build/nls.keys.json', // Required to generate translations. - - // Process monitor - 'out-build/vs/base/node/cpuUsage.sh', Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts +++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts -@@ -53,7 +53,7 @@ import './services/dialogs/browser/fileD +@@ -54,7 +54,7 @@ import './services/dialogs/browser/fileD import './services/host/browser/browserHostService.js'; import './services/lifecycle/browser/lifecycleService.js'; import './services/clipboard/browser/clipboardService.js'; -import './services/localization/browser/localeService.js'; -+import './services/localization/electron-sandbox/localeService.js'; ++import './services/localization/electron-browser/localeService.js'; import './services/path/browser/pathService.js'; import './services/themes/browser/browserHostColorSchemeService.js'; import './services/encryption/browser/encryptionService.js'; diff --git a/patches/external-file-actions.diff b/patches/external-file-actions.diff index 912279e8a4f9..56f9b7c5af14 100644 --- a/patches/external-file-actions.diff +++ b/patches/external-file-actions.diff @@ -90,7 +90,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts -@@ -16,6 +16,8 @@ export const serverOptions: OptionDescri +@@ -18,6 +18,8 @@ export const serverOptions: OptionDescri /* ----- code-server ----- */ 'disable-update-check': { type: 'boolean' }, 'auth': { type: 'string' }, @@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -100,6 +102,8 @@ export interface ServerParsedArgs { +@@ -104,6 +106,8 @@ export interface ServerParsedArgs { /* ----- code-server ----- */ 'disable-update-check'?: boolean; 'auth'?: string; @@ -112,7 +112,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -364,6 +364,8 @@ export class WebClientServer { +@@ -369,6 +369,8 @@ export class WebClientServer { serverBasePath: basePath, webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', userDataPath: this._environmentService.userDataPath, @@ -126,11 +126,11 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts +++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts @@ -7,11 +7,11 @@ import { Event } from '../../base/common - import { Disposable } from '../../base/common/lifecycle.js'; + import { Disposable, DisposableStore, MutableDisposable } from '../../base/common/lifecycle.js'; import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js'; import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js'; --import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext } from '../common/contextkeys.js'; -+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js'; +-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext } from '../common/contextkeys.js'; ++import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js'; import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow, isEditableElement } from '../../base/browser/dom.js'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; @@ -139,7 +139,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js'; import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js'; import { getRemoteName } from '../../platform/remote/common/remoteHosts.js'; -@@ -70,7 +70,7 @@ export class WorkbenchContextKeysHandler +@@ -71,7 +71,7 @@ export class WorkbenchContextKeysHandler @IContextKeyService private readonly contextKeyService: IContextKeyService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IConfigurationService private readonly configurationService: IConfigurationService, @@ -148,9 +148,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts @IProductService private readonly productService: IProductService, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, @IEditorService private readonly editorService: IEditorService, -@@ -197,6 +197,10 @@ export class WorkbenchContextKeysHandler - this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService); - this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART)); +@@ -200,6 +200,10 @@ export class WorkbenchContextKeysHandler + this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService); + this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized()); + // code-server + IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true) @@ -208,7 +208,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts +++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts -@@ -39,6 +39,9 @@ export const HasWebFileSystemAccess = ne +@@ -37,6 +37,9 @@ export const HasWebFileSystemAccess = ne export const EmbedderIdentifierContext = new RawContextKey('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined')); @@ -217,7 +217,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts + //#endregion - + //#region < --- Window --- > Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -330,7 +330,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts +++ code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts -@@ -92,6 +92,7 @@ export abstract class AbstractDiskFileSy +@@ -99,6 +99,7 @@ export abstract class AbstractDiskFileSy private async readFile(uriTransformer: IURITransformer, _resource: UriComponents, opts?: IFileAtomicReadOptions): Promise { const resource = this.transformIncoming(uriTransformer, _resource, true); @@ -338,7 +338,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS const buffer = await this.provider.readFile(resource, opts); return VSBuffer.wrap(buffer); -@@ -110,6 +111,7 @@ export abstract class AbstractDiskFileSy +@@ -117,6 +118,7 @@ export abstract class AbstractDiskFileSy } }); @@ -346,7 +346,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS const fileStream = this.provider.readFileStream(resource, opts, cts.token); listenStream(fileStream, { onData: chunk => emitter.fire(VSBuffer.wrap(chunk)), -@@ -130,7 +132,7 @@ export abstract class AbstractDiskFileSy +@@ -137,7 +139,7 @@ export abstract class AbstractDiskFileSy private writeFile(uriTransformer: IURITransformer, _resource: UriComponents, content: VSBuffer, opts: IFileWriteOptions): Promise { const resource = this.transformIncoming(uriTransformer, _resource); diff --git a/patches/getting-started.diff b/patches/getting-started.diff index 25e1ed316412..ee53750d4195 100644 --- a/patches/getting-started.diff +++ b/patches/getting-started.diff @@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js'; import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js'; import './gettingStartedColors.js'; -@@ -872,6 +872,72 @@ export class GettingStartedPage extends +@@ -876,6 +876,72 @@ export class GettingStartedPage extends $('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved")) ); @@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro const leftColumn = $('.categories-column.categories-column-left', {},); const rightColumn = $('.categories-column.categories-column-right', {},); -@@ -907,6 +973,9 @@ export class GettingStartedPage extends +@@ -911,6 +977,9 @@ export class GettingStartedPage extends recentList.setLimit(5); reset(leftColumn, startList.getDomElement(), recentList.getDomElement()); } @@ -181,7 +181,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts -@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri +@@ -20,6 +20,7 @@ export const serverOptions: OptionDescri 'auth': { type: 'string' }, 'disable-file-downloads': { type: 'boolean' }, 'disable-file-uploads': { type: 'boolean' }, @@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -104,6 +105,7 @@ export interface ServerParsedArgs { +@@ -108,6 +109,7 @@ export interface ServerParsedArgs { 'auth'?: string; 'disable-file-downloads'?: boolean; 'disable-file-uploads'?: boolean; @@ -201,7 +201,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -368,6 +368,7 @@ export class WebClientServer { +@@ -373,6 +373,7 @@ export class WebClientServer { userDataPath: this._environmentService.userDataPath, isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'], isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'], @@ -214,15 +214,15 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts +++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts @@ -7,7 +7,7 @@ import { Event } from '../../base/common - import { Disposable } from '../../base/common/lifecycle.js'; + import { Disposable, DisposableStore, MutableDisposable } from '../../base/common/lifecycle.js'; import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js'; import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js'; --import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js'; -+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js'; +-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js'; ++import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js'; import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow, isEditableElement } from '../../base/browser/dom.js'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; -@@ -200,6 +200,7 @@ export class WorkbenchContextKeysHandler +@@ -203,6 +203,7 @@ export class WorkbenchContextKeysHandler // code-server IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true) IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true) @@ -234,7 +234,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts +++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts -@@ -41,6 +41,7 @@ export const EmbedderIdentifierContext = +@@ -39,6 +39,7 @@ export const EmbedderIdentifierContext = export const IsEnabledFileDownloads = new RawContextKey('isEnabledFileDownloads', true, true); export const IsEnabledFileUploads = new RawContextKey('isEnabledFileUploads', true, true); diff --git a/patches/integration.diff b/patches/integration.diff index 4bb397651b14..70de17b788fd 100644 --- a/patches/integration.diff +++ b/patches/integration.diff @@ -269,10 +269,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -334,6 +334,7 @@ export class WebClientServer { +@@ -333,6 +333,7 @@ export class WebClientServer { } : undefined; - const productConfiguration = { + const productConfiguration: Partial> = { + codeServerVersion: this._productService.codeServerVersion, embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? { diff --git a/patches/local-storage.diff b/patches/local-storage.diff index da73ef401148..a358148481ab 100644 --- a/patches/local-storage.diff +++ b/patches/local-storage.diff @@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -359,6 +359,7 @@ export class WebClientServer { +@@ -364,6 +364,7 @@ export class WebClientServer { remoteAuthority, serverBasePath: basePath, webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', @@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts +++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts -@@ -147,8 +147,10 @@ export class WorkspaceService extends Di +@@ -148,8 +148,10 @@ export class WorkspaceService extends Di this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService)); this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => { this.onWorkspaceConfigurationChanged(fromCache).then(() => { @@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co }); })); -@@ -555,6 +557,12 @@ export class WorkspaceService extends Di +@@ -556,6 +558,12 @@ export class WorkspaceService extends Di previousFolders = this.workspace.folders; this.workspace.update(workspace); } else { diff --git a/patches/logout.diff b/patches/logout.diff index 46591632a2a3..49fb8a996d72 100644 --- a/patches/logout.diff +++ b/patches/logout.diff @@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts -@@ -15,6 +15,7 @@ import { URI } from '../../base/common/u +@@ -17,6 +17,7 @@ import { join } from '../../base/common/ export const serverOptions: OptionDescriptions> = { /* ----- code-server ----- */ 'disable-update-check': { type: 'boolean' }, @@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -98,6 +99,7 @@ export const serverOptions: OptionDescri +@@ -102,6 +103,7 @@ export const serverOptions: OptionDescri export interface ServerParsedArgs { /* ----- code-server ----- */ 'disable-update-check'?: boolean; @@ -40,14 +40,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -342,6 +342,7 @@ export class WebClientServer { +@@ -341,6 +341,7 @@ export class WebClientServer { codeServerVersion: this._productService.codeServerVersion, rootEndpoint: rootBase, updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined, + logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined, embedderIdentifier: 'server-distro', extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts diff --git a/patches/marketplace.diff b/patches/marketplace.diff index a64602dbda1a..25a22b093b1d 100644 --- a/patches/marketplace.diff +++ b/patches/marketplace.diff @@ -40,15 +40,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -327,7 +327,6 @@ export class WebClientServer { +@@ -326,7 +326,6 @@ export class WebClientServer { const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH); const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH); - const webExtensionRoute = posix.join(basePath, this._productPath, WEB_EXTENSION_PATH); - const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(path.resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority }); + const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority }); -@@ -343,14 +342,7 @@ export class WebClientServer { +@@ -342,14 +341,7 @@ export class WebClientServer { codeServerVersion: this._productService.codeServerVersion, rootEndpoint: rootBase, embedderIdentifier: 'server-distro', @@ -61,9 +61,9 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts - }).toString(true) - } : undefined + extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; - if (!this._environmentService.isBuilt) { + const proposedApi = this._environmentService.args['enable-proposed-api']; Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts diff --git a/patches/proposed-api.diff b/patches/proposed-api.diff index dd9f25badfc7..ccd274634617 100644 --- a/patches/proposed-api.diff +++ b/patches/proposed-api.diff @@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts -@@ -314,10 +314,7 @@ function extensionDescriptionArrayToMap( +@@ -321,10 +321,7 @@ function extensionDescriptionArrayToMap( } export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean { diff --git a/patches/proxy-uri.diff b/patches/proxy-uri.diff index 2ccd9843820d..6380538128a7 100644 --- a/patches/proxy-uri.diff +++ b/patches/proxy-uri.diff @@ -71,14 +71,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -343,6 +343,7 @@ export class WebClientServer { +@@ -342,6 +342,7 @@ export class WebClientServer { rootEndpoint: rootBase, updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined, logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined, + proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/', embedderIdentifier: 'server-distro', extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -96,7 +96,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts -@@ -19,6 +19,7 @@ import { ISecretStorageProvider } from ' +@@ -20,6 +20,7 @@ import { ISecretStorageProvider } from ' import { isFolderToOpen, isWorkspaceToOpen } from '../../../platform/window/common/window.js'; import type { IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from '../../../workbench/browser/web.api.js'; import { AuthenticationSessionInfo } from '../../../workbench/services/authentication/browser/authenticationService.js'; @@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js'; import { create } from '../../../workbench/workbench.web.main.internal.js'; -@@ -600,6 +601,39 @@ class WorkspaceProvider implements IWork +@@ -604,6 +605,39 @@ class WorkspaceProvider implements IWork settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined, workspaceProvider: WorkspaceProvider.create(config), urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute), diff --git a/patches/series b/patches/series index 61c801ae9357..ffc15fdd9d75 100644 --- a/patches/series +++ b/patches/series @@ -20,3 +20,5 @@ getting-started.diff keepalive.diff clipboard.diff display-language.diff +trusted-domains.diff +signature-verification.diff diff --git a/patches/service-worker.diff b/patches/service-worker.diff index 507a16b5e6bb..f2e1058fb4f7 100644 --- a/patches/service-worker.diff +++ b/patches/service-worker.diff @@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -344,6 +344,10 @@ export class WebClientServer { +@@ -343,6 +343,10 @@ export class WebClientServer { updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined, logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined, proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/', @@ -64,4 +64,4 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts + }, embedderIdentifier: 'server-distro', extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; diff --git a/patches/signature-verification.diff b/patches/signature-verification.diff new file mode 100644 index 000000000000..8c05f4a3f760 --- /dev/null +++ b/patches/signature-verification.diff @@ -0,0 +1,34 @@ +Disable signature verification. + +Extension signature verification is now mandatory for all platforms and needs to be disabled. + +Index: code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts ++++ code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts +@@ -34,6 +34,7 @@ import { + ExtensionSignatureVerificationCode, + computeSize, + IAllowedExtensionsService, ++ // @ts-expect-error no-unused-variable + VerifyExtensionSignatureConfigKey, + shouldRequireRepositorySignatureFor, + } from '../common/extensionManagement.js'; +@@ -87,6 +88,7 @@ export class ExtensionManagementService + @IDownloadService private downloadService: IDownloadService, + @IInstantiationService private readonly instantiationService: IInstantiationService, + @IFileService private readonly fileService: IFileService, ++ // @ts-expect-error no-unused-variable + @IConfigurationService private readonly configurationService: IConfigurationService, + @IExtensionGalleryManifestService protected readonly extensionGalleryManifestService: IExtensionGalleryManifestService, + @IProductService productService: IProductService, +@@ -339,8 +341,7 @@ export class ExtensionManagementService + + private async downloadExtension(extension: IGalleryExtension, operation: InstallOperation, verifySignature: boolean, clientTargetPlatform?: TargetPlatform): Promise<{ readonly location: URI; readonly verificationStatus: ExtensionSignatureVerificationCode | undefined }> { + if (verifySignature) { +- const value = this.configurationService.getValue(VerifyExtensionSignatureConfigKey); +- verifySignature = isBoolean(value) ? value : true; ++ verifySignature = false; + } + const { location, verificationStatus } = await this.extensionsDownloader.download(extension, operation, verifySignature, clientTargetPlatform); + const shouldRequireSignature = shouldRequireRepositorySignatureFor(extension.private, await this.extensionGalleryManifestService.getExtensionGalleryManifest()); diff --git a/patches/sourcemaps.diff b/patches/sourcemaps.diff index dd6bc63a4640..888bfa873220 100644 --- a/patches/sourcemaps.diff +++ b/patches/sourcemaps.diff @@ -10,29 +10,29 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js =================================================================== --- code-server.orig/lib/vscode/build/gulpfile.reh.js +++ code-server/lib/vscode/build/gulpfile.reh.js -@@ -256,8 +256,7 @@ function packageTask(type, platform, arc +@@ -257,8 +257,7 @@ function packageTask(type, platform, arc const src = gulp.src(sourceFolderName + '/**', { base: '.' }) .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) - .pipe(util.setExecutableBit(['**/*.sh'])) -- .pipe(filter(['**', '!**/*.js.map'])); +- .pipe(filter(['**', '!**/*.{js,css}.map'])); + .pipe(util.setExecutableBit(['**/*.sh'])); const workspaceExtensionPoints = ['debuggers', 'jsonValidation']; const isUIExtension = (manifest) => { -@@ -296,9 +295,9 @@ function packageTask(type, platform, arc +@@ -297,9 +296,9 @@ function packageTask(type, platform, arc .map(name => `.build/extensions/${name}/**`); const extensions = gulp.src(extensionPaths, { base: '.build', dot: true }); - const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true }); - const sources = es.merge(src, extensions, extensionsCommonDependencies) + const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true }) - .pipe(filter(['**', '!**/*.js.map'], { dot: true })); + .pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true })); + const sources = es.merge(src, extensions, extensionsCommonDependencies); let version = packageJson.version; const quality = product.quality; -@@ -451,7 +450,7 @@ function tweakProductForServerWeb(produc +@@ -452,7 +451,7 @@ function tweakProductForServerWeb(produc const minifyTask = task.define(`minify-vscode-${type}`, task.series( bundleTask, util.rimraf(`out-vscode-${type}-min`), diff --git a/patches/store-socket.diff b/patches/store-socket.diff index d6bc187edca4..31ae8ee7db35 100644 --- a/patches/store-socket.diff +++ b/patches/store-socket.diff @@ -21,18 +21,18 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService. +import * as _http from 'http'; import * as performance from '../../../base/common/performance.js'; + import type * as vscode from 'vscode'; import { createApiFactoryAndRegisterActors } from '../common/extHost.api.impl.js'; - import { RequireInterceptor } from '../common/extHostRequireInterceptor.js'; -@@ -17,6 +18,7 @@ import { ExtensionRuntime } from '../com +@@ -18,6 +19,7 @@ import { ExtensionRuntime } from '../com import { CLIServer } from './extHostCLIServer.js'; - import { realpathSync } from '../../../base/node/extpath.js'; + import { realpathSync } from '../../../base/node/pfs.js'; import { ExtHostConsoleForwarder } from './extHostConsoleForwarder.js'; +import { IExtHostWorkspace } from '../common/extHostWorkspace.js'; import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js'; - import { createRequire } from 'node:module'; - const require = createRequire(import.meta.url); -@@ -97,6 +99,52 @@ export class ExtHostExtensionService ext - await interceptor.install(); + import nodeModule from 'node:module'; + import { assertType } from '../../../base/common/types.js'; +@@ -226,6 +228,52 @@ export class ExtHostExtensionService ext + performance.mark('code/extHost/didInitAPI'); + (async () => { @@ -96,7 +96,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts import minimist from 'minimist'; import * as nativeWatchdog from 'native-watchdog'; import * as net from 'net'; -@@ -423,7 +424,28 @@ async function startExtensionHostProcess +@@ -436,7 +437,28 @@ async function startExtensionHostProcess ); // rewrite onTerminate-function to be a proper shutdown diff --git a/patches/telemetry.diff b/patches/telemetry.diff index 06e21ef627f9..d0896f9aff23 100644 --- a/patches/telemetry.diff +++ b/patches/telemetry.diff @@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts import { NullPolicyService } from '../../platform/policy/common/policy.js'; import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js'; import { LoggerService } from '../../platform/log/node/loggerService.js'; -@@ -158,11 +160,23 @@ export async function setupServerService +@@ -164,11 +166,23 @@ export async function setupServerService const requestService = new RequestService('remote', configurationService, environmentService, logService); services.set(IRequestService, requestService); @@ -134,7 +134,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -348,6 +348,8 @@ export class WebClientServer { +@@ -347,6 +347,8 @@ export class WebClientServer { scope: vscodeBase + '/', path: rootBase + '/_static/out/browser/serviceWorker.js', }, @@ -142,7 +142,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts + telemetryEndpoint: this._productService.telemetryEndpoint, embedderIdentifier: 'server-distro', extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts diff --git a/patches/trusted-domains.diff b/patches/trusted-domains.diff new file mode 100644 index 000000000000..9d68bdfa6dc9 --- /dev/null +++ b/patches/trusted-domains.diff @@ -0,0 +1,49 @@ +Allow configuring trusted domains via product.json or flag. + +Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts ++++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +@@ -22,6 +22,7 @@ export const serverOptions: OptionDescri + 'disable-file-uploads': { type: 'boolean' }, + 'disable-getting-started-override': { type: 'boolean' }, + 'locale': { type: 'string' }, ++ 'link-protection-trusted-domains': { type: 'string[]' }, + + /* ----- server setup ----- */ + +@@ -112,6 +113,7 @@ export interface ServerParsedArgs { + 'disable-file-uploads'?: boolean; + 'disable-getting-started-override'?: boolean, + 'locale'?: string ++ 'link-protection-trusted-domains'?: string[], + + /* ----- server setup ----- */ + +Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts ++++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +@@ -338,6 +338,14 @@ export class WebClientServer { + scopes: [['user:email'], ['repo']] + } : undefined; + ++ const linkProtectionTrustedDomains: string[] = []; ++ if (this._environmentService.args['link-protection-trusted-domains']) { ++ linkProtectionTrustedDomains.push(...this._environmentService.args['link-protection-trusted-domains']); ++ } ++ if (this._productService.linkProtectionTrustedDomains) { ++ linkProtectionTrustedDomains.push(...this._productService.linkProtectionTrustedDomains); ++ } ++ + const productConfiguration: Partial> = { + codeServerVersion: this._productService.codeServerVersion, + rootEndpoint: rootBase, +@@ -352,6 +360,7 @@ export class WebClientServer { + telemetryEndpoint: this._productService.telemetryEndpoint, + embedderIdentifier: 'server-distro', + extensionsGallery: this._productService.extensionsGallery, ++ linkProtectionTrustedDomains, + }; + + const proposedApi = this._environmentService.args['enable-proposed-api']; diff --git a/patches/update-check.diff b/patches/update-check.diff index 700d1cf40727..0f9eba9fe15f 100644 --- a/patches/update-check.diff +++ b/patches/update-check.diff @@ -105,20 +105,20 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -341,6 +341,7 @@ export class WebClientServer { - const productConfiguration = { +@@ -340,6 +340,7 @@ export class WebClientServer { + const productConfiguration: Partial> = { codeServerVersion: this._productService.codeServerVersion, rootEndpoint: rootBase, + updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined, embedderIdentifier: 'server-distro', extensionsGallery: this._productService.extensionsGallery, - } satisfies Partial; + }; Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts -@@ -13,6 +13,8 @@ import { memoize } from '../../base/comm - import { URI } from '../../base/common/uri.js'; +@@ -15,6 +15,8 @@ import { joinPath } from '../../base/com + import { join } from '../../base/common/path.js'; export const serverOptions: OptionDescriptions> = { + /* ----- code-server ----- */ @@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts /* ----- server setup ----- */ -@@ -94,6 +96,8 @@ export const serverOptions: OptionDescri +@@ -98,6 +100,8 @@ export const serverOptions: OptionDescri }; export interface ServerParsedArgs { diff --git a/patches/webview.diff b/patches/webview.diff index a148c68aa991..bb45f1bc176a 100644 --- a/patches/webview.diff +++ b/patches/webview.diff @@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -355,6 +355,7 @@ export class WebClientServer { +@@ -360,6 +360,7 @@ export class WebClientServer { const workbenchWebConfiguration = { remoteAuthority, serverBasePath: basePath, @@ -70,29 +70,21 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index -+ content="default-src 'none'; script-src 'sha256-ap/AtocvSWp0rrxaO19DJy/nOpazT6M5Cv9utUWe7MA=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> - +- content="default-src 'none'; script-src 'sha256-qzQMf4WjRXHohkk4Hg1T0LJIElTDtjITLXbR/RuGA/Q=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> ++ content="default-src 'none'; script-src 'sha256-q8xbX8bFRtUAF+eVy0H2EWJWeyp3LsLyd7qwg1qndEg=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> -@@ -349,6 +349,12 @@ - - const hostname = location.hostname; + { + /** + * @param {MessageEvent} event +@@ -351,6 +351,12 @@ const hostname = location.hostname; diff --git a/src/browser/favicon.afdesign b/src/browser/favicon.afdesign deleted file mode 100644 index b654f32e82b1..000000000000 --- a/src/browser/favicon.afdesign +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:625d2049c38ae27df0613fa533020e889fa98affd603050f46d3748be7b90d0b -size 38675 diff --git a/src/browser/media/favicon-dark-support.svg b/src/browser/media/favicon-dark-support.svg index 06f1fa00d62c..d64bf32ed96e 100644 --- a/src/browser/media/favicon-dark-support.svg +++ b/src/browser/media/favicon-dark-support.svg @@ -1,7 +1,4 @@ - \ No newline at end of file + + + + diff --git a/src/browser/media/favicon.ico b/src/browser/media/favicon.ico index e721447bd9d1..56078ead6697 100644 Binary files a/src/browser/media/favicon.ico and b/src/browser/media/favicon.ico differ diff --git a/src/browser/media/favicon.svg b/src/browser/media/favicon.svg index 45388729b6b4..01a01541ec75 100644 --- a/src/browser/media/favicon.svg +++ b/src/browser/media/favicon.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + diff --git a/src/browser/media/pwa-icon-192.png b/src/browser/media/pwa-icon-192.png index a6ee503115d8..9f46dd830361 100644 Binary files a/src/browser/media/pwa-icon-192.png and b/src/browser/media/pwa-icon-192.png differ diff --git a/src/browser/media/pwa-icon-512.png b/src/browser/media/pwa-icon-512.png index ff42978ce9a5..9b899e8d690e 100644 Binary files a/src/browser/media/pwa-icon-512.png and b/src/browser/media/pwa-icon-512.png differ diff --git a/src/browser/media/pwa-icon-maskable-192.png b/src/browser/media/pwa-icon-maskable-192.png new file mode 100644 index 000000000000..3f28593b3aee Binary files /dev/null and b/src/browser/media/pwa-icon-maskable-192.png differ diff --git a/src/browser/media/pwa-icon-maskable-512.png b/src/browser/media/pwa-icon-maskable-512.png new file mode 100644 index 000000000000..7df85f7665ac Binary files /dev/null and b/src/browser/media/pwa-icon-maskable-512.png differ diff --git a/src/browser/media/pwa-icon.png b/src/browser/media/pwa-icon.png deleted file mode 100644 index d4f5188ffc0c..000000000000 Binary files a/src/browser/media/pwa-icon.png and /dev/null differ diff --git a/src/browser/pages/global.css b/src/browser/pages/global.css index e6e42e65652d..ba79ea6134c6 100644 --- a/src/browser/pages/global.css +++ b/src/browser/pages/global.css @@ -15,7 +15,8 @@ body { color: #111; color: light-dark(#111, #ddd); margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; overflow: hidden; } diff --git a/src/node/cli.ts b/src/node/cli.ts index a07a18b0a260..70ede42a0591 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -30,7 +30,7 @@ export enum LogLevel { export class OptionalString extends Optional {} /** - * Code flags provided by the user. + * (VS) Code flags provided by the user. */ export interface UserProvidedCodeArgs { "disable-telemetry"?: boolean @@ -53,7 +53,9 @@ export interface UserProvidedCodeArgs { "disable-getting-started-override"?: boolean "disable-proxy"?: boolean "session-socket"?: string - "abs-proxy-base-path"?: string + "link-protection-trusted-domains"?: string[] + // locale is used by both VS Code and code-server. + locale?: string } /** @@ -73,7 +75,6 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs { enable?: string[] help?: boolean host?: string - locale?: string port?: number json?: boolean log?: LogLevel @@ -91,6 +92,8 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs { verbose?: boolean "app-name"?: string "welcome-text"?: string + "abs-proxy-base-path"?: string + i18n?: string /* Positional arguments. */ _?: string[] } @@ -194,6 +197,10 @@ export const options: Options> = { enable: { type: "string[]" }, help: { type: "boolean", short: "h", description: "Show this output." }, json: { type: "boolean" }, + "link-protection-trusted-domains": { + type: "string[]", + description: "Links matching a trusted domain can be opened without link protection.", + }, locale: { // The preferred way to set the locale is via the UI. type: "string", @@ -278,17 +285,24 @@ export const options: Options> = { "app-name": { type: "string", short: "an", - description: "The name to use in branding. Will be shown in titlebar and welcome message", + description: + "Will replace the {{app}} placeholder in any strings, which by default includes the title bar and welcome message", }, "welcome-text": { type: "string", short: "w", description: "Text to show on login page", + deprecated: true, }, "abs-proxy-base-path": { type: "string", description: "The base path to prefix to all absproxy requests", }, + i18n: { + type: "string", + path: true, + description: "Path to JSON file with custom translations. Merges with default strings and supports all i18n keys.", + }, } export const optionDescriptions = (opts: Partial>> = options): string[] => { @@ -707,12 +721,16 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA // We convert the config file into a set of flags. // This is a temporary measure until we add a proper CLI library. - const configFileArgv = Object.entries(config).map(([optName, opt]) => { - if (opt === true) { - return `--${optName}` - } - return `--${optName}=${opt}` - }) + const configFileArgv = Object.entries(config) + .map(([optName, opt]) => { + if (opt === true) { + return `--${optName}` + } else if (Array.isArray(opt)) { + return opt.map((o) => `--${optName}=${o}`) + } + return `--${optName}=${opt}` + }) + .flat() const args = parse(configFileArgv, { configFile: configPath, }) diff --git a/src/node/http.ts b/src/node/http.ts index e0fb3a4caf6b..6500dc87fadc 100644 --- a/src/node/http.ts +++ b/src/node/http.ts @@ -1,9 +1,8 @@ import { field, logger } from "@coder/logger" import * as express from "express" -import * as expressCore from "express-serve-static-core" import * as http from "http" import * as net from "net" -import * as qs from "qs" +import qs from "qs" import { Disposable } from "../common/emitter" import { CookieKeys, HttpCode, HttpError } from "../common/http" import { normalize } from "../common/util" @@ -185,12 +184,7 @@ export const constructRedirectPath = (req: express.Request, query: qs.ParsedQs, * preserved. `to` should be a simple path without any query parameters * `override` will merge with the existing query (use `undefined` to unset). */ -export const redirect = ( - req: express.Request, - res: express.Response, - to: string, - override: expressCore.Query = {}, -): void => { +export const redirect = (req: express.Request, res: express.Response, to: string, override: qs.ParsedQs = {}): void => { const query = Object.assign({}, req.query, override) Object.keys(override).forEach((key) => { if (typeof override[key] === "undefined") { diff --git a/src/node/i18n/index.ts b/src/node/i18n/index.ts index 4ee718e13aa2..e8186067ba98 100644 --- a/src/node/i18n/index.ts +++ b/src/node/i18n/index.ts @@ -1,3 +1,4 @@ +import { promises as fs } from "fs" import i18next, { init } from "i18next" import * as en from "./locales/en.json" import * as ja from "./locales/ja.json" @@ -5,29 +6,54 @@ import * as th from "./locales/th.json" import * as ur from "./locales/ur.json" import * as zhCn from "./locales/zh-cn.json" +const defaultResources = { + en: { + translation: en, + }, + "zh-cn": { + translation: zhCn, + }, + th: { + translation: th, + }, + ja: { + translation: ja, + }, + ur: { + translation: ur, + }, +} + +export async function loadCustomStrings(filePath: string): Promise { + try { + // Read custom strings from file path only + const fileContent = await fs.readFile(filePath, "utf8") + const customStringsData = JSON.parse(fileContent) + + // User-provided strings override all languages. + Object.keys(defaultResources).forEach((locale) => { + i18next.addResourceBundle(locale, "translation", customStringsData) + }) + } catch (error) { + if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") { + throw new Error(`Custom strings file not found: ${filePath}\nPlease ensure the file exists and is readable.`) + } else if (error instanceof SyntaxError) { + throw new Error(`Invalid JSON in custom strings file: ${filePath}\n${error.message}`) + } else { + throw new Error( + `Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)}`, + ) + } + } +} + init({ lng: "en", fallbackLng: "en", // language to use if translations in user language are not available. returnNull: false, lowerCaseLng: true, debug: process.env.NODE_ENV === "development", - resources: { - en: { - translation: en, - }, - "zh-cn": { - translation: zhCn, - }, - th: { - translation: th, - }, - ja: { - translation: ja, - }, - ur: { - translation: ur, - }, - }, + resources: defaultResources, }) export default i18next diff --git a/src/node/main.ts b/src/node/main.ts index 04e4470b9088..6f8e28dbdea7 100644 --- a/src/node/main.ts +++ b/src/node/main.ts @@ -1,15 +1,16 @@ import { field, logger } from "@coder/logger" import http from "http" +import * as os from "os" import * as path from "path" import { Disposable } from "../common/emitter" import { plural } from "../common/util" import { createApp, ensureAddress } from "./app" import { AuthType, DefaultedArgs, Feature, toCodeArgs, UserProvidedArgs } from "./cli" import { commit, version, vsRootPath } from "./constants" +import { loadCustomStrings } from "./i18n" import { register } from "./routes" import { VSCodeModule } from "./routes/vscode" import { isDirectory, open } from "./util" -import * as os from "os" /** * Return true if the user passed an extension-related VS Code flag. @@ -122,6 +123,12 @@ export const runCodeServer = async ( ): Promise<{ dispose: Disposable["dispose"]; server: http.Server }> => { logger.info(`code-server ${version} ${commit}`) + // Load custom strings if provided + if (args.i18n) { + await loadCustomStrings(args.i18n) + logger.info("Loaded custom strings") + } + logger.info(`Using user-data-dir ${args["user-data-dir"]}`) logger.debug(`Using extensions-dir ${args["extensions-dir"]}`) @@ -144,6 +151,8 @@ export const runCodeServer = async ( logger.info(" - Using password from $PASSWORD") } else if (args.usingEnvHashedPassword) { logger.info(" - Using password from $HASHED_PASSWORD") + } else if (args["hashed-password"]) { + logger.info(` - Using hashed-password from ${args.config}`) } else { logger.info(` - Using password from ${args.config}`) } diff --git a/src/node/routes/errors.ts b/src/node/routes/errors.ts index 1f1475e9beee..da0ee8d7c07f 100644 --- a/src/node/routes/errors.ts +++ b/src/node/routes/errors.ts @@ -3,10 +3,10 @@ import express from "express" import { promises as fs } from "fs" import path from "path" import { HttpCode } from "../../common/http" -import type { WebsocketRequest } from "../wsRouter" import { rootPath } from "../constants" import { replaceTemplates } from "../http" import { escapeHtml, getMediaMime } from "../util" +import type { WebsocketRequest } from "../wsRouter" interface ErrorWithStatusCode { statusCode: number diff --git a/src/node/routes/index.ts b/src/node/routes/index.ts index 36cf76b4a7ca..2841b5a01113 100644 --- a/src/node/routes/index.ts +++ b/src/node/routes/index.ts @@ -14,8 +14,8 @@ import { Heart } from "../heart" import { redirect } from "../http" import { CoderSettings, SettingsProvider } from "../settings" import { UpdateProvider } from "../update" -import type { WebsocketRequest } from "../wsRouter" import { getMediaMime, paths } from "../util" +import type { WebsocketRequest } from "../wsRouter" import * as domainProxy from "./domainProxy" import { errorHandler, wsErrorHandler } from "./errors" import * as health from "./health" diff --git a/src/node/routes/login.ts b/src/node/routes/login.ts index 29d51a59d13b..7a8bb5134c68 100644 --- a/src/node/routes/login.ts +++ b/src/node/routes/login.ts @@ -32,6 +32,8 @@ const getRoot = async (req: Request, error?: Error): Promise => { i18n.changeLanguage(locale) const appName = req.args["app-name"] || "code-server" const welcomeText = req.args["welcome-text"] || (i18n.t("WELCOME", { app: appName }) as string) + + // Determine password message using i18n let passwordMsg = i18n.t("LOGIN_PASSWORD", { configFile: req.args.config }) if (req.args.usingEnvPassword) { passwordMsg = i18n.t("LOGIN_USING_ENV_PASSWORD") diff --git a/src/node/routes/pathProxy.ts b/src/node/routes/pathProxy.ts index 254c5e623a79..7d4f286f6519 100644 --- a/src/node/routes/pathProxy.ts +++ b/src/node/routes/pathProxy.ts @@ -13,7 +13,11 @@ const getProxyTarget = ( ): string => { // If there is a base path, strip it out. const base = (req as any).base || "" - return `http://0.0.0.0:${req.params.port}${opts?.proxyBasePath || ""}/${req.originalUrl.slice(base.length)}` + const port = parseInt(req.params.port, 10) + if (isNaN(port)) { + throw new HttpError("Invalid port", HttpCode.BadRequest) + } + return `http://0.0.0.0:${port}${opts?.proxyBasePath || ""}/${req.originalUrl.slice(base.length)}` } export async function proxy( diff --git a/src/node/routes/vscode.ts b/src/node/routes/vscode.ts index 4efb32993115..33d1287a7892 100644 --- a/src/node/routes/vscode.ts +++ b/src/node/routes/vscode.ts @@ -4,8 +4,8 @@ import * as express from "express" import { promises as fs } from "fs" import * as http from "http" import * as net from "net" -import * as path from "path" import * as os from "os" +import * as path from "path" import { logError } from "../../common/util" import { CodeArgs, toCodeArgs } from "../cli" import { isDevMode, vsRootPath } from "../constants" @@ -186,11 +186,22 @@ router.get("/manifest.json", async (req, res) => { display: "fullscreen", display_override: ["window-controls-overlay"], description: "Run Code on a remote server.", - icons: [192, 512].map((size) => ({ - src: `{{BASE}}/_static/src/browser/media/pwa-icon-${size}.png`, - type: "image/png", - sizes: `${size}x${size}`, - })), + icons: [192, 512] + .map((size) => [ + { + src: `{{BASE}}/_static/src/browser/media/pwa-icon-${size}.png`, + type: "image/png", + sizes: `${size}x${size}`, + purpose: "any", + }, + { + src: `{{BASE}}/_static/src/browser/media/pwa-icon-maskable-${size}.png`, + type: "image/png", + sizes: `${size}x${size}`, + purpose: "maskable", + }, + ]) + .flat(), }, null, 2, diff --git a/src/node/settings.ts b/src/node/settings.ts index 709ce950cb89..cc55dd5f9508 100644 --- a/src/node/settings.ts +++ b/src/node/settings.ts @@ -1,5 +1,5 @@ import { logger } from "@coder/logger" -import { Query } from "express-serve-static-core" +import type { ParsedQs } from "qs" import { promises as fs } from "fs" export type Settings = { [key: string]: Settings | string | boolean | number } @@ -17,7 +17,7 @@ export class SettingsProvider { public async read(): Promise { try { const raw = (await fs.readFile(this.settingsPath, "utf8")).trim() - return raw ? JSON.parse(raw) : {} + return raw ? JSON.parse(raw) : ({} as T) } catch (error: any) { if (error.code !== "ENOENT") { logger.warn(error.message) @@ -52,5 +52,5 @@ export interface UpdateSettings { * Global code-server settings. */ export interface CoderSettings extends UpdateSettings { - query?: Query + query?: ParsedQs } diff --git a/src/node/vscodeSocket.ts b/src/node/vscodeSocket.ts index 4af30ae91a4f..e01d1a15012b 100644 --- a/src/node/vscodeSocket.ts +++ b/src/node/vscodeSocket.ts @@ -2,8 +2,9 @@ import { logger } from "@coder/logger" import express from "express" import * as http from "http" import * as path from "path" -import { HttpCode } from "../common/http" +import { HttpCode, HttpError } from "../common/http" import { listen } from "./app" +import { errorHandler } from "./routes/errors" import { canConnect } from "./util" export interface EditorSessionEntry { @@ -44,24 +45,18 @@ export async function makeEditorSessionManagerServer( async (req, res) => { const filePath = req.query.filePath if (!filePath) { - res.status(HttpCode.BadRequest).send("filePath is required") - return - } - try { - const socketPath = await editorSessionManager.getConnectedSocketPath(filePath) - const response: GetSessionResponse = { socketPath } - res.json(response) - } catch (error: unknown) { - res.status(HttpCode.ServerError).send(error) + throw new HttpError("filePath is required", HttpCode.BadRequest) } + const socketPath = await editorSessionManager.getConnectedSocketPath(filePath) + const response: GetSessionResponse = { socketPath } + res.json(response) }, ) router.post<{}, string, AddSessionRequest | undefined>("/add-session", async (req, res) => { const entry = req.body?.entry if (!entry) { - res.status(400).send("entry is required") - return + throw new HttpError("entry is required", HttpCode.BadRequest) } editorSessionManager.addSession(entry) res.status(200).send("session added") @@ -70,13 +65,14 @@ export async function makeEditorSessionManagerServer( router.post<{}, string, DeleteSessionRequest | undefined>("/delete-session", async (req, res) => { const socketPath = req.body?.socketPath if (!socketPath) { - res.status(400).send("socketPath is required") - return + throw new HttpError("socketPath is required", HttpCode.BadRequest) } editorSessionManager.deleteSession(socketPath) res.status(200).send("session deleted") }) + router.use(errorHandler) + const server = http.createServer(router) try { await listen(server, { socket: codeServerSocketPath }) diff --git a/test/package-lock.json b/test/package-lock.json index 70d29a4fdb30..f7ee4863c278 100644 --- a/test/package-lock.json +++ b/test/package-lock.json @@ -11,7 +11,6 @@ "@types/jest": "^27.0.2", "@types/jsdom": "^16.2.13", "@types/node-fetch": "^2.5.8", - "@types/supertest": "^2.0.11", "@types/wtfnode": "^0.7.0", "argon2": "^0.28.0", "extract-zip": "^2.0.1", @@ -20,7 +19,6 @@ "jsdom": "^16.4.0", "node-fetch": "^2.6.7", "playwright": "^1.46.0", - "supertest": "^6.1.6", "ts-jest": "^27.0.7", "wtfnode": "^0.9.1" } @@ -1104,13 +1102,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/cookiejar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", - "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -1171,13 +1162,6 @@ "@types/tough-cookie": "*" } }, - "node_modules/@types/methods": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", - "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "22.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", @@ -1220,29 +1204,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/superagent": { - "version": "8.1.9", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.9.tgz", - "integrity": "sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cookiejar": "^2.1.5", - "@types/methods": "^1.1.4", - "@types/node": "*", - "form-data": "^4.0.0" - } - }, - "node_modules/@types/supertest": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.16.tgz", - "integrity": "sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/superagent": "*" - } - }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -1464,13 +1425,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true, - "license": "MIT" - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1689,24 +1643,18 @@ "dev": true, "license": "MIT" }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, "node_modules/callsites": { @@ -1883,16 +1831,6 @@ "node": ">= 0.8" } }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1914,13 +1852,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", @@ -2030,24 +1961,6 @@ "node": ">=0.10.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2085,17 +1998,6 @@ "node": ">=8" } }, - "node_modules/dezalgo": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", - "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", - "dev": true, - "license": "ISC", - "dependencies": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, "node_modules/diff-sequences": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", @@ -2130,6 +2032,21 @@ "node": ">=8" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.32", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz", @@ -2178,14 +2095,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -2200,6 +2114,35 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2366,13 +2309,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "dev": true, - "license": "MIT" - }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -2421,36 +2357,22 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, - "node_modules/formidable": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" - }, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -2559,17 +2481,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2588,6 +2515,20 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -2637,13 +2578,13 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2666,23 +2607,10 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -2692,12 +2620,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { "node": ">= 0.4" }, @@ -2725,16 +2656,6 @@ "node": ">= 0.4" } }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/html-encoding-sniffer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", @@ -3764,15 +3685,17 @@ } }, "node_modules/jsdom/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -3918,6 +3841,16 @@ "tmpl": "1.0.5" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -3925,16 +3858,6 @@ "dev": true, "license": "MIT" }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3949,19 +3872,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -4216,19 +4126,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4531,22 +4428,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -4722,24 +4603,6 @@ "dev": true, "license": "ISC" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4763,25 +4626,6 @@ "node": ">=8" } }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4932,43 +4776,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/superagent": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", - "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", - "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, - "node_modules/supertest": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", - "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "methods": "^1.1.2", - "superagent": "^8.1.2" - }, - "engines": { - "node": ">=6.4.0" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/test/package.json b/test/package.json index 06d0e3fb3e74..6d2e92edd2ee 100644 --- a/test/package.json +++ b/test/package.json @@ -7,7 +7,6 @@ "@types/jest": "^27.0.2", "@types/jsdom": "^16.2.13", "@types/node-fetch": "^2.5.8", - "@types/supertest": "^2.0.11", "@types/wtfnode": "^0.7.0", "argon2": "^0.28.0", "extract-zip": "^2.0.1", @@ -16,7 +15,6 @@ "jsdom": "^16.4.0", "node-fetch": "^2.6.7", "playwright": "^1.46.0", - "supertest": "^6.1.6", "ts-jest": "^27.0.7", "wtfnode": "^0.9.1" }, diff --git a/test/unit/node/cli.test.ts b/test/unit/node/cli.test.ts index 552576fac4c9..668a3c55776c 100644 --- a/test/unit/node/cli.test.ts +++ b/test/unit/node/cli.test.ts @@ -6,6 +6,7 @@ import { bindAddrFromArgs, defaultConfigFile, parse, + parseConfigFile, setDefaults, shouldOpenInExistingInstance, toCodeArgs, @@ -74,6 +75,7 @@ describe("parser", () => { "--verbose", ["--app-name", "custom instance name"], ["--welcome-text", "welcome to code"], + ["--i18n", "path/to/custom-strings.json"], "2", ["--locale", "ja"], @@ -144,6 +146,7 @@ describe("parser", () => { verbose: true, "app-name": "custom instance name", "welcome-text": "welcome to code", + i18n: path.resolve("path/to/custom-strings.json"), version: true, "bind-addr": "192.169.0.1:8080", "session-socket": "/tmp/override-code-server-ipc-socket", @@ -287,12 +290,17 @@ describe("parser", () => { }) it("should support repeatable flags", async () => { + expect(() => parse(["--proxy-domain", ""])).toThrowError(/--proxy-domain requires a value/) expect(parse(["--proxy-domain", "*.coder.com"])).toEqual({ "proxy-domain": ["*.coder.com"], }) expect(parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"])).toEqual({ "proxy-domain": ["*.coder.com", "test.com"], }) + // Commas are literal, at the moment. + expect(parse(["--proxy-domain", "*.coder.com,test.com"])).toEqual({ + "proxy-domain": ["*.coder.com,test.com"], + }) }) it("should enforce cert-key with cert value or otherwise generate one", async () => { @@ -341,6 +349,28 @@ describe("parser", () => { }) }) + it("should parse i18n flag with file path", async () => { + // Test with file path (no validation at CLI parsing level) + const args = parse(["--i18n", "/path/to/custom-strings.json"]) + expect(args).toEqual({ + i18n: "/path/to/custom-strings.json", + }) + }) + + it("should parse i18n flag with relative file path", async () => { + // Test with relative file path + expect(() => parse(["--i18n", "./custom-strings.json"])).not.toThrow() + expect(() => parse(["--i18n", "strings.json"])).not.toThrow() + }) + + it("should support app-name and deprecated welcome-text flags", async () => { + const args = parse(["--app-name", "My App", "--welcome-text", "Welcome!"]) + expect(args).toEqual({ + "app-name": "My App", + "welcome-text": "Welcome!", + }) + }) + it("should use env var github token", async () => { process.env.GITHUB_TOKEN = "ga-foo" const args = parse([]) @@ -490,6 +520,20 @@ describe("parser", () => { }), ).toThrowError(expectedErrMsg) }) + it("should fail to parse invalid config", () => { + expect(() => parseConfigFile("test", "/fake-config-path")).toThrowError("invalid config: test") + }) + it("should parse repeatable options", () => { + const configContents = ` + install-extension: + - extension.number1 + - extension.number2 + ` + expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({ + config: "/fake-config-path", + "install-extension": ["extension.number1", "extension.number2"], + }) + }) it("should ignore optional strings set to false", async () => { expect(parse(["--cert=false"])).toEqual({}) }) diff --git a/test/unit/node/i18n.test.ts b/test/unit/node/i18n.test.ts new file mode 100644 index 000000000000..90b10d04822c --- /dev/null +++ b/test/unit/node/i18n.test.ts @@ -0,0 +1,154 @@ +import { promises as fs } from "fs" +import * as os from "os" +import * as path from "path" +import { loadCustomStrings } from "../../../src/node/i18n" + +describe("i18n", () => { + let tempDir: string + let validJsonFile: string + let invalidJsonFile: string + let nonExistentFile: string + + beforeEach(async () => { + // Create temporary directory for test files + tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "code-server-i18n-test-")) + + // Create test files + validJsonFile = path.join(tempDir, "valid.json") + invalidJsonFile = path.join(tempDir, "invalid.json") + nonExistentFile = path.join(tempDir, "does-not-exist.json") + + // Write valid JSON file + await fs.writeFile( + validJsonFile, + JSON.stringify({ + WELCOME: "Custom Welcome", + LOGIN_TITLE: "My Custom App", + LOGIN_BELOW: "Please log in to continue", + }), + ) + + // Write invalid JSON file + await fs.writeFile(invalidJsonFile, '{"WELCOME": "Missing closing quote}') + }) + + afterEach(async () => { + // Clean up temporary directory + await fs.rmdir(tempDir, { recursive: true }) + }) + + describe("loadCustomStrings", () => { + it("should load valid JSON file successfully", async () => { + // Should not throw an error + await expect(loadCustomStrings(validJsonFile)).resolves.toBeUndefined() + }) + + it("should throw clear error for non-existent file", async () => { + await expect(loadCustomStrings(nonExistentFile)).rejects.toThrow( + `Custom strings file not found: ${nonExistentFile}\nPlease ensure the file exists and is readable.`, + ) + }) + + it("should throw clear error for invalid JSON", async () => { + await expect(loadCustomStrings(invalidJsonFile)).rejects.toThrow( + `Invalid JSON in custom strings file: ${invalidJsonFile}`, + ) + }) + + it("should handle empty JSON object", async () => { + const emptyJsonFile = path.join(tempDir, "empty.json") + await fs.writeFile(emptyJsonFile, "{}") + + await expect(loadCustomStrings(emptyJsonFile)).resolves.toBeUndefined() + }) + + it("should handle nested JSON objects", async () => { + const nestedJsonFile = path.join(tempDir, "nested.json") + await fs.writeFile( + nestedJsonFile, + JSON.stringify({ + WELCOME: "Hello World", + NESTED: { + KEY: "Value", + }, + }), + ) + + await expect(loadCustomStrings(nestedJsonFile)).resolves.toBeUndefined() + }) + + it("should handle special characters and unicode", async () => { + const unicodeJsonFile = path.join(tempDir, "unicode.json") + await fs.writeFile( + unicodeJsonFile, + JSON.stringify({ + WELCOME: "欢迎来到 code-server", + LOGIN_TITLE: "Willkommen bei {{app}}", + SPECIAL: "Special chars: àáâãäåæçèéêë 🚀 ♠️ ∆", + }), + "utf8", + ) + + await expect(loadCustomStrings(unicodeJsonFile)).resolves.toBeUndefined() + }) + + it("should handle generic errors that are not ENOENT or SyntaxError", async () => { + const testFile = path.join(tempDir, "test.json") + await fs.writeFile(testFile, "{}") + + // Mock fs.readFile to throw a generic error + const originalReadFile = fs.readFile + const mockError = new Error("Permission denied") + fs.readFile = jest.fn().mockRejectedValue(mockError) + + await expect(loadCustomStrings(testFile)).rejects.toThrow( + `Failed to load custom strings from ${testFile}: Permission denied`, + ) + + // Restore original function + fs.readFile = originalReadFile + }) + + it("should handle errors that are not Error instances", async () => { + const testFile = path.join(tempDir, "test.json") + await fs.writeFile(testFile, "{}") + + // Mock fs.readFile to throw a non-Error object + const originalReadFile = fs.readFile + fs.readFile = jest.fn().mockRejectedValue("String error") + + await expect(loadCustomStrings(testFile)).rejects.toThrow( + `Failed to load custom strings from ${testFile}: String error`, + ) + + // Restore original function + fs.readFile = originalReadFile + }) + + it("should handle null/undefined errors", async () => { + const testFile = path.join(tempDir, "test.json") + await fs.writeFile(testFile, "{}") + + // Mock fs.readFile to throw null + const originalReadFile = fs.readFile + fs.readFile = jest.fn().mockRejectedValue(null) + + await expect(loadCustomStrings(testFile)).rejects.toThrow(`Failed to load custom strings from ${testFile}: null`) + + // Restore original function + fs.readFile = originalReadFile + }) + + it("should complete without errors for valid input", async () => { + const testFile = path.join(tempDir, "resource-test.json") + const customStrings = { + WELCOME: "Custom Welcome Message", + LOGIN_TITLE: "Custom Login Title", + } + await fs.writeFile(testFile, JSON.stringify(customStrings)) + + // Should not throw any errors + await expect(loadCustomStrings(testFile)).resolves.toBeUndefined() + }) + }) +}) diff --git a/test/unit/node/main.test.ts b/test/unit/node/main.test.ts new file mode 100644 index 000000000000..09ee6b512ef9 --- /dev/null +++ b/test/unit/node/main.test.ts @@ -0,0 +1,175 @@ +import { promises as fs } from "fs" +import * as path from "path" +import { setDefaults, parse } from "../../../src/node/cli" +import { loadCustomStrings } from "../../../src/node/i18n" +import { tmpdir } from "../../utils/helpers" + +// Mock the i18n module +jest.mock("../../../src/node/i18n", () => ({ + loadCustomStrings: jest.fn(), +})) + +// Mock logger to avoid console output during tests +jest.mock("@coder/logger", () => ({ + logger: { + info: jest.fn(), + debug: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + level: 0, + }, + field: jest.fn(), + Level: { + Trace: 0, + Debug: 1, + Info: 2, + Warn: 3, + Error: 4, + }, +})) + +const mockedLoadCustomStrings = loadCustomStrings as jest.MockedFunction + +describe("main", () => { + let tempDir: string + let mockServer: any + + beforeEach(async () => { + tempDir = await tmpdir("code-server-main-test") + + // Reset mocks + jest.clearAllMocks() + + // Mock the server creation to avoid actually starting a server + mockServer = { + server: { + listen: jest.fn(), + address: jest.fn(() => ({ address: "127.0.0.1", port: 8080 })), + close: jest.fn(), + }, + editorSessionManagerServer: { + address: jest.fn(() => null), + }, + dispose: jest.fn(), + } + }) + + afterEach(async () => { + // Clean up temp directory + try { + await fs.rmdir(tempDir, { recursive: true }) + } catch (error) { + // Ignore cleanup errors + } + }) + + describe("runCodeServer", () => { + it("should load custom strings when i18n flag is provided", async () => { + // Create a test custom strings file + const customStringsFile = path.join(tempDir, "custom-strings.json") + await fs.writeFile( + customStringsFile, + JSON.stringify({ + WELCOME: "Custom Welcome", + LOGIN_TITLE: "My App", + }), + ) + + // Create args with i18n flag + const cliArgs = parse([ + `--config=${path.join(tempDir, "config.yaml")}`, + `--user-data-dir=${tempDir}`, + "--bind-addr=localhost:0", + "--log=warn", + "--auth=none", + `--i18n=${customStringsFile}`, + ]) + const args = await setDefaults(cliArgs) + + // Mock the app module + jest.doMock("../../../src/node/app", () => ({ + createApp: jest.fn().mockResolvedValue(mockServer), + ensureAddress: jest.fn().mockReturnValue(new URL("http://localhost:8080")), + })) + + // Mock routes module + jest.doMock("../../../src/node/routes", () => ({ + register: jest.fn().mockResolvedValue(jest.fn()), + })) + + // Mock loadCustomStrings to succeed + mockedLoadCustomStrings.mockResolvedValue(undefined) + + // Import runCodeServer after mocking + const mainModule = await import("../../../src/node/main") + const result = await mainModule.runCodeServer(args) + + // Verify that loadCustomStrings was called with the correct file path + expect(mockedLoadCustomStrings).toHaveBeenCalledWith(customStringsFile) + expect(mockedLoadCustomStrings).toHaveBeenCalledTimes(1) + + // Clean up + await result.dispose() + }) + + it("should not load custom strings when i18n flag is not provided", async () => { + // Create args without i18n flag + const cliArgs = parse([ + `--config=${path.join(tempDir, "config.yaml")}`, + `--user-data-dir=${tempDir}`, + "--bind-addr=localhost:0", + "--log=warn", + "--auth=none", + ]) + const args = await setDefaults(cliArgs) + + // Mock the app module + jest.doMock("../../../src/node/app", () => ({ + createApp: jest.fn().mockResolvedValue(mockServer), + ensureAddress: jest.fn().mockReturnValue(new URL("http://localhost:8080")), + })) + + // Mock routes module + jest.doMock("../../../src/node/routes", () => ({ + register: jest.fn().mockResolvedValue(jest.fn()), + })) + + // Import runCodeServer after mocking + const mainModule = await import("../../../src/node/main") + const result = await mainModule.runCodeServer(args) + + // Verify that loadCustomStrings was NOT called + expect(mockedLoadCustomStrings).not.toHaveBeenCalled() + + // Clean up + await result.dispose() + }) + + it("should handle errors when loadCustomStrings fails", async () => { + // Create args with i18n flag pointing to non-existent file + const nonExistentFile = path.join(tempDir, "does-not-exist.json") + const cliArgs = parse([ + `--config=${path.join(tempDir, "config.yaml")}`, + `--user-data-dir=${tempDir}`, + "--bind-addr=localhost:0", + "--log=warn", + "--auth=none", + `--i18n=${nonExistentFile}`, + ]) + const args = await setDefaults(cliArgs) + + // Mock loadCustomStrings to throw an error + const mockError = new Error("Custom strings file not found") + mockedLoadCustomStrings.mockRejectedValue(mockError) + + // Import runCodeServer after mocking + const mainModule = await import("../../../src/node/main") + + // Verify that runCodeServer throws the error from loadCustomStrings + await expect(mainModule.runCodeServer(args)).rejects.toThrow("Custom strings file not found") + + // Verify that loadCustomStrings was called + expect(mockedLoadCustomStrings).toHaveBeenCalledWith(nonExistentFile) + }) + }) +}) diff --git a/test/unit/node/settings.test.ts b/test/unit/node/settings.test.ts index 59c6f46a50bc..ad04b15ff81b 100644 --- a/test/unit/node/settings.test.ts +++ b/test/unit/node/settings.test.ts @@ -29,7 +29,7 @@ describe("settings", () => { const settings = new SettingsProvider(pathToMockSettingsFile) await settings.read() // This happens when we can't parse a JSON (usually error in file) - expect(logger.warn).toHaveBeenCalledWith(expect.stringMatching(/Unexpected token/)) + expect(logger.warn).toHaveBeenCalledWith(expect.stringMatching(/Expected ':'/)) }) }) describe("with invalid settings file path", () => {