mirror of
https://github.com/coder/code-server.git
synced 2026-04-16 21:31:43 -05:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27a112c3a7 | ||
|
|
74cc50d5e6 | ||
|
|
85ee441006 | ||
|
|
a56769b2c3 | ||
|
|
05d8904ec5 | ||
|
|
3669c96c9c | ||
|
|
37357b0142 | ||
|
|
405eb0f511 | ||
|
|
6e26dad1b1 | ||
|
|
1671bf1c18 | ||
|
|
1face85ad9 | ||
|
|
9ec786b62a | ||
|
|
409c64e0df | ||
|
|
35e78fe35b | ||
|
|
cade03e321 | ||
|
|
9dd999ba78 | ||
|
|
1aca01f8d8 | ||
|
|
e05219d9c0 | ||
|
|
d0e20d514d | ||
|
|
9bd3b83ef5 | ||
|
|
2c9b4e7fd5 | ||
|
|
7af90ea623 | ||
|
|
8b55b5003d | ||
|
|
e5b8d447e5 | ||
|
|
c8257a3074 | ||
|
|
0c72b20fa7 | ||
|
|
ea2caf00ac | ||
|
|
3f2e3340d8 | ||
|
|
47d6d3ada5 | ||
|
|
dded82bb47 | ||
|
|
5d5b7b1944 | ||
|
|
c36b2d3edd | ||
|
|
3b7634c578 | ||
|
|
ec0899a81b | ||
|
|
bbf2e24648 | ||
|
|
9045919d2b | ||
|
|
cb29e65982 | ||
|
|
7eb8f4be87 | ||
|
|
cd4d1b614d | ||
|
|
5051c0f9e4 | ||
|
|
b07335a0f1 | ||
|
|
e3c09efcbc | ||
|
|
e0c960b30e | ||
|
|
55b311a954 | ||
|
|
0a92b76304 | ||
|
|
400ac7b8d0 | ||
|
|
53722c5361 | ||
|
|
e2c489dd00 | ||
|
|
e1c84998d7 | ||
|
|
cc3c22deee | ||
|
|
727555b414 | ||
|
|
4b7bca38e2 | ||
|
|
50c3e4bb1b | ||
|
|
2809245dda | ||
|
|
949aed1cef | ||
|
|
db5f99dc78 | ||
|
|
fd761b4e8b | ||
|
|
611798650f | ||
|
|
0db3cbe4e7 | ||
|
|
31c211aded | ||
|
|
6f8493ebc6 | ||
|
|
34b8d2ed69 | ||
|
|
3172cb16b8 | ||
|
|
9b89774ff6 | ||
|
|
626d2cf1c3 | ||
|
|
ebf2df63f5 | ||
|
|
ac65db2c88 | ||
|
|
33aa21fd0f | ||
|
|
d23d1a9541 | ||
|
|
a6fad66e5e | ||
|
|
18cd97dc12 | ||
|
|
ef713bde58 | ||
|
|
1c3fcf2a83 | ||
|
|
96800cc521 | ||
|
|
0b7c044857 | ||
|
|
7cc61ab1f4 | ||
|
|
b7ef8f9bd7 | ||
|
|
b60985e53b | ||
|
|
b18a647d0a | ||
|
|
f4f02655a1 | ||
|
|
08cbdfbdf1 | ||
|
|
339a448471 |
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -20,6 +20,8 @@ body:
|
|||||||
- **Remote OS**: Ubuntu
|
- **Remote OS**: Ubuntu
|
||||||
- **Remote Architecture**: amd64
|
- **Remote Architecture**: amd64
|
||||||
- **`code-server --version`**: 4.0.1
|
- **`code-server --version`**: 4.0.1
|
||||||
|
|
||||||
|
Please do not just put "latest" for the version.
|
||||||
value: |
|
value: |
|
||||||
- Web Browser:
|
- Web Browser:
|
||||||
- Local OS:
|
- Local OS:
|
||||||
|
|||||||
268
.github/workflows/build.yaml
vendored
268
.github/workflows/build.yaml
vendored
@@ -22,127 +22,114 @@ concurrency:
|
|||||||
# will skip running `npm install` if it successfully fetched from cache
|
# will skip running `npm install` if it successfully fetched from cache
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
changes:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
ci: ${{ steps.filter.outputs.ci }}
|
||||||
|
code: ${{ steps.filter.outputs.code }}
|
||||||
|
deps: ${{ steps.filter.outputs.deps }}
|
||||||
|
docs: ${{ steps.filter.outputs.docs }}
|
||||||
|
helm: ${{ steps.filter.outputs.helm }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Check changed files
|
||||||
|
uses: dorny/paths-filter@v3
|
||||||
|
id: filter
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
ci:
|
||||||
|
- ".github/**"
|
||||||
|
- "ci/**"
|
||||||
|
docs:
|
||||||
|
- "docs/**"
|
||||||
|
- "README.md"
|
||||||
|
- "CHANGELOG.md"
|
||||||
|
helm:
|
||||||
|
- "ci/helm-chart/**"
|
||||||
|
code:
|
||||||
|
- "src/**"
|
||||||
|
- "test/**"
|
||||||
|
deps:
|
||||||
|
- "lib/**"
|
||||||
|
- "patches/**"
|
||||||
|
- "package-lock.json"
|
||||||
|
- "test/package-lock.json"
|
||||||
|
- id: debug
|
||||||
|
run: |
|
||||||
|
echo "${{ toJSON(steps.filter )}}"
|
||||||
|
|
||||||
prettier:
|
prettier:
|
||||||
name: Run prettier check
|
name: Run prettier check
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
|
||||||
- run: npx prettier --check .
|
- run: npx prettier --check .
|
||||||
|
|
||||||
doctoc:
|
doctoc:
|
||||||
name: Doctoc markdown files
|
name: Doctoc markdown files
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.docs == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-node@v4
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
docs/**
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
- run: npm run doctoc
|
||||||
run: SKIP_SUBMODULE_DEPS=1 npm ci
|
|
||||||
|
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
run: npm run doctoc
|
|
||||||
|
|
||||||
lint-helm:
|
lint-helm:
|
||||||
name: Lint Helm chart
|
name: Lint Helm chart
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.helm == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: azure/setup-helm@v4
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
ci/helm-chart/**
|
|
||||||
|
|
||||||
- name: Install helm
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
uses: azure/setup-helm@v4
|
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- run: helm plugin install https://github.com/instrumenta/helm-kubeval
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
- run: helm kubeval ci/helm-chart
|
||||||
run: helm plugin install https://github.com/instrumenta/helm-kubeval
|
|
||||||
|
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
run: helm kubeval ci/helm-chart
|
|
||||||
|
|
||||||
lint-ts:
|
lint-ts:
|
||||||
name: Lint TypeScript files
|
name: Lint TypeScript files
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.code == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
**/*.ts
|
|
||||||
**/*.js
|
|
||||||
files_ignore: |
|
|
||||||
lib/vscode/**
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
- run: npm run lint:ts
|
||||||
run: SKIP_SUBMODULE_DEPS=1 npm ci
|
|
||||||
|
|
||||||
- name: Lint TypeScript files
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
run: npm run lint:ts
|
|
||||||
|
|
||||||
lint-actions:
|
lint-actions:
|
||||||
name: Lint GitHub Actions
|
name: Lint GitHub Actions
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.ci == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -156,42 +143,23 @@ jobs:
|
|||||||
name: Run unit tests
|
name: Run unit tests
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.code == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v45
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
**/*.ts
|
|
||||||
files_ignore: |
|
|
||||||
lib/vscode/**
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
- run: npm run test:unit
|
||||||
run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- uses: codecov/codecov-action@v5
|
||||||
|
if: success()
|
||||||
- if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
run: npm run test:unit
|
|
||||||
|
|
||||||
- name: Upload coverage report to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
if: success()
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build code-server
|
name: Build code-server
|
||||||
@@ -201,44 +169,31 @@ jobs:
|
|||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
DISABLE_V8_COMPILE_CACHE: 1
|
DISABLE_V8_COMPILE_CACHE: 1
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||||
- name: Install system dependencies
|
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
|
||||||
|
|
||||||
- name: Install quilt
|
|
||||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
|
||||||
with:
|
with:
|
||||||
packages: quilt
|
packages: quilt
|
||||||
version: 1.0
|
version: 1.0
|
||||||
|
- run: quilt push -a
|
||||||
- name: Patch Code
|
- uses: actions/setup-node@v4
|
||||||
run: quilt push -a
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
- run: npm run build
|
||||||
- env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
# Get Code's git hash. When this changes it means the content is
|
# Get Code's git hash. When this changes it means the content is
|
||||||
# different and we need to rebuild.
|
# different and we need to rebuild.
|
||||||
- name: Get latest lib/vscode rev
|
- name: Get latest lib/vscode rev
|
||||||
id: vscode-rev
|
id: vscode-rev
|
||||||
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# We need to rebuild when we have a new version of Code, when any of
|
# We need to rebuild when we have a new version of Code, when any of
|
||||||
# the patches changed, or when the code-server version changes (since
|
# the patches changed, or when the code-server version changes (since
|
||||||
# it gets embedded into the code). Use VSCODE_CACHE_VERSION to
|
# it gets embedded into the code). Use VSCODE_CACHE_VERSION to
|
||||||
@@ -249,7 +204,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: lib/vscode-reh-web-*
|
path: lib/vscode-reh-web-*
|
||||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||||
|
|
||||||
- name: Build vscode
|
- name: Build vscode
|
||||||
env:
|
env:
|
||||||
VERSION: "0.0.0"
|
VERSION: "0.0.0"
|
||||||
@@ -259,107 +213,77 @@ jobs:
|
|||||||
npm ci
|
npm ci
|
||||||
popd
|
popd
|
||||||
npm run build:vscode
|
npm run build:vscode
|
||||||
|
|
||||||
# The release package does not contain any native modules
|
# The release package does not contain any native modules
|
||||||
# and is neutral to architecture/os/libc version.
|
# and is neutral to architecture/os/libc version.
|
||||||
- run: npm run release
|
- run: npm run release
|
||||||
if: success()
|
if: success()
|
||||||
|
|
||||||
# https://github.com/actions/upload-artifact/issues/38
|
# https://github.com/actions/upload-artifact/issues/38
|
||||||
- run: tar -czf package.tar.gz release
|
- run: tar -czf package.tar.gz release
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
- name: Upload npm package artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: npm-package
|
name: npm-package
|
||||||
path: ./package.tar.gz
|
path: ./package.tar.gz
|
||||||
|
|
||||||
test-e2e:
|
test-e2e:
|
||||||
name: Run e2e tests
|
name: Run e2e tests
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 25
|
timeout-minutes: 25
|
||||||
|
needs: [changes, build]
|
||||||
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
- name: Install system dependencies
|
|
||||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
- name: Download npm package
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: npm-package
|
name: npm-package
|
||||||
|
|
||||||
- run: tar -xzf package.tar.gz
|
- run: tar -xzf package.tar.gz
|
||||||
|
|
||||||
- run: cd release && npm install --unsafe-perm --omit=dev
|
- run: cd release && npm install --unsafe-perm --omit=dev
|
||||||
|
|
||||||
- name: Install Playwright OS dependencies
|
- name: Install Playwright OS dependencies
|
||||||
run: |
|
run: |
|
||||||
./test/node_modules/.bin/playwright install-deps
|
./test/node_modules/.bin/playwright install-deps
|
||||||
./test/node_modules/.bin/playwright install
|
./test/node_modules/.bin/playwright install
|
||||||
|
|
||||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
|
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
- name: Upload test artifacts
|
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: failed-test-videos
|
name: failed-test-videos
|
||||||
path: ./test/test-results
|
path: ./test/test-results
|
||||||
|
- run: rm -rf ./release ./test/test-results
|
||||||
- name: Remove release packages and test artifacts
|
|
||||||
run: rm -rf ./release ./test/test-results
|
|
||||||
|
|
||||||
test-e2e-proxy:
|
test-e2e-proxy:
|
||||||
name: Run e2e tests behind proxy
|
name: Run e2e tests behind proxy
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 25
|
timeout-minutes: 25
|
||||||
|
needs: [changes, build]
|
||||||
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
- name: Install system dependencies
|
|
||||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
- name: Download npm package
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: npm-package
|
name: npm-package
|
||||||
|
|
||||||
- run: tar -xzf package.tar.gz
|
- run: tar -xzf package.tar.gz
|
||||||
|
|
||||||
- run: cd release && npm install --unsafe-perm --omit=dev
|
- run: cd release && npm install --unsafe-perm --omit=dev
|
||||||
|
|
||||||
- name: Install Playwright OS dependencies
|
- name: Install Playwright OS dependencies
|
||||||
run: |
|
run: |
|
||||||
./test/node_modules/.bin/playwright install-deps
|
./test/node_modules/.bin/playwright install-deps
|
||||||
./test/node_modules/.bin/playwright install
|
./test/node_modules/.bin/playwright install
|
||||||
|
|
||||||
- name: Cache Caddy
|
- name: Cache Caddy
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
id: caddy-cache
|
id: caddy-cache
|
||||||
@@ -367,7 +291,6 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
~/.cache/caddy
|
~/.cache/caddy
|
||||||
key: cache-caddy-2.5.2
|
key: cache-caddy-2.5.2
|
||||||
|
|
||||||
- name: Install Caddy
|
- name: Install Caddy
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -376,16 +299,13 @@ jobs:
|
|||||||
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
|
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
|
||||||
mkdir -p ~/.cache/caddy
|
mkdir -p ~/.cache/caddy
|
||||||
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
||||||
|
- run: ~/.cache/caddy/caddy start --config ./ci/Caddyfile
|
||||||
- run: sudo ~/.cache/caddy/caddy start --config ./ci/Caddyfile
|
|
||||||
|
|
||||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
|
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
|
||||||
|
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
||||||
|
if: always()
|
||||||
|
|
||||||
- if: always()
|
- uses: actions/upload-artifact@v4
|
||||||
run: sudo ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
if: always()
|
||||||
|
|
||||||
- if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: failed-test-videos-proxy
|
name: failed-test-videos-proxy
|
||||||
path: ./test/test-results
|
path: ./test/test-results
|
||||||
|
|||||||
10
.github/workflows/publish.yaml
vendored
10
.github/workflows/publish.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
|
|
||||||
- name: Download npm package from release artifacts
|
- name: Download npm package from release artifacts
|
||||||
uses: robinraju/release-downloader@v1.11
|
uses: robinraju/release-downloader@v1.12
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: ${{ github.event.inputs.version || github.ref_name }}
|
tag: ${{ github.event.inputs.version || github.ref_name }}
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Validate package
|
- name: Validate package
|
||||||
uses: heyhusen/archlinux-package-action@v2.2.1
|
uses: heyhusen/archlinux-package-action@v2.4.0
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ env.VERSION }}
|
VERSION: ${{ env.VERSION }}
|
||||||
with:
|
with:
|
||||||
@@ -145,7 +145,7 @@ jobs:
|
|||||||
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code-server
|
- name: Checkout code-server
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -176,7 +176,7 @@ jobs:
|
|||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Download deb artifacts
|
- name: Download deb artifacts
|
||||||
uses: robinraju/release-downloader@v1.11
|
uses: robinraju/release-downloader@v1.12
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: v${{ env.VERSION }}
|
tag: v${{ env.VERSION }}
|
||||||
@@ -184,7 +184,7 @@ jobs:
|
|||||||
out-file-path: "release-packages"
|
out-file-path: "release-packages"
|
||||||
|
|
||||||
- name: Download rpm artifacts
|
- name: Download rpm artifacts
|
||||||
uses: robinraju/release-downloader@v1.11
|
uses: robinraju/release-downloader@v1.12
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: v${{ env.VERSION }}
|
tag: v${{ env.VERSION }}
|
||||||
|
|||||||
155
.github/workflows/release.yaml
vendored
155
.github/workflows/release.yaml
vendored
@@ -19,95 +19,27 @@ concurrency:
|
|||||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
package-linux-amd64:
|
|
||||||
name: x86-64 Linux build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 15
|
|
||||||
needs: npm-version
|
|
||||||
container: "centos:8"
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: .node-version
|
|
||||||
cache: npm
|
|
||||||
cache-dependency-path: |
|
|
||||||
package-lock.json
|
|
||||||
test/package-lock.json
|
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
|
||||||
|
|
||||||
- name: Install development tools
|
|
||||||
run: |
|
|
||||||
cd /etc/yum.repos.d/
|
|
||||||
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
|
|
||||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
|
|
||||||
yum install -y gcc-c++ make jq rsync python3 libsecret-devel krb5-devel
|
|
||||||
|
|
||||||
- name: Install nfpm and envsubst
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.local/bin
|
|
||||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.22.2/nfpm_2.22.2_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
|
||||||
curl -sSfL https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
|
|
||||||
chmod +x envsubst
|
|
||||||
mv envsubst ~/.local/bin
|
|
||||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Download npm package
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: npm-release-package
|
|
||||||
|
|
||||||
- run: tar -xzf package.tar.gz
|
|
||||||
|
|
||||||
- run: npm run release:standalone
|
|
||||||
|
|
||||||
- run: npm run test:integration
|
|
||||||
|
|
||||||
- name: Upload coverage report to Codecov
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
if: success()
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
|
||||||
- name: Get and set VERSION
|
|
||||||
run: |
|
|
||||||
TAG="${{ inputs.version || github.ref_name }}"
|
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- env:
|
|
||||||
VERSION: ${{ env.VERSION }}
|
|
||||||
run: npm run package
|
|
||||||
|
|
||||||
- uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
draft: true
|
|
||||||
discussion_category_name: "📣 Announcements"
|
|
||||||
files: ./release-packages/*
|
|
||||||
|
|
||||||
package-linux-cross:
|
package-linux-cross:
|
||||||
name: Linux cross-compile builds
|
name: ${{ matrix.prefix }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
needs: npm-version
|
needs: npm-version
|
||||||
container: "debian:buster"
|
container: "python:3.8-slim-buster"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
- prefix: x86_64-linux-gnu
|
||||||
|
npm_arch: x64
|
||||||
|
apt_arch: amd64
|
||||||
|
package_arch: amd64
|
||||||
- prefix: aarch64-linux-gnu
|
- prefix: aarch64-linux-gnu
|
||||||
npm_arch: arm64
|
npm_arch: arm64
|
||||||
apt_arch: arm64
|
apt_arch: arm64
|
||||||
|
package_arch: arm64
|
||||||
- prefix: arm-linux-gnueabihf
|
- prefix: arm-linux-gnueabihf
|
||||||
npm_arch: armv7l
|
npm_arch: armv7l
|
||||||
apt_arch: armhf
|
apt_arch: armhf
|
||||||
|
package_arch: armv7l
|
||||||
|
|
||||||
env:
|
env:
|
||||||
AR: ${{ format('{0}-ar', matrix.prefix) }}
|
AR: ${{ format('{0}-ar', matrix.prefix) }}
|
||||||
@@ -121,6 +53,7 @@ jobs:
|
|||||||
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
|
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
|
||||||
TARGET_ARCH: ${{ matrix.apt_arch }}
|
TARGET_ARCH: ${{ matrix.apt_arch }}
|
||||||
npm_config_arch: ${{ matrix.npm_arch }}
|
npm_config_arch: ${{ matrix.npm_arch }}
|
||||||
|
PKG_ARCH: ${{ matrix.package_arch }}
|
||||||
# Not building from source results in an x86_64 argon2, as if
|
# Not building from source results in an x86_64 argon2, as if
|
||||||
# npm_config_arch is being ignored.
|
# npm_config_arch is being ignored.
|
||||||
npm_config_build_from_source: true
|
npm_config_build_from_source: true
|
||||||
@@ -141,7 +74,7 @@ jobs:
|
|||||||
- name: Install cross-compiler and system dependencies
|
- name: Install cross-compiler and system dependencies
|
||||||
run: |
|
run: |
|
||||||
dpkg --add-architecture $TARGET_ARCH
|
dpkg --add-architecture $TARGET_ARCH
|
||||||
apt-get update && apt-get install -y --no-install-recommends \
|
apt update && apt install -y --no-install-recommends \
|
||||||
crossbuild-essential-$TARGET_ARCH \
|
crossbuild-essential-$TARGET_ARCH \
|
||||||
libx11-dev:$TARGET_ARCH \
|
libx11-dev:$TARGET_ARCH \
|
||||||
libx11-xcb-dev:$TARGET_ARCH \
|
libx11-xcb-dev:$TARGET_ARCH \
|
||||||
@@ -149,8 +82,7 @@ jobs:
|
|||||||
libsecret-1-dev:$TARGET_ARCH \
|
libsecret-1-dev:$TARGET_ARCH \
|
||||||
libkrb5-dev:$TARGET_ARCH \
|
libkrb5-dev:$TARGET_ARCH \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
curl wget rsync gettext-base \
|
curl wget rsync gettext-base
|
||||||
python3
|
|
||||||
|
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
|
||||||
@@ -183,7 +115,7 @@ jobs:
|
|||||||
|
|
||||||
- env:
|
- env:
|
||||||
VERSION: ${{ env.VERSION }}
|
VERSION: ${{ env.VERSION }}
|
||||||
run: npm run package ${npm_config_arch}
|
run: npm run package $PKG_ARCH
|
||||||
|
|
||||||
- uses: softprops/action-gh-release@v1
|
- uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
@@ -193,6 +125,67 @@ jobs:
|
|||||||
|
|
||||||
package-macos-amd64:
|
package-macos-amd64:
|
||||||
name: x86-64 macOS build
|
name: x86-64 macOS build
|
||||||
|
runs-on: macos-13
|
||||||
|
timeout-minutes: 15
|
||||||
|
needs: npm-version
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: .node-version
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: |
|
||||||
|
package-lock.json
|
||||||
|
test/package-lock.json
|
||||||
|
|
||||||
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
|
||||||
|
- name: Install nfpm
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.local/bin
|
||||||
|
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||||
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# The version of node-gyp we use depends on distutils but it was removed
|
||||||
|
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
|
||||||
|
# next update Node we can probably remove this. For now, install
|
||||||
|
# setuptools since it contains distutils.
|
||||||
|
- run: brew install python-setuptools
|
||||||
|
|
||||||
|
- name: Download npm package
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: npm-release-package
|
||||||
|
|
||||||
|
- run: tar -xzf package.tar.gz
|
||||||
|
- run: npm run release:standalone
|
||||||
|
- run: npm run test:native
|
||||||
|
|
||||||
|
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||||
|
- name: Get and set VERSION
|
||||||
|
run: |
|
||||||
|
TAG="${{ inputs.version || github.ref_name }}"
|
||||||
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Build packages with nfpm
|
||||||
|
env:
|
||||||
|
VERSION: ${{ env.VERSION }}
|
||||||
|
run: npm run package
|
||||||
|
|
||||||
|
- uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
discussion_category_name: "📣 Announcements"
|
||||||
|
files: ./release-packages/*
|
||||||
|
|
||||||
|
package-macos-arm64:
|
||||||
|
name: arm64 macOS build
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
needs: npm-version
|
needs: npm-version
|
||||||
@@ -275,7 +268,7 @@ jobs:
|
|||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: dawidd6/action-download-artifact@v6
|
uses: dawidd6/action-download-artifact@v10
|
||||||
id: download
|
id: download
|
||||||
with:
|
with:
|
||||||
branch: ${{ github.ref }}
|
branch: ${{ github.ref }}
|
||||||
|
|||||||
6
.github/workflows/security.yaml
vendored
6
.github/workflows/security.yaml
vendored
@@ -43,7 +43,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read # for actions/checkout to fetch code
|
contents: read # for actions/checkout to fetch code
|
||||||
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner in repo mode
|
- name: Run Trivy vulnerability scanner in repo mode
|
||||||
uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2
|
uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5
|
||||||
with:
|
with:
|
||||||
scan-type: "fs"
|
scan-type: "fs"
|
||||||
scan-ref: "."
|
scan-ref: "."
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
contents: read # for actions/checkout to fetch code
|
contents: read # for actions/checkout to fetch code
|
||||||
security-events: write # for github/codeql-action/autobuild to send a status report
|
security-events: write # for github/codeql-action/autobuild to send a status report
|
||||||
name: Analyze with CodeQL
|
name: Analyze with CodeQL
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
|||||||
4
.github/workflows/trivy-docker.yaml
vendored
4
.github/workflows/trivy-docker.yaml
vendored
@@ -44,14 +44,14 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
trivy-scan-image:
|
trivy-scan-image:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner in image mode
|
- name: Run Trivy vulnerability scanner in image mode
|
||||||
uses: aquasecurity/trivy-action@915b19bbe73b92a6cf82a1bc12b087c9a19a5fe2
|
uses: aquasecurity/trivy-action@6c175e9c4083a92bbca2f9724c8a5e33bc2d97a5
|
||||||
with:
|
with:
|
||||||
image-ref: "docker.io/codercom/code-server:latest"
|
image-ref: "docker.io/codercom/code-server:latest"
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
20.18.1
|
22.15.1
|
||||||
|
|||||||
141
CHANGELOG.md
141
CHANGELOG.md
@@ -22,6 +22,147 @@ Code v99.99.999
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## [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
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.99.2.
|
||||||
|
|
||||||
|
## [4.99.1](https://github.com/coder/code-server/releases/tag/v4.99.1) - 2025-04-08
|
||||||
|
|
||||||
|
Code v1.99.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.99.1.
|
||||||
|
|
||||||
|
## [4.99.0](https://github.com/coder/code-server/releases/tag/v4.99.0) - 2025-04-07
|
||||||
|
|
||||||
|
Code v1.99.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.99.0.
|
||||||
|
|
||||||
|
## [4.98.0](https://github.com/coder/code-server/releases/tag/v4.98.0) - 2025-03-07
|
||||||
|
|
||||||
|
Code v1.98.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.98.0.
|
||||||
|
|
||||||
|
## [4.97.2](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-02-18
|
||||||
|
|
||||||
|
Code v1.97.2
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added back macOS amd64 builds.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.97.2.
|
||||||
|
- Softened dark mode login page colors.
|
||||||
|
|
||||||
|
## [4.96.4](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-01-20
|
||||||
|
|
||||||
|
Code v1.96.4
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.96.4.
|
||||||
|
|
||||||
|
## [4.96.2](https://github.com/coder/code-server/releases/tag/v4.96.2) - 2024-12-20
|
||||||
|
|
||||||
|
Code v1.96.2
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.96.2.
|
||||||
|
|
||||||
|
## [4.96.1](https://github.com/coder/code-server/releases/tag/v4.96.1) - 2024-12-18
|
||||||
|
|
||||||
|
Code v1.96.1
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Dark color scheme for login and error pages.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.96.1.
|
||||||
|
|
||||||
## [4.95.3](https://github.com/coder/code-server/releases/tag/v4.95.3) - 2024-11-18
|
## [4.95.3](https://github.com/coder/code-server/releases/tag/v4.95.3) - 2024-11-18
|
||||||
|
|
||||||
Code v1.95.3
|
Code v1.95.3
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ bundle_code_server() {
|
|||||||
rsync src/browser/pages/*.css "$RELEASE_PATH/src/browser/pages"
|
rsync src/browser/pages/*.css "$RELEASE_PATH/src/browser/pages"
|
||||||
rsync src/browser/robots.txt "$RELEASE_PATH/src/browser"
|
rsync src/browser/robots.txt "$RELEASE_PATH/src/browser"
|
||||||
|
|
||||||
# Add typings for plugins
|
|
||||||
mkdir -p "$RELEASE_PATH/typings"
|
|
||||||
rsync typings/pluginapi.d.ts "$RELEASE_PATH/typings"
|
|
||||||
|
|
||||||
# Adds the commit to package.json
|
# Adds the commit to package.json
|
||||||
jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
|
jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
|
||||||
cat << EOF
|
cat << EOF
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ main() {
|
|||||||
echo "USE AT YOUR OWN RISK!"
|
echo "USE AT YOUR OWN RISK!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-20}" ]; then
|
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
|
||||||
echo "ERROR: code-server currently requires node v20."
|
echo "ERROR: code-server currently requires node v22."
|
||||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
if [ -n "$FORCE_NODE_VERSION" ]; then
|
||||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ main() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CODE_SERVER_PATH="$path" CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
|
CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
@@ -6,15 +6,10 @@ main() {
|
|||||||
|
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
|
|
||||||
echo "Building test plugin"
|
|
||||||
pushd test/unit/node/test-plugin
|
|
||||||
make -s out/index.js
|
|
||||||
popd
|
|
||||||
|
|
||||||
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
||||||
# information. We must also run it from the root otherwise coverage will not
|
# information. We must also run it from the root otherwise coverage will not
|
||||||
# include our source files.
|
# include our source files.
|
||||||
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts" --testPathIgnorePatterns "./test/unit/node/test-plugin"
|
./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 3.24.0
|
version: 3.27.3
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
appVersion: 4.93.1
|
appVersion: 4.100.3
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: {{ .Values.replicaCount | default 1 }}
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: Recreate
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: codercom/code-server
|
repository: codercom/code-server
|
||||||
tag: '4.93.1'
|
tag: '4.100.3'
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
||||||
# Specifies one or more secrets to be used when pulling images from a
|
# Specifies one or more secrets to be used when pulling images from a
|
||||||
@@ -19,6 +19,9 @@ nameOverride: ""
|
|||||||
fullnameOverride: ""
|
fullnameOverride: ""
|
||||||
hostnameOverride: ""
|
hostnameOverride: ""
|
||||||
|
|
||||||
|
# The existing secret to use for code-server authentication in the frontend. the password is stored in the secret under the key `password`
|
||||||
|
# existingSecret: ""
|
||||||
|
|
||||||
serviceAccount:
|
serviceAccount:
|
||||||
# Specifies whether a service account should be created
|
# Specifies whether a service account should be created
|
||||||
create: true
|
create: true
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ RUN sed -i "s/# en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen \
|
|||||||
&& locale-gen
|
&& locale-gen
|
||||||
ENV LANG=en_US.UTF-8
|
ENV LANG=en_US.UTF-8
|
||||||
|
|
||||||
RUN adduser --gecos '' --disabled-password coder \
|
RUN if grep -q 1000 /etc/passwd; then \
|
||||||
|
userdel -r "$(id -un 1000)"; \
|
||||||
|
fi \
|
||||||
|
&& adduser --gecos '' --disabled-password coder \
|
||||||
&& echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
&& echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||||
|
|
||||||
RUN ARCH="$(dpkg --print-architecture)" \
|
RUN ARCH="$(dpkg --print-architecture)" \
|
||||||
|
|||||||
@@ -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).
|
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||||
Here is what is needed:
|
Here is what is needed:
|
||||||
|
|
||||||
- `node` v20.x
|
- `node` v22.x
|
||||||
- `git` v2.x or greater
|
- `git` v2.x or greater
|
||||||
- [`git-lfs`](https://git-lfs.github.com)
|
- [`git-lfs`](https://git-lfs.github.com)
|
||||||
- [`npm`](https://www.npmjs.com/)
|
- [`npm`](https://www.npmjs.com/)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ on how to set up a Google VM on which you can install code-server.
|
|||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
There are four ways to get started:
|
There are five ways to get started:
|
||||||
|
|
||||||
1. Using the [install
|
1. Using the [install
|
||||||
script](https://github.com/coder/code-server/blob/main/install.sh), which
|
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)
|
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
|
4. Using our one-click buttons and guides to [deploy code-server to a cloud
|
||||||
provider](https://github.com/coder/deploy-code-server) ⚡
|
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
|
If you use the install script, you can preview what occurs during the install
|
||||||
process:
|
process:
|
||||||
|
|||||||
@@ -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
|
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
|
```shell
|
||||||
nvm install 18
|
nvm install 18
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
||||||
- [Proxying to a Svelte app](#proxying-to-a-svelte-app)
|
- [Proxying to a Svelte app](#proxying-to-a-svelte-app)
|
||||||
- [Prefixing `/absproxy/<port>` with a path](#prefixing-absproxyport-with-a-path)
|
- [Prefixing `/absproxy/<port>` with a path](#prefixing-absproxyport-with-a-path)
|
||||||
|
- [Preflight requests](#preflight-requests)
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
@@ -119,22 +120,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. 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
|
[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
|
choice). Once you have a domain name, add an A record to your domain that contains your
|
||||||
instance's IP address.
|
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
|
```console
|
||||||
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
|
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/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
|
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 update
|
||||||
sudo apt install caddy
|
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
|
```text
|
||||||
mydomain.com {
|
mydomain.com {
|
||||||
@@ -153,7 +154,7 @@ sudo apt install caddy
|
|||||||
|
|
||||||
Remember to replace `mydomain.com` with your domain name!
|
Remember to replace `mydomain.com` with your domain name!
|
||||||
|
|
||||||
1. Reload Caddy:
|
5. Reload Caddy:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
sudo systemctl reload caddy
|
sudo systemctl reload caddy
|
||||||
@@ -164,21 +165,22 @@ At this point, you should be able to access code-server via
|
|||||||
|
|
||||||
### Using Let's Encrypt with NGINX
|
### 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
|
[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
|
choice). Once you have a domain name, add an A record to your domain that contains your
|
||||||
instance's IP address.
|
instance's IP address.
|
||||||
|
|
||||||
1. Install NGINX:
|
3. Install NGINX:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y nginx certbot python3-certbot-nginx
|
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:
|
configuration:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -199,13 +201,11 @@ At this point, you should be able to access code-server via
|
|||||||
|
|
||||||
Be sure to replace `mydomain.com` with your domain name!
|
Be sure to replace `mydomain.com` with your domain name!
|
||||||
|
|
||||||
1. Enable the config:
|
5. Enable the config:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server
|
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
|
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.
|
Be sure to replace `me@example.com` with your actual email.
|
||||||
|
|
||||||
At this point, you should be able to access code-server via
|
At this point, you should be able to access code-server via
|
||||||
@@ -271,9 +271,9 @@ should see OSSStatus: 9836 in the browser console.
|
|||||||
If you want to use external authentication mechanism (e.g., Sign in with
|
If you want to use external authentication mechanism (e.g., Sign in with
|
||||||
Google), you can do this with a reverse proxy such as:
|
Google), you can do this with a reverse proxy such as:
|
||||||
|
|
||||||
- [Pomerium](https://www.pomerium.io/guides/code-server.html)
|
- [Pomerium](https://www.pomerium.com/docs/guides/code-server.html)
|
||||||
- [oauth2_proxy](https://github.com/pusher/oauth2_proxy)
|
- [oauth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/)
|
||||||
- [Cloudflare Access](https://teams.cloudflare.com/access)
|
- [Cloudflare Access](https://www.cloudflare.com/zero-trust/products/access/)
|
||||||
|
|
||||||
## HTTPS and self-signed certificates
|
## HTTPS and self-signed certificates
|
||||||
|
|
||||||
@@ -292,7 +292,9 @@ redirect all HTTP requests to HTTPS.
|
|||||||
> You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate
|
> You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate
|
||||||
> for free.
|
> 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
|
## Accessing web services
|
||||||
|
|
||||||
@@ -378,14 +380,16 @@ PUBLIC_URL=/absproxy/3000 \
|
|||||||
BROWSER=none yarn start
|
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
|
You should then be able to visit
|
||||||
code-server!
|
`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.
|
> We highly recommend using the subdomain approach instead to avoid this class of issue.
|
||||||
|
|
||||||
### Proxying to a Vue app
|
### 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`
|
1. add `vue.config.js`
|
||||||
2. update the values to match this (you can use any free port):
|
2. update the values to match this (you can use any free port):
|
||||||
@@ -406,7 +410,8 @@ Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/#
|
|||||||
|
|
||||||
### Proxying to an Angular app
|
### 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 `<base href="./.">` in `src/index.html`
|
1. use `<base href="./.">` in `src/index.html`
|
||||||
2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json`
|
2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json`
|
||||||
@@ -415,7 +420,8 @@ For additional context, see [this GitHub Discussion](https://github.com/coder/co
|
|||||||
|
|
||||||
### Proxying to a Svelte app
|
### 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
|
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):
|
2. Update the values to match this (you can use any free port):
|
||||||
@@ -436,9 +442,19 @@ For additional context, see [this Github Issue](https://github.com/sveltejs/kit/
|
|||||||
|
|
||||||
### Prefixing `/absproxy/<port>` with a path
|
### Prefixing `/absproxy/<port>` 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.
|
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`.
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ includes installing instructions based on your operating system.
|
|||||||
## Node.js version
|
## Node.js version
|
||||||
|
|
||||||
We use the same major version of Node.js shipped with Code's remote, which is
|
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).
|
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||||
|
|
||||||
Using other versions of Node.js [may lead to unexpected
|
Using other versions of Node.js [may lead to unexpected
|
||||||
@@ -62,8 +62,7 @@ Proceed to [installing](#installing)
|
|||||||
## Alpine
|
## Alpine
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
apk add alpine-sdk bash libstdc++ libc6-compat
|
apk add alpine-sdk bash libstdc++ libc6-compat python3 krb5-dev
|
||||||
npm config set python python3
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Proceed to [installing](#installing)
|
Proceed to [installing](#installing)
|
||||||
@@ -79,7 +78,7 @@ Proceed to [installing](#installing)
|
|||||||
## FreeBSD
|
## FreeBSD
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkg install -y git python npm-node20 pkgconf
|
pkg install -y git python npm-node22 pkgconf
|
||||||
pkg install -y libinotify
|
pkg install -y libinotify
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ npm config set python python3
|
|||||||
node -v
|
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)
|
5. Now install code-server following our guide on [installing with npm](./npm.md)
|
||||||
|
|
||||||
|
|||||||
12
flake.lock
generated
12
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1726560853,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1730359060,
|
"lastModified": 1739303263,
|
||||||
"narHash": "sha256-Hkk0mf4pgvX9Ut0YA397nsFqMLhzFVBdFHc4PhBrxYE=",
|
"narHash": "sha256-c/Z/6gZLN8BIpYh1B3qMzEn0TArjf4F2lmy59lDLVBM=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e19cfce6f3f08d07653157d8826f5c920c770d7b",
|
"rev": "6cc4213488e886db863878a1e3dc26cc932d38b8",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
flake-utils.lib.eachDefaultSystem
|
flake-utils.lib.eachDefaultSystem
|
||||||
(system:
|
(system:
|
||||||
let pkgs = nixpkgs.legacyPackages.${system};
|
let pkgs = nixpkgs.legacyPackages.${system};
|
||||||
nodejs = pkgs.nodejs_20;
|
nodejs = pkgs.nodejs_22;
|
||||||
in {
|
in {
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
|
|||||||
Submodule lib/vscode updated: 42b266171e...dfaf44141e
1539
package-lock.json
generated
1539
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -30,7 +30,7 @@
|
|||||||
"publish:docker": "./ci/steps/docker-buildx-push.sh",
|
"publish:docker": "./ci/steps/docker-buildx-push.sh",
|
||||||
"fmt": "npm run prettier && ./ci/dev/doctoc.sh",
|
"fmt": "npm run prettier && ./ci/dev/doctoc.sh",
|
||||||
"lint:scripts": "./ci/dev/lint-scripts.sh",
|
"lint:scripts": "./ci/dev/lint-scripts.sh",
|
||||||
"lint:ts": "eslint --max-warnings=0 --fix $(git ls-files '*.ts' '*.js' | grep -v 'lib/vscode' | grep -v test-plugin)",
|
"lint:ts": "eslint --max-warnings=0 --fix $(git ls-files '*.ts' '*.js' | grep -v 'lib/vscode')",
|
||||||
"test": "echo 'Run npm run test:unit or npm run test:e2e' && exit 1",
|
"test": "echo 'Run npm run test:unit or npm run test:e2e' && exit 1",
|
||||||
"watch": "VSCODE_DEV=1 VSCODE_IPC_HOOK_CLI= NODE_OPTIONS='--max_old_space_size=32384 --trace-warnings' ts-node ./ci/dev/watch.ts",
|
"watch": "VSCODE_DEV=1 VSCODE_IPC_HOOK_CLI= NODE_OPTIONS='--max_old_space_size=32384 --trace-warnings' ts-node ./ci/dev/watch.ts",
|
||||||
"icons": "./ci/dev/gen_icons.sh"
|
"icons": "./ci/dev/gen_icons.sh"
|
||||||
@@ -44,10 +44,10 @@
|
|||||||
"@types/compression": "^1.7.3",
|
"@types/compression": "^1.7.3",
|
||||||
"@types/cookie-parser": "^1.4.4",
|
"@types/cookie-parser": "^1.4.4",
|
||||||
"@types/eslint__js": "^8.42.3",
|
"@types/eslint__js": "^8.42.3",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^5.0.0",
|
||||||
"@types/http-proxy": "1.17.7",
|
"@types/http-proxy": "1.17.7",
|
||||||
"@types/js-yaml": "^4.0.6",
|
"@types/js-yaml": "^4.0.6",
|
||||||
"@types/node": "20.x",
|
"@types/node": "22.x",
|
||||||
"@types/pem": "^1.14.1",
|
"@types/pem": "^1.14.1",
|
||||||
"@types/proxy-from-env": "^1.0.1",
|
"@types/proxy-from-env": "^1.0.1",
|
||||||
"@types/safe-compare": "^1.1.0",
|
"@types/safe-compare": "^1.1.0",
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
"eslint-import-resolver-typescript": "^3.6.0",
|
"eslint-import-resolver-typescript": "^3.6.0",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"globals": "^15.10.0",
|
"globals": "^16.1.0",
|
||||||
"prettier": "3.4.2",
|
"prettier": "3.4.2",
|
||||||
"prettier-plugin-sh": "^0.14.0",
|
"prettier-plugin-sh": "^0.14.0",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"express": "5.0.0-beta.3",
|
"express": "^5.0.1",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
"httpolyglot": "^0.1.2",
|
"httpolyglot": "^0.1.2",
|
||||||
"i18next": "^23.5.1",
|
"i18next": "^23.5.1",
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"limiter": "^2.1.0",
|
"limiter": "^2.1.0",
|
||||||
"pem": "^1.14.8",
|
"pem": "^1.14.8",
|
||||||
"proxy-agent": "^6.3.1",
|
"proxy-agent": "^6.3.1",
|
||||||
"qs": "6.13.0",
|
"qs": "6.14.0",
|
||||||
"rotating-file-stream": "^3.1.1",
|
"rotating-file-stream": "^3.1.1",
|
||||||
"safe-buffer": "^5.2.1",
|
"safe-buffer": "^5.2.1",
|
||||||
"safe-compare": "^1.1.4",
|
"safe-compare": "^1.1.4",
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
"xdg-basedir": "^4.0.0"
|
"xdg-basedir": "^4.0.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "20.x"
|
"@types/node": "22.x"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"code-server": "out/node/entry.js"
|
"code-server": "out/node/entry.js"
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
"remote-development"
|
"remote-development"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "20"
|
"node": "22"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"transform": {
|
"transform": {
|
||||||
|
|||||||
@@ -111,21 +111,26 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -271,16 +271,15 @@ export class WebClientServer {
|
@@ -245,7 +245,9 @@ export class WebClientServer {
|
||||||
return void res.end();
|
};
|
||||||
}
|
|
||||||
|
// Prefix routes with basePath for clients
|
||||||
|
- const basePath = getFirstHeader('x-forwarded-prefix') || this._basePath;
|
||||||
|
+ const rootBase = relativeRoot(getOriginalUrl(req))
|
||||||
|
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||||
|
+ const basePath = vscodeBase || getFirstHeader('x-forwarded-prefix') || this._basePath;
|
||||||
|
|
||||||
|
const queryConnectionToken = parsedUrl.query[connectionTokenQueryName];
|
||||||
|
if (typeof queryConnectionToken === 'string') {
|
||||||
|
@@ -284,10 +286,14 @@ export class WebClientServer {
|
||||||
|
};
|
||||||
|
|
||||||
- const getFirstHeader = (headerName: string) => {
|
|
||||||
- const val = req.headers[headerName];
|
|
||||||
- return Array.isArray(val) ? val[0] : val;
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
|
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
|
||||||
+ // For now we are getting the remote authority from the client to avoid
|
+ // For now we are getting the remote authority from the client to avoid
|
||||||
+ // needing specific configuration for reverse proxies to work. Set this to
|
+ // needing specific configuration for reverse proxies to work. Set this to
|
||||||
+ // something invalid to make sure we catch code that is using this value
|
+ // something invalid to make sure we catch code that is using this value
|
||||||
+ // from the backend when it should not.
|
+ // from the backend when it should not.
|
||||||
const remoteAuthority = (
|
let remoteAuthority = (
|
||||||
useTestResolver
|
useTestResolver
|
||||||
? 'test+test'
|
? 'test+test'
|
||||||
- : (getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host)
|
- : (getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host)
|
||||||
@@ -133,43 +138,26 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
);
|
);
|
||||||
if (!remoteAuthority) {
|
if (!remoteAuthority) {
|
||||||
return serveError(req, res, 400, `Bad request.`);
|
return serveError(req, res, 400, `Bad request.`);
|
||||||
@@ -307,8 +306,12 @@ export class WebClientServer {
|
@@ -334,6 +340,7 @@ export class WebClientServer {
|
||||||
scopes: [['user:email'], ['repo']]
|
|
||||||
} : undefined;
|
|
||||||
|
|
||||||
+ const base = relativeRoot(getOriginalUrl(req))
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
|
||||||
+
|
|
||||||
const productConfiguration = {
|
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
+ rootEndpoint: base,
|
+ rootEndpoint: rootBase,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
...this._productService.extensionsGallery,
|
...this._productService.extensionsGallery,
|
||||||
@@ -337,7 +340,7 @@ export class WebClientServer {
|
@@ -387,7 +394,9 @@ export class WebClientServer {
|
||||||
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
|
|
||||||
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
|
||||||
productConfiguration,
|
|
||||||
- callbackRoute: this._callbackRoute
|
|
||||||
+ callbackRoute: vscodeBase + this._callbackRoute
|
|
||||||
};
|
|
||||||
|
|
||||||
const cookies = cookie.parse(req.headers.cookie || '');
|
|
||||||
@@ -354,9 +357,11 @@ export class WebClientServer {
|
|
||||||
const values: { [key: string]: string } = {
|
|
||||||
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
|
|
||||||
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
||||||
- WORKBENCH_WEB_BASE_URL: this._staticRoute,
|
WORKBENCH_WEB_BASE_URL: staticRoute,
|
||||||
+ WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute,
|
|
||||||
WORKBENCH_NLS_URL,
|
WORKBENCH_NLS_URL,
|
||||||
- WORKBENCH_NLS_FALLBACK_URL: `${this._staticRoute}/out/nls.messages.js`
|
- WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`
|
||||||
+ WORKBENCH_NLS_FALLBACK_URL: `${vscodeBase}${this._staticRoute}/out/nls.messages.js`,
|
+ WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
|
||||||
+ BASE: base,
|
+ BASE: rootBase,
|
||||||
+ VS_BASE: vscodeBase,
|
+ VS_BASE: basePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEV ---------------------------------------------------------------------------------------
|
// DEV ---------------------------------------------------------------------------------------
|
||||||
@@ -393,7 +398,7 @@ export class WebClientServer {
|
@@ -424,7 +433,7 @@ export class WebClientServer {
|
||||||
'default-src \'self\';',
|
'default-src \'self\';',
|
||||||
'img-src \'self\' https: data: blob:;',
|
'img-src \'self\' https: data: blob:;',
|
||||||
'media-src \'self\';',
|
'media-src \'self\';',
|
||||||
@@ -178,7 +166,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
'child-src \'self\';',
|
'child-src \'self\';',
|
||||||
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
||||||
'worker-src \'self\' data: blob:;',
|
'worker-src \'self\' data: blob:;',
|
||||||
@@ -466,3 +471,70 @@ export class WebClientServer {
|
@@ -497,3 +506,70 @@ export class WebClientServer {
|
||||||
return void res.end(data);
|
return void res.end(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -253,7 +241,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -56,6 +56,7 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -57,6 +57,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||||
|
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
@@ -265,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.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||||
@@ -317,7 +317,8 @@ class LocalStorageURLCallbackProvider ex
|
@@ -332,7 +332,8 @@ class LocalStorageURLCallbackProvider ex
|
||||||
this.startListening();
|
this.startListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
}
|
}
|
||||||
|
|
||||||
private startListening(): void {
|
private startListening(): void {
|
||||||
@@ -563,17 +564,6 @@ class WorkspaceProvider implements IWork
|
@@ -579,17 +580,6 @@ class WorkspaceProvider implements IWork
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
// Find config by checking for DOM
|
// Find config by checking for DOM
|
||||||
@@ -582,8 +572,8 @@ function readCookie(name: string): strin
|
@@ -598,8 +588,8 @@ function readCookie(name: string): strin
|
||||||
if (!configElement || !configElementAttribute) {
|
if (!configElement || !configElementAttribute) {
|
||||||
throw new Error('Missing web configuration element');
|
throw new Error('Missing web configuration element');
|
||||||
}
|
}
|
||||||
@@ -308,7 +296,7 @@ Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/ext
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
@@ -98,7 +98,7 @@ export abstract class AbstractExtensionR
|
@@ -120,7 +120,7 @@ export abstract class AbstractExtensionR
|
||||||
: version,
|
: version,
|
||||||
path: 'extension'
|
path: 'extension'
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||||
@@ -43,7 +43,12 @@ export interface ExtensionManagementPipe
|
@@ -44,7 +44,12 @@ export interface ExtensionManagementPipe
|
||||||
force?: boolean;
|
force?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
|||||||
|
|
||||||
export interface ICommandsExecuter {
|
export interface ICommandsExecuter {
|
||||||
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
|
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
|
||||||
@@ -105,6 +110,9 @@ export class CLIServerBase {
|
@@ -106,6 +111,9 @@ export class CLIServerBase {
|
||||||
case 'extensionManagement':
|
case 'extensionManagement':
|
||||||
returnObj = await this.manageExtensions(data);
|
returnObj = await this.manageExtensions(data);
|
||||||
break;
|
break;
|
||||||
@@ -50,7 +50,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
|||||||
default:
|
default:
|
||||||
sendResponse(404, `Unknown message type: ${data.type}`);
|
sendResponse(404, `Unknown message type: ${data.type}`);
|
||||||
break;
|
break;
|
||||||
@@ -172,6 +180,10 @@ export class CLIServerBase {
|
@@ -173,6 +181,10 @@ export class CLIServerBase {
|
||||||
return await this._commands.executeCommand<string | undefined>('_remoteCLI.getSystemStatus');
|
return await this._commands.executeCommand<string | undefined>('_remoteCLI.getSystemStatus');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||||
@@ -119,6 +119,7 @@ export interface NativeParsedArgs {
|
@@ -122,6 +122,7 @@ export interface NativeParsedArgs {
|
||||||
|
'disable-chromium-sandbox'?: boolean;
|
||||||
sandbox?: boolean;
|
sandbox?: boolean;
|
||||||
|
|
||||||
'enable-coi'?: boolean;
|
'enable-coi'?: boolean;
|
||||||
+ 'stdin-to-clipboard'?: boolean;
|
+ 'stdin-to-clipboard'?: boolean;
|
||||||
|
'unresponsive-sample-interval'?: string;
|
||||||
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
'unresponsive-sample-period'?: string;
|
||||||
'no-proxy-server'?: boolean;
|
'enable-rdp-display-tracking'?: boolean;
|
||||||
Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
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.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||||
@@ -90,6 +90,7 @@ export const OPTIONS: OptionDescriptions
|
@@ -91,6 +91,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.") },
|
'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.") },
|
'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.") },
|
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||||
@@ -102,7 +102,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||||
@@ -76,6 +76,7 @@ const isSupportedForPipe = (optionId: ke
|
@@ -77,6 +77,7 @@ const isSupportedForPipe = (optionId: ke
|
||||||
case 'verbose':
|
case 'verbose':
|
||||||
case 'remote':
|
case 'remote':
|
||||||
case 'locate-shell-integration-path':
|
case 'locate-shell-integration-path':
|
||||||
@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
|||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -293,6 +294,22 @@ export async function main(desc: Product
|
@@ -295,6 +296,22 @@ export async function main(desc: Product
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -131,5 +131,5 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
if (parsedArgs.status) {
|
if (parsedArgs.status) {
|
||||||
sendToPipe({
|
await sendToPipe({
|
||||||
type: 'status'
|
type: 'status'
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||||
@@ -320,6 +320,10 @@ export class Extension implements IExten
|
@@ -340,6 +340,10 @@ export class Extension implements IExten
|
||||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
|||||||
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
||||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||||
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
|
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
|
||||||
@@ -245,6 +245,9 @@ export async function setupServerService
|
@@ -255,6 +255,9 @@ export async function setupServerService
|
||||||
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
||||||
socketServer.registerChannel('extensions', channel);
|
socketServer.registerChannel('extensions', channel);
|
||||||
|
|
||||||
@@ -153,31 +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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/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 { streamToBuffer } from '../../base/common/buffer.js';
|
||||||
import { IProductConfiguration } from '../../base/common/product.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 { getLocaleFromConfig, getBrowserNLSConfiguration } from './remoteLanguagePacks.js';
|
||||||
import { CharCode } from '../../base/common/charCode.js';
|
import { CharCode } from '../../base/common/charCode.js';
|
||||||
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
|
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
|
||||||
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
|
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
|
||||||
@@ -98,6 +99,7 @@ export class WebClientServer {
|
@@ -385,14 +386,22 @@ export class WebClientServer {
|
||||||
private readonly _webExtensionResourceUrlTemplate: URI | undefined;
|
|
||||||
|
|
||||||
private readonly _staticRoute: string;
|
|
||||||
+ private readonly _serverRoot: string;
|
|
||||||
private readonly _callbackRoute: string;
|
|
||||||
private readonly _webExtensionRoute: string;
|
|
||||||
|
|
||||||
@@ -113,6 +115,7 @@ export class WebClientServer {
|
|
||||||
) {
|
|
||||||
this._webExtensionResourceUrlTemplate = this._productService.extensionsGallery?.resourceUrlTemplate ? URI.parse(this._productService.extensionsGallery.resourceUrlTemplate) : undefined;
|
|
||||||
|
|
||||||
+ this._serverRoot = serverRootPath;
|
|
||||||
this._staticRoute = `${serverRootPath}/static`;
|
|
||||||
this._callbackRoute = `${serverRootPath}/callback`;
|
|
||||||
this._webExtensionRoute = `/web-extension-resource`;
|
|
||||||
@@ -351,14 +354,22 @@ export class WebClientServer {
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const cookies = cookie.parse(req.headers.cookie || '');
|
const cookies = cookie.parse(req.headers.cookie || '');
|
||||||
@@ -193,7 +177,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
+ try {
|
+ try {
|
||||||
+ const nlsFile = await getBrowserNLSConfiguration(locale, this._environmentService.userDataPath);
|
+ const nlsFile = await getBrowserNLSConfiguration(locale, this._environmentService.userDataPath);
|
||||||
+ WORKBENCH_NLS_URL = nlsFile
|
+ WORKBENCH_NLS_URL = nlsFile
|
||||||
+ ? `${vscodeBase}${this._serverRoot}/vscode-remote-resource?path=${encodeURIComponent(nlsFile)}`
|
+ ? `${vscodeBase}/vscode-remote-resource?path=${encodeURIComponent(nlsFile)}`
|
||||||
+ : '';
|
+ : '';
|
||||||
+ } catch (error) {
|
+ } catch (error) {
|
||||||
+ console.error("Failed to generate translations", error);
|
+ console.error("Failed to generate translations", error);
|
||||||
@@ -214,7 +198,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -105,6 +106,7 @@ export interface ServerParsedArgs {
|
@@ -107,6 +108,7 @@ export interface ServerParsedArgs {
|
||||||
'disable-file-downloads'?: boolean;
|
'disable-file-downloads'?: boolean;
|
||||||
'disable-file-uploads'?: boolean;
|
'disable-file-uploads'?: boolean;
|
||||||
'disable-getting-started-override'?: boolean,
|
'disable-getting-started-override'?: boolean,
|
||||||
@@ -288,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.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||||
@@ -435,9 +435,6 @@ export class InstallAction extends Exten
|
@@ -475,9 +475,6 @@ export class InstallAction extends Exten
|
||||||
if (this.extension.isBuiltin) {
|
if (this.extension.isBuiltin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -298,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
if (this.extension.state !== ExtensionState.Uninstalled) {
|
if (this.extension.state !== ExtensionState.Uninstalled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -742,7 +739,7 @@ export abstract class InstallInOtherServ
|
@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
||||||
@@ -307,7 +291,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prefers to run on UI
|
// Prefers to run on UI
|
||||||
@@ -2028,17 +2025,6 @@ export class SetLanguageAction extends E
|
@@ -2073,17 +2070,6 @@ export class SetLanguageAction extends E
|
||||||
update(): void {
|
update(): void {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.class = SetLanguageAction.DisabledClass;
|
this.class = SetLanguageAction.DisabledClass;
|
||||||
@@ -325,7 +309,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async run(): Promise<any> {
|
override async run(): Promise<any> {
|
||||||
@@ -2055,7 +2041,6 @@ export class ClearLanguageAction extends
|
@@ -2100,7 +2086,6 @@ export class ClearLanguageAction extends
|
||||||
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
|
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -333,7 +317,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
@ILocaleService private readonly localeService: ILocaleService,
|
@ILocaleService private readonly localeService: ILocaleService,
|
||||||
) {
|
) {
|
||||||
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
||||||
@@ -2065,17 +2050,6 @@ export class ClearLanguageAction extends
|
@@ -2110,17 +2095,6 @@ export class ClearLanguageAction extends
|
||||||
update(): void {
|
update(): void {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.class = ClearLanguageAction.DisabledClass;
|
this.class = ClearLanguageAction.DisabledClass;
|
||||||
@@ -367,7 +351,7 @@ 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.orig/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
||||||
@@ -52,7 +52,7 @@ import './services/dialogs/browser/fileD
|
@@ -53,7 +53,7 @@ import './services/dialogs/browser/fileD
|
||||||
import './services/host/browser/browserHostService.js';
|
import './services/host/browser/browserHostService.js';
|
||||||
import './services/lifecycle/browser/lifecycleService.js';
|
import './services/lifecycle/browser/lifecycleService.js';
|
||||||
import './services/clipboard/browser/clipboardService.js';
|
import './services/clipboard/browser/clipboardService.js';
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -99,6 +101,8 @@ export interface ServerParsedArgs {
|
@@ -101,6 +103,8 @@ export interface ServerParsedArgs {
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check'?: boolean;
|
'disable-update-check'?: boolean;
|
||||||
'auth'?: string;
|
'auth'?: string;
|
||||||
@@ -112,9 +112,9 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -335,6 +335,8 @@ export class WebClientServer {
|
@@ -369,6 +369,8 @@ export class WebClientServer {
|
||||||
serverBasePath: this._basePath,
|
serverBasePath: basePath,
|
||||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||||
userDataPath: this._environmentService.userDataPath,
|
userDataPath: this._environmentService.userDataPath,
|
||||||
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||||
+ isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
+ isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
||||||
@@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||||
@@ -7,11 +7,11 @@ import { Event } from '../../base/common
|
@@ -7,11 +7,11 @@ import { Event } from '../../base/common
|
||||||
import { Disposable } from '../../base/common/lifecycle.js';
|
import { Disposable, DisposableStore } from '../../base/common/lifecycle.js';
|
||||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.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 { 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 } from '../common/contextkeys.js';
|
||||||
@@ -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.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
@@ -41,6 +41,9 @@ export const HasWebFileSystemAccess = ne
|
@@ -36,6 +36,9 @@ export const HasWebFileSystemAccess = ne
|
||||||
|
|
||||||
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
|
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('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
|
//#endregion
|
||||||
|
|
||||||
|
//#region < --- Window --- >
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
|
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
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
|
||||||
@@ -231,7 +231,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
|
|||||||
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
|
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
|
||||||
import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
|
import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
|
||||||
import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.js';
|
import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.js';
|
||||||
@@ -139,7 +139,7 @@ export class SimpleFileDialog extends Di
|
@@ -144,7 +144,7 @@ export class SimpleFileDialog extends Di
|
||||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||||
@IModelService private readonly modelService: IModelService,
|
@IModelService private readonly modelService: IModelService,
|
||||||
@ILanguageService private readonly languageService: ILanguageService,
|
@ILanguageService private readonly languageService: ILanguageService,
|
||||||
@@ -240,10 +240,10 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
|
|||||||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
||||||
@IPathService protected readonly pathService: IPathService,
|
@IPathService protected readonly pathService: IPathService,
|
||||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||||
@@ -283,20 +283,22 @@ export class SimpleFileDialog extends Di
|
@@ -310,20 +310,22 @@ export class SimpleFileDialog extends Di
|
||||||
this.filePickBox.sortByLabel = false;
|
|
||||||
this.filePickBox.ignoreFocusOut = true;
|
this.filePickBox.ignoreFocusOut = true;
|
||||||
this.filePickBox.ok = true;
|
this.filePickBox.ok = true;
|
||||||
|
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;
|
||||||
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
|
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
|
||||||
- this.filePickBox.customButton = true;
|
- this.filePickBox.customButton = true;
|
||||||
- this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
- this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
|||||||
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
|
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
|
||||||
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
|
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
|
||||||
import './gettingStartedColors.js';
|
import './gettingStartedColors.js';
|
||||||
@@ -834,6 +834,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"))
|
$('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 leftColumn = $('.categories-column.categories-column-left', {},);
|
||||||
const rightColumn = $('.categories-column.categories-column-right', {},);
|
const rightColumn = $('.categories-column.categories-column-right', {},);
|
||||||
|
|
||||||
@@ -869,6 +935,9 @@ export class GettingStartedPage extends
|
@@ -911,6 +977,9 @@ export class GettingStartedPage extends
|
||||||
recentList.setLimit(5);
|
recentList.setLimit(5);
|
||||||
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -103,6 +104,7 @@ export interface ServerParsedArgs {
|
@@ -105,6 +106,7 @@ export interface ServerParsedArgs {
|
||||||
'auth'?: string;
|
'auth'?: string;
|
||||||
'disable-file-downloads'?: boolean;
|
'disable-file-downloads'?: boolean;
|
||||||
'disable-file-uploads'?: 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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -339,6 +339,7 @@ export class WebClientServer {
|
@@ -373,6 +373,7 @@ export class WebClientServer {
|
||||||
userDataPath: this._environmentService.userDataPath,
|
userDataPath: this._environmentService.userDataPath,
|
||||||
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||||
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
||||||
@@ -214,7 +214,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||||
@@ -7,7 +7,7 @@ import { Event } from '../../base/common
|
@@ -7,7 +7,7 @@ import { Event } from '../../base/common
|
||||||
import { Disposable } from '../../base/common/lifecycle.js';
|
import { Disposable, DisposableStore } from '../../base/common/lifecycle.js';
|
||||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.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 { 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 } from '../common/contextkeys.js';
|
||||||
@@ -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.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
@@ -43,6 +43,7 @@ export const EmbedderIdentifierContext =
|
@@ -38,6 +38,7 @@ export const EmbedderIdentifierContext =
|
||||||
|
|
||||||
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||||
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
||||||
|
|||||||
@@ -187,10 +187,10 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
|||||||
import { IndexedDB } from '../../base/browser/indexedDB.js';
|
import { IndexedDB } from '../../base/browser/indexedDB.js';
|
||||||
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
|
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
|
||||||
+import { CodeServerClient } from '../../workbench/browser/client.js';
|
+import { CodeServerClient } from '../../workbench/browser/client.js';
|
||||||
import { ITelemetryService } from '../../platform/telemetry/common/telemetry.js';
|
|
||||||
import { IProgressService } from '../../platform/progress/common/progress.js';
|
import { IProgressService } from '../../platform/progress/common/progress.js';
|
||||||
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
|
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
|
||||||
@@ -131,6 +132,9 @@ export class BrowserMain extends Disposa
|
import { dirname, joinPath } from '../../base/common/resources.js';
|
||||||
|
@@ -130,6 +131,9 @@ export class BrowserMain extends Disposa
|
||||||
// Startup
|
// Startup
|
||||||
const instantiationService = workbench.startup();
|
const instantiationService = workbench.startup();
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -55,6 +55,8 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -56,6 +56,8 @@ export type ExtensionVirtualWorkspaceSup
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
@@ -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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -308,6 +308,7 @@ export class WebClientServer {
|
@@ -333,6 +333,7 @@ export class WebClientServer {
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
|
||||||
const productConfiguration = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
+ codeServerVersion: this._productService.codeServerVersion,
|
+ codeServerVersion: this._productService.codeServerVersion,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
@@ -299,7 +299,7 @@ Index: code-server/lib/vscode/src/server-main.ts
|
|||||||
|
|
||||||
function sanitizeStringArg(val: any): string | undefined {
|
function sanitizeStringArg(val: any): string | undefined {
|
||||||
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
|
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
|
||||||
@@ -283,3 +287,22 @@ function prompt(question: string): Promi
|
@@ -286,3 +290,22 @@ function prompt(question: string): Promi
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -330,6 +330,7 @@ export class WebClientServer {
|
@@ -364,6 +364,7 @@ export class WebClientServer {
|
||||||
remoteAuthority,
|
remoteAuthority,
|
||||||
serverBasePath: this._basePath,
|
serverBasePath: basePath,
|
||||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||||
+ userDataPath: this._environmentService.userDataPath,
|
+ userDataPath: this._environmentService.userDataPath,
|
||||||
_wrapWebWorkerExtHostInIframe,
|
_wrapWebWorkerExtHostInIframe,
|
||||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||||
@@ -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.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||||
@@ -145,8 +145,10 @@ export class WorkspaceService extends Di
|
@@ -147,8 +147,10 @@ export class WorkspaceService extends Di
|
||||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
|
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
|
||||||
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
||||||
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
||||||
@@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -552,6 +554,12 @@ export class WorkspaceService extends Di
|
@@ -555,6 +557,12 @@ export class WorkspaceService extends Di
|
||||||
previousFolders = this.workspace.folders;
|
previousFolders = this.workspace.folders;
|
||||||
this.workspace.update(workspace);
|
this.workspace.update(workspace);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -58,6 +58,7 @@ export interface IProductConfiguration {
|
@@ -59,6 +59,7 @@ export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -97,6 +98,7 @@ export const serverOptions: OptionDescri
|
@@ -99,6 +100,7 @@ export const serverOptions: OptionDescri
|
||||||
export interface ServerParsedArgs {
|
export interface ServerParsedArgs {
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check'?: boolean;
|
'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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -313,6 +313,7 @@ export class WebClientServer {
|
@@ -341,6 +341,7 @@ export class WebClientServer {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: base,
|
rootEndpoint: rootBase,
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
@@ -47,6 +47,16 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
@@ -49,6 +49,16 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||||
version: pkg.version
|
version: pkg.version
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -40,31 +40,30 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -115,7 +115,7 @@ export class WebClientServer {
|
@@ -326,7 +326,6 @@ export class WebClientServer {
|
||||||
|
|
||||||
this._staticRoute = `${serverRootPath}/static`;
|
const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH);
|
||||||
this._callbackRoute = `${serverRootPath}/callback`;
|
const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH);
|
||||||
- this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
|
- const webExtensionRoute = posix.join(basePath, this._productPath, WEB_EXTENSION_PATH);
|
||||||
+ this._webExtensionRoute = `/web-extension-resource`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority });
|
||||||
@@ -313,14 +313,7 @@ export class WebClientServer {
|
|
||||||
|
@@ -342,14 +341,7 @@ export class WebClientServer {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: base,
|
rootEndpoint: rootBase,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
- ...this._productService.extensionsGallery,
|
- ...this._productService.extensionsGallery,
|
||||||
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
||||||
- scheme: 'http',
|
- scheme: 'http',
|
||||||
- authority: remoteAuthority,
|
- authority: remoteAuthority,
|
||||||
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
- path: `${webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||||
- }).toString(true)
|
- }).toString(true)
|
||||||
- } : undefined
|
- } : undefined
|
||||||
+ extensionsGallery: this._productService.extensionsGallery,
|
+ extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
|
|
||||||
if (!this._environmentService.isBuilt) {
|
const proposedApi = this._environmentService.args['enable-proposed-api'];
|
||||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
@@ -75,9 +74,9 @@ Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/ext
|
|||||||
import { getTelemetryLevel, supportsTelemetry } from '../../telemetry/common/telemetryUtils.js';
|
import { getTelemetryLevel, supportsTelemetry } from '../../telemetry/common/telemetryUtils.js';
|
||||||
-import { RemoteAuthorities } from '../../../base/common/network.js';
|
-import { RemoteAuthorities } from '../../../base/common/network.js';
|
||||||
import { TargetPlatform } from '../../extensions/common/extensions.js';
|
import { TargetPlatform } from '../../extensions/common/extensions.js';
|
||||||
|
import { ExtensionGalleryResourceType, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../extensionManagement/common/extensionGalleryManifest.js';
|
||||||
const WEB_EXTENSION_RESOURCE_END_POINT_SEGMENT = '/web-extension-resource/';
|
import { ILogService } from '../../log/common/log.js';
|
||||||
@@ -140,9 +139,9 @@ export abstract class AbstractExtensionR
|
@@ -163,9 +162,9 @@ export abstract class AbstractExtensionR
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _isWebExtensionResourceEndPoint(uri: URI): boolean {
|
protected _isWebExtensionResourceEndPoint(uri: URI): boolean {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -59,6 +59,7 @@ export interface IProductConfiguration {
|
@@ -60,6 +60,7 @@ export interface IProductConfiguration {
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
readonly logoutEndpoint?: string
|
readonly logoutEndpoint?: string
|
||||||
@@ -71,14 +71,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -314,6 +314,7 @@ export class WebClientServer {
|
@@ -342,6 +342,7 @@ export class WebClientServer {
|
||||||
rootEndpoint: base,
|
rootEndpoint: rootBase,
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
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
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||||
@@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
|
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
|
||||||
import { create } from '../../../workbench/workbench.web.main.internal.js';
|
import { create } from '../../../workbench/workbench.web.main.internal.js';
|
||||||
|
|
||||||
@@ -584,6 +585,39 @@ class WorkspaceProvider implements IWork
|
@@ -600,6 +601,39 @@ class WorkspaceProvider implements IWork
|
||||||
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
||||||
workspaceProvider: WorkspaceProvider.create(config),
|
workspaceProvider: WorkspaceProvider.create(config),
|
||||||
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
||||||
@@ -148,7 +148,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
@@ -77,8 +77,8 @@ export class ForwardedPortsView extends
|
@@ -83,8 +83,8 @@ export class ForwardedPortsView extends
|
||||||
private async enableForwardedPortsFeatures() {
|
private async enableForwardedPortsFeatures() {
|
||||||
this.contextKeyListener.clear();
|
this.contextKeyListener.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,5 @@ getting-started.diff
|
|||||||
keepalive.diff
|
keepalive.diff
|
||||||
clipboard.diff
|
clipboard.diff
|
||||||
display-language.diff
|
display-language.diff
|
||||||
|
trusted-domains.diff
|
||||||
|
signature-verification.diff
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -60,6 +60,10 @@ export interface IProductConfiguration {
|
@@ -61,6 +61,10 @@ export interface IProductConfiguration {
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
readonly logoutEndpoint?: string
|
readonly logoutEndpoint?: string
|
||||||
readonly proxyEndpointTemplate?: string
|
readonly proxyEndpointTemplate?: string
|
||||||
@@ -54,14 +54,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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -315,6 +315,10 @@ export class WebClientServer {
|
@@ -343,6 +343,10 @@ export class WebClientServer {
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||||
+ serviceWorker: {
|
+ serviceWorker: {
|
||||||
+ scope: vscodeBase + '/',
|
+ scope: vscodeBase + '/',
|
||||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||||
+ },
|
+ },
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
|
|||||||
34
patches/signature-verification.diff
Normal file
34
patches/signature-verification.diff
Normal file
@@ -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());
|
||||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
||||||
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
||||||
@@ -253,8 +253,7 @@ function packageTask(type, platform, arc
|
@@ -256,8 +256,7 @@ function packageTask(type, platform, arc
|
||||||
|
|
||||||
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||||
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
||||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
|||||||
|
|
||||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||||
const isUIExtension = (manifest) => {
|
const isUIExtension = (manifest) => {
|
||||||
@@ -293,9 +292,9 @@ function packageTask(type, platform, arc
|
@@ -296,9 +295,9 @@ function packageTask(type, platform, arc
|
||||||
.map(name => `.build/extensions/${name}/**`);
|
.map(name => `.build/extensions/${name}/**`);
|
||||||
|
|
||||||
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
||||||
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
|||||||
|
|
||||||
let version = packageJson.version;
|
let version = packageJson.version;
|
||||||
const quality = product.quality;
|
const quality = product.quality;
|
||||||
@@ -454,7 +453,7 @@ function tweakProductForServerWeb(produc
|
@@ -451,7 +450,7 @@ function tweakProductForServerWeb(produc
|
||||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||||
bundleTask,
|
bundleTask,
|
||||||
util.rimraf(`out-vscode-${type}-min`),
|
util.rimraf(`out-vscode-${type}-min`),
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
|||||||
|
|
||||||
+import * as _http from 'http';
|
+import * as _http from 'http';
|
||||||
import * as performance from '../../../base/common/performance.js';
|
import * as performance from '../../../base/common/performance.js';
|
||||||
|
import type * as vscode from 'vscode';
|
||||||
import { createApiFactoryAndRegisterActors } from '../common/extHost.api.impl.js';
|
import { createApiFactoryAndRegisterActors } from '../common/extHost.api.impl.js';
|
||||||
import { RequireInterceptor } from '../common/extHostRequireInterceptor.js';
|
@@ -18,6 +19,7 @@ import { ExtensionRuntime } from '../com
|
||||||
@@ -17,6 +18,7 @@ import { ExtensionRuntime } from '../com
|
|
||||||
import { CLIServer } from './extHostCLIServer.js';
|
import { CLIServer } from './extHostCLIServer.js';
|
||||||
import { realpathSync } from '../../../base/node/extpath.js';
|
import { realpathSync } from '../../../base/node/extpath.js';
|
||||||
import { ExtHostConsoleForwarder } from './extHostConsoleForwarder.js';
|
import { ExtHostConsoleForwarder } from './extHostConsoleForwarder.js';
|
||||||
+import { IExtHostWorkspace } from '../common/extHostWorkspace.js';
|
+import { IExtHostWorkspace } from '../common/extHostWorkspace.js';
|
||||||
import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js';
|
import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js';
|
||||||
import { createRequire } from 'node:module';
|
import nodeModule from 'node:module';
|
||||||
const require = createRequire(import.meta.url);
|
import { assertType } from '../../../base/common/types.js';
|
||||||
@@ -97,6 +99,52 @@ export class ExtHostExtensionService ext
|
@@ -226,6 +228,52 @@ export class ExtHostExtensionService ext
|
||||||
await interceptor.install();
|
|
||||||
performance.mark('code/extHost/didInitAPI');
|
performance.mark('code/extHost/didInitAPI');
|
||||||
|
|
||||||
+ (async () => {
|
+ (async () => {
|
||||||
@@ -96,7 +96,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
|||||||
import minimist from 'minimist';
|
import minimist from 'minimist';
|
||||||
import * as nativeWatchdog from 'native-watchdog';
|
import * as nativeWatchdog from 'native-watchdog';
|
||||||
import * as net from 'net';
|
import * as net from 'net';
|
||||||
@@ -422,7 +423,28 @@ async function startExtensionHostProcess
|
@@ -437,7 +438,28 @@ async function startExtensionHostProcess
|
||||||
);
|
);
|
||||||
|
|
||||||
// rewrite onTerminate-function to be a proper shutdown
|
// rewrite onTerminate-function to be a proper shutdown
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
|||||||
import { NullPolicyService } from '../../platform/policy/common/policy.js';
|
import { NullPolicyService } from '../../platform/policy/common/policy.js';
|
||||||
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
|
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
|
||||||
import { LoggerService } from '../../platform/log/node/loggerService.js';
|
import { LoggerService } from '../../platform/log/node/loggerService.js';
|
||||||
@@ -152,11 +154,23 @@ export async function setupServerService
|
@@ -158,11 +160,23 @@ export async function setupServerService
|
||||||
const requestService = new RequestService(configurationService, environmentService, logService);
|
const requestService = new RequestService('remote', configurationService, environmentService, logService);
|
||||||
services.set(IRequestService, requestService);
|
services.set(IRequestService, requestService);
|
||||||
|
|
||||||
+ let isContainer = undefined;
|
+ let isContainer = undefined;
|
||||||
@@ -134,20 +134,20 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -319,6 +319,8 @@ export class WebClientServer {
|
@@ -347,6 +347,8 @@ export class WebClientServer {
|
||||||
scope: vscodeBase + '/',
|
scope: vscodeBase + '/',
|
||||||
path: base + '/_static/out/browser/serviceWorker.js',
|
path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||||
},
|
},
|
||||||
+ enableTelemetry: this._productService.enableTelemetry,
|
+ enableTelemetry: this._productService.enableTelemetry,
|
||||||
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -64,6 +64,7 @@ export interface IProductConfiguration {
|
@@ -65,6 +65,7 @@ export interface IProductConfiguration {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
readonly scope: string;
|
readonly scope: string;
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
@@ -55,7 +55,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
@@ -57,7 +57,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||||
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
||||||
controlUrl: "",
|
controlUrl: "",
|
||||||
recommendationsUrl: "",
|
recommendationsUrl: "",
|
||||||
|
|||||||
49
patches/trusted-domains.diff
Normal file
49
patches/trusted-domains.diff
Normal file
@@ -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
|
||||||
|
@@ -20,6 +20,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 ----- */
|
||||||
|
|
||||||
|
@@ -109,6 +110,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<Mutable<IProductConfiguration>> = {
|
||||||
|
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'];
|
||||||
@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
|
|||||||
|
|
||||||
export class BrowserStorageService extends AbstractStorageService {
|
export class BrowserStorageService extends AbstractStorageService {
|
||||||
|
|
||||||
@@ -298,7 +299,11 @@ export class IndexedDBStorageDatabase ex
|
@@ -300,7 +301,11 @@ export class IndexedDBStorageDatabase ex
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {
|
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -57,6 +57,7 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -58,6 +58,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
@@ -105,14 +105,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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -312,6 +312,7 @@ export class WebClientServer {
|
@@ -340,6 +340,7 @@ export class WebClientServer {
|
||||||
const productConfiguration = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: base,
|
rootEndpoint: rootBase,
|
||||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
} satisfies Partial<IProductConfiguration>;
|
};
|
||||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -93,6 +95,8 @@ export const serverOptions: OptionDescri
|
@@ -95,6 +97,8 @@ export const serverOptions: OptionDescri
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ServerParsedArgs {
|
export interface ServerParsedArgs {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
@@ -225,7 +225,7 @@ export class BrowserWorkbenchEnvironment
|
@@ -220,7 +220,7 @@ export class BrowserWorkbenchEnvironment
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
get webviewExternalEndpoint(): string {
|
get webviewExternalEndpoint(): string {
|
||||||
@@ -54,11 +54,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -326,6 +326,7 @@ export class WebClientServer {
|
@@ -360,6 +360,7 @@ export class WebClientServer {
|
||||||
const workbenchWebConfiguration = {
|
const workbenchWebConfiguration = {
|
||||||
remoteAuthority,
|
remoteAuthority,
|
||||||
serverBasePath: this._basePath,
|
serverBasePath: basePath,
|
||||||
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
+ webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||||
_wrapWebWorkerExtHostInIframe,
|
_wrapWebWorkerExtHostInIframe,
|
||||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||||
@@ -70,29 +70,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
<meta http-equiv="Content-Security-Policy"
|
<meta http-equiv="Content-Security-Policy"
|
||||||
- content="default-src 'none'; script-src 'sha256-DXeP32g8BdMsVuVabYTmznoTH59F7M7UtV0vXemEFqc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
- content="default-src 'none'; script-src 'sha256-gEAyFzmkyqMoTTnN+3KReFUYoHsK4RAJEb+6eiul+UY=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||||
+ content="default-src 'none'; script-src 'sha256-z5v/0xE4zQPgV1fazhHB/UlsTzdm39hRMk3V8Av0HI4=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
+ content="default-src 'none'; script-src 'sha256-1qYtPnTQa4VwKNJO61EOhs2agF9TvuQSYIJ27OgzZqI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||||
|
|
||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
<!-- Disable pinch zooming -->
|
||||||
@@ -349,6 +349,12 @@
|
<meta name="viewport"
|
||||||
|
@@ -351,6 +351,12 @@
|
||||||
const hostname = location.hostname;
|
|
||||||
|
|
||||||
+ // It is safe to run if we are on the same host.
|
|
||||||
+ const parent = new URL(parentOrigin)
|
|
||||||
+ if (parent.hostname === hostname) {
|
|
||||||
+ return start(parentOrigin)
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (!crypto.subtle) {
|
|
||||||
// cannot validate, not running in a secure context
|
|
||||||
throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
|
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
||||||
===================================================================
|
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
|
||||||
@@ -343,6 +343,12 @@
|
|
||||||
|
|
||||||
const hostname = location.hostname;
|
const hostname = location.hostname;
|
||||||
|
|
||||||
@@ -113,12 +96,12 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
|
|||||||
<meta http-equiv="Content-Security-Policy" content="
|
<meta http-equiv="Content-Security-Policy" content="
|
||||||
default-src 'none';
|
default-src 'none';
|
||||||
child-src 'self' data: blob:;
|
child-src 'self' data: blob:;
|
||||||
- script-src 'self' 'unsafe-eval' 'sha256-xM2KVDKIoeb8vVxk4ezEUsxdTZh5wFnKO3YmFhy9tkk=' https: http://localhost:* blob:;
|
- script-src 'self' 'unsafe-eval' 'sha256-cl8ijlOzEe+0GRCQNJQu2k6nUQ0fAYNYIuuKEm72JDs=' https: http://localhost:* blob:;
|
||||||
+ script-src 'self' 'unsafe-eval' 'sha256-6eZXxikxkENULU0EOkVQSd4hglGixLg3Aow9psZ6u2Y=' https: http://localhost:* blob:;
|
+ script-src 'self' 'unsafe-eval' 'sha256-yhZXuB8LS6t73dvNg6rtLX8y4PHLnqRm5+6DdOGkOcw=' https: http://localhost:* blob:;
|
||||||
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -23,6 +23,13 @@
|
@@ -25,6 +25,13 @@
|
||||||
// validation not requested
|
// validation not requested
|
||||||
return start();
|
return start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ body,
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
background: rgb(244, 247, 252);
|
background: rgb(244, 247, 252);
|
||||||
background: light-dark(rgb(244, 247, 252), #111);
|
background: light-dark(rgb(244, 247, 252), #111827);
|
||||||
color: #111;
|
color: #111;
|
||||||
color: light-dark(#111, #ddd);
|
color: light-dark(#111, #ddd);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -29,14 +29,15 @@ button {
|
|||||||
|
|
||||||
.-button {
|
.-button {
|
||||||
background-color: rgb(87, 114, 245);
|
background-color: rgb(87, 114, 245);
|
||||||
background-color: light-dark(rgb(87, 114, 245), rgb(50, 85, 250));
|
background-color: light-dark(rgb(87, 114, 245), rgb(26, 86, 219));
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: none;
|
border: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: white;
|
color: white;
|
||||||
color: light-dark(white, #ddd);
|
color: light-dark(white, white);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 18px 20px;
|
padding: 18px 20px;
|
||||||
|
font-weight: 500;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +54,10 @@ button {
|
|||||||
|
|
||||||
.card-box {
|
.card-box {
|
||||||
background-color: rgb(250, 253, 258);
|
background-color: rgb(250, 253, 258);
|
||||||
background-color: light-dark(rgb(250, 253, 258), #000);
|
background-color: light-dark(rgb(250, 253, 258), #1f2937);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px,
|
light-dark(rgba(60, 66, 87, 0.117647), rgba(10, 10, 10, 0.617647)) 0px 7px 14px 0px,
|
||||||
rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
||||||
max-width: 650px;
|
max-width: 650px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -64,9 +65,9 @@ button {
|
|||||||
|
|
||||||
.card-box > .header {
|
.card-box > .header {
|
||||||
border-bottom: 1px solid #ddd;
|
border-bottom: 1px solid #ddd;
|
||||||
border-bottom: 1px solid light-dark(#ddd, #222);
|
border-bottom: 1px solid light-dark(#ddd, #111827);
|
||||||
color: #444;
|
color: #444;
|
||||||
color: light-dark(#444, #ccc);
|
color: light-dark(#444, #fff);
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ button {
|
|||||||
|
|
||||||
.card-box > .header > .sub {
|
.card-box > .header > .sub {
|
||||||
color: #555;
|
color: #555;
|
||||||
color: light-dark(#555, #aaa);
|
color: light-dark(#555, #9ca3af);
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,15 +30,23 @@ body {
|
|||||||
|
|
||||||
.login-form > .field > .password {
|
.login-form > .field > .password {
|
||||||
background-color: rgb(244, 247, 252);
|
background-color: rgb(244, 247, 252);
|
||||||
background-color: light-dark(rgb(244, 247, 252), #222);
|
background-color: light-dark(rgb(244, 247, 252), #374151);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border: 1px solid light-dark(#ddd, #333);
|
border: 1px solid light-dark(#ddd, #4b5563);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-form > .field > .password::placeholder {
|
||||||
|
color: rgb(148 163 184);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form > .field > .password:focus {
|
||||||
|
outline: 2px solid rgb(63, 131, 248);
|
||||||
|
}
|
||||||
|
|
||||||
.login-form > .user {
|
.login-form > .user {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export enum LogLevel {
|
|||||||
export class OptionalString extends Optional<string> {}
|
export class OptionalString extends Optional<string> {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code flags provided by the user.
|
* (VS) Code flags provided by the user.
|
||||||
*/
|
*/
|
||||||
export interface UserProvidedCodeArgs {
|
export interface UserProvidedCodeArgs {
|
||||||
"disable-telemetry"?: boolean
|
"disable-telemetry"?: boolean
|
||||||
@@ -53,7 +53,9 @@ export interface UserProvidedCodeArgs {
|
|||||||
"disable-getting-started-override"?: boolean
|
"disable-getting-started-override"?: boolean
|
||||||
"disable-proxy"?: boolean
|
"disable-proxy"?: boolean
|
||||||
"session-socket"?: string
|
"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[]
|
enable?: string[]
|
||||||
help?: boolean
|
help?: boolean
|
||||||
host?: string
|
host?: string
|
||||||
locale?: string
|
|
||||||
port?: number
|
port?: number
|
||||||
json?: boolean
|
json?: boolean
|
||||||
log?: LogLevel
|
log?: LogLevel
|
||||||
@@ -84,12 +85,14 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
|||||||
"trusted-origins"?: string[]
|
"trusted-origins"?: string[]
|
||||||
version?: boolean
|
version?: boolean
|
||||||
"proxy-domain"?: string[]
|
"proxy-domain"?: string[]
|
||||||
|
"skip-auth-preflight"?: boolean
|
||||||
"reuse-window"?: boolean
|
"reuse-window"?: boolean
|
||||||
"new-window"?: boolean
|
"new-window"?: boolean
|
||||||
"ignore-last-opened"?: boolean
|
"ignore-last-opened"?: boolean
|
||||||
verbose?: boolean
|
verbose?: boolean
|
||||||
"app-name"?: string
|
"app-name"?: string
|
||||||
"welcome-text"?: string
|
"welcome-text"?: string
|
||||||
|
"abs-proxy-base-path"?: string
|
||||||
/* Positional arguments. */
|
/* Positional arguments. */
|
||||||
_?: string[]
|
_?: string[]
|
||||||
}
|
}
|
||||||
@@ -193,6 +196,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
enable: { type: "string[]" },
|
enable: { type: "string[]" },
|
||||||
help: { type: "boolean", short: "h", description: "Show this output." },
|
help: { type: "boolean", short: "h", description: "Show this output." },
|
||||||
json: { type: "boolean" },
|
json: { type: "boolean" },
|
||||||
|
"link-protection-trusted-domains": {
|
||||||
|
type: "string[]",
|
||||||
|
description: "Links matching a trusted domain can be opened without link protection.",
|
||||||
|
},
|
||||||
locale: {
|
locale: {
|
||||||
// The preferred way to set the locale is via the UI.
|
// The preferred way to set the locale is via the UI.
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -252,6 +259,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
description: "GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).",
|
description: "GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).",
|
||||||
},
|
},
|
||||||
"proxy-domain": { type: "string[]", description: "Domain used for proxying ports." },
|
"proxy-domain": { type: "string[]", description: "Domain used for proxying ports." },
|
||||||
|
"skip-auth-preflight": {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Allows preflight requests through proxy without authentication.",
|
||||||
|
},
|
||||||
"ignore-last-opened": {
|
"ignore-last-opened": {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
short: "e",
|
short: "e",
|
||||||
@@ -702,12 +713,16 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA
|
|||||||
|
|
||||||
// We convert the config file into a set of flags.
|
// We convert the config file into a set of flags.
|
||||||
// This is a temporary measure until we add a proper CLI library.
|
// This is a temporary measure until we add a proper CLI library.
|
||||||
const configFileArgv = Object.entries(config).map(([optName, opt]) => {
|
const configFileArgv = Object.entries(config)
|
||||||
if (opt === true) {
|
.map(([optName, opt]) => {
|
||||||
return `--${optName}`
|
if (opt === true) {
|
||||||
}
|
return `--${optName}`
|
||||||
return `--${optName}=${opt}`
|
} else if (Array.isArray(opt)) {
|
||||||
})
|
return opt.map((o) => `--${optName}=${o}`)
|
||||||
|
}
|
||||||
|
return `--${optName}=${opt}`
|
||||||
|
})
|
||||||
|
.flat()
|
||||||
const args = parse(configFileArgv, {
|
const args = parse(configFileArgv, {
|
||||||
configFile: configPath,
|
configFile: configPath,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { field, logger } from "@coder/logger"
|
import { field, logger } from "@coder/logger"
|
||||||
import http from "http"
|
import http from "http"
|
||||||
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { Disposable } from "../common/emitter"
|
import { Disposable } from "../common/emitter"
|
||||||
import { plural } from "../common/util"
|
import { plural } from "../common/util"
|
||||||
@@ -51,7 +52,11 @@ export const runCodeCli = async (args: DefaultedArgs): Promise<void> => {
|
|||||||
try {
|
try {
|
||||||
// See vscode.loadVSCode for more on this jank.
|
// See vscode.loadVSCode for more on this jank.
|
||||||
process.env.CODE_SERVER_PARENT_PID = process.pid.toString()
|
process.env.CODE_SERVER_PARENT_PID = process.pid.toString()
|
||||||
const modPath = path.join(vsRootPath, "out/server-main.js")
|
let modPath = path.join(vsRootPath, "out/server-main.js")
|
||||||
|
if (os.platform() === "win32") {
|
||||||
|
// On Windows, absolute paths of ESM modules must be a valid file URI.
|
||||||
|
modPath = "file:///" + modPath.replace(/\\/g, "/")
|
||||||
|
}
|
||||||
const mod = (await eval(`import("${modPath}")`)) as VSCodeModule
|
const mod = (await eval(`import("${modPath}")`)) as VSCodeModule
|
||||||
const serverModule = await mod.loadCodeWithNls()
|
const serverModule = await mod.loadCodeWithNls()
|
||||||
await serverModule.spawnCli(await toCodeArgs(args))
|
await serverModule.spawnCli(await toCodeArgs(args))
|
||||||
@@ -158,6 +163,9 @@ export const runCodeServer = async (
|
|||||||
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
|
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
|
||||||
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
|
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
|
||||||
}
|
}
|
||||||
|
if (args["skip-auth-preflight"]) {
|
||||||
|
logger.info(" - Skipping authentication for preflight requests")
|
||||||
|
}
|
||||||
if (process.env.VSCODE_PROXY_URI) {
|
if (process.env.VSCODE_PROXY_URI) {
|
||||||
logger.info(`Using proxy URI in PORTS tab: ${process.env.VSCODE_PROXY_URI}`)
|
logger.info(`Using proxy URI in PORTS tab: ${process.env.VSCODE_PROXY_URI}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,302 +0,0 @@
|
|||||||
import { field, Level, Logger } from "@coder/logger"
|
|
||||||
import * as express from "express"
|
|
||||||
import * as fs from "fs"
|
|
||||||
import * as path from "path"
|
|
||||||
import * as semver from "semver"
|
|
||||||
import * as pluginapi from "../../typings/pluginapi"
|
|
||||||
import { HttpCode, HttpError } from "../common/http"
|
|
||||||
import { version } from "./constants"
|
|
||||||
import { authenticated, ensureAuthenticated, replaceTemplates } from "./http"
|
|
||||||
import { proxy } from "./proxy"
|
|
||||||
import * as util from "./util"
|
|
||||||
import { Router as WsRouter, WebsocketRouter, wss } from "./wsRouter"
|
|
||||||
const fsp = fs.promises
|
|
||||||
|
|
||||||
// Represents a required module which could be anything.
|
|
||||||
type Module = any
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject code-server when `require`d. This is required because the API provides
|
|
||||||
* more than just types so these need to be provided at run-time.
|
|
||||||
*/
|
|
||||||
const originalLoad = require("module")._load
|
|
||||||
require("module")._load = function (request: string, parent: object, isMain: boolean): Module {
|
|
||||||
return request === "code-server" ? codeServer : originalLoad.apply(this, [request, parent, isMain])
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The module you get when importing "code-server".
|
|
||||||
*/
|
|
||||||
export const codeServer = {
|
|
||||||
HttpCode,
|
|
||||||
HttpError,
|
|
||||||
Level,
|
|
||||||
authenticated,
|
|
||||||
ensureAuthenticated,
|
|
||||||
express,
|
|
||||||
field,
|
|
||||||
proxy,
|
|
||||||
replaceTemplates,
|
|
||||||
WsRouter,
|
|
||||||
wss,
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Plugin extends pluginapi.Plugin {
|
|
||||||
/**
|
|
||||||
* These fields are populated from the plugin's package.json
|
|
||||||
* and now guaranteed to exist.
|
|
||||||
*/
|
|
||||||
name: string
|
|
||||||
version: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* path to the node module on the disk.
|
|
||||||
*/
|
|
||||||
modulePath: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Application extends pluginapi.Application {
|
|
||||||
/*
|
|
||||||
* Clone of the above without functions.
|
|
||||||
*/
|
|
||||||
plugin: Omit<Plugin, "init" | "deinit" | "router" | "applications">
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PluginAPI implements the plugin API described in typings/pluginapi.d.ts
|
|
||||||
* Please see that file for details.
|
|
||||||
*/
|
|
||||||
export class PluginAPI {
|
|
||||||
private readonly plugins = new Map<string, Plugin>()
|
|
||||||
private readonly logger: Logger
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
logger: Logger,
|
|
||||||
/**
|
|
||||||
* These correspond to $CS_PLUGIN_PATH and $CS_PLUGIN respectively.
|
|
||||||
*/
|
|
||||||
private readonly csPlugin = "",
|
|
||||||
private readonly csPluginPath = `${path.join(util.paths.data, "plugins")}:/usr/share/code-server/plugins`,
|
|
||||||
private readonly workingDirectory: string | undefined = undefined,
|
|
||||||
) {
|
|
||||||
this.logger = logger.named("pluginapi")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* applications grabs the full list of applications from
|
|
||||||
* all loaded plugins.
|
|
||||||
*/
|
|
||||||
public async applications(): Promise<Application[]> {
|
|
||||||
const apps = new Array<Application>()
|
|
||||||
for (const [, p] of this.plugins) {
|
|
||||||
if (!p.applications) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const pluginApps = await p.applications()
|
|
||||||
|
|
||||||
// Add plugin key to each app.
|
|
||||||
apps.push(
|
|
||||||
...pluginApps.map((app) => {
|
|
||||||
app = { ...app, path: path.join(p.routerPath, app.path || "") }
|
|
||||||
app = { ...app, iconPath: path.join(app.path || "", app.iconPath) }
|
|
||||||
return {
|
|
||||||
...app,
|
|
||||||
plugin: {
|
|
||||||
name: p.name,
|
|
||||||
version: p.version,
|
|
||||||
modulePath: p.modulePath,
|
|
||||||
|
|
||||||
displayName: p.displayName,
|
|
||||||
description: p.description,
|
|
||||||
routerPath: p.routerPath,
|
|
||||||
homepageURL: p.homepageURL,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return apps
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mount mounts all plugin routers onto r and websocket routers onto wr.
|
|
||||||
*/
|
|
||||||
public mount(r: express.Router, wr: express.Router): void {
|
|
||||||
for (const [, p] of this.plugins) {
|
|
||||||
if (p.router) {
|
|
||||||
r.use(`${p.routerPath}`, p.router())
|
|
||||||
}
|
|
||||||
if (p.wsRouter) {
|
|
||||||
wr.use(`${p.routerPath}`, (p.wsRouter() as WebsocketRouter).router)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* loadPlugins loads all plugins based on this.csPlugin,
|
|
||||||
* this.csPluginPath and the built in plugins.
|
|
||||||
*/
|
|
||||||
public async loadPlugins(loadBuiltin = true): Promise<void> {
|
|
||||||
for (const dir of this.csPlugin.split(":")) {
|
|
||||||
if (!dir) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
await this.loadPlugin(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const dir of this.csPluginPath.split(":")) {
|
|
||||||
if (!dir) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
await this._loadPlugins(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadBuiltin) {
|
|
||||||
await this._loadPlugins(path.join(__dirname, "../../plugins"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* _loadPlugins is the counterpart to loadPlugins.
|
|
||||||
*
|
|
||||||
* It differs in that it loads all plugins in a single
|
|
||||||
* directory whereas loadPlugins uses all available directories
|
|
||||||
* as documented.
|
|
||||||
*/
|
|
||||||
private async _loadPlugins(dir: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const entries = await fsp.readdir(dir, { withFileTypes: true })
|
|
||||||
for (const ent of entries) {
|
|
||||||
if (!ent.isDirectory()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
await this.loadPlugin(path.join(dir, ent.name))
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.code !== "ENOENT") {
|
|
||||||
this.logger.warn(`failed to load plugins from ${q(dir)}: ${error.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async loadPlugin(dir: string): Promise<void> {
|
|
||||||
try {
|
|
||||||
const str = await fsp.readFile(path.join(dir, "package.json"), {
|
|
||||||
encoding: "utf8",
|
|
||||||
})
|
|
||||||
const packageJSON: PackageJSON = JSON.parse(str)
|
|
||||||
for (const [, p] of this.plugins) {
|
|
||||||
if (p.name === packageJSON.name) {
|
|
||||||
this.logger.warn(
|
|
||||||
`ignoring duplicate plugin ${q(p.name)} at ${q(dir)}, using previously loaded ${q(p.modulePath)}`,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const p = this._loadPlugin(dir, packageJSON)
|
|
||||||
this.plugins.set(p.name, p)
|
|
||||||
} catch (error: any) {
|
|
||||||
if (error.code !== "ENOENT") {
|
|
||||||
this.logger.warn(`failed to load plugin: ${error.stack}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* _loadPlugin is the counterpart to loadPlugin and actually
|
|
||||||
* loads the plugin now that we know there is no duplicate
|
|
||||||
* and that the package.json has been read.
|
|
||||||
*/
|
|
||||||
private _loadPlugin(dir: string, packageJSON: PackageJSON): Plugin {
|
|
||||||
dir = path.resolve(dir)
|
|
||||||
|
|
||||||
const logger = this.logger.named(packageJSON.name)
|
|
||||||
logger.debug("loading plugin", field("plugin_dir", dir), field("package_json", packageJSON))
|
|
||||||
|
|
||||||
if (!packageJSON.name) {
|
|
||||||
throw new Error("plugin package.json missing name")
|
|
||||||
}
|
|
||||||
if (!packageJSON.version) {
|
|
||||||
throw new Error("plugin package.json missing version")
|
|
||||||
}
|
|
||||||
if (!packageJSON.engines || !packageJSON.engines["code-server"]) {
|
|
||||||
throw new Error(`plugin package.json missing code-server range like:
|
|
||||||
"engines": {
|
|
||||||
"code-server": "^3.7.0"
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
if (!semver.satisfies(version, packageJSON.engines["code-server"])) {
|
|
||||||
this.logger.warn(
|
|
||||||
`plugin range ${q(packageJSON.engines["code-server"])} incompatible` + ` with code-server version ${version}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const pluginModule = require(dir)
|
|
||||||
if (!pluginModule.plugin) {
|
|
||||||
throw new Error("plugin module does not export a plugin")
|
|
||||||
}
|
|
||||||
|
|
||||||
const p = {
|
|
||||||
name: packageJSON.name,
|
|
||||||
version: packageJSON.version,
|
|
||||||
modulePath: dir,
|
|
||||||
...pluginModule.plugin,
|
|
||||||
} as Plugin
|
|
||||||
|
|
||||||
if (!p.displayName) {
|
|
||||||
throw new Error("plugin missing displayName")
|
|
||||||
}
|
|
||||||
if (!p.description) {
|
|
||||||
throw new Error("plugin missing description")
|
|
||||||
}
|
|
||||||
if (!p.routerPath) {
|
|
||||||
throw new Error("plugin missing router path")
|
|
||||||
}
|
|
||||||
if (!p.routerPath.startsWith("/")) {
|
|
||||||
throw new Error(`plugin router path ${q(p.routerPath)}: invalid`)
|
|
||||||
}
|
|
||||||
if (!p.homepageURL) {
|
|
||||||
throw new Error("plugin missing homepage")
|
|
||||||
}
|
|
||||||
|
|
||||||
p.init({
|
|
||||||
logger: logger,
|
|
||||||
workingDirectory: this.workingDirectory,
|
|
||||||
})
|
|
||||||
|
|
||||||
logger.debug("loaded")
|
|
||||||
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
public async dispose(): Promise<void> {
|
|
||||||
await Promise.all(
|
|
||||||
Array.from(this.plugins.values()).map(async (p) => {
|
|
||||||
if (!p.deinit) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await p.deinit()
|
|
||||||
} catch (error: any) {
|
|
||||||
this.logger.error("plugin failed to deinit", field("name", p.name), field("error", error.message))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PackageJSON {
|
|
||||||
name: string
|
|
||||||
version: string
|
|
||||||
engines: {
|
|
||||||
"code-server": string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function q(s: string | undefined): string {
|
|
||||||
if (s === undefined) {
|
|
||||||
s = "undefined"
|
|
||||||
}
|
|
||||||
return JSON.stringify(s)
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import * as express from "express"
|
|
||||||
import { PluginAPI } from "../plugin"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the /api/applications endpoint
|
|
||||||
*
|
|
||||||
* See typings/pluginapi.d.ts for details.
|
|
||||||
*/
|
|
||||||
export function router(papi: PluginAPI): express.Router {
|
|
||||||
const router = express.Router()
|
|
||||||
|
|
||||||
router.get("/", async (req, res) => {
|
|
||||||
res.json(await papi.applications())
|
|
||||||
})
|
|
||||||
|
|
||||||
return router
|
|
||||||
}
|
|
||||||
@@ -61,6 +61,11 @@ router.all(/.*/, async (req, res, next) => {
|
|||||||
|
|
||||||
ensureProxyEnabled(req)
|
ensureProxyEnabled(req)
|
||||||
|
|
||||||
|
if (req.method === "OPTIONS" && req.args["skip-auth-preflight"]) {
|
||||||
|
// Allow preflight requests with `skip-auth-preflight` flag
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
// Must be authenticated to use the proxy.
|
// Must be authenticated to use the proxy.
|
||||||
const isAuthenticated = await authenticated(req)
|
const isAuthenticated = await authenticated(req)
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { logger } from "@coder/logger"
|
|||||||
import express from "express"
|
import express from "express"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { WebsocketRequest } from "../../../typings/pluginapi"
|
|
||||||
import { HttpCode } from "../../common/http"
|
import { HttpCode } from "../../common/http"
|
||||||
import { rootPath } from "../constants"
|
import { rootPath } from "../constants"
|
||||||
import { replaceTemplates } from "../http"
|
import { replaceTemplates } from "../http"
|
||||||
import { escapeHtml, getMediaMime } from "../util"
|
import { escapeHtml, getMediaMime } from "../util"
|
||||||
|
import type { WebsocketRequest } from "../wsRouter"
|
||||||
|
|
||||||
interface ErrorWithStatusCode {
|
interface ErrorWithStatusCode {
|
||||||
statusCode: number
|
statusCode: number
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import * as express from "express"
|
|||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as tls from "tls"
|
import * as tls from "tls"
|
||||||
import * as pluginapi from "../../../typings/pluginapi"
|
|
||||||
import { Disposable } from "../../common/emitter"
|
import { Disposable } from "../../common/emitter"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { plural } from "../../common/util"
|
import { plural } from "../../common/util"
|
||||||
@@ -12,12 +11,11 @@ import { App } from "../app"
|
|||||||
import { AuthType, DefaultedArgs } from "../cli"
|
import { AuthType, DefaultedArgs } from "../cli"
|
||||||
import { commit, rootPath } from "../constants"
|
import { commit, rootPath } from "../constants"
|
||||||
import { Heart } from "../heart"
|
import { Heart } from "../heart"
|
||||||
import { ensureAuthenticated, redirect } from "../http"
|
import { redirect } from "../http"
|
||||||
import { PluginAPI } from "../plugin"
|
|
||||||
import { CoderSettings, SettingsProvider } from "../settings"
|
import { CoderSettings, SettingsProvider } from "../settings"
|
||||||
import { UpdateProvider } from "../update"
|
import { UpdateProvider } from "../update"
|
||||||
import { getMediaMime, paths } from "../util"
|
import { getMediaMime, paths } from "../util"
|
||||||
import * as apps from "./apps"
|
import type { WebsocketRequest } from "../wsRouter"
|
||||||
import * as domainProxy from "./domainProxy"
|
import * as domainProxy from "./domainProxy"
|
||||||
import { errorHandler, wsErrorHandler } from "./errors"
|
import { errorHandler, wsErrorHandler } from "./errors"
|
||||||
import * as health from "./health"
|
import * as health from "./health"
|
||||||
@@ -81,65 +79,53 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
|||||||
app.router.use(common)
|
app.router.use(common)
|
||||||
app.wsRouter.use(common)
|
app.wsRouter.use(common)
|
||||||
|
|
||||||
app.router.use(async (req, res, next) => {
|
app.router.use(/.*/, async (req, res, next) => {
|
||||||
// If we're handling TLS ensure all requests are redirected to HTTPS.
|
// If we're handling TLS ensure all requests are redirected to HTTPS.
|
||||||
// TODO: This does *NOT* work if you have a base path since to specify the
|
// TODO: This does *NOT* work if you have a base path since to specify the
|
||||||
// protocol we need to specify the whole path.
|
// protocol we need to specify the whole path.
|
||||||
if (args.cert && !(req.connection as tls.TLSSocket).encrypted) {
|
if (args.cert && !(req.connection as tls.TLSSocket).encrypted) {
|
||||||
return res.redirect(`https://${req.headers.host}${req.originalUrl}`)
|
return res.redirect(`https://${req.headers.host}${req.originalUrl}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return security.txt.
|
|
||||||
if (req.originalUrl === "/security.txt" || req.originalUrl === "/.well-known/security.txt") {
|
|
||||||
const resourcePath = path.resolve(rootPath, "src/browser/security.txt")
|
|
||||||
res.set("Content-Type", getMediaMime(resourcePath))
|
|
||||||
return res.send(await fs.readFile(resourcePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return robots.txt.
|
|
||||||
if (req.originalUrl === "/robots.txt") {
|
|
||||||
const resourcePath = path.resolve(rootPath, "src/browser/robots.txt")
|
|
||||||
res.set("Content-Type", getMediaMime(resourcePath))
|
|
||||||
return res.send(await fs.readFile(resourcePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.router.get(["/security.txt", "/.well-known/security.txt"], async (_, res) => {
|
||||||
|
const resourcePath = path.resolve(rootPath, "src/browser/security.txt")
|
||||||
|
res.set("Content-Type", getMediaMime(resourcePath))
|
||||||
|
res.send(await fs.readFile(resourcePath))
|
||||||
|
})
|
||||||
|
|
||||||
|
app.router.get("/robots.txt", async (_, res) => {
|
||||||
|
const resourcePath = path.resolve(rootPath, "src/browser/robots.txt")
|
||||||
|
res.set("Content-Type", getMediaMime(resourcePath))
|
||||||
|
res.send(await fs.readFile(resourcePath))
|
||||||
|
})
|
||||||
|
|
||||||
app.router.use("/", domainProxy.router)
|
app.router.use("/", domainProxy.router)
|
||||||
app.wsRouter.use("/", domainProxy.wsRouter.router)
|
app.wsRouter.use("/", domainProxy.wsRouter.router)
|
||||||
|
|
||||||
app.router.all("/proxy/:port/:path(.*)?", async (req, res) => {
|
app.router.all("/proxy/:port{/*path}", async (req, res) => {
|
||||||
await pathProxy.proxy(req, res)
|
await pathProxy.proxy(req, res)
|
||||||
})
|
})
|
||||||
app.wsRouter.get("/proxy/:port/:path(.*)?", async (req) => {
|
app.wsRouter.get("/proxy/:port{/*path}", async (req) => {
|
||||||
await pathProxy.wsProxy(req as pluginapi.WebsocketRequest)
|
await pathProxy.wsProxy(req as unknown as WebsocketRequest)
|
||||||
})
|
})
|
||||||
// These two routes pass through the path directly.
|
// These two routes pass through the path directly.
|
||||||
// So the proxied app must be aware it is running
|
// So the proxied app must be aware it is running
|
||||||
// under /absproxy/<someport>/
|
// under /absproxy/<someport>/
|
||||||
app.router.all("/absproxy/:port/:path(.*)?", async (req, res) => {
|
app.router.all("/absproxy/:port{/*path}", async (req, res) => {
|
||||||
await pathProxy.proxy(req, res, {
|
await pathProxy.proxy(req, res, {
|
||||||
passthroughPath: true,
|
passthroughPath: true,
|
||||||
proxyBasePath: args["abs-proxy-base-path"],
|
proxyBasePath: args["abs-proxy-base-path"],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
app.wsRouter.get("/absproxy/:port/:path(.*)?", async (req) => {
|
app.wsRouter.get("/absproxy/:port{/*path}", async (req) => {
|
||||||
await pathProxy.wsProxy(req as pluginapi.WebsocketRequest, {
|
await pathProxy.wsProxy(req as unknown as WebsocketRequest, {
|
||||||
passthroughPath: true,
|
passthroughPath: true,
|
||||||
proxyBasePath: args["abs-proxy-base-path"],
|
proxyBasePath: args["abs-proxy-base-path"],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
let pluginApi: PluginAPI
|
|
||||||
if (!process.env.CS_DISABLE_PLUGINS) {
|
|
||||||
const workingDir = args._ && args._.length > 0 ? path.resolve(args._[args._.length - 1]) : undefined
|
|
||||||
pluginApi = new PluginAPI(logger, process.env.CS_PLUGIN, process.env.CS_PLUGIN_PATH, workingDir)
|
|
||||||
await pluginApi.loadPlugins()
|
|
||||||
pluginApi.mount(app.router, app.wsRouter)
|
|
||||||
app.router.use("/api/applications", ensureAuthenticated, apps.router(pluginApi))
|
|
||||||
}
|
|
||||||
|
|
||||||
app.router.use(express.json())
|
app.router.use(express.json())
|
||||||
app.router.use(express.urlencoded({ extended: true }))
|
app.router.use(express.urlencoded({ extended: true }))
|
||||||
|
|
||||||
@@ -172,7 +158,9 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
|||||||
|
|
||||||
app.router.use("/update", update.router)
|
app.router.use("/update", update.router)
|
||||||
|
|
||||||
// Note that the root route is replaced in Coder Enterprise by the plugin API.
|
// For historic reasons we also load at /vscode because the root was replaced
|
||||||
|
// by a plugin in v1 of Coder. The plugin system (which was for internal use
|
||||||
|
// only) has been removed, but leave the additional route for now.
|
||||||
for (const routePrefix of ["/vscode", "/"]) {
|
for (const routePrefix of ["/vscode", "/"]) {
|
||||||
app.router.use(routePrefix, vscode.router)
|
app.router.use(routePrefix, vscode.router)
|
||||||
app.wsRouter.use(routePrefix, vscode.wsRouter.router)
|
app.wsRouter.use(routePrefix, vscode.wsRouter.router)
|
||||||
@@ -187,7 +175,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
heart.dispose()
|
heart.dispose()
|
||||||
pluginApi?.dispose()
|
|
||||||
vscode.dispose()
|
vscode.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Request, Response } from "express"
|
import { Request, Response } from "express"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as pluginapi from "../../../typings/pluginapi"
|
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
|
||||||
import { proxy as _proxy } from "../proxy"
|
import { proxy as _proxy } from "../proxy"
|
||||||
|
import type { WebsocketRequest } from "../wsRouter"
|
||||||
|
|
||||||
const getProxyTarget = (
|
const getProxyTarget = (
|
||||||
req: Request,
|
req: Request,
|
||||||
@@ -13,7 +13,11 @@ const getProxyTarget = (
|
|||||||
): string => {
|
): string => {
|
||||||
// If there is a base path, strip it out.
|
// If there is a base path, strip it out.
|
||||||
const base = (req as any).base || ""
|
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(
|
export async function proxy(
|
||||||
@@ -26,7 +30,9 @@ export async function proxy(
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
ensureProxyEnabled(req)
|
ensureProxyEnabled(req)
|
||||||
|
|
||||||
if (!(await authenticated(req))) {
|
if (req.method === "OPTIONS" && req.args["skip-auth-preflight"]) {
|
||||||
|
// Allow preflight requests with `skip-auth-preflight` flag
|
||||||
|
} else if (!(await authenticated(req))) {
|
||||||
// If visiting the root (/:port only) redirect to the login page.
|
// If visiting the root (/:port only) redirect to the login page.
|
||||||
if (!req.params.path || req.params.path === "/") {
|
if (!req.params.path || req.params.path === "/") {
|
||||||
const to = self(req)
|
const to = self(req)
|
||||||
@@ -49,7 +55,7 @@ export async function proxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function wsProxy(
|
export async function wsProxy(
|
||||||
req: pluginapi.WebsocketRequest,
|
req: WebsocketRequest,
|
||||||
opts?: {
|
opts?: {
|
||||||
passthroughPath?: boolean
|
passthroughPath?: boolean
|
||||||
proxyBasePath?: string
|
proxyBasePath?: string
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ import * as express from "express"
|
|||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { WebsocketRequest } from "../../../typings/pluginapi"
|
|
||||||
import { logError } from "../../common/util"
|
import { logError } from "../../common/util"
|
||||||
import { CodeArgs, toCodeArgs } from "../cli"
|
import { CodeArgs, toCodeArgs } from "../cli"
|
||||||
import { isDevMode, vsRootPath } from "../constants"
|
import { isDevMode, vsRootPath } from "../constants"
|
||||||
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, replaceTemplates, self } from "../http"
|
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, replaceTemplates, self } from "../http"
|
||||||
import { SocketProxyProvider } from "../socket"
|
import { SocketProxyProvider } from "../socket"
|
||||||
import { isFile } from "../util"
|
import { isFile } from "../util"
|
||||||
import { Router as WsRouter } from "../wsRouter"
|
import { type WebsocketRequest, Router as WsRouter } from "../wsRouter"
|
||||||
|
|
||||||
export const router = express.Router()
|
export const router = express.Router()
|
||||||
|
|
||||||
@@ -58,7 +58,11 @@ async function loadVSCode(req: express.Request): Promise<IVSCodeServerAPI> {
|
|||||||
// which will also require that we switch to ESM, since a hybrid approach
|
// which will also require that we switch to ESM, since a hybrid approach
|
||||||
// breaks importing `rotating-file-stream` for some reason. To work around
|
// breaks importing `rotating-file-stream` for some reason. To work around
|
||||||
// this, use `eval` for now, but we should consider switching to ESM.
|
// this, use `eval` for now, but we should consider switching to ESM.
|
||||||
const modPath = path.join(vsRootPath, "out/server-main.js")
|
let modPath = path.join(vsRootPath, "out/server-main.js")
|
||||||
|
if (os.platform() === "win32") {
|
||||||
|
// On Windows, absolute paths of ESM modules must be a valid file URI.
|
||||||
|
modPath = "file:///" + modPath.replace(/\\/g, "/")
|
||||||
|
}
|
||||||
const mod = (await eval(`import("${modPath}")`)) as VSCodeModule
|
const mod = (await eval(`import("${modPath}")`)) as VSCodeModule
|
||||||
const serverModule = await mod.loadCodeWithNls()
|
const serverModule = await mod.loadCodeWithNls()
|
||||||
return serverModule.createServer(null, {
|
return serverModule.createServer(null, {
|
||||||
@@ -171,7 +175,7 @@ router.get("/manifest.json", async (req, res) => {
|
|||||||
const appName = req.args["app-name"] || "code-server"
|
const appName = req.args["app-name"] || "code-server"
|
||||||
res.writeHead(200, { "Content-Type": "application/manifest+json" })
|
res.writeHead(200, { "Content-Type": "application/manifest+json" })
|
||||||
|
|
||||||
return res.end(
|
res.end(
|
||||||
replaceTemplates(
|
replaceTemplates(
|
||||||
req,
|
req,
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class SettingsProvider<T> {
|
|||||||
public async read(): Promise<T> {
|
public async read(): Promise<T> {
|
||||||
try {
|
try {
|
||||||
const raw = (await fs.readFile(this.settingsPath, "utf8")).trim()
|
const raw = (await fs.readFile(this.settingsPath, "utf8")).trim()
|
||||||
return raw ? JSON.parse(raw) : {}
|
return raw ? JSON.parse(raw) : ({} as T)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.code !== "ENOENT") {
|
if (error.code !== "ENOENT") {
|
||||||
logger.warn(error.message)
|
logger.warn(error.message)
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import * as expressCore from "express-serve-static-core"
|
import * as expressCore from "express-serve-static-core"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
|
import * as stream from "stream"
|
||||||
import Websocket from "ws"
|
import Websocket from "ws"
|
||||||
import * as pluginapi from "../../typings/pluginapi"
|
|
||||||
|
export interface WebsocketRequest extends express.Request {
|
||||||
|
ws: stream.Duplex
|
||||||
|
head: Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InternalWebsocketRequest extends WebsocketRequest {
|
||||||
|
_ws_handled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export const handleUpgrade = (app: express.Express, server: http.Server): void => {
|
export const handleUpgrade = (app: express.Express, server: http.Server): void => {
|
||||||
server.on("upgrade", (req, socket, head) => {
|
server.on("upgrade", (req, socket, head) => {
|
||||||
@@ -22,9 +31,11 @@ export const handleUpgrade = (app: express.Express, server: http.Server): void =
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InternalWebsocketRequest extends pluginapi.WebsocketRequest {
|
export type WebSocketHandler = (
|
||||||
_ws_handled: boolean
|
req: WebsocketRequest,
|
||||||
}
|
res: express.Response,
|
||||||
|
next: express.NextFunction,
|
||||||
|
) => void | Promise<void>
|
||||||
|
|
||||||
export class WebsocketRouter {
|
export class WebsocketRouter {
|
||||||
public readonly router = express.Router()
|
public readonly router = express.Router()
|
||||||
@@ -36,13 +47,13 @@ export class WebsocketRouter {
|
|||||||
* If the origin header exists it must match the host or the connection will
|
* If the origin header exists it must match the host or the connection will
|
||||||
* be prevented.
|
* be prevented.
|
||||||
*/
|
*/
|
||||||
public ws(route: expressCore.PathParams, ...handlers: pluginapi.WebSocketHandler[]): void {
|
public ws(route: expressCore.PathParams, ...handlers: WebSocketHandler[]): void {
|
||||||
this.router.get(
|
this.router.get(
|
||||||
route,
|
route,
|
||||||
...handlers.map((handler) => {
|
...handlers.map((handler) => {
|
||||||
const wrapped: express.Handler = (req, res, next) => {
|
const wrapped: express.Handler = (req, res, next) => {
|
||||||
;(req as InternalWebsocketRequest)._ws_handled = true
|
;(req as InternalWebsocketRequest)._ws_handled = true
|
||||||
return handler(req as pluginapi.WebsocketRequest, res, next)
|
return handler(req as WebsocketRequest, res, next)
|
||||||
}
|
}
|
||||||
return wrapped
|
return wrapped
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,7 +1,26 @@
|
|||||||
import { clean, getMaybeProxiedPathname } from "../utils/helpers"
|
import { clean, getMaybeProxiedPathname } from "../utils/helpers"
|
||||||
import { describe, test, expect } from "./baseFixture"
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
const routes = ["/", "/vscode", "/vscode/"]
|
const routes = {
|
||||||
|
"/": [
|
||||||
|
/\.\/manifest.json/,
|
||||||
|
/\.\/_static\//,
|
||||||
|
/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
/http:\/\/localhost:[0-9]+\/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
],
|
||||||
|
"/vscode": [
|
||||||
|
/\.\/vscode\/manifest.json/,
|
||||||
|
/\.\/_static\//,
|
||||||
|
/vscode\/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
/http:\/\/localhost:[0-9]+\/vscode\/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
],
|
||||||
|
"/vscode/": [
|
||||||
|
/\.\/manifest.json/,
|
||||||
|
/\.\/\.\.\/_static\//,
|
||||||
|
/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
/http:\/\/localhost:[0-9]+\/vscode\/[a-z]+-[0-9a-z]+\/static\//,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
describe("VS Code Routes", ["--disable-workspace-trust"], {}, async () => {
|
describe("VS Code Routes", ["--disable-workspace-trust"], {}, async () => {
|
||||||
const testName = "vscode-routes-default"
|
const testName = "vscode-routes-default"
|
||||||
@@ -10,7 +29,7 @@ describe("VS Code Routes", ["--disable-workspace-trust"], {}, async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("should load all route variations", async ({ codeServerPage }) => {
|
test("should load all route variations", async ({ codeServerPage }) => {
|
||||||
for (const route of routes) {
|
for (const [route, matchers] of Object.entries(routes)) {
|
||||||
await codeServerPage.navigate(route)
|
await codeServerPage.navigate(route)
|
||||||
|
|
||||||
// Check there were no redirections
|
// Check there were no redirections
|
||||||
@@ -18,21 +37,16 @@ describe("VS Code Routes", ["--disable-workspace-trust"], {}, async () => {
|
|||||||
const pathname = getMaybeProxiedPathname(url)
|
const pathname = getMaybeProxiedPathname(url)
|
||||||
expect(pathname).toBe(route)
|
expect(pathname).toBe(route)
|
||||||
|
|
||||||
// TODO@jsjoeio
|
// Check that assets are pointing to the right spot. Some will be
|
||||||
// now that we are in a proper browser instead of scraping the HTML we
|
// relative, without a leading dot (VS Code's assets). Some will be
|
||||||
// could possibly intercept requests to make sure assets are loading from
|
// relative with a leading dot (our assets). Others will have been
|
||||||
// the right spot.
|
// resolved against the origin.
|
||||||
//
|
const elements = await codeServerPage.page.locator("[src]").all()
|
||||||
// Check that page loaded from correct route
|
for (const element of elements) {
|
||||||
const html = await codeServerPage.page.innerHTML("html")
|
const src = await element.getAttribute("src")
|
||||||
switch (route) {
|
if (src && !matchers.some((m) => m.test(src))) {
|
||||||
case "/":
|
throw new Error(`${src} did not match any validators for route ${route}`)
|
||||||
case "/vscode/":
|
}
|
||||||
expect(html).toMatch(/src="\.\/[a-z]+-[0-9a-z]+\/static\//)
|
|
||||||
break
|
|
||||||
case "/vscode":
|
|
||||||
expect(html).toMatch(/src="\.\/vscode\/[a-z]+-[0-9a-z]+\/static\//)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -85,7 +99,7 @@ describe("VS Code Routes with no workspace or folder", ["--disable-workspace-tru
|
|||||||
|
|
||||||
// If you visit again without query parameters it will re-attach them by
|
// If you visit again without query parameters it will re-attach them by
|
||||||
// redirecting. It should always redirect to the same route.
|
// redirecting. It should always redirect to the same route.
|
||||||
for (const route of routes) {
|
for (const route of Object.keys(routes)) {
|
||||||
await codeServerPage.navigate(route)
|
await codeServerPage.navigate(route)
|
||||||
const url = new URL(codeServerPage.page.url())
|
const url = new URL(codeServerPage.page.url())
|
||||||
const pathname = getMaybeProxiedPathname(url)
|
const pathname = getMaybeProxiedPathname(url)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"include": ["./**/*.ts"],
|
"include": ["./**/*.ts"]
|
||||||
"exclude": ["./unit/node/test-plugin"]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
bindAddrFromArgs,
|
bindAddrFromArgs,
|
||||||
defaultConfigFile,
|
defaultConfigFile,
|
||||||
parse,
|
parse,
|
||||||
|
parseConfigFile,
|
||||||
setDefaults,
|
setDefaults,
|
||||||
shouldOpenInExistingInstance,
|
shouldOpenInExistingInstance,
|
||||||
toCodeArgs,
|
toCodeArgs,
|
||||||
@@ -108,6 +109,8 @@ describe("parser", () => {
|
|||||||
|
|
||||||
["--abs-proxy-base-path", "/codeserver/app1"],
|
["--abs-proxy-base-path", "/codeserver/app1"],
|
||||||
|
|
||||||
|
"--skip-auth-preflight",
|
||||||
|
|
||||||
["--session-socket", "/tmp/override-code-server-ipc-socket"],
|
["--session-socket", "/tmp/override-code-server-ipc-socket"],
|
||||||
|
|
||||||
["--host", "0.0.0.0"],
|
["--host", "0.0.0.0"],
|
||||||
@@ -146,6 +149,7 @@ describe("parser", () => {
|
|||||||
"bind-addr": "192.169.0.1:8080",
|
"bind-addr": "192.169.0.1:8080",
|
||||||
"session-socket": "/tmp/override-code-server-ipc-socket",
|
"session-socket": "/tmp/override-code-server-ipc-socket",
|
||||||
"abs-proxy-base-path": "/codeserver/app1",
|
"abs-proxy-base-path": "/codeserver/app1",
|
||||||
|
"skip-auth-preflight": true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -284,12 +288,17 @@ describe("parser", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("should support repeatable flags", async () => {
|
it("should support repeatable flags", async () => {
|
||||||
|
expect(() => parse(["--proxy-domain", ""])).toThrowError(/--proxy-domain requires a value/)
|
||||||
expect(parse(["--proxy-domain", "*.coder.com"])).toEqual({
|
expect(parse(["--proxy-domain", "*.coder.com"])).toEqual({
|
||||||
"proxy-domain": ["*.coder.com"],
|
"proxy-domain": ["*.coder.com"],
|
||||||
})
|
})
|
||||||
expect(parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"])).toEqual({
|
expect(parse(["--proxy-domain", "*.coder.com", "--proxy-domain", "test.com"])).toEqual({
|
||||||
"proxy-domain": ["*.coder.com", "test.com"],
|
"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 () => {
|
it("should enforce cert-key with cert value or otherwise generate one", async () => {
|
||||||
@@ -487,6 +496,20 @@ describe("parser", () => {
|
|||||||
}),
|
}),
|
||||||
).toThrowError(expectedErrMsg)
|
).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 () => {
|
it("should ignore optional strings set to false", async () => {
|
||||||
expect(parse(["--cert=false"])).toEqual({})
|
expect(parse(["--cert=false"])).toEqual({})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
import { logger } from "@coder/logger"
|
|
||||||
import * as express from "express"
|
|
||||||
import * as fs from "fs"
|
|
||||||
import * as path from "path"
|
|
||||||
import { HttpCode } from "../../../src/common/http"
|
|
||||||
import { AuthType } from "../../../src/node/cli"
|
|
||||||
import { codeServer, PluginAPI } from "../../../src/node/plugin"
|
|
||||||
import * as apps from "../../../src/node/routes/apps"
|
|
||||||
import * as httpserver from "../../utils/httpserver"
|
|
||||||
const fsp = fs.promises
|
|
||||||
|
|
||||||
// Jest overrides `require` so our usual override doesn't work.
|
|
||||||
jest.mock("code-server", () => codeServer, { virtual: true })
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use $LOG_LEVEL=debug to see debug logs.
|
|
||||||
*/
|
|
||||||
describe("plugin", () => {
|
|
||||||
let papi: PluginAPI
|
|
||||||
let s: httpserver.HttpServer
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
// Only include the test plugin to avoid contaminating results with other
|
|
||||||
// plugins that might be on the filesystem.
|
|
||||||
papi = new PluginAPI(logger, `${path.resolve(__dirname, "test-plugin")}:meow`, "")
|
|
||||||
await papi.loadPlugins(false)
|
|
||||||
|
|
||||||
const app = express.default()
|
|
||||||
const wsApp = express.default()
|
|
||||||
|
|
||||||
const common: express.RequestHandler = (req, _, next) => {
|
|
||||||
// Routes might use these arguments.
|
|
||||||
req.args = {
|
|
||||||
_: [],
|
|
||||||
auth: AuthType.None,
|
|
||||||
host: "localhost",
|
|
||||||
port: 8080,
|
|
||||||
"proxy-domain": [],
|
|
||||||
config: "~/.config/code-server/config.yaml",
|
|
||||||
verbose: false,
|
|
||||||
"disable-file-downloads": false,
|
|
||||||
usingEnvPassword: false,
|
|
||||||
usingEnvHashedPassword: false,
|
|
||||||
"extensions-dir": "",
|
|
||||||
"user-data-dir": "",
|
|
||||||
"session-socket": "",
|
|
||||||
}
|
|
||||||
next()
|
|
||||||
}
|
|
||||||
|
|
||||||
app.use(common)
|
|
||||||
wsApp.use(common)
|
|
||||||
|
|
||||||
papi.mount(app, wsApp)
|
|
||||||
app.use("/api/applications", apps.router(papi))
|
|
||||||
|
|
||||||
s = new httpserver.HttpServer()
|
|
||||||
await s.listen(app)
|
|
||||||
s.listenUpgrade(wsApp)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
await s.dispose()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("/api/applications", async () => {
|
|
||||||
const resp = await s.fetch("/api/applications")
|
|
||||||
expect(resp.status).toBe(200)
|
|
||||||
const body = await resp.json()
|
|
||||||
logger.debug(`${JSON.stringify(body)}`)
|
|
||||||
expect(body).toStrictEqual([
|
|
||||||
{
|
|
||||||
name: "Test App",
|
|
||||||
version: "4.0.1",
|
|
||||||
|
|
||||||
description: "This app does XYZ.",
|
|
||||||
iconPath: "/test-plugin/test-app/icon.svg",
|
|
||||||
homepageURL: "https://example.com",
|
|
||||||
path: "/test-plugin/test-app",
|
|
||||||
|
|
||||||
plugin: {
|
|
||||||
name: "test-plugin",
|
|
||||||
version: "1.0.0",
|
|
||||||
modulePath: path.join(__dirname, "test-plugin"),
|
|
||||||
|
|
||||||
displayName: "Test Plugin",
|
|
||||||
description: "Plugin used in code-server tests.",
|
|
||||||
routerPath: "/test-plugin",
|
|
||||||
homepageURL: "https://example.com",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it("/test-plugin/test-app", async () => {
|
|
||||||
const indexHTML = await fsp.readFile(path.join(__dirname, "test-plugin/public/index.html"), {
|
|
||||||
encoding: "utf8",
|
|
||||||
})
|
|
||||||
const resp = await s.fetch("/test-plugin/test-app")
|
|
||||||
expect(resp.status).toBe(200)
|
|
||||||
const body = await resp.text()
|
|
||||||
expect(body).toBe(indexHTML)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("/test-plugin/test-app (websocket)", async () => {
|
|
||||||
const ws = s.ws("/test-plugin/test-app")
|
|
||||||
const message = await new Promise((resolve) => {
|
|
||||||
ws.once("message", (message) => resolve(message))
|
|
||||||
})
|
|
||||||
ws.terminate()
|
|
||||||
expect(message).toBe("hello")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("/test-plugin/error", async () => {
|
|
||||||
const resp = await s.fetch("/test-plugin/error")
|
|
||||||
expect(resp.status).toBe(HttpCode.LargePayload)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -268,6 +268,21 @@ describe("proxy", () => {
|
|||||||
const text = await resp.text()
|
const text = await resp.text()
|
||||||
expect(text).toBe("app being served behind a prefixed path")
|
expect(text).toBe("app being served behind a prefixed path")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should not allow OPTIONS without authentication by default", async () => {
|
||||||
|
process.env.PASSWORD = "test"
|
||||||
|
codeServer = await integration.setup(["--auth=password"])
|
||||||
|
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
|
||||||
|
expect(resp.status).toBe(401)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should allow OPTIONS with `skip-auth-preflight` flag", async () => {
|
||||||
|
process.env.PASSWORD = "test"
|
||||||
|
codeServer = await integration.setup(["--auth=password", "--skip-auth-preflight"])
|
||||||
|
e.post("/wsup", (req, res) => {})
|
||||||
|
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
|
||||||
|
expect(resp.status).toBe(200)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// NOTE@jsjoeio
|
// NOTE@jsjoeio
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ describe("settings", () => {
|
|||||||
const settings = new SettingsProvider<CoderSettings>(pathToMockSettingsFile)
|
const settings = new SettingsProvider<CoderSettings>(pathToMockSettingsFile)
|
||||||
await settings.read()
|
await settings.read()
|
||||||
// This happens when we can't parse a JSON (usually error in file)
|
// 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", () => {
|
describe("with invalid settings file path", () => {
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
settings: {
|
|
||||||
"import/resolver": {
|
|
||||||
typescript: {
|
|
||||||
project: __dirname,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
1
test/unit/node/test-plugin/.gitignore
vendored
1
test/unit/node/test-plugin/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
out
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
out/index.js: src/index.ts
|
|
||||||
# Typescript always emits, even on errors.
|
|
||||||
npm run build || rm out/index.js
|
|
||||||
|
|
||||||
node_modules: package.json package-lock.json
|
|
||||||
npm install
|
|
||||||
90
test/unit/node/test-plugin/package-lock.json
generated
90
test/unit/node/test-plugin/package-lock.json
generated
@@ -1,90 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "test-plugin",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"requires": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/body-parser": {
|
|
||||||
"version": "1.19.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
|
|
||||||
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
|
|
||||||
"requires": {
|
|
||||||
"@types/connect": "*",
|
|
||||||
"@types/node": "*"
|
|
||||||
},
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/connect": {
|
|
||||||
"version": "3.4.33",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
|
|
||||||
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
|
|
||||||
"requires": {
|
|
||||||
"@types/node": "*"
|
|
||||||
},
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/express": {
|
|
||||||
"version": "4.17.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz",
|
|
||||||
"integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==",
|
|
||||||
"requires": {
|
|
||||||
"@types/body-parser": "*",
|
|
||||||
"@types/express-serve-static-core": "*",
|
|
||||||
"@types/qs": "*",
|
|
||||||
"@types/serve-static": "*"
|
|
||||||
},
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/express-serve-static-core": {
|
|
||||||
"version": "4.17.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz",
|
|
||||||
"integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==",
|
|
||||||
"requires": {
|
|
||||||
"@types/node": "*",
|
|
||||||
"@types/qs": "*",
|
|
||||||
"@types/range-parser": "*"
|
|
||||||
},
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/mime": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/node": {
|
|
||||||
"version": "14.14.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.6.tgz",
|
|
||||||
"integrity": "sha512-6QlRuqsQ/Ox/aJEQWBEJG7A9+u7oSYl3mem/K8IzxXG/kAGbV1YPD9Bg9Zw3vyxC/YP+zONKwy8hGkSt1jxFMw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/qs": {
|
|
||||||
"version": "6.9.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz",
|
|
||||||
"integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/range-parser": {
|
|
||||||
"version": "1.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
|
||||||
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"@types/serve-static": {
|
|
||||||
"version": "1.13.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.6.tgz",
|
|
||||||
"integrity": "sha512-nuRJmv7jW7VmCVTn+IgYDkkbbDGyIINOeu/G0d74X3lm6E5KfMeQPJhxIt1ayQeQB3cSxvYs1RA/wipYoFB4EA==",
|
|
||||||
"requires": {
|
|
||||||
"@types/mime": "*",
|
|
||||||
"@types/node": "*"
|
|
||||||
},
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"typescript": {
|
|
||||||
"version": "4.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz",
|
|
||||||
"integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"private": true,
|
|
||||||
"name": "test-plugin",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"engines": {
|
|
||||||
"code-server": "*"
|
|
||||||
},
|
|
||||||
"main": "out/index.js",
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/express": "^4.17.8",
|
|
||||||
"typescript": "^4.0.5"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg width="121" height="131" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="9.612%" y1="66.482%" x2="89.899%" y2="33.523%" id="a"><stop stop-color="#FCEE39" offset="0%"/><stop stop-color="#F37B3D" offset="100%"/></linearGradient><linearGradient x1="8.601%" y1="15.03%" x2="99.641%" y2="89.058%" id="b"><stop stop-color="#EF5A6B" offset="0%"/><stop stop-color="#F26F4E" offset="57%"/><stop stop-color="#F37B3D" offset="100%"/></linearGradient><linearGradient x1="90.118%" y1="69.931%" x2="17.938%" y2="38.628%" id="c"><stop stop-color="#7C59A4" offset="0%"/><stop stop-color="#AF4C92" offset="38.52%"/><stop stop-color="#DC4183" offset="76.54%"/><stop stop-color="#ED3D7D" offset="95.7%"/></linearGradient><linearGradient x1="91.376%" y1="19.144%" x2="18.895%" y2="70.21%" id="d"><stop stop-color="#EF5A6B" offset="0%"/><stop stop-color="#EE4E72" offset="36.4%"/><stop stop-color="#ED3D7D" offset="100%"/></linearGradient></defs><g fill="none"><path d="M118.623 71.8c.9-.8 1.4-1.9 1.5-3.2.1-2.6-1.8-4.7-4.4-4.9-1.2-.1-2.4.4-3.3 1.1l-83.8 45.9c-1.9.8-3.6 2.2-4.7 4.1-2.9 4.8-1.3 11 3.6 13.9 3.4 2 7.5 1.8 10.7-.2.2-.2.5-.3.7-.5l78-54.8c.4-.3 1.5-1.1 1.7-1.4z" fill="url(#a)" transform="translate(-.023)"/><path d="M118.823 65.1l-63.8-62.6c-1.4-1.5-3.4-2.5-5.7-2.5-4.3 0-7.7 3.5-7.7 7.7 0 2.1.8 3.9 2.1 5.3.4.4.8.7 1.2 1l67.4 57.7c.8.7 1.8 1.2 3 1.3 2.6.1 4.7-1.8 4.9-4.4 0-1.3-.5-2.6-1.4-3.5z" fill="url(#b)" transform="translate(-.023)"/><path d="M57.123 59.5c-.1 0-39.4-31-40.2-31.5l-1.8-.9c-5.8-2.2-12.2.8-14.4 6.6-1.9 5.1.2 10.7 4.6 13.4.7.4 1.3.7 2 .9.4.2 45.4 18.8 45.4 18.8 1.8.8 3.9.3 5.1-1.2 1.5-1.9 1.2-4.6-.7-6.1z" fill="url(#c)" transform="translate(-.023)"/><path d="M49.323 0c-1.7 0-3.3.6-4.6 1.5l-39.8 26.8c-.1.1-.2.1-.2.2h-.1c-1.7 1.2-3.1 3-3.9 5.1-2.2 5.8.8 12.3 6.6 14.4 3.6 1.4 7.5.7 10.4-1.4.7-.5 1.3-1 1.8-1.6l34.6-31.2c1.8-1.4 3-3.6 3-6.1 0-4.2-3.5-7.7-7.8-7.7z" fill="url(#d)" transform="translate(-.023)"/><path fill="#000" d="M34.6 37.4h51v51h-51z"/><path fill="#FFF" d="M39 78.8h19.1V82H39zm-.2-28l1.5-1.4c.4.5.8.8 1.3.8.6 0 .9-.4.9-1.2v-5.3h2.3V49c0 1-.3 1.8-.8 2.3-.5.5-1.3.8-2.3.8-1.5.1-2.3-.5-2.9-1.3zm6.5-7H52v1.9h-4.4V47h4v1.8h-4v1.3h4.5v2h-6.7zm9.7 2h-2.5v-2h7.3v2h-2.5v6.3H55zM39 54h4.3c1 0 1.8.3 2.3.7.3.3.5.8.5 1.4 0 1-.5 1.5-1.3 1.9 1 .3 1.6.9 1.6 2 0 1.4-1.2 2.3-3.1 2.3H39V54zm4.8 2.6c0-.5-.4-.7-1-.7h-1.5v1.5h1.4c.7-.1 1.1-.3 1.1-.8zM43 59h-1.8v1.5H43c.7 0 1.1-.3 1.1-.8s-.4-.7-1.1-.7zm3.8-5h3.9c1.3 0 2.1.3 2.7.9.5.5.7 1.1.7 1.9 0 1.3-.7 2.1-1.7 2.6l2 2.9h-2.6l-1.7-2.5h-1v2.5h-2.3V54zm3.8 4c.8 0 1.2-.4 1.2-1 0-.7-.5-1-1.2-1h-1.5v2h1.5z"/><path d="M56.8 54H59l3.5 8.4H60l-.6-1.5h-3.2l-.6 1.5h-2.4l3.6-8.4zm2 5l-.9-2.3L57 59h1.8zm4-5h2.3v8.3h-2.3zm2.9 0h2.1l3.4 4.4V54h2.3v8.3h-2L68 57.8v4.6h-2.3zm8 7.1l1.3-1.5c.8.7 1.7 1 2.7 1 .6 0 1-.2 1-.6 0-.4-.3-.5-1.4-.8-1.8-.4-3.1-.9-3.1-2.6 0-1.5 1.2-2.7 3.2-2.7 1.4 0 2.5.4 3.4 1.1l-1.2 1.6c-.8-.5-1.6-.8-2.3-.8-.6 0-.8.2-.8.5 0 .4.3.5 1.4.8 1.9.4 3.1 1 3.1 2.6 0 1.7-1.3 2.7-3.4 2.7-1.5.1-2.9-.4-3.9-1.3z" fill="#FFF"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Test Plugin</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Welcome to the test plugin!</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import * as cs from "code-server"
|
|
||||||
import * as fspath from "path"
|
|
||||||
|
|
||||||
export const plugin: cs.Plugin = {
|
|
||||||
displayName: "Test Plugin",
|
|
||||||
routerPath: "/test-plugin",
|
|
||||||
homepageURL: "https://example.com",
|
|
||||||
description: "Plugin used in code-server tests.",
|
|
||||||
|
|
||||||
init(config) {
|
|
||||||
config.logger.debug("test-plugin loaded!")
|
|
||||||
},
|
|
||||||
|
|
||||||
router() {
|
|
||||||
const r = cs.express.Router()
|
|
||||||
r.get("/test-app", (_, res) => {
|
|
||||||
res.sendFile(fspath.resolve(__dirname, "../public/index.html"))
|
|
||||||
})
|
|
||||||
r.get("/goland/icon.svg", (_, res) => {
|
|
||||||
res.sendFile(fspath.resolve(__dirname, "../public/icon.svg"))
|
|
||||||
})
|
|
||||||
r.get("/error", () => {
|
|
||||||
throw new cs.HttpError("error", cs.HttpCode.LargePayload)
|
|
||||||
})
|
|
||||||
return r
|
|
||||||
},
|
|
||||||
|
|
||||||
wsRouter() {
|
|
||||||
const wr = cs.WsRouter()
|
|
||||||
wr.ws("/test-app", (req) => {
|
|
||||||
cs.wss.handleUpgrade(req, req.ws, req.head, (ws) => {
|
|
||||||
req.ws.resume()
|
|
||||||
ws.send("hello")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return wr
|
|
||||||
},
|
|
||||||
|
|
||||||
applications() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: "Test App",
|
|
||||||
version: "4.0.1",
|
|
||||||
iconPath: "/icon.svg",
|
|
||||||
path: "/test-app",
|
|
||||||
|
|
||||||
description: "This app does XYZ.",
|
|
||||||
homepageURL: "https://example.com",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
|
||||||
|
|
||||||
/* Basic Options */
|
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
|
||||||
"target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
|
|
||||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
|
|
||||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
|
||||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
|
||||||
"outDir": "./out" /* Redirect output structure to the directory. */,
|
|
||||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
|
||||||
// "composite": true, /* Enable project compilation */
|
|
||||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
|
||||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
"strict": true /* Enable all strict type-checking options. */,
|
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
|
||||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
|
||||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
|
||||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
|
||||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
|
||||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
|
|
||||||
/* Module Resolution Options */
|
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
|
||||||
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
|
|
||||||
"paths": {
|
|
||||||
"code-server": ["../../../../typings/pluginapi"]
|
|
||||||
} /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */,
|
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
|
||||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
|
||||||
|
|
||||||
/* Source Map Options */
|
|
||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
|
||||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
|
||||||
|
|
||||||
/* Experimental Options */
|
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
|
||||||
|
|
||||||
/* Advanced Options */
|
|
||||||
"skipLibCheck": true /* Skip type checking of declaration files. */,
|
|
||||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
297
typings/pluginapi.d.ts
vendored
297
typings/pluginapi.d.ts
vendored
@@ -1,297 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file describes the code-server plugin API for adding new applications.
|
|
||||||
*/
|
|
||||||
import { field, Level, Logger } from "@coder/logger"
|
|
||||||
import * as express from "express"
|
|
||||||
import * as expressCore from "express-serve-static-core"
|
|
||||||
import ProxyServer from "http-proxy"
|
|
||||||
import * as stream from "stream"
|
|
||||||
import Websocket from "ws"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overlay
|
|
||||||
*
|
|
||||||
* The homepage of code-server will launch into VS Code. However, there will be an overlay
|
|
||||||
* button that when clicked, will show all available applications with their names,
|
|
||||||
* icons and provider plugins. When one clicks on an app's icon, they will be directed
|
|
||||||
* to <code-server-root>/<plugin-path>/<app-path> to access the application.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugins
|
|
||||||
*
|
|
||||||
* Plugins are just node modules that contain a top level export "plugin" that implements
|
|
||||||
* the Plugin interface.
|
|
||||||
*
|
|
||||||
* 1. code-server uses $CS_PLUGIN to find plugins.
|
|
||||||
*
|
|
||||||
* e.g. CS_PLUGIN=/tmp/will:/tmp/teffen will cause code-server to load
|
|
||||||
* /tmp/will and /tmp/teffen as plugins.
|
|
||||||
*
|
|
||||||
* 2. code-server uses $CS_PLUGIN_PATH to find plugins. Each subdirectory in
|
|
||||||
* $CS_PLUGIN_PATH with a package.json where the engine is code-server is
|
|
||||||
* a valid plugin.
|
|
||||||
*
|
|
||||||
* e.g. CS_PLUGIN_PATH=/tmp/nhooyr:/tmp/ash will cause code-server to search
|
|
||||||
* /tmp/nhooyr and then /tmp/ash for plugins.
|
|
||||||
*
|
|
||||||
* CS_PLUGIN_PATH defaults to
|
|
||||||
* ~/.local/share/code-server/plugins:/usr/share/code-server/plugins
|
|
||||||
* if unset.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 3. Built in plugins are loaded from __dirname/../plugins
|
|
||||||
*
|
|
||||||
* Plugins are required as soon as they are found and then initialized.
|
|
||||||
* See the Plugin interface for details.
|
|
||||||
*
|
|
||||||
* If two plugins are found with the exact same name, then code-server will
|
|
||||||
* use the first one and emit a warning.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Programmability
|
|
||||||
*
|
|
||||||
* There is also a /api/applications endpoint to allow programmatic access to all
|
|
||||||
* available applications. It could be used to create a custom application dashboard
|
|
||||||
* for example. An important difference with the API is that all application paths
|
|
||||||
* will be absolute (i.e have the plugin path prepended) so that they may be used
|
|
||||||
* directly.
|
|
||||||
*
|
|
||||||
* Example output:
|
|
||||||
*
|
|
||||||
* [
|
|
||||||
* {
|
|
||||||
* "name": "Test App",
|
|
||||||
* "version": "4.0.1",
|
|
||||||
* "iconPath": "/test-plugin/test-app/icon.svg",
|
|
||||||
* "path": "/test-plugin/test-app",
|
|
||||||
* "description": "This app does XYZ.",
|
|
||||||
* "homepageURL": "https://example.com",
|
|
||||||
* "plugin": {
|
|
||||||
* "name": "test-plugin",
|
|
||||||
* "version": "1.0.0",
|
|
||||||
* "modulePath": "/Users/nhooyr/src/coder/code-server/test/test-plugin",
|
|
||||||
* "displayName": "Test Plugin",
|
|
||||||
* "description": "Plugin used in code-server tests.",
|
|
||||||
* "routerPath": "/test-plugin",
|
|
||||||
* "homepageURL": "https://example.com"
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
|
|
||||||
export enum HttpCode {
|
|
||||||
Ok = 200,
|
|
||||||
Redirect = 302,
|
|
||||||
NotFound = 404,
|
|
||||||
BadRequest = 400,
|
|
||||||
Unauthorized = 401,
|
|
||||||
LargePayload = 413,
|
|
||||||
ServerError = 500,
|
|
||||||
}
|
|
||||||
|
|
||||||
export declare class HttpError extends Error {
|
|
||||||
constructor(message: string, status: HttpCode, details?: object)
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebsocketRequest extends express.Request {
|
|
||||||
ws: stream.Duplex
|
|
||||||
head: Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
export type WebSocketHandler = (
|
|
||||||
req: WebsocketRequest,
|
|
||||||
res: express.Response,
|
|
||||||
next: express.NextFunction,
|
|
||||||
) => void | Promise<void>
|
|
||||||
|
|
||||||
export interface WebsocketRouter {
|
|
||||||
readonly router: express.Router
|
|
||||||
ws(route: expressCore.PathParams, ...handlers: WebSocketHandler[]): void
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a router for websocket routes.
|
|
||||||
*/
|
|
||||||
export function WsRouter(): WebsocketRouter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The websocket server used by code-server.
|
|
||||||
*/
|
|
||||||
export const wss: Websocket.Server
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Express import used by code-server.
|
|
||||||
*
|
|
||||||
* Re-exported so plugins don't have to import duplicate copies of Express and
|
|
||||||
* to avoid potential version differences or issues caused by running separate
|
|
||||||
* instances.
|
|
||||||
*/
|
|
||||||
export { express }
|
|
||||||
/**
|
|
||||||
* Use to add a field to a log.
|
|
||||||
*
|
|
||||||
* Re-exported so plugins don't have to import duplicate copies of the logger.
|
|
||||||
*/
|
|
||||||
export { field, Level, Logger }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* code-server's proxy server.
|
|
||||||
*/
|
|
||||||
export const proxy: ProxyServer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Middleware to ensure the user is authenticated. Throws if they are not.
|
|
||||||
*/
|
|
||||||
export function ensureAuthenticated(
|
|
||||||
req: express.Request,
|
|
||||||
res?: express.Response,
|
|
||||||
next?: express.NextFunction,
|
|
||||||
): Promise<void>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the user is authenticated.
|
|
||||||
*/
|
|
||||||
export function authenticated(req: express.Request): Promise<void>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace variables in HTML: TO, BASE, CS_STATIC_BASE, and OPTIONS.
|
|
||||||
*/
|
|
||||||
export function replaceTemplates<T extends object>(
|
|
||||||
req: express.Request,
|
|
||||||
content: string,
|
|
||||||
extraOpts?: Omit<T, "base" | "csStaticBase" | "logLevel">,
|
|
||||||
): string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Your plugin module must have a top level export "plugin" that implements this interface.
|
|
||||||
*
|
|
||||||
* The plugin's router will be mounted at <code-sever-root>/<plugin-path>
|
|
||||||
*/
|
|
||||||
export interface Plugin {
|
|
||||||
/**
|
|
||||||
* name is used as the plugin's unique identifier.
|
|
||||||
* No two plugins may share the same name.
|
|
||||||
*
|
|
||||||
* Fetched from package.json.
|
|
||||||
*/
|
|
||||||
readonly name?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version for the plugin in the overlay.
|
|
||||||
*
|
|
||||||
* Fetched from package.json.
|
|
||||||
*/
|
|
||||||
readonly version?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name used in the overlay.
|
|
||||||
*/
|
|
||||||
readonly displayName: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used in overlay.
|
|
||||||
* Should be a full sentence describing the plugin.
|
|
||||||
*/
|
|
||||||
readonly description: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path at which the plugin router is to be registered.
|
|
||||||
*/
|
|
||||||
readonly routerPath: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to plugin homepage.
|
|
||||||
*/
|
|
||||||
readonly homepageURL: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* init is called so that the plugin may initialize itself with the config.
|
|
||||||
*/
|
|
||||||
init(config: PluginConfig): void
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the plugin should dispose/shutdown everything.
|
|
||||||
*/
|
|
||||||
deinit?(): Promise<void>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the plugin's router.
|
|
||||||
*
|
|
||||||
* Mounted at <code-sever-root>/<plugin-path>
|
|
||||||
*
|
|
||||||
* If not present, the plugin provides no routes.
|
|
||||||
*/
|
|
||||||
router?(): express.Router
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the plugin's websocket router.
|
|
||||||
*
|
|
||||||
* Mounted at <code-sever-root>/<plugin-path>
|
|
||||||
*
|
|
||||||
* If not present, the plugin provides no websockets.
|
|
||||||
*/
|
|
||||||
wsRouter?(): WebsocketRouter
|
|
||||||
|
|
||||||
/**
|
|
||||||
* code-server uses this to collect the list of applications that
|
|
||||||
* the plugin can currently provide.
|
|
||||||
* It is called when /api/applications is hit or the overlay needs to
|
|
||||||
* refresh the list of applications
|
|
||||||
*
|
|
||||||
* Ensure this is as fast as possible.
|
|
||||||
*
|
|
||||||
* If not present, the plugin provides no applications.
|
|
||||||
*/
|
|
||||||
applications?(): Application[] | Promise<Application[]>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PluginConfig contains the configuration required for initializing
|
|
||||||
* a plugin.
|
|
||||||
*/
|
|
||||||
export interface PluginConfig {
|
|
||||||
/**
|
|
||||||
* All plugin logs should be logged via this logger.
|
|
||||||
*/
|
|
||||||
readonly logger: Logger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This can be specified by the user on the command line. Plugins should
|
|
||||||
* default to this directory when applicable. For example, the Jupyter plugin
|
|
||||||
* uses this to launch in this directory.
|
|
||||||
*/
|
|
||||||
readonly workingDirectory?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application represents a user accessible application.
|
|
||||||
*/
|
|
||||||
export interface Application {
|
|
||||||
readonly name: string
|
|
||||||
readonly version: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When the user clicks on the icon in the overlay, they will be
|
|
||||||
* redirected to <code-server-root>/<plugin-path>/<app-path>
|
|
||||||
* where the application should be accessible.
|
|
||||||
*
|
|
||||||
* If undefined, then <code-server-root>/<plugin-path> is used.
|
|
||||||
*/
|
|
||||||
readonly path?: string
|
|
||||||
|
|
||||||
readonly description?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path at which the icon for this application can be accessed.
|
|
||||||
* <code-server-root>/<plugin-path>/<app-path>/<icon-path>
|
|
||||||
*/
|
|
||||||
readonly iconPath: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to application homepage.
|
|
||||||
*/
|
|
||||||
readonly homepageURL: string
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user