mirror of
https://github.com/coder/code-server.git
synced 2026-04-14 15:19:07 -05:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
325181d414 | ||
|
|
7b2b0e0b21 | ||
|
|
ae83e049b9 | ||
|
|
b2ac660763 | ||
|
|
7d5bade76c |
137
.github/workflows/ci.yaml
vendored
137
.github/workflows/ci.yaml
vendored
@@ -29,9 +29,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -41,17 +38,21 @@ jobs:
|
||||
- name: Install helm
|
||||
uses: azure/setup-helm@v1.1
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
# NOTE@jsjoeio
|
||||
# disabling this until we can audit the build process
|
||||
# and the usefulness of this step
|
||||
# See: https://github.com/coder/code-server/issues/4287
|
||||
# - name: Fetch dependencies from cache
|
||||
# id: cache-yarn
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: "**/node_modules"
|
||||
# key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# yarn-build-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
# if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
- name: Run yarn fmt
|
||||
@@ -70,9 +71,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -81,7 +79,7 @@ jobs:
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -104,53 +102,56 @@ jobs:
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install quilt
|
||||
run: sudo apt update && sudo apt install quilt
|
||||
|
||||
- name: Patch Code
|
||||
run: quilt push -a
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
# TODO@Teffen investigate why this omits code-oss-dev/node_modules
|
||||
# - name: Fetch dependencies from cache
|
||||
# id: cache-yarn
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: |
|
||||
# "**/node_modules"
|
||||
# "**/vendor/modules"
|
||||
# "**/vendor/modules/code-oss-dev/node_modules"
|
||||
# key: yarn-build-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/vendor/yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# yarn-build-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
# if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
- name: Build code-server
|
||||
run: yarn build
|
||||
|
||||
# Get Code's git hash. When this changes it means the content is
|
||||
# different and we need to rebuild.
|
||||
- name: Get latest lib/vscode rev
|
||||
# Parse the hash of the latest commit inside vendor/modules/code-oss-dev
|
||||
# use this to avoid rebuilding it if nothing changed
|
||||
# How it works: the `git log` command fetches the hash of the last commit
|
||||
# that changed a file inside `vendor/modules/code-oss-dev`. If a commit changes any file in there,
|
||||
# the hash returned will change, and we rebuild vscode. If the hash did not change,
|
||||
# (for example, a change to `src/` or `docs/`), we reuse the same build as last time.
|
||||
# This saves a lot of time in CI, as compiling VSCode can take anywhere from 5-10 minutes.
|
||||
- name: Get latest vendor/modules/code-oss-dev rev
|
||||
id: vscode-rev
|
||||
run: echo "::set-output name=rev::$(git rev-parse HEAD:./lib/vscode)"
|
||||
run: echo "::set-output name=rev::$(jq -r '.devDependencies["code-oss-dev"]' vendor/package.json | sed -r 's|.*#(.*)$|\1|')"
|
||||
|
||||
# We need to rebuild when we have a new version of Code or when any of
|
||||
# the patches changed. Use VSCODE_CACHE_VERSION to force a rebuild.
|
||||
- name: Fetch prebuilt Code package from cache
|
||||
- name: Attempt to fetch vscode build from cache
|
||||
id: cache-vscode
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: lib/vscode-reh-web-*
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff') }}
|
||||
path: |
|
||||
vendor/modules/code-oss-dev/.build
|
||||
vendor/modules/code-oss-dev/out-build
|
||||
vendor/modules/code-oss-dev/out-vscode-reh-web
|
||||
vendor/modules/code-oss-dev/out-vscode-reh-web-min
|
||||
key: vscode-reh-build-${{ steps.vscode-rev.outputs.rev }}
|
||||
|
||||
- name: Build vscode
|
||||
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
||||
@@ -178,7 +179,7 @@ jobs:
|
||||
run: tar -czf package.tar.gz release
|
||||
|
||||
- name: Upload npm package artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: npm-package
|
||||
path: ./package.tar.gz
|
||||
@@ -195,13 +196,9 @@ jobs:
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
name: "npm-package"
|
||||
@@ -228,10 +225,7 @@ jobs:
|
||||
container: "centos:7"
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -274,7 +268,7 @@ jobs:
|
||||
run: yarn package
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-packages
|
||||
path: ./release-packages
|
||||
@@ -320,10 +314,7 @@ jobs:
|
||||
NODE_VERSION: v14.17.4
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -361,7 +352,7 @@ jobs:
|
||||
run: yarn package ${NPM_CONFIG_ARCH}
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-packages
|
||||
path: ./release-packages
|
||||
@@ -372,10 +363,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -405,7 +393,7 @@ jobs:
|
||||
run: yarn package
|
||||
|
||||
- name: Upload release artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-packages
|
||||
path: ./release-packages
|
||||
@@ -420,11 +408,7 @@ jobs:
|
||||
# since VS Code will load faster due to the bundling.
|
||||
CODE_SERVER_TEST_ENTRY: "./release-packages/code-server-linux-amd64"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js v14
|
||||
uses: actions/setup-node@v3
|
||||
@@ -433,7 +417,7 @@ jobs:
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -466,7 +450,7 @@ jobs:
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: failed-test-videos
|
||||
path: ./test/test-results
|
||||
@@ -477,12 +461,10 @@ jobs:
|
||||
trivy-scan-repo:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
#Commit SHA for v0.0.17
|
||||
uses: aquasecurity/trivy-action@296212627a1e693efa09c00adc3e03b2ba8edf18
|
||||
with:
|
||||
scan-type: "fs"
|
||||
@@ -492,7 +474,6 @@ jobs:
|
||||
template: "@/contrib/sarif.tpl"
|
||||
output: "trivy-repo-results.sarif"
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
with:
|
||||
|
||||
13
.github/workflows/docker.yaml
vendored
13
.github/workflows/docker.yaml
vendored
@@ -35,19 +35,6 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq .version package.json)"
|
||||
|
||||
- name: Download artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
branch: v${{ steps.version.outputs.version }}
|
||||
workflow_conclusion: completed
|
||||
name: "release-packages"
|
||||
path: release-packages
|
||||
|
||||
- name: Run ./ci/steps/docker-buildx-push.sh
|
||||
run: ./ci/steps/docker-buildx-push.sh
|
||||
env:
|
||||
|
||||
79
.github/workflows/docs-preview.yaml
vendored
79
.github/workflows/docs-preview.yaml
vendored
@@ -17,24 +17,89 @@ permissions:
|
||||
security-events: none
|
||||
statuses: none
|
||||
|
||||
# Cancel in-progress runs for pull requests when developers push
|
||||
# additional changes, and serialize builds in branches.
|
||||
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
name: Docs preview
|
||||
runs-on: ubuntu-20.04
|
||||
environment: CI
|
||||
# Only run if PR comes from base repo
|
||||
# Reason: forks cannot access secrets and this will always fail
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.9.1
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
- name: Checkout m
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: coder/m
|
||||
ref: refs/heads/master
|
||||
ssh-key: ${{ secrets.READONLY_M_DEPLOY_KEY }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
|
||||
- name: Cache Node Modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: "/node_modules"
|
||||
key: node-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Create Deployment
|
||||
id: deployment
|
||||
run: ./ci/scripts/github_deployment.sh create
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
DEPLOY_ENVIRONMENT: codercom-preview-docs
|
||||
|
||||
- name: Deploy Preview to Vercel
|
||||
id: preview
|
||||
run: ./ci/scripts/deploy_vercel.sh
|
||||
env:
|
||||
VERCEL_ORG_ID: team_tGkWfhEGGelkkqUUm9nXq17r
|
||||
VERCEL_PROJECT_ID: QmZRucMRh3GFk1817ZgXjRVuw5fhTspHPHKct3JNQDEPGd
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
||||
CODE_SERVER_DOCS_MAIN_BRANCH: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Install node_modules
|
||||
run: yarn install
|
||||
|
||||
- name: Check docs
|
||||
run: yarn ts-node ./product/coder.com/site/scripts/checkDocs.ts
|
||||
env:
|
||||
BASE_URL: ${{ steps.preview.outputs.url }}
|
||||
|
||||
- name: Update Deployment
|
||||
# If we don't specify always, it won't run this check if failed.
|
||||
# This means the deployment would be stuck pending.
|
||||
if: always()
|
||||
run: ./ci/scripts/github_deployment.sh update
|
||||
env:
|
||||
GITHUB_DEPLOYMENT: ${{ steps.deployment.outputs.id }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
DEPLOY_STATUS: ${{ steps.preview.outcome }}
|
||||
DEPLOY_URL: ${{ steps.preview.outputs.url }}
|
||||
|
||||
- name: Comment Credentials
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
if: always()
|
||||
with:
|
||||
header: codercom-preview-docs
|
||||
message: |
|
||||
✨ code-server docs for PR #${{ github.event.number }} is ready! It will be updated on every commit.
|
||||
* _Host_: https://coder.com/docs/code-server/${{ steps.vars.outputs.sha_short }}
|
||||
* _Last deploy status_: success
|
||||
✨ Coder.com for PR #${{ github.event.number }} deployed! It will be updated on every commit.
|
||||
|
||||
* _Host_: ${{ steps.preview.outputs.url }}/docs/code-server
|
||||
* _Last deploy status_: ${{ steps.preview.outcome }}
|
||||
* _Commit_: ${{ github.event.pull_request.head.sha }}
|
||||
* _Workflow status_: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
20
.github/workflows/npm-brew.yaml
vendored
20
.github/workflows/npm-brew.yaml
vendored
@@ -23,16 +23,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq .version package.json)"
|
||||
|
||||
- name: Download artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
branch: v${{ steps.version.outputs.version }}
|
||||
workflow_conclusion: completed
|
||||
name: "npm-package"
|
||||
path: release-npm-package
|
||||
|
||||
@@ -56,20 +49,11 @@ jobs:
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Checkout cdrci/homebrew-core
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: cdrci/homebrew-core
|
||||
path: homebrew-core
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
|
||||
- name: Bump code-server homebrew version
|
||||
env:
|
||||
HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}}
|
||||
|
||||
65
.github/workflows/trivy-docker.yaml
vendored
65
.github/workflows/trivy-docker.yaml
vendored
@@ -1,65 +0,0 @@
|
||||
name: Trivy Nightly Docker Scan
|
||||
|
||||
on:
|
||||
# Run scans if the workflow is modified, in order to test the
|
||||
# workflow itself. This results in some spurious notifications,
|
||||
# but seems okay for testing.
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- .github/workflows/trivy-docker.yaml
|
||||
|
||||
# Run scans against master whenever changes are merged.
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- .github/workflows/trivy-docker.yaml
|
||||
|
||||
schedule:
|
||||
# Run at 10:15 am UTC (3:15am PT/5:15am CT)
|
||||
# Run at 0 minutes 0 hours of every day.
|
||||
- cron: "15 10 * * *"
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: none
|
||||
checks: none
|
||||
contents: read
|
||||
deployments: none
|
||||
issues: none
|
||||
packages: none
|
||||
pull-requests: none
|
||||
repository-projects: none
|
||||
security-events: write
|
||||
statuses: none
|
||||
|
||||
# Cancel in-progress runs for pull requests when developers push
|
||||
# additional changes, and serialize builds in branches.
|
||||
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
trivy-scan-image:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run Trivy vulnerability scanner in image mode
|
||||
uses: aquasecurity/trivy-action@296212627a1e693efa09c00adc3e03b2ba8edf18
|
||||
with:
|
||||
image-ref: "docker.io/codercom/code-server:latest"
|
||||
ignore-unfixed: true
|
||||
format: "sarif"
|
||||
output: "trivy-image-results.sarif"
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
with:
|
||||
sarif_file: "trivy-image-results.sarif"
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -8,17 +8,12 @@ release-packages/
|
||||
release-gcp/
|
||||
release-images/
|
||||
node_modules
|
||||
vendor/modules
|
||||
node-*
|
||||
/plugins
|
||||
/lib/coder-cloud-agent
|
||||
.home
|
||||
coverage
|
||||
**/.DS_Store
|
||||
|
||||
# Code packages itself here.
|
||||
/lib/vscode-reh-web-*
|
||||
|
||||
# Failed e2e test videos are saved here
|
||||
test/test-results
|
||||
|
||||
# Quilt's internal data.
|
||||
/.pc
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "lib/vscode"]
|
||||
path = lib/vscode
|
||||
url = https://github.com/microsoft/vscode
|
||||
@@ -7,7 +7,7 @@ useTabs: false
|
||||
|
||||
overrides:
|
||||
# Attempt to keep VScode's existing code style intact.
|
||||
- files: "lib/vscode/**/*.ts"
|
||||
- files: "vendor/modules/code-oss-dev/**/*.ts"
|
||||
options:
|
||||
# No limit defined upstream.
|
||||
printWidth: 10000
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"description": "Static images and the manifest live here in `src/browser/media` (see the explorer)."
|
||||
},
|
||||
{
|
||||
"directory": "lib/vscode",
|
||||
"directory": "vendor/modules/code-oss-dev",
|
||||
"line": 1,
|
||||
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
|
||||
}
|
||||
|
||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -20,34 +20,13 @@ VS Code v99.99.999
|
||||
|
||||
-->
|
||||
|
||||
## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22
|
||||
## [Unreleased](https://github.com/coder/code-server/releases)
|
||||
|
||||
Code v1.64.2
|
||||
|
||||
### Added
|
||||
|
||||
- Added tests for `handleArgsSocketCatchError`, `setDefaults` and
|
||||
`optionDescriptions`.
|
||||
Code v0.00.0
|
||||
|
||||
### Changed
|
||||
|
||||
- We switched from using the fork `coder/vscode` to a submodule of
|
||||
`microsoft/vscode` + patches managed by `quilt` for how Code sits inside the
|
||||
code-server codebase.
|
||||
- Upgraded to Code 1.64.2.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Update popup notification through `--disable-update-check` is now fixed.
|
||||
- Fixed PWA icons not loading on iPad
|
||||
- Fixed the homebrew release process. Our `cdrci` bot should now automatically
|
||||
update the version as part of the release pipeline.
|
||||
- Fixed titleBar color setting being ignored in PWA.
|
||||
|
||||
### Security
|
||||
|
||||
- Updated to `minimist-list`.
|
||||
- Updated `cloud-agent` to `v0.2.4` which uses `nhooyr.io/webscoket` `v1.8.7`.
|
||||
- Add here
|
||||
|
||||
## [4.1.0](https://github.com/coder/code-server/releases/tag/v4.1.0) - 2022-03-03
|
||||
|
||||
|
||||
@@ -50,11 +50,6 @@ release_nfpm() {
|
||||
|
||||
export NFPM_ARCH
|
||||
|
||||
# Code deletes some files from the extension node_modules directory which
|
||||
# leaves broken symlinks in the corresponding .bin directory. nfpm will fail
|
||||
# on these broken symlinks so clean them up.
|
||||
rm -fr "./release-standalone/lib/vscode/extensions/node_modules/.bin"
|
||||
|
||||
PKG_FORMAT="deb"
|
||||
NFPM_ARCH="$(get_nfpm_arch $PKG_FORMAT "$ARCH")"
|
||||
nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
|
||||
|
||||
@@ -15,8 +15,8 @@ main() {
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
VSCODE_SRC_PATH="lib/vscode"
|
||||
VSCODE_OUT_PATH="$RELEASE_PATH/lib/vscode"
|
||||
VSCODE_SRC_PATH="vendor/modules/code-oss-dev"
|
||||
VSCODE_OUT_PATH="$RELEASE_PATH/vendor/modules/code-oss-dev"
|
||||
|
||||
mkdir -p "$RELEASE_PATH"
|
||||
|
||||
@@ -25,7 +25,7 @@ main() {
|
||||
|
||||
rsync ./docs/README.md "$RELEASE_PATH"
|
||||
rsync LICENSE.txt "$RELEASE_PATH"
|
||||
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
|
||||
rsync ./vendor/modules/code-oss-dev/ThirdPartyNotices.txt "$RELEASE_PATH"
|
||||
}
|
||||
|
||||
bundle_code_server() {
|
||||
@@ -66,10 +66,31 @@ EOF
|
||||
|
||||
bundle_vscode() {
|
||||
mkdir -p "$VSCODE_OUT_PATH"
|
||||
rsync ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
|
||||
rsync "$VSCODE_SRC_PATH/yarn.lock" "$VSCODE_OUT_PATH"
|
||||
rsync "$VSCODE_SRC_PATH/out-vscode-reh-web${MINIFY:+-min}/" "$VSCODE_OUT_PATH/out"
|
||||
|
||||
# Add the commit, date, our name, links, and enable telemetry. This just makes
|
||||
# telemetry available; telemetry can still be disabled by flag or setting.
|
||||
rsync "$VSCODE_SRC_PATH/.build/extensions/" "$VSCODE_OUT_PATH/extensions"
|
||||
if [ "$KEEP_MODULES" = 0 ]; then
|
||||
rm -Rf "$VSCODE_OUT_PATH/extensions/node_modules"
|
||||
else
|
||||
rsync "$VSCODE_SRC_PATH/node_modules/" "$VSCODE_OUT_PATH/node_modules"
|
||||
fi
|
||||
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/postinstall.js" "$VSCODE_OUT_PATH/extensions"
|
||||
|
||||
mkdir -p "$VSCODE_OUT_PATH/resources/"
|
||||
rsync "$VSCODE_SRC_PATH/resources/" "$VSCODE_OUT_PATH/resources/"
|
||||
|
||||
# TODO: We should look into using VS Code's packaging task (see
|
||||
# gulpfile.reh.js). For now copy this directory into the right spot (for some
|
||||
# reason VS Code uses a different path in production).
|
||||
mkdir -p "$VSCODE_OUT_PATH/bin/helpers"
|
||||
rsync "$VSCODE_SRC_PATH/resources/server/bin/helpers/" "$VSCODE_OUT_PATH/bin/helpers"
|
||||
chmod +x "$VSCODE_OUT_PATH/bin/helpers/browser.sh"
|
||||
|
||||
# Add the commit and date and enable telemetry. This just makes telemetry
|
||||
# available; telemetry can still be disabled by flag or setting.
|
||||
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
|
||||
cat << EOF
|
||||
{
|
||||
@@ -77,48 +98,15 @@ bundle_vscode() {
|
||||
"commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
|
||||
"quality": "stable",
|
||||
"date": $(jq -n 'now | todate'),
|
||||
"codeServerVersion": "$VERSION",
|
||||
"nameShort": "code-server",
|
||||
"nameLong": "code-server",
|
||||
"applicationName": "code-server",
|
||||
"dataFolderName": ".code-server",
|
||||
"win32MutexName": "codeserver",
|
||||
"licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE.txt",
|
||||
"win32DirName": "code-server",
|
||||
"win32NameVersion": "code-server",
|
||||
"win32AppUserModelId": "coder.code-server",
|
||||
"win32ShellNameShort": "c&ode-server",
|
||||
"darwinBundleIdentifier": "com.coder.code.server",
|
||||
"linuxIconName": "com.coder.code.server",
|
||||
"reportIssueUrl": "https://github.com/coder/code-server/issues/new",
|
||||
"documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
|
||||
"keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
|
||||
"keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
|
||||
"keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
|
||||
"introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
|
||||
"tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
|
||||
"newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
|
||||
"linkProtectionTrustedDomains": [
|
||||
"https://open-vsx.org"
|
||||
]
|
||||
"codeServerVersion": "$VERSION"
|
||||
}
|
||||
EOF
|
||||
) > "$VSCODE_OUT_PATH/product.json"
|
||||
|
||||
# Use the package.json for the web/remote server. It does not have the right
|
||||
# version though so pull that from the main package.json. Also remove keytar
|
||||
# since the web does not rely on it and that removes the dependency on
|
||||
# libsecret.
|
||||
jq --slurp '.[0] * {version: .[1].version} | del(.dependencies.keytar)' \
|
||||
"$VSCODE_SRC_PATH/remote/package.json" \
|
||||
"$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
|
||||
|
||||
rsync "$VSCODE_SRC_PATH/remote/yarn.lock" "$VSCODE_OUT_PATH/yarn.lock"
|
||||
|
||||
if [ "$KEEP_MODULES" = 0 ]; then
|
||||
rm -Rf "$VSCODE_OUT_PATH/extensions/node_modules"
|
||||
rm -Rf "$VSCODE_OUT_PATH/node_modules"
|
||||
fi
|
||||
# We remove the scripts field so that later on we can run
|
||||
# yarn to fetch node_modules if necessary without build scripts running.
|
||||
# We cannot use --no-scripts because we still want dependent package scripts to run.
|
||||
jq 'del(.scripts)' < "$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
|
||||
|
||||
pushd "$VSCODE_OUT_PATH"
|
||||
symlink_asar
|
||||
|
||||
@@ -29,6 +29,12 @@ main() {
|
||||
|
||||
cd "$RELEASE_PATH"
|
||||
yarn --production --frozen-lockfile
|
||||
|
||||
# HACK: the version of Typescript vscode 1.57 uses in extensions/
|
||||
# leaves a few stray symlinks. Clean them up so nfpm does not fail.
|
||||
# Remove this line when its no longer needed.
|
||||
|
||||
rm -fr "$RELEASE_PATH/vendor/modules/code-oss-dev/extensions/node_modules/.bin"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Builds vscode into lib/vscode/out-vscode.
|
||||
# Builds vscode into vendor/modules/code-oss-dev/out-vscode.
|
||||
|
||||
# MINIFY controls whether a minified version of vscode is built.
|
||||
MINIFY=${MINIFY-true}
|
||||
@@ -9,7 +9,7 @@ MINIFY=${MINIFY-true}
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
cd lib/vscode
|
||||
cd vendor/modules/code-oss-dev
|
||||
|
||||
# Any platform works since we have our own packaging step (for now).
|
||||
yarn gulp "vscode-reh-web-linux-x64${MINIFY:+-min}"
|
||||
|
||||
@@ -90,8 +90,8 @@ symlink_asar() {
|
||||
}
|
||||
|
||||
vscode_yarn() {
|
||||
echo 'Installing Code dependencies...'
|
||||
cd lib/vscode
|
||||
echo 'Installing vendor dependencies...'
|
||||
cd vendor/modules/code-oss-dev
|
||||
yarn --production --frozen-lockfile
|
||||
|
||||
symlink_asar
|
||||
|
||||
@@ -9,15 +9,6 @@ set -euo pipefail
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
source ./ci/lib.sh
|
||||
source ./ci/steps/steps-lib.sh
|
||||
|
||||
# NOTE@jsjoeio - only needed if we use the download_artifact
|
||||
# because we talk to the GitHub API.
|
||||
# Needed to use GitHub API
|
||||
if ! is_env_var_set "GITHUB_TOKEN"; then
|
||||
echo "GITHUB_TOKEN is not set. Cannot download npm release-packages without GitHub credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
download_artifact release-packages ./release-packages
|
||||
local assets=(./release-packages/code-server*"$VERSION"*{.tar.gz,.deb,.rpm})
|
||||
|
||||
@@ -19,7 +19,7 @@ main() {
|
||||
"*.sh"
|
||||
)
|
||||
prettier --write --loglevel=warn $(
|
||||
git ls-files "${prettierExts[@]}" | grep -v "lib/vscode" | grep -v 'helm-chart'
|
||||
git ls-files "${prettierExts[@]}" | grep -v "lib/vscode" | grep -v "vendor/modules/code-oss-dev" | grep -v 'helm-chart'
|
||||
)
|
||||
|
||||
doctoc --title '# FAQ' docs/FAQ.md > /dev/null
|
||||
|
||||
@@ -4,10 +4,10 @@ set -euo pipefail
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
eslint --max-warnings=0 --fix $(git ls-files "*.ts" "*.tsx" "*.js" | grep -v "lib/vscode")
|
||||
stylelint $(git ls-files "*.css" | grep -v "lib/vscode")
|
||||
eslint --max-warnings=0 --fix $(git ls-files "*.ts" "*.tsx" "*.js" | grep -v "vendor/modules/code-oss-dev" | grep -v "lib/vscode")
|
||||
stylelint $(git ls-files "*.css" | grep -v "vendor/modules/code-oss-dev" | grep -v "lib/vscode")
|
||||
tsc --noEmit --skipLibCheck
|
||||
shellcheck -e SC2046,SC2164,SC2154,SC1091,SC1090,SC2002 $(git ls-files "*.sh" | grep -v "lib/vscode")
|
||||
shellcheck -e SC2046,SC2164,SC2154,SC1091,SC1090,SC2002 $(git ls-files "*.sh" | grep -v "vendor/modules/code-oss-dev" | grep -v "lib/vscode")
|
||||
if command -v helm && helm kubeval --help > /dev/null; then
|
||||
helm kubeval ci/helm-chart
|
||||
fi
|
||||
|
||||
@@ -1,32 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Install dependencies in $1.
|
||||
install-deps() {
|
||||
local args=(install)
|
||||
if [[ ${CI-} ]]; then
|
||||
args+=(--frozen-lockfile)
|
||||
fi
|
||||
# If there is no package.json then yarn will look upward and end up installing
|
||||
# from the root resulting in an infinite loop (this can happen if you have not
|
||||
# checked out the submodule yet for example).
|
||||
if [[ ! -f "$1/package.json" ]]; then
|
||||
echo "$1/package.json is missing; did you run git submodule update --init?"
|
||||
exit 1
|
||||
fi
|
||||
pushd "$1"
|
||||
echo "Installing dependencies for $PWD"
|
||||
yarn "${args[@]}"
|
||||
popd
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
source ./ci/lib.sh
|
||||
|
||||
install-deps test
|
||||
install-deps test/e2e/extensions/test-extension
|
||||
install-deps lib/vscode
|
||||
pushd test
|
||||
echo "Installing dependencies for $PWD"
|
||||
yarn install
|
||||
popd
|
||||
|
||||
local args=(install)
|
||||
if [[ ${CI-} ]]; then
|
||||
args+=(--frozen-lockfile)
|
||||
fi
|
||||
|
||||
pushd test
|
||||
echo "Installing dependencies for $PWD"
|
||||
yarn "${args[@]}"
|
||||
popd
|
||||
|
||||
pushd test/e2e/extensions/test-extension
|
||||
echo "Installing dependencies for $PWD"
|
||||
yarn "${args[@]}"
|
||||
popd
|
||||
|
||||
pushd vendor
|
||||
echo "Installing dependencies for $PWD"
|
||||
|
||||
# We install in 'modules' instead of 'node_modules' because VS Code's
|
||||
# extensions use a webpack config which cannot differentiate between its own
|
||||
# node_modules and itself being in a directory with the same name.
|
||||
args+=(--modules-folder modules)
|
||||
|
||||
# We ignore scripts because NPM/Yarn's default behavior is to assume that
|
||||
# devDependencies are not needed, and that even git repo based packages are
|
||||
# assumed to be compiled. Because the default behavior for VS Code's
|
||||
# `postinstall` assumes we're also compiled, this needs to be ignored.
|
||||
args+=(--ignore-scripts)
|
||||
|
||||
yarn "${args[@]}"
|
||||
|
||||
# Finally, run the vendor `postinstall`
|
||||
yarn run postinstall
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -37,7 +37,7 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -d $dir/lib/vscode/out ]]; then
|
||||
if [[ ! -d $dir/vendor/modules/code-oss-dev/out ]]; then
|
||||
echo >&2 "No VS Code build detected"
|
||||
help
|
||||
exit 1
|
||||
|
||||
@@ -14,17 +14,11 @@ main() {
|
||||
# Our code imports from `out` in order to work during development but if you
|
||||
# have only built for production you will have not have this directory. In
|
||||
# that case symlink `out` to a production build directory.
|
||||
if [[ ! -e lib/vscode/out ]]; then
|
||||
pushd lib
|
||||
local out=(vscode-reh-web-*)
|
||||
if [[ -d "${out[0]}" ]]; then
|
||||
ln -s "../${out[0]}/out" ./vscode/out
|
||||
else
|
||||
echo "Could not find lib/vscode/out or lib/vscode-reh-web-*"
|
||||
echo "Code must be built before running unit tests"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
local vscode="vendor/modules/code-oss-dev"
|
||||
local link="$vscode/out"
|
||||
local target="out-build"
|
||||
if [[ ! -e $link ]] && [[ -d $vscode/$target ]]; then
|
||||
ln -s "$target" "$link"
|
||||
fi
|
||||
|
||||
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
||||
|
||||
@@ -14,7 +14,7 @@ class Watcher {
|
||||
private rootPath = path.resolve(process.cwd())
|
||||
private readonly paths = {
|
||||
/** Path to uncompiled VS Code source. */
|
||||
vscodeDir: path.join(this.rootPath, "lib/vscode"),
|
||||
vscodeDir: path.join(this.rootPath, "vendor", "modules", "code-oss-dev"),
|
||||
pluginDir: process.env.PLUGIN_DIR,
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 2.3.0
|
||||
version: 2.2.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 4.2.0
|
||||
appVersion: 4.1.0
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: codercom/code-server
|
||||
tag: '4.2.0'
|
||||
tag: '4.1.0'
|
||||
pullPolicy: Always
|
||||
|
||||
# Specifies one or more secrets to be used when pulling images from a
|
||||
|
||||
@@ -14,7 +14,7 @@ pkg_json_version() {
|
||||
}
|
||||
|
||||
vscode_version() {
|
||||
jq -r .version lib/vscode/package.json
|
||||
jq -r .version vendor/modules/code-oss-dev/package.json
|
||||
}
|
||||
|
||||
os() {
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
main() {
|
||||
REPO="homebrew-core"
|
||||
GITHUB_USERNAME="cdrci"
|
||||
UPSTREAM_USERNAME_AND_REPO="Homebrew/$REPO"
|
||||
cd "$(dirname "$0")/../.."
|
||||
# Only sourcing this so we get access to $VERSION
|
||||
source ./ci/lib.sh
|
||||
source ./ci/steps/steps-lib.sh
|
||||
@@ -23,18 +21,25 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE: we need to make sure coderci/homebrew-core
|
||||
# is up-to-date
|
||||
# otherwise, brew bump-formula-pr will use an
|
||||
# outdated base
|
||||
echo "Cloning coderci/homebrew-core"
|
||||
git clone https://github.com/coderci/homebrew-core.git
|
||||
|
||||
# Make sure the git clone step is successful
|
||||
if ! directory_exists "$REPO"; then
|
||||
echo "git clone failed. Cannot find $REPO directory."
|
||||
if directory_exists "homebrew-core"; then
|
||||
echo "git clone failed. Cannot find homebrew-core directory."
|
||||
ls -la
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Changing into $REPO directory"
|
||||
pushd "$REPO" && pwd
|
||||
echo "Changing into homebrew-core directory"
|
||||
pushd homebrew-core && pwd
|
||||
|
||||
echo "Adding $UPSTREAM_USERNAME_AND_REPO"
|
||||
git remote add upstream "https://github.com/$UPSTREAM_USERNAME_AND_REPO.git"
|
||||
echo "Adding Homebrew/homebrew-core"
|
||||
git remote add upstream https://github.com/Homebrew/homebrew-core.git
|
||||
|
||||
# Make sure the git remote step is successful
|
||||
if ! git config remote.upstream.url > /dev/null; then
|
||||
@@ -45,22 +50,24 @@ main() {
|
||||
fi
|
||||
|
||||
# TODO@jsjoeio - can I somehow check that this succeeded?
|
||||
echo "Fetching upstream $UPSTREAM_USERNAME_AND_REPO commits"
|
||||
git fetch upstream master
|
||||
echo "Fetching upstream Homebrew/hombrew-core commits"
|
||||
git fetch upstream
|
||||
|
||||
# TODO@jsjoeio - can I somehow check that this succeeded?
|
||||
echo "Merging in latest $UPSTREAM_USERNAME_AND_REPO changes branch master"
|
||||
echo "Merging in latest Homebrew/homebrew-core changes"
|
||||
git merge upstream/master
|
||||
|
||||
echo "Pushing changes to coderci/homebrew-core fork on GitHub"
|
||||
|
||||
# GIT_ASKPASS lets us use the password when pushing without revealing it in the process list
|
||||
# See: https://serverfault.com/a/912788
|
||||
PATH_TO_GIT_ASKPASS="$HOME/git-askpass.sh"
|
||||
# Source: https://serverfault.com/a/912788
|
||||
# shellcheck disable=SC2016,SC2028
|
||||
echo 'echo $HOMEBREW_GITHUB_API_TOKEN' > "$PATH_TO_GIT_ASKPASS"
|
||||
echo 'echo $HOMEBREW_GITHUB_API_TOKEN' > "$PATH_TO_ASKPASS"
|
||||
|
||||
# Make sure the git-askpass.sh file creation is successful
|
||||
if ! file_exists "$PATH_TO_GIT_ASKPASS"; then
|
||||
if file_exists "$PATH_TO_GIT_ASKPASS"; then
|
||||
echo "git-askpass.sh not found in $HOME."
|
||||
ls -la "$HOME"
|
||||
exit 1
|
||||
@@ -70,20 +77,16 @@ main() {
|
||||
chmod +x "$PATH_TO_GIT_ASKPASS"
|
||||
|
||||
# Make sure the git-askpass.sh file is executable
|
||||
if ! is_executable "$PATH_TO_GIT_ASKPASS"; then
|
||||
if is_executable "$PATH_TO_GIT_ASKPASS"; then
|
||||
echo "$PATH_TO_GIT_ASKPASS is not executable."
|
||||
ls -la "$PATH_TO_GIT_ASKPASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE: we need to make sure our fork is up-to-date
|
||||
# otherwise, brew bump-formula-pr will use an
|
||||
# outdated base
|
||||
echo "Pushing changes to $GITHUB_USERNAME/$REPO fork on GitHub"
|
||||
# Export the variables so git sees them
|
||||
export HOMEBREW_GITHUB_API_TOKEN="$HOMEBREW_GITHUB_API_TOKEN"
|
||||
export GIT_ASKPASS="$PATH_TO_GIT_ASKPASS"
|
||||
git push "https://$GITHUB_USERNAME@github.com/$GITHUB_USERNAME/$REPO.git" --all
|
||||
export GIT_ASKPASS="$PATH_TO_ASKPASS"
|
||||
git push https://coder-oss@github.com/coder-oss/homebrew-core.git --all
|
||||
|
||||
# Find the docs for bump-formula-pr here
|
||||
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
|
||||
@@ -91,12 +94,21 @@ main() {
|
||||
if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit 2>&1); then
|
||||
if [[ $output == *"Duplicate PRs should not be opened"* ]]; then
|
||||
echo "$VERSION is already submitted"
|
||||
exit 0
|
||||
else
|
||||
echo "$output"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clean up and remove homebrew-core
|
||||
popd
|
||||
rm -rf homebrew-core
|
||||
|
||||
# Make sure homebrew-core is removed
|
||||
if directory_exists "homebrew-core"; then
|
||||
echo "rm -rf homebrew-core failed."
|
||||
ls -la
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -4,9 +4,12 @@ set -euo pipefail
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
# NOTE@jsjoeio - this script assumes that you've downloaded
|
||||
# the release-packages artifact to ./release-packages before
|
||||
# running this docker buildx step
|
||||
# ci/lib.sh sets VERSION and provides download_artifact here
|
||||
source ./ci/lib.sh
|
||||
|
||||
# Download the release-packages artifact
|
||||
download_artifact release-packages ./release-packages
|
||||
|
||||
docker buildx bake -f ci/release-image/docker-bake.hcl --push
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,14 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NOTE@jsjoeio - only needed if we use the download_artifact
|
||||
# because we talk to the GitHub API.
|
||||
# Needed to use GitHub API
|
||||
if ! is_env_var_set "GITHUB_TOKEN"; then
|
||||
echo "GITHUB_TOKEN is not set. Cannot download npm release artifact without GitHub credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Publishing Information
|
||||
# All the variables below are used to determine how we should publish
|
||||
# the npm package. We also use this information for bumping the version.
|
||||
@@ -43,13 +51,6 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that we're using at least v7 of npm CLI
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Couldn't find jq"
|
||||
echo "We need this in order to modify the package.json for dev builds."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This allows us to publish to npm in CI workflows
|
||||
if [[ ${CI-} ]]; then
|
||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||
@@ -85,10 +86,6 @@ main() {
|
||||
# See: https://github.com/coder/code-server/pull/3935
|
||||
echo "node_modules.asar" > release/.npmignore
|
||||
|
||||
# We use this to set the name of the package in the
|
||||
# package.json
|
||||
PACKAGE_NAME="code-server"
|
||||
|
||||
# NOTES:@jsjoeio
|
||||
# We only need to run npm version for "development" and "staging".
|
||||
# This is because our release:prep script automatically bumps the version
|
||||
@@ -115,14 +112,12 @@ main() {
|
||||
# Source: https://github.com/actions/checkout/issues/58#issuecomment-614041550
|
||||
PR_NUMBER=$(echo "$GITHUB_REF" | awk 'BEGIN { FS = "/" } ; { print $3 }')
|
||||
NPM_VERSION="$VERSION-$PR_NUMBER-$COMMIT_SHA"
|
||||
PACKAGE_NAME="@coder/code-server-pr"
|
||||
# This means the npm version will be tagged with "<pr number>"
|
||||
# and installed when a user runs `yarn install code-server@<pr number>`
|
||||
NPM_TAG="$PR_NUMBER"
|
||||
fi
|
||||
|
||||
echo "using tag: $NPM_TAG"
|
||||
echo "using package name: $PACKAGE_NAME"
|
||||
|
||||
# We modify the version in the package.json
|
||||
# to be the current version + the PR number + commit SHA
|
||||
@@ -130,14 +125,9 @@ main() {
|
||||
# Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
||||
# Example: "version": "4.0.1-beta-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
||||
pushd release
|
||||
# NOTE@jsjoeio
|
||||
# NOTE:@jsjoeio
|
||||
# I originally tried to use `yarn version` but ran into issues and abandoned it.
|
||||
npm version "$NPM_VERSION"
|
||||
# NOTE@jsjoeio
|
||||
# Use the development package name
|
||||
# This is so we don't clutter the code-server versions on npm
|
||||
# with development versions.
|
||||
jq ".name |= \"$PACKAGE_NAME\"" package.json
|
||||
popd
|
||||
fi
|
||||
|
||||
@@ -151,10 +141,7 @@ main() {
|
||||
return
|
||||
fi
|
||||
|
||||
# NOTE@jsjoeio
|
||||
# Since the dev builds are scoped to @coder
|
||||
# We pass --access public to ensure npm knows it's not private.
|
||||
yarn publish --non-interactive release --tag "$NPM_TAG" --access public
|
||||
yarn publish --non-interactive release --tag "$NPM_TAG"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
- [Creating pull requests](#creating-pull-requests)
|
||||
- [Commits and commit history](#commits-and-commit-history)
|
||||
- [Development workflow](#development-workflow)
|
||||
- [Version updates to Code](#version-updates-to-code)
|
||||
- [Patching Code](#patching-code)
|
||||
- [Updates to VS Code](#updates-to-vs-code)
|
||||
- [Build](#build)
|
||||
- [Help](#help)
|
||||
- [Test](#test)
|
||||
@@ -17,7 +16,7 @@
|
||||
- [Integration tests](#integration-tests)
|
||||
- [End-to-end tests](#end-to-end-tests)
|
||||
- [Structure](#structure)
|
||||
- [Modifications to Code](#modifications-to-code)
|
||||
- [Modifications to VS Code](#modifications-to-vs-code)
|
||||
- [Currently Known Issues](#currently-known-issues)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
@@ -45,8 +44,6 @@ Here is what is needed:
|
||||
signature
|
||||
verification](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification)
|
||||
or follow [this tutorial](https://joeprevite.com/verify-commits-on-github)
|
||||
- `quilt`
|
||||
- Used to manage patches to Code
|
||||
- `rsync` and `unzip`
|
||||
- Used for code-server releases
|
||||
- `bats`
|
||||
@@ -60,7 +57,7 @@ If you're developing code-server on Linux, make sure you have installed or insta
|
||||
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev python-is-python3
|
||||
```
|
||||
|
||||
These are required by Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for more information.
|
||||
These are required by VS Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for more information.
|
||||
|
||||
## Creating pull requests
|
||||
|
||||
@@ -81,44 +78,41 @@ we'll guide you.
|
||||
|
||||
## Development workflow
|
||||
|
||||
The current development workflow is a bit tricky because we have this repo and we use our `coder/vscode` fork inside it with [`yarn link`](https://classic.yarnpkg.com/lang/en/docs/cli/link/).
|
||||
|
||||
Here are these steps you should follow to get your dev environment setup:
|
||||
|
||||
1. `git clone https://github.com/coder/code-server.git` - Clone `code-server`
|
||||
2. `git submodule update --init` - Clone `vscode` submodule
|
||||
3. `quilt push -a` - Apply patches to the `vscode` submodule.
|
||||
4. `yarn` - Install dependencies
|
||||
5. `yarn watch` - Launch code-server localhost:8080. code-server will be live
|
||||
reloaded when changes are made; the browser needs to be refreshed manually.
|
||||
2. `git clone https://github.com/coder/vscode.git` - Clone `vscode`
|
||||
3. `cd vscode && yarn install` - install the dependencies in the `vscode` repo
|
||||
4. `cd code-server && yarn install` - install the dependencies in the `code-server` repo
|
||||
5. `cd vscode && yarn link` - use `yarn` to create a symlink to the `vscode` repo (`code-oss-dev` package)
|
||||
6. `cd code-server && yarn link code-oss-dev --modules-folder vendor/modules` - links your local `vscode` repo (`code-oss-dev` package) inside your local version of code-server
|
||||
7. `cd code-server && yarn watch` - this will spin up code-server on localhost:8080 which you can start developing. It will live reload changes to the source.
|
||||
|
||||
When pulling down changes that include modifications to the patches you will
|
||||
need to apply them with `quilt`. If you pull down changes that update the
|
||||
`vscode` submodule you will need to run `git submodule update --init` and
|
||||
re-apply the patches.
|
||||
### Updates to VS Code
|
||||
|
||||
### Version updates to Code
|
||||
If changes are made and merged into `main` in the [`coder/vscode`](https://github.com/coder/vscode) repo, then you'll need to update the version in the `code-server` repo by following these steps:
|
||||
|
||||
1. Update the package tag listed in `vendor/package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"vscode": "coder/vscode#<latest-commit-sha>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Update the `lib/vscode` submodule to the desired upstream version branch.
|
||||
2. From the code-server **project root**, run `yarn install`.
|
||||
3. Apply the patches (`quilt push -a`) or restore your stashed changes. At this
|
||||
stage you may need to resolve conflicts. For example use `quilt push -f`,
|
||||
manually apply the rejected portions, then `quilt refresh`.
|
||||
4. Test code-server locally to make sure everything works.
|
||||
5. Check the Node.js version that's used by Electron (which is shipped with VS
|
||||
Then, test code-server locally to make sure everything works.
|
||||
3. Check the Node.js version that's used by Electron (which is shipped with VS
|
||||
Code. If necessary, update your version of Node.js to match.
|
||||
6. Commit the updated submodule and patches to `code-server`.
|
||||
7. Open a PR.
|
||||
4. Open a PR
|
||||
|
||||
### Patching Code
|
||||
|
||||
0. You can go through the patch stack with `quilt push` and `quilt pop`.
|
||||
1. Create a new patch (`quilt new {name}.diff`) or use an existing patch.
|
||||
2. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
|
||||
**must** be added before you make changes to it.
|
||||
3. Make your changes. Patches do not need to be independent of each other but
|
||||
each patch must result in a working code-server without any broken in-between
|
||||
states otherwise they are difficult to test and modify.
|
||||
4. Add your changes to the patch (`quilt refresh`)
|
||||
5. Add a comment in the patch about the reason for the patch and how to
|
||||
reproduce the behavior it fixes or adds. Every patch should have an e2e test
|
||||
as well.
|
||||
> Watch for updates to
|
||||
> `vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.html`. You may need to
|
||||
> make changes to `src/browser/pages/vscode.html`.
|
||||
|
||||
### Build
|
||||
|
||||
@@ -214,46 +208,99 @@ code-server running locally. In CI, this is taken care of for you.
|
||||
|
||||
## Structure
|
||||
|
||||
The `code-server` script serves as an HTTP API for login and starting a remote
|
||||
The `code-server` script serves as an HTTP API for login and starting a remote VS
|
||||
Code process.
|
||||
|
||||
The CLI code is in [src/node](../src/node) and the HTTP routes are implemented
|
||||
in [src/node/routes](../src/node/routes).
|
||||
|
||||
Most of the meaty parts are in the Code portion of the codebase under
|
||||
[lib/vscode](../lib/vscode), which we describe next.
|
||||
Most of the meaty parts are in the VS Code portion of the codebase under
|
||||
[vendor/modules/code-oss-dev](../vendor/modules/code-oss-dev), which we describe next.
|
||||
|
||||
### Modifications to Code
|
||||
### Modifications to VS Code
|
||||
|
||||
Our modifications to Code can be found in the [patches](../patches) directory.
|
||||
We pull in Code as a submodule pointing to an upstream release branch.
|
||||
In v1 of code-server, we had a patch of VS Code that split the codebase into a
|
||||
front-end and a server. The front-end consisted of the UI code, while the server
|
||||
ran the extensions and exposed an API to the front-end for file access and all
|
||||
UI needs.
|
||||
|
||||
In v1 of code-server, we had Code as a submodule and used a single massive patch
|
||||
that split the codebase into a front-end and a server. The front-end consisted
|
||||
of the UI code, while the server ran the extensions and exposed an API to the
|
||||
front-end for file access and all UI needs.
|
||||
Over time, Microsoft added support to VS Code to run it on the web. They have
|
||||
made the front-end open source, but not the server. As such, code-server v2 (and
|
||||
later) uses the VS Code front-end and implements the server. We do this by using
|
||||
a Git subtree to fork and modify VS Code. This code lives under
|
||||
[vendor/modules/code-oss-dev](../vendor/modules/code-oss-dev).
|
||||
|
||||
Over time, Microsoft added support to Code to run it on the web. They had made
|
||||
the front-end open source, but not the server. As such, code-server v2 (and
|
||||
later) uses the Code front-end and implements the server. We did this by using a
|
||||
Git subtree to fork and modify Code.
|
||||
Some noteworthy changes in our version of VS Code include:
|
||||
|
||||
Microsoft eventually made the server open source and we were able to reduce our
|
||||
changes significantly. Some time later we moved back to a submodule and patches
|
||||
(managed by `quilt` this time instead of the mega-patch).
|
||||
- Adding our build file, [`vendor/modules/code-oss-dev/coder.js`](../vendor/modules/code-oss-dev/coder.js), which includes build steps specific to code-server
|
||||
- Node.js version detection changes in [`build/lib/node.ts`](../vendor/modules/code-oss-dev/build/lib/node.ts) and [`build/lib/util.ts`](../vendor/modules/code-oss-dev/build/lib/util.ts)
|
||||
- Allowing extra extension directories
|
||||
- Added extra arguments to [`src/vs/platform/environment/common/argv.ts`](../vendor/modules/code-oss-dev/src/vs/platform/environment/common/argv.ts) and to [`src/vs/platform/environment/node/argv.ts`](../vendor/modules/code-oss-dev/src/vs/platform/environment/node/argv.ts)
|
||||
- Added extra environment state to [`src/vs/platform/environment/common/environment.ts`](../vendor/modules/code-oss-dev/src/vs/platform/environment/common/environment.ts);
|
||||
- Added extra getters to [`src/vs/platform/environment/common/environmentService.ts`](../vendor/modules/code-oss-dev/src/vs/platform/environment/common/environmentService.ts)
|
||||
- Added extra scanning paths to [`src/vs/platform/extensionManagement/node/extensionsScanner.ts`](../vendor/modules/code-oss-dev/src/vs/platform/extensionManagement/node/extensionsScanner.ts)
|
||||
- Additions/removals from [`package.json`](../vendor/modules/code-oss-dev/package.json):
|
||||
- Removing `electron`, `keytar` and `native-keymap` to avoid pulling in desktop dependencies during build on Linux
|
||||
- Removing `gulp-azure-storage` and `gulp-tar` (unsued in our build process, may pull in outdated dependencies)
|
||||
- Adding `proxy-agent`, `proxy-from-env` (for proxying) and `rimraf` (used during build/install steps)
|
||||
- Adding our branding/custom URLs/version:
|
||||
- [`product.json`](../vendor/modules/code-oss-dev/product.json)
|
||||
- [`src/vs/base/common/product.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/product.ts)
|
||||
- [`src/vs/workbench/browser/parts/dialogs/dialogHandler.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts)
|
||||
- [`src/vs/workbench/contrib/welcome/page/browser/vs_code_welcome_page.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/contrib/welcome/page/browser/vs_code_welcome_page.ts)
|
||||
- [`src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts)
|
||||
- Removing azure/macOS signing related dependencies from [`build/package.json`](../vendor/modules/code-oss-dev/build/package.json)
|
||||
- Modifying `.gitignore` to allow us to add files to `src/vs/server` and modifying `.eslintignore` to ignore lint on the shared files below (we use different formatter settings than VS Code).
|
||||
- Sharing some files with our codebase via symlinks:
|
||||
- [`src/vs/base/common/ipc.d.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/ipc.d.ts) points to [`typings/ipc.d.ts`](../typings/ipc.d.ts)
|
||||
- [`src/vs/base/common/util.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/util.ts) points to [`src/common/util.ts`](../src/common/util.ts)
|
||||
- [`src/vs/base/node/proxy_agent.ts`](../vendor/modules/code-oss-dev/src/vs/base/node/proxy_agent.ts) points to [`src/node/proxy_agent.ts`](../src/node/proxy_agent.ts)
|
||||
- Allowing socket changes by adding `setSocket` in [`src/vs/base/parts/ipc/common/ipc.net.ts`](../vendor/modules/code-oss-dev/src/vs/base/parts/ipc/common/ipc.net.ts)
|
||||
- We use this for connection persistence in our server-side code.
|
||||
- Added our server-side Node.JS code to `src/vs/server`.
|
||||
- This code includes the logic to spawn the various services (extension host, terminal, etc.) and some glue
|
||||
- Added [`src/vs/workbench/browser/client.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/browser/client.ts) to hold some server customizations.
|
||||
- Includes the functionality for the Log Out command and menu item
|
||||
- Also, imported and called `initialize` from the main web file, [`src/vs/workbench/browser/web.main.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/browser/web.main.ts)
|
||||
- Added a (hopefully temporary) hotfix to [`src/vs/workbench/common/resources.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/common/resources.ts) to get context menu actions working for the Git integration.
|
||||
- Added connection type to WebSocket query parameters in [`src/vs/platform/remote/common/remoteAgentConnection.ts`](../vendor/modules/code-oss-dev/src/vs/platform/remote/common/remoteAgentConnection.ts)
|
||||
- Added `CODE_SERVER*` variables to the sanitization list in [`src/vs/base/common/processes.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/processes.ts)
|
||||
- Fix localization support:
|
||||
- Added file [`src/vs/workbench/services/localizations/browser/localizationsService.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/localizations/browser/localizationsService.ts).
|
||||
- Modified file [`src/vs/base/common/platform.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/platform.ts)
|
||||
- Modified file [`src/vs/base/node/languagePacks.js`](../vendor/modules/code-oss-dev/src/vs/base/node/languagePacks.js)
|
||||
- Added code to allow server to inject settings to [`src/vs/platform/product/common/product.ts`](../vendor/modules/code-oss-dev/src/vs/platform/product/common/product.ts)
|
||||
- Extension fixes:
|
||||
- Avoid disabling extensions by extensionKind in [`src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts) (Needed for vscode-icons)
|
||||
- Remove broken symlinks in [`extensions/postinstall.js`](../vendor/modules/code-oss-dev/extensions/postinstall.js)
|
||||
- Add tip about extension gallery in [`src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts)
|
||||
- Use our own server for GitHub authentication in [`extensions/github-authentication/src/githubServer.ts`](../vendor/modules/code-oss-dev/extensions/github-authentication/src/githubServer.ts)
|
||||
- Settings persistence on the server in [`src/vs/workbench/services/environment/browser/environmentService.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/environment/browser/environmentService.ts)
|
||||
- Add extension install fallback in [`src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts)
|
||||
- Add proxy-agent monkeypatch and keep extension host indefinitely running in [`src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts)
|
||||
- Patch build system to avoid removing extension dependencies for `yarn global add` users in [`build/lib/extensions.ts`](../vendor/modules/code-oss-dev/build/lib/extensions.ts)
|
||||
- Allow all extensions to use proposed APIs in [`src/vs/workbench/services/environment/browser/environmentService.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/services/environment/browser/environmentService.ts)
|
||||
- Make storage writes async to allow extensions to wait for them to complete in [`src/vs/platform/storage/common/storage.ts`](../vendor/modules/code-oss-dev/src/vs/platform/storage/common/storage.ts)
|
||||
- Specify webview path in [`src/vs/code/browser/workbench/workbench.ts`](../vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.ts)
|
||||
- URL readability improvements for folder/workspace in [`src/vs/code/browser/workbench/workbench.ts`](../vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.ts)
|
||||
- Socket/Authority-related fixes (for remote proxying etc.):
|
||||
- [`src/vs/code/browser/workbench/workbench.ts`](../vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.ts)
|
||||
- [`src/vs/platform/remote/browser/browserSocketFactory.ts`](../vendor/modules/code-oss-dev/src/vs/platform/remote/browser/browserSocketFactory.ts)
|
||||
- [`src/vs/base/common/network.ts`](../vendor/modules/code-oss-dev/src/vs/base/common/network.ts)
|
||||
- Added code to write out IPC path in [`src/vs/workbench/api/node/extHostCLIServer.ts`](../vendor/modules/code-oss-dev/src/vs/workbench/api/node/extHostCLIServer.ts)
|
||||
|
||||
As the web portion of Code continues to mature, we'll be able to shrink and
|
||||
possibly eliminate our patches. In the meantime, upgrading the Code version
|
||||
requires us to ensure that our changes are still applied correctly and work as
|
||||
intended. In the future, we'd like to run Code unit tests against our builds to
|
||||
ensure that features work as expected.
|
||||
As the web portion of VS Code matures, we'll be able to shrink and possibly
|
||||
eliminate our modifications. In the meantime, upgrading the VS Code version requires
|
||||
us to ensure that our changes are still applied and work as intended. In the future,
|
||||
we'd like to run VS Code unit tests against our builds to ensure that features
|
||||
work as expected.
|
||||
|
||||
> We have [extension docs](../ci/README.md) on the CI and build system.
|
||||
|
||||
If the functionality you're working on does NOT depend on code from Code, please
|
||||
If the functionality you're working on does NOT depend on code from VS Code, please
|
||||
move it out and into code-server.
|
||||
|
||||
### Currently Known Issues
|
||||
|
||||
- Creating custom Code extensions and debugging them doesn't work
|
||||
- Creating custom VS Code extensions and debugging them doesn't work
|
||||
- Extension profiling and tips are currently disabled
|
||||
|
||||
@@ -164,7 +164,7 @@ If you're the current release manager, follow these steps:
|
||||
|
||||
### Publishing a release
|
||||
|
||||
1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.2.0)
|
||||
1. Create a release branch called `v0.0.0` but replace with new version
|
||||
1. Run `yarn release:prep` and type in the new version (e.g., `3.8.1`)
|
||||
1. GitHub Actions will generate the `npm-package`, `release-packages` and
|
||||
`release-images` artifacts. You do not have to wait for this step to complete
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# code-server
|
||||
|
||||
[](https://github.com/coder/code-server/discussions) [](https://coder.com/community) [](https://twitter.com/coderhq) [](https://codecov.io/gh/coder/code-server) [](https://github.com/coder/code-server/tree/v4.2.0/docs)
|
||||
[](https://github.com/coder/code-server/discussions) [](https://coder.com/community) [](https://twitter.com/coderhq) [](https://codecov.io/gh/coder/code-server) [](https://github.com/coder/code-server/tree/v4.1.0/docs)
|
||||
|
||||
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
|
||||
access it in the browser.
|
||||
|
||||
@@ -60,6 +60,6 @@ As `code-server` is based on VS Code, you can follow the steps described on Duck
|
||||
code-server --enable-proposed-api genuitecllc.codetogether
|
||||
```
|
||||
|
||||
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.2.0/FAQ#how-does-the-config-file-work).
|
||||
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.1.0/FAQ#how-does-the-config-file-work).
|
||||
|
||||
3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session.
|
||||
|
||||
@@ -52,7 +52,7 @@ There are several approaches to operating and exposing code-server securely:
|
||||
We highly recommend using [port forwarding via
|
||||
SSH](https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding) to access
|
||||
code-server. If you have an SSH server on your remote machine, this approach
|
||||
doesn't require any additional setup at all.
|
||||
doesn't required additional setup.
|
||||
|
||||
The downside to SSH forwarding, however, is that you can't access code-server
|
||||
when using machines without SSH clients (such as iPads). If this applies to you,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# code-server Helm Chart
|
||||
|
||||
[](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.2.0-informational?style=flat-square)
|
||||
[](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.1.0-informational?style=flat-square)
|
||||
|
||||
[code-server](https://github.com/coder/code-server) code-server is VS Code running
|
||||
on a remote server, accessible through the browser.
|
||||
@@ -73,7 +73,7 @@ and their default values.
|
||||
| hostnameOverride | string | `""` |
|
||||
| image.pullPolicy | string | `"Always"` |
|
||||
| image.repository | string | `"codercom/code-server"` |
|
||||
| image.tag | string | `"4.2.0"` |
|
||||
| image.tag | string | `"4.1.0"` |
|
||||
| imagePullSecrets | list | `[]` |
|
||||
| ingress.enabled | bool | `false` |
|
||||
| nameOverride | string | `""` |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"versions": ["v4.2.0"],
|
||||
"versions": ["v4.1.0"],
|
||||
"routes": [
|
||||
{
|
||||
"title": "Home",
|
||||
|
||||
Submodule lib/vscode deleted from f80445acd5
12
package.json
12
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-server",
|
||||
"license": "MIT",
|
||||
"version": "4.2.0",
|
||||
"version": "4.1.0",
|
||||
"description": "Run VS Code on a remote server.",
|
||||
"homepage": "https://github.com/coder/code-server",
|
||||
"bugs": {
|
||||
@@ -51,7 +51,7 @@
|
||||
"@types/ws": "^8.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"audit-ci": "^6.0.0",
|
||||
"audit-ci": "^5.0.0",
|
||||
"codecov": "^3.8.3",
|
||||
"doctoc": "^2.0.0",
|
||||
"eslint": "^7.7.0",
|
||||
@@ -69,7 +69,7 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"ansi-regex": "^5.0.1",
|
||||
"normalize-package-data": "^4.0.0",
|
||||
"normalize-package-data": "^3.0.0",
|
||||
"doctoc/underscore": "^1.13.1",
|
||||
"doctoc/**/trim": "^1.0.0",
|
||||
"postcss": "^8.2.1",
|
||||
@@ -81,8 +81,7 @@
|
||||
"vm2": "^3.9.6",
|
||||
"follow-redirects": "^1.14.8",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nanoid": "^3.1.31",
|
||||
"minimist": "npm:minimist-lite@2.2.0"
|
||||
"nanoid": "^3.1.31"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "1.1.16",
|
||||
@@ -128,6 +127,7 @@
|
||||
"testEnvironment": "node",
|
||||
"testPathIgnorePatterns": [
|
||||
"/node_modules/",
|
||||
"/vendor/",
|
||||
"/lib/",
|
||||
"/out/",
|
||||
"test/e2e"
|
||||
@@ -158,7 +158,7 @@
|
||||
"<rootDir>/release-npm-package",
|
||||
"<rootDir>/release-gcp",
|
||||
"<rootDir>/release-images",
|
||||
"<rootDir>/lib"
|
||||
"<rootDir>/vendor"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"^.+\\.(css|less)$": "<rootDir>/test/utils/cssStub.ts"
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
Add base path support
|
||||
|
||||
Some users will host code-server behind a path-rewriting reverse proxy, for
|
||||
example domain.tld/my/base/path. This patch adds support for that since Code
|
||||
assumes everything is on / by default.
|
||||
|
||||
To test this serve code-server behind a reverse proxy with a path like /code.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
@@ -151,8 +151,10 @@ class RemoteAuthoritiesImpl {
|
||||
}
|
||||
return URI.from({
|
||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||
- authority: `${host}:${port}`,
|
||||
- path: `/vscode-remote-resource`,
|
||||
+ authority: platform.isWeb ? window.location.host : `${host}:${port}`,
|
||||
+ path: platform.isWeb
|
||||
+ ? URI.joinPath(URI.parse(window.location.href), `/vscode-remote-resource`).path
|
||||
+ : `/vscode-remote-resource`,
|
||||
query
|
||||
});
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
@@ -11,8 +11,8 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
- <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="{{BASE}}/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="{{BASE}}/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -27,23 +27,26 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
- <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
|
||||
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
- <script src="./static/out/vs/loader.js"></script>
|
||||
- <script src="./static/out/vs/webPackagePaths.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
<script>
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
- self.webPackagePaths[key] = `${window.location.origin}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
+ self.webPackagePaths[key] = new URL(
|
||||
+ `{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
+ window.location,
|
||||
+ ).toString();
|
||||
});
|
||||
require.config({
|
||||
- baseUrl: `${window.location.origin}/static/out`,
|
||||
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
@@ -11,8 +11,8 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
- <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="{{BASE}}/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="{{BASE}}/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -24,10 +24,10 @@
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
- <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
- <link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
|
||||
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
|
||||
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
||||
+ <link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.css">
|
||||
|
||||
</head>
|
||||
|
||||
@@ -35,14 +35,17 @@
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
- <script src="./static/out/vs/loader.js"></script>
|
||||
- <script src="./static/out/vs/webPackagePaths.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
<script>
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
- self.webPackagePaths[key] = `${window.location.origin}/static/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
+ self.webPackagePaths[key] = new URL(
|
||||
+ `{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
+ window.location,
|
||||
+ ).toString();
|
||||
});
|
||||
require.config({
|
||||
- baseUrl: `${window.location.origin}/static/out`,
|
||||
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
@@ -55,7 +58,7 @@
|
||||
<script>
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
</script>
|
||||
- <script src="./static/out/vs/workbench/workbench.web.main.nls.js"></script>
|
||||
- <script src="./static/out/vs/workbench/workbench.web.main.js"></script>
|
||||
- <script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.nls.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
</html>
|
||||
Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||
@@ -274,7 +274,7 @@ export class BrowserSocketFactory implem
|
||||
|
||||
connect(host: string, port: number, query: string, debugLabel: string, callback: IConnectCallback): void {
|
||||
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
|
||||
- const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
+ const socket = this._webSocketFactory.create(`${webSocketSchema}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
const errorListener = socket.onError((err) => callback(err, undefined));
|
||||
socket.onOpen(() => {
|
||||
errorListener.dispose();
|
||||
@@ -282,6 +282,3 @@ export class BrowserSocketFactory implem
|
||||
});
|
||||
}
|
||||
}
|
||||
-
|
||||
-
|
||||
-
|
||||
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
|
||||
@@ -252,7 +252,10 @@ export class WebClientServer {
|
||||
return res.end();
|
||||
}
|
||||
|
||||
- const remoteAuthority = req.headers.host;
|
||||
+ // It is not possible to reliably detect the remote authority on the server
|
||||
+ // in all cases. Set this to something invalid to make sure we catch code
|
||||
+ // that is using this when it should not.
|
||||
+ const remoteAuthority = 'remote';
|
||||
|
||||
function escapeAttribute(value: string): string {
|
||||
return value.replace(/"/g, '"');
|
||||
@@ -272,6 +275,8 @@ export class WebClientServer {
|
||||
accessToken: this._environmentService.args['github-auth'],
|
||||
scopes: [['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
+ const base = relativeRoot(getOriginalUrl(req))
|
||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
@@ -279,6 +284,7 @@ export class WebClientServer {
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
+ rootEndpoint: base,
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
|
||||
@@ -289,7 +295,9 @@ export class WebClientServer {
|
||||
} : undefined
|
||||
}
|
||||
})))
|
||||
- .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '');
|
||||
+ .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
+ .replace(/{{BASE}}/g, base)
|
||||
+ .replace(/{{VS_BASE}}/g, vscodeBase);
|
||||
|
||||
const cspDirectives = [
|
||||
'default-src \'self\';',
|
||||
@@ -368,3 +376,70 @@ export class WebClientServer {
|
||||
return res.end(data);
|
||||
}
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * Remove extra slashes in a URL.
|
||||
+ *
|
||||
+ * This is meant to fill the job of `path.join` so you can concatenate paths and
|
||||
+ * then normalize out any extra slashes.
|
||||
+ *
|
||||
+ * If you are using `path.join` you do not need this but note that `path` is for
|
||||
+ * file system paths, not URLs.
|
||||
+ */
|
||||
+export const normalizeUrlPath = (url: string, keepTrailing = false): string => {
|
||||
+ return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Get the relative path that will get us to the root of the page. For each
|
||||
+ * slash we need to go up a directory. Will not have a trailing slash.
|
||||
+ *
|
||||
+ * For example:
|
||||
+ *
|
||||
+ * / => .
|
||||
+ * /foo => .
|
||||
+ * /foo/ => ./..
|
||||
+ * /foo/bar => ./..
|
||||
+ * /foo/bar/ => ./../..
|
||||
+ *
|
||||
+ * All paths must be relative in order to work behind a reverse proxy since we
|
||||
+ * we do not know the base path. Anything that needs to be absolute (for
|
||||
+ * example cookies) must get the base path from the frontend.
|
||||
+ *
|
||||
+ * All relative paths must be prefixed with the relative root to ensure they
|
||||
+ * work no matter the depth at which they happen to appear.
|
||||
+ *
|
||||
+ * For Express `req.originalUrl` should be used as they remove the base from the
|
||||
+ * standard `url` property making it impossible to get the true depth.
|
||||
+ */
|
||||
+export const relativeRoot = (originalUrl: string): string => {
|
||||
+ const depth = (originalUrl.split("?", 1)[0].match(/\//g) || []).length
|
||||
+ return normalizeUrlPath("./" + (depth > 1 ? "../".repeat(depth - 1) : ""))
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Get the relative path to the current resource.
|
||||
+ *
|
||||
+ * For example:
|
||||
+ *
|
||||
+ * / => .
|
||||
+ * /foo => ./foo
|
||||
+ * /foo/ => .
|
||||
+ * /foo/bar => ./bar
|
||||
+ * /foo/bar/ => .
|
||||
+ */
|
||||
+export const relativePath = (originalUrl: string): string => {
|
||||
+ const parts = originalUrl.split("?", 1)[0].split("/")
|
||||
+ return normalizeUrlPath("./" + parts[parts.length - 1])
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * code-server serves Code using Express. Express removes the base from the url
|
||||
+ * and puts the original in `originalUrl` so we must use this to get the correct
|
||||
+ * depth. Code is not aware it is behind Express so the types do not match. We
|
||||
+ * may want to continue moving code into Code and eventually remove the Express
|
||||
+ * wrapper or move the web server back into code-server.
|
||||
+ */
|
||||
+export const getOriginalUrl = (req: http.IncomingMessage): string => {
|
||||
+ return (req as any).originalUrl || req.url
|
||||
+}
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -32,6 +32,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
|
||||
export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
+ readonly rootEndpoint?: string
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -504,6 +504,7 @@ function doCreateUri(path: string, query
|
||||
});
|
||||
}
|
||||
|
||||
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
return URI.parse(window.location.href).with({ path, query });
|
||||
}
|
||||
|
||||
@@ -515,7 +516,7 @@ function doCreateUri(path: string, query
|
||||
if (!configElement || !configElementAttribute) {
|
||||
throw new Error('Missing web configuration element');
|
||||
}
|
||||
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
|
||||
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
|
||||
|
||||
// Create workbench
|
||||
create(document.body, {
|
||||
@@ -1,19 +0,0 @@
|
||||
Add connection type to web sockets
|
||||
|
||||
This allows the backend to distinguish them. In our case we use them to count a
|
||||
single "open" of Code so we need to be able to distinguish between web sockets
|
||||
from two instances and two web sockets used in a single instance.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
@@ -231,7 +231,7 @@ async function connectToRemoteExtensionH
|
||||
|
||||
let socket: ISocket;
|
||||
try {
|
||||
- socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
+ socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `type=${connectionTypeToString(connectionType)}&reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
} catch (error) {
|
||||
options.logService.error(`${logPrefix} socketFactory.connect() failed or timed out. Error:`);
|
||||
options.logService.error(error);
|
||||
@@ -1,265 +0,0 @@
|
||||
Add display language support
|
||||
|
||||
This likely needs tweaking if we want to upstream.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -198,6 +198,9 @@ export async function setupServerService
|
||||
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
||||
socketServer.registerChannel('extensions', channel);
|
||||
|
||||
+ const localizationsChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILocalizationsService));
|
||||
+ socketServer.registerChannel('localizations', localizationsChannel);
|
||||
+
|
||||
const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
|
||||
socketServer.registerChannel('encryption', encryptionChannel);
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/platform.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
@@ -83,6 +83,17 @@ if (typeof navigator === 'object' && !is
|
||||
_isWeb = true;
|
||||
_locale = navigator.language;
|
||||
_language = _locale;
|
||||
+
|
||||
+ const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
|
||||
+ const rawNlsConfig = el && el.getAttribute('data-settings');
|
||||
+ if (rawNlsConfig) {
|
||||
+ try {
|
||||
+ const nlsConfig: NLSConfig = JSON.parse(rawNlsConfig);
|
||||
+ _locale = nlsConfig.locale;
|
||||
+ _translationsConfigFile = nlsConfig._translationsConfigFile;
|
||||
+ _language = nlsConfig.availableLanguages['*'] || LANGUAGE_DEFAULT;
|
||||
+ } catch (error) { /* Oh well. */ }
|
||||
+ }
|
||||
}
|
||||
|
||||
// Native environment
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
@@ -23,6 +23,9 @@
|
||||
<!-- Workbench Auth Session -->
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
+ <!-- NLS Configuration -->
|
||||
+ <meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
|
||||
+
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
|
||||
@@ -38,6 +41,27 @@
|
||||
<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
<script>
|
||||
+ let nlsConfig
|
||||
+ try {
|
||||
+ nlsConfig = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
|
||||
+ if (nlsConfig._resolvedLanguagePackCoreLocation) {
|
||||
+ const bundles = Object.create(null)
|
||||
+ nlsConfig.loadBundle = (bundle, _language, cb) => {
|
||||
+ const result = bundles[bundle]
|
||||
+ if (result) {
|
||||
+ return cb(undefined, result)
|
||||
+ }
|
||||
+ const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
|
||||
+ fetch(`{{VS_BASE}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
|
||||
+ .then((response) => response.json())
|
||||
+ .then((json) => {
|
||||
+ bundles[bundle] = json
|
||||
+ cb(undefined, json)
|
||||
+ })
|
||||
+ .catch(cb)
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (error) { /* Probably fine. */ }
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
self.webPackagePaths[key] = new URL(
|
||||
`{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
@@ -52,7 +76,8 @@
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
- paths: self.webPackagePaths
|
||||
+ paths: self.webPackagePaths,
|
||||
+ 'vs/nls': nlsConfig,
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
@@ -105,7 +105,7 @@ export abstract class AbstractNativeEnvi
|
||||
return URI.file(join(vscodePortable, 'argv.json'));
|
||||
}
|
||||
|
||||
- return joinPath(this.userHome, this.productService.dataFolderName, 'argv.json');
|
||||
+ return joinPath(this.appSettingsHome, 'argv.json');
|
||||
}
|
||||
|
||||
@memoize
|
||||
Index: code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
@@ -30,6 +30,12 @@ export function getNLSConfiguration(lang
|
||||
if (InternalNLSConfiguration.is(value)) {
|
||||
value._languagePackSupport = true;
|
||||
}
|
||||
+ // If the configuration has no results keep trying since code-server
|
||||
+ // doesn't restart when a language is installed so this result would
|
||||
+ // persist (the plugin might not be installed yet for example).
|
||||
+ if (value.locale !== 'en' && value.locale !== 'en-us' && Object.keys(value.availableLanguages).length === 0) {
|
||||
+ _cache.delete(key);
|
||||
+ }
|
||||
return value;
|
||||
});
|
||||
_cache.set(key, result);
|
||||
@@ -44,3 +50,43 @@ export namespace InternalNLSConfiguratio
|
||||
return candidate && typeof candidate._languagePackId === 'string';
|
||||
}
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * The code below is copied from from src/main.js.
|
||||
+ */
|
||||
+
|
||||
+export const getLocaleFromConfig = async (argvResource: string): Promise<string> => {
|
||||
+ try {
|
||||
+ const content = stripComments(await fs.promises.readFile(argvResource, 'utf8'));
|
||||
+ return JSON.parse(content).locale;
|
||||
+ } catch (error) {
|
||||
+ if (error.code !== "ENOENT") {
|
||||
+ console.warn(error)
|
||||
+ }
|
||||
+ return 'en';
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+const stripComments = (content: string): string => {
|
||||
+ const regexp = /('(?:[^\\']*(?:\\.)?)*')|('(?:[^\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
|
||||
+
|
||||
+ return content.replace(regexp, (match, _m1, _m2, m3, m4) => {
|
||||
+ // Only one of m1, m2, m3, m4 matches
|
||||
+ if (m3) {
|
||||
+ // A block comment. Replace with nothing
|
||||
+ return '';
|
||||
+ } else if (m4) {
|
||||
+ // A line comment. If it ends in \r?\n then keep it.
|
||||
+ const length_1 = m4.length;
|
||||
+ if (length_1 > 2 && m4[length_1 - 1] === '\n') {
|
||||
+ return m4[length_1 - 2] === '\r' ? '\r\n' : '\n';
|
||||
+ }
|
||||
+ else {
|
||||
+ return '';
|
||||
+ }
|
||||
+ } else {
|
||||
+ // We match a string
|
||||
+ return match;
|
||||
+ }
|
||||
+ });
|
||||
+};
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
import { streamToBuffer } from 'vs/base/common/buffer';
|
||||
import { IProductConfiguration } from 'vs/base/common/product';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
+import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
|
||||
|
||||
const textMimeType = {
|
||||
'.html': 'text/html',
|
||||
@@ -277,6 +278,8 @@ export class WebClientServer {
|
||||
} : undefined;
|
||||
const base = relativeRoot(getOriginalUrl(req))
|
||||
const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
+ const locale = this._environmentService.args.locale || await getLocaleFromConfig(this._environmentService.argvResource.fsPath);
|
||||
+ const nlsConfiguration = await getNLSConfiguration(locale, this._environmentService.userDataPath)
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
@@ -301,7 +304,8 @@ export class WebClientServer {
|
||||
})))
|
||||
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
.replace(/{{BASE}}/g, base)
|
||||
- .replace(/{{VS_BASE}}/g, vscodeBase);
|
||||
+ .replace(/{{VS_BASE}}/g, vscodeBase)
|
||||
+ .replace(/{{NLS_CONFIGURATION}}/g, () => escapeAttribute(JSON.stringify(nlsConfiguration)));
|
||||
|
||||
const cspDirectives = [
|
||||
'default-src \'self\';',
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
+ 'locale': { type: 'string' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -90,6 +91,7 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
+ 'locale'?: string
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
|
||||
@@ -0,0 +1,28 @@
|
||||
+/*---------------------------------------------------------------------------------------------
|
||||
+ * Copyright (c) Coder Technologies. All rights reserved.
|
||||
+ * Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
+ *--------------------------------------------------------------------------------------------*/
|
||||
+
|
||||
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
+import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
+
|
||||
+/**
|
||||
+ * Add localizations service for the browser.
|
||||
+ * @author coder
|
||||
+ */
|
||||
+
|
||||
+// @ts-ignore: interface is implemented via proxy
|
||||
+export class LocalizationsService implements ILocalizationsService {
|
||||
+
|
||||
+ declare readonly _serviceBrand: undefined;
|
||||
+
|
||||
+ constructor(
|
||||
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
+ ) {
|
||||
+ return ProxyChannel.toService<ILocalizationsService>(remoteAgentService.getConnection()!.getChannel('localizations'));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+registerSingleton(ILocalizationsService, LocalizationsService, true);
|
||||
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
@@ -109,6 +109,10 @@ registerSingleton(ICustomEndpointTelemet
|
||||
|
||||
//#region --- workbench contributions
|
||||
|
||||
+// Localizations
|
||||
+import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
|
||||
+import 'vs/workbench/services/localizations/browser/localizationsService';
|
||||
+
|
||||
// Output
|
||||
import 'vs/workbench/contrib/output/common/outputChannelModelService';
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
Use our own GitHub auth relay server
|
||||
|
||||
Microsoft's does not work with self-hosted instances so we run our own.
|
||||
|
||||
Also add an extra set of scopes so that tokens provided via --github-auth will
|
||||
work for the PR extension.
|
||||
|
||||
Index: code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
+++ code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
@@ -17,7 +17,7 @@ const localize = nls.loadMessageBundle()
|
||||
const CLIENT_ID = '01ab8ac9400c4e429b23';
|
||||
|
||||
const NETWORK_ERROR = 'network error';
|
||||
-const AUTH_RELAY_SERVER = 'vscode-auth.github.com';
|
||||
+const AUTH_RELAY_SERVER = 'auth.code-server.dev';
|
||||
// const AUTH_RELAY_STAGING_SERVER = 'client-auth-staging-14a768b.herokuapp.com';
|
||||
|
||||
class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler {
|
||||
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
|
||||
@@ -274,7 +274,7 @@ export class WebClientServer {
|
||||
id: generateUuid(),
|
||||
providerId: 'github',
|
||||
accessToken: this._environmentService.args['github-auth'],
|
||||
- scopes: [['user:email'], ['repo']]
|
||||
+ scopes: [['read:user', 'user:email', 'repo'], ['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
const base = relativeRoot(getOriginalUrl(req))
|
||||
const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -17,6 +17,7 @@ import { isFolderToOpen, isWorkspaceToOp
|
||||
import { create, ICredentialsProvider, IURLCallbackProvider, IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/workbench.web.main';
|
||||
import { posix } from 'vs/base/common/path';
|
||||
import { ltrim } from 'vs/base/common/strings';
|
||||
+import { equals as arrayEquals } from 'vs/base/common/arrays';
|
||||
|
||||
interface ICredential {
|
||||
service: string;
|
||||
@@ -24,6 +25,13 @@ interface ICredential {
|
||||
password: string;
|
||||
}
|
||||
|
||||
+interface IToken {
|
||||
+ accessToken: string
|
||||
+ account?: { label: string }
|
||||
+ id: string
|
||||
+ scopes: string[]
|
||||
+}
|
||||
+
|
||||
class LocalStorageCredentialsProvider implements ICredentialsProvider {
|
||||
|
||||
private static readonly CREDENTIALS_STORAGE_KEY = 'credentials.provider';
|
||||
@@ -51,6 +59,58 @@ class LocalStorageCredentialsProvider im
|
||||
scopes,
|
||||
accessToken: authSessionInfo!.accessToken
|
||||
}))));
|
||||
+
|
||||
+ // Add tokens for extensions to use. This works for extensions like the
|
||||
+ // pull requests one or GitLens.
|
||||
+ const extensionId = `vscode.${authSessionInfo.providerId}-authentication`;
|
||||
+ const service = `${product.urlProtocol}${extensionId}`;
|
||||
+ const account = `${authSessionInfo.providerId}.auth`;
|
||||
+ // Oddly the scopes need to match exactly so we cannot just have one token
|
||||
+ // with all the scopes, instead we have to duplicate the token for each
|
||||
+ // expected set of scopes.
|
||||
+ const tokens: IToken[] = authSessionInfo.scopes.map((scopes) => ({
|
||||
+ id: authSessionInfo!.id,
|
||||
+ scopes: scopes.sort(), // Sort for comparing later.
|
||||
+ accessToken: authSessionInfo!.accessToken,
|
||||
+ }));
|
||||
+ this.getPassword(service, account).then((raw) => {
|
||||
+ let existing: {
|
||||
+ content: IToken[]
|
||||
+ } | undefined;
|
||||
+
|
||||
+ if (raw) {
|
||||
+ try {
|
||||
+ const json = JSON.parse(raw);
|
||||
+ json.content = JSON.parse(json.content);
|
||||
+ existing = json;
|
||||
+ } catch (error) {
|
||||
+ console.log(error);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Keep tokens for account and scope combinations we do not have in case
|
||||
+ // there is an extension that uses scopes we have not accounted for (in
|
||||
+ // these cases the user will need to manually authenticate the extension
|
||||
+ // through the UI) or the user has tokens for other accounts.
|
||||
+ if (existing?.content) {
|
||||
+ existing.content = existing.content.filter((existingToken) => {
|
||||
+ const scopes = existingToken.scopes.sort();
|
||||
+ return !(tokens.find((token) => {
|
||||
+ return arrayEquals(scopes, token.scopes)
|
||||
+ && token.account?.label === existingToken.account?.label;
|
||||
+ }))
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return this.setPassword(service, account, JSON.stringify({
|
||||
+ extensionId,
|
||||
+ ...(existing || {}),
|
||||
+ content: JSON.stringify([
|
||||
+ ...tokens,
|
||||
+ ...(existing?.content || []),
|
||||
+ ])
|
||||
+ }));
|
||||
+ })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
Add a notification when accessing code-server in an insecure context
|
||||
|
||||
This is done because otherwise when things like the clipboard do not work users
|
||||
may think code-server is broken. Ideally there would be a notification at the
|
||||
point where these things are used instead of this though.
|
||||
|
||||
To test access over something like an HTTP domain or an IP address (not
|
||||
localhost).
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
+import { localize } from 'vs/nls';
|
||||
+import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export class CodeServerClient extends Disposable {
|
||||
constructor (
|
||||
+ @INotificationService private notificationService: INotificationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -42,5 +45,32 @@ export class CodeServerClient extends Di
|
||||
}
|
||||
});
|
||||
}
|
||||
+
|
||||
+ if (!window.isSecureContext) {
|
||||
+ this.notificationService.notify({
|
||||
+ severity: Severity.Warning,
|
||||
+ message: localize(
|
||||
+ 'insecureContext',
|
||||
+ "{0} is being accessed in an insecure context. Web views, the clipboard, and other functionality may not work as expected.",
|
||||
+ 'code-server',
|
||||
+ ),
|
||||
+ actions: {
|
||||
+ primary: [
|
||||
+ {
|
||||
+ id: 'understand',
|
||||
+ label: localize('confirmInsecure', "I understand"),
|
||||
+ tooltip: '',
|
||||
+ class: undefined,
|
||||
+ enabled: true,
|
||||
+ checked: true,
|
||||
+ dispose: () => undefined,
|
||||
+ run: () => {
|
||||
+ return Promise.resolve();
|
||||
+ },
|
||||
+ },
|
||||
+ ],
|
||||
+ },
|
||||
+ });
|
||||
+ }
|
||||
}
|
||||
}
|
||||
@@ -1,269 +0,0 @@
|
||||
Prepare Code for integration with code-server
|
||||
|
||||
1. We already have the arguments so allow passing them in. There is also a
|
||||
slight change in a few directories to preserve the directory structure we
|
||||
have been using and to not override passed-in arguments.
|
||||
2. Modify the terminal environment to filter out code-server environment variables.
|
||||
3. Add the code-server version to the help dialog.
|
||||
4. Add ready events for use in an iframe.
|
||||
5. Add our icons.
|
||||
6. Remove sourcemap host since we cannot upload ours there.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/server.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
@@ -12,7 +12,7 @@ import { createServer as doCreateServer,
|
||||
import { parseArgs, ErrorReporter } from 'vs/platform/environment/node/argv';
|
||||
import { join, dirname } from 'vs/base/common/path';
|
||||
import { performance } from 'perf_hooks';
|
||||
-import { serverOptions } from 'vs/server/node/serverEnvironmentService';
|
||||
+import { serverOptions, ServerParsedArgs } from 'vs/server/node/serverEnvironmentService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import * as perf from 'vs/base/common/performance';
|
||||
|
||||
@@ -33,37 +33,42 @@ const errorReporter: ErrorReporter = {
|
||||
}
|
||||
};
|
||||
|
||||
-const args = parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||
+function parse(): ServerParsedArgs {
|
||||
+ return parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||
+}
|
||||
|
||||
-const REMOTE_DATA_FOLDER = args['server-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
||||
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
|
||||
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
||||
-const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
|
||||
-const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
-args['user-data-dir'] = USER_DATA_PATH;
|
||||
-const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
-const BUILTIN_EXTENSIONS_FOLDER_PATH = join(APP_ROOT, 'extensions');
|
||||
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
-
|
||||
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
|
||||
- try {
|
||||
- if (!fs.existsSync(f)) {
|
||||
- fs.mkdirSync(f, { mode: 0o700 });
|
||||
- }
|
||||
- } catch (err) { console.error(err); }
|
||||
-});
|
||||
+function createDirs(args: ServerParsedArgs): string {
|
||||
+ const REMOTE_DATA_FOLDER = args['server-data-dir'] || args['user-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
||||
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
|
||||
+ const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
||||
+ const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
|
||||
+ const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
+ args['user-data-dir'] = USER_DATA_PATH;
|
||||
+ const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
+ const BUILTIN_EXTENSIONS_FOLDER_PATH = args['builtin-extensions-dir'] || join(APP_ROOT, 'extensions');
|
||||
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
+
|
||||
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
|
||||
+ try {
|
||||
+ if (!fs.existsSync(f)) {
|
||||
+ fs.mkdirSync(f, { mode: 0o700 });
|
||||
+ }
|
||||
+ } catch (err) { console.error(err); }
|
||||
+ });
|
||||
+ return REMOTE_DATA_FOLDER
|
||||
+}
|
||||
|
||||
/**
|
||||
* invoked by server-main.js
|
||||
*/
|
||||
-export function spawnCli() {
|
||||
- runCli(args, REMOTE_DATA_FOLDER, serverOptions);
|
||||
+export function spawnCli(args = parse()): Promise<void> {
|
||||
+ return runCli(args, createDirs(args), serverOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* invoked by server-main.js
|
||||
*/
|
||||
-export function createServer(address: string | net.AddressInfo | null): Promise<IServerAPI> {
|
||||
- return doCreateServer(address, args, REMOTE_DATA_FOLDER);
|
||||
+export function createServer(address: string | net.AddressInfo | null, args = parse()): Promise<IServerAPI> {
|
||||
+ return doCreateServer(address, args, createDirs(args));
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/base/common/processes.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/processes.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/processes.ts
|
||||
@@ -111,6 +111,8 @@ export function sanitizeProcessEnvironme
|
||||
/^VSCODE_(?!SHELL_LOGIN).+$/,
|
||||
/^SNAP(|_.*)$/,
|
||||
/^GDK_PIXBUF_.+$/,
|
||||
+ /^CODE_SERVER_.+$/,
|
||||
+ /^CS_.+$/,
|
||||
];
|
||||
const envKeys = Object.keys(env);
|
||||
envKeys
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
|
||||
@@ -144,11 +144,12 @@ export class BrowserDialogHandler implem
|
||||
async about(): Promise<void> {
|
||||
const detailString = (useAgo: boolean): string => {
|
||||
return localize('aboutDetail',
|
||||
- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
|
||||
+ "code-server: v{4}\nCode: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
|
||||
this.productService.version || 'Unknown',
|
||||
this.productService.commit || 'Unknown',
|
||||
this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
|
||||
- navigator.userAgent
|
||||
+ navigator.userAgent,
|
||||
+ this.productService.codeServerVersion || 'Unknown'
|
||||
);
|
||||
};
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -0,0 +1,46 @@
|
||||
+import { Disposable } from 'vs/base/common/lifecycle';
|
||||
+
|
||||
+export class CodeServerClient extends Disposable {
|
||||
+ constructor (
|
||||
+ ) {
|
||||
+ super();
|
||||
+ }
|
||||
+
|
||||
+ async startup(): Promise<void> {
|
||||
+ // Emit ready events
|
||||
+ const event = new CustomEvent('ide-ready');
|
||||
+ window.dispatchEvent(event);
|
||||
+
|
||||
+ if (parent) {
|
||||
+ // Tell the parent loading has completed.
|
||||
+ parent.postMessage({ event: 'loaded' }, '*');
|
||||
+
|
||||
+ // Proxy or stop proxing events as requested by the parent.
|
||||
+ const listeners = new Map<string, (event: Event) => void>();
|
||||
+
|
||||
+ window.addEventListener('message', parentEvent => {
|
||||
+ const eventName = parentEvent.data.bind || parentEvent.data.unbind;
|
||||
+ if (eventName) {
|
||||
+ const oldListener = listeners.get(eventName);
|
||||
+ if (oldListener) {
|
||||
+ document.removeEventListener(eventName, oldListener);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (parentEvent.data.bind && parentEvent.data.prop) {
|
||||
+ const listener = (event: Event) => {
|
||||
+ parent?.postMessage(
|
||||
+ {
|
||||
+ event: parentEvent.data.event,
|
||||
+ [parentEvent.data.prop]: event[parentEvent.data.prop as keyof Event],
|
||||
+ },
|
||||
+ window.location.origin,
|
||||
+ );
|
||||
+ };
|
||||
+ listeners.set(parentEvent.data.bind, listener);
|
||||
+ document.addEventListener(parentEvent.data.bind, listener);
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -69,6 +69,7 @@ import { ICredentialsService } from 'vs/
|
||||
import { IndexedDB } from 'vs/base/browser/indexedDB';
|
||||
import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService';
|
||||
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
+import { CodeServerClient } from 'vs/workbench/browser/client';
|
||||
|
||||
export class BrowserMain extends Disposable {
|
||||
|
||||
@@ -103,6 +104,9 @@ export class BrowserMain extends Disposa
|
||||
// Startup
|
||||
const instantiationService = workbench.startup();
|
||||
|
||||
+ const codeServerClient = this._register(instantiationService.createInstance(CodeServerClient));
|
||||
+ await codeServerClient.startup();
|
||||
+
|
||||
// Window
|
||||
this._register(instantiationService.createInstance(BrowserWindow));
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -31,6 +31,8 @@ export type ExtensionVirtualWorkspaceSup
|
||||
};
|
||||
|
||||
export interface IProductConfiguration {
|
||||
+ readonly codeServerVersion?: string
|
||||
+
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
readonly quality?: string;
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
@@ -11,7 +11,8 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" href="/code-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -26,7 +27,8 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
</head>
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
@@ -11,7 +11,8 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" href="/code-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -23,7 +24,8 @@
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
|
||||
|
||||
Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
||||
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
||||
@@ -365,7 +365,7 @@ function packageTask(type, platform, arc
|
||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||
optimizeTask,
|
||||
util.rimraf(`out-vscode-${type}-min`),
|
||||
- common.minifyTask(`out-vscode-${type}`, `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
|
||||
+ common.minifyTask(`out-vscode-${type}`, ``)
|
||||
));
|
||||
gulp.task(minifyTask);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
Remove last opened functionality
|
||||
|
||||
This conflicts with our own handling of the last opened workspace. If we wanted
|
||||
to switch to this we would need to pass through the disable-last-opened flag and
|
||||
respect it here then remove our own redirction code that handles this.
|
||||
|
||||
Our version might be better anyway since it puts the workspace in the URL.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -350,19 +350,6 @@ class WorkspaceProvider implements IWork
|
||||
workspace = { folderUri: URI.revive(config.folderUri) };
|
||||
} else if (config.workspaceUri) {
|
||||
workspace = { workspaceUri: URI.revive(config.workspaceUri) };
|
||||
- } else {
|
||||
- workspace = (() => {
|
||||
- const lastWorkspaceRaw = window.localStorage.getItem(WorkspaceProvider.LAST_WORKSPACE_STORAGE_KEY);
|
||||
- if (lastWorkspaceRaw) {
|
||||
- try {
|
||||
- return parse(lastWorkspaceRaw); // use marshalling#parse() to revive potential URIs
|
||||
- } catch (error) {
|
||||
- // Ignore
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return undefined;
|
||||
- })();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
Make storage local to the remote server
|
||||
|
||||
This solves two problems:
|
||||
1. Extensions running in the browser (like Vim) might use these paths
|
||||
directly instead of using the file service and most likely can't write
|
||||
to `/User` on disk.
|
||||
2. Settings will be stored in the file system instead of in browser
|
||||
storage. Using browser storage makes sharing or seeding settings
|
||||
between browsers difficult. We may want to revisit this once/if we get
|
||||
settings sync.
|
||||
|
||||
Unfortunately this does not affect state which uses a separate method with
|
||||
IndexedDB and does not appear nearly as easy to redirect to disk.
|
||||
|
||||
To test install the Vim extension and make sure something that uses file storage
|
||||
works (history recall for example) and change settings from the UI and on disk
|
||||
while making sure they appear on the other side.
|
||||
|
||||
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
|
||||
@@ -289,6 +289,7 @@ export class WebClientServer {
|
||||
enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
|
||||
logLevel: this._logService.getLevel(),
|
||||
},
|
||||
+ userDataPath: this._environmentService.userDataPath,
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -205,6 +205,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly configurationDefaults?: Record<string, any>;
|
||||
|
||||
+ /**
|
||||
+ * Path to the user data directory.
|
||||
+ */
|
||||
+ readonly userDataPath?: string
|
||||
+
|
||||
//#endregion
|
||||
|
||||
|
||||
Index: code-server/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
|
||||
@@ -126,7 +126,14 @@ export class BrowserWorkbenchEnvironment
|
||||
get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
|
||||
|
||||
@memoize
|
||||
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); }
|
||||
+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
|
||||
+
|
||||
+ get userDataPath(): string {
|
||||
+ if (!this.options.userDataPath) {
|
||||
+ throw new Error('userDataPath was not provided to the browser');
|
||||
+ }
|
||||
+ return this.options.userDataPath;
|
||||
+ }
|
||||
|
||||
@memoize
|
||||
get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||
@@ -1,21 +0,0 @@
|
||||
Propagate the log level to the client
|
||||
|
||||
This can be tested by using `--log trace`. You should see plenty of debug and
|
||||
trace logs in the console.
|
||||
|
||||
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
|
||||
@@ -285,7 +285,10 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
- developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
+ developmentOptions: {
|
||||
+ enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
|
||||
+ logLevel: this._logService.getLevel(),
|
||||
+ },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
@@ -1,107 +0,0 @@
|
||||
Add a logout command and menu item
|
||||
|
||||
This will only show if you have authentication enabled.
|
||||
|
||||
This has e2e tests but are currently disabled and need to be fixed.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -34,6 +34,7 @@ export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
readonly updateEndpoint?: string
|
||||
+ readonly logoutEndpoint?: string
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -13,6 +13,7 @@ import { IEnvironmentService, INativeEnv
|
||||
export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
+ 'auth': { type: 'string' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -88,6 +89,7 @@ export const serverOptions: OptionDescri
|
||||
export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
+ 'auth'?: 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
|
||||
@@ -287,6 +287,7 @@ export class WebClientServer {
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
+ logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
|
||||
extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
+import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
+import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class CodeServerClient extends Disposable {
|
||||
+ static LOGOUT_COMMAND_ID = 'code-server.logout';
|
||||
+
|
||||
constructor (
|
||||
@ILogService private logService: ILogService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@@ -82,6 +86,10 @@ export class CodeServerClient extends Di
|
||||
if (this.productService.updateEndpoint) {
|
||||
this.checkUpdates(this.productService.updateEndpoint)
|
||||
}
|
||||
+
|
||||
+ if (this.productService.logoutEndpoint) {
|
||||
+ this.addLogoutCommand(this.productService.logoutEndpoint);
|
||||
+ }
|
||||
}
|
||||
|
||||
private checkUpdates(updateEndpoint: string) {
|
||||
@@ -133,4 +141,25 @@ export class CodeServerClient extends Di
|
||||
|
||||
updateLoop();
|
||||
}
|
||||
+
|
||||
+ private addLogoutCommand(logoutEndpoint: string) {
|
||||
+ CommandsRegistry.registerCommand(CodeServerClient.LOGOUT_COMMAND_ID, () => {
|
||||
+ const logoutUrl = new URL(logoutEndpoint, window.location.href);
|
||||
+ // Cookies must be set with absolute paths and must use the same path to
|
||||
+ // be unset (we set it on the root) so send the relative root and the
|
||||
+ // current href so the backend can derive the absolute path to the root.
|
||||
+ logoutUrl.searchParams.set('base', this.productService.rootEndpoint || ".");
|
||||
+ logoutUrl.searchParams.set('href', window.location.href);
|
||||
+ window.location.assign(logoutUrl);
|
||||
+ });
|
||||
+
|
||||
+ for (const menuId of [MenuId.CommandPalette, MenuId.MenubarHomeMenu]) {
|
||||
+ MenuRegistry.appendMenuItem(menuId, {
|
||||
+ command: {
|
||||
+ id: CodeServerClient.LOGOUT_COMMAND_ID,
|
||||
+ title: localize('logout', "Sign out of {0}", 'code-server'),
|
||||
+ },
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
Add Open VSX default and an env var for marketplace, fix old marketplace
|
||||
|
||||
Our old marketplace only supports `serviceUrl` but this causes the marketplace
|
||||
to be disabled entirely so this moves the template var check to fix that.
|
||||
|
||||
This can be tested by setting EXTENSIONS_GALLERY set to:
|
||||
|
||||
'{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
@@ -45,7 +45,14 @@ else if (typeof require?.__$__nodeRequir
|
||||
}
|
||||
|
||||
Object.assign(product, {
|
||||
- version: pkg.version
|
||||
+ version: pkg.version,
|
||||
+ extensionsGallery: env.EXTENSIONS_GALLERY ? JSON.parse(env.EXTENSIONS_GALLERY) : (product.extensionsGallery || {
|
||||
+ serviceUrl: "https://open-vsx.org/vscode/gallery",
|
||||
+ itemUrl: "https://open-vsx.org/vscode/item",
|
||||
+ resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
||||
+ controlUrl: "",
|
||||
+ recommendationsUrl: "",
|
||||
+ }),
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
@@ -285,14 +285,14 @@ export class WebClientServer {
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
+ extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
|
||||
+ 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
scheme: 'http',
|
||||
authority: remoteAuthority,
|
||||
path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||
- }).toString(true)
|
||||
- } : undefined
|
||||
+ }).toString(true) : undefined
|
||||
+ },
|
||||
}
|
||||
})))
|
||||
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
@@ -1,106 +0,0 @@
|
||||
Patch the Node version to use the current version of Node
|
||||
|
||||
Previously it would use the yarnrc which results in builds that cannot run with
|
||||
the version of Node they were built with because the native modules are
|
||||
targeting the wrong version.
|
||||
|
||||
One way test this is to build in a fresh Docker container, run the build, then
|
||||
try opening the built-in terminal.
|
||||
|
||||
Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
||||
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
||||
@@ -122,9 +122,7 @@ const serverWithWebEntryPoints = [
|
||||
];
|
||||
|
||||
function getNodeVersion() {
|
||||
- const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
|
||||
const nodeVersion = getNodeVersion();
|
||||
Index: code-server/lib/vscode/build/lib/node.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/node.js
|
||||
+++ code-server/lib/vscode/build/lib/node.js
|
||||
@@ -7,9 +7,7 @@ Object.defineProperty(exports, "__esModu
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
|
||||
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
|
||||
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1];
|
||||
+const version = process.versions.node;
|
||||
const platform = process.platform;
|
||||
const arch = platform === 'darwin' ? 'x64' : process.arch;
|
||||
const node = platform === 'win32' ? 'node.exe' : 'node';
|
||||
Index: code-server/lib/vscode/build/lib/node.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/node.ts
|
||||
+++ code-server/lib/vscode/build/lib/node.ts
|
||||
@@ -7,9 +7,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
|
||||
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
|
||||
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)![1];
|
||||
+const version = process.versions.node;
|
||||
|
||||
const platform = process.platform;
|
||||
const arch = platform === 'darwin' ? 'x64' : process.arch;
|
||||
Index: code-server/lib/vscode/build/lib/util.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/util.js
|
||||
+++ code-server/lib/vscode/build/lib/util.js
|
||||
@@ -298,9 +298,7 @@ function streamToPromise(stream) {
|
||||
}
|
||||
exports.streamToPromise = streamToPromise;
|
||||
function getElectronVersion() {
|
||||
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
exports.getElectronVersion = getElectronVersion;
|
||||
function acquireWebNodePaths() {
|
||||
Index: code-server/lib/vscode/build/lib/util.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/util.ts
|
||||
+++ code-server/lib/vscode/build/lib/util.ts
|
||||
@@ -371,9 +371,7 @@ export function streamToPromise(stream:
|
||||
}
|
||||
|
||||
export function getElectronVersion(): string {
|
||||
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)![1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
|
||||
export function acquireWebNodePaths() {
|
||||
@@ -455,4 +453,3 @@ export function buildWebNodePaths(outDir
|
||||
result.taskName = 'build-web-node-paths';
|
||||
return result;
|
||||
}
|
||||
-
|
||||
Index: code-server/lib/vscode/remote/.yarnrc
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/remote/.yarnrc
|
||||
+++ /dev/null
|
||||
@@ -1,3 +0,0 @@
|
||||
-disturl "http://nodejs.org/dist"
|
||||
-target "14.16.0"
|
||||
-runtime "node"
|
||||
Index: code-server/lib/vscode/.yarnrc
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/.yarnrc
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-disturl "https://electronjs.org/headers"
|
||||
-target "13.5.2"
|
||||
-runtime "electron"
|
||||
-build_from_source "true"
|
||||
@@ -1,26 +0,0 @@
|
||||
Replace rimraf with fs.rmSync in postinstall
|
||||
|
||||
The postinstall gets ran when you install with npm but rimraf is a development
|
||||
dependency so it will not exist.
|
||||
|
||||
Index: code-server/lib/vscode/extensions/postinstall.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/extensions/postinstall.js
|
||||
+++ code-server/lib/vscode/extensions/postinstall.js
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const rimraf = require('rimraf');
|
||||
|
||||
const root = path.join(__dirname, 'node_modules', 'typescript');
|
||||
|
||||
@@ -21,7 +20,7 @@ function processRoot() {
|
||||
if (!toKeep.has(name)) {
|
||||
const filePath = path.join(root, name);
|
||||
console.log(`Removed ${filePath}`);
|
||||
- rimraf.sync(filePath);
|
||||
+ fs.rmSync(filePath, { recursive: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
Unconditionally enable the proposed API
|
||||
|
||||
To test run an extension that uses the proposed API.
|
||||
|
||||
We also override isProposedApiEnabled in case an extension does not declare the
|
||||
APIs it needs correctly (the Jupyter extension had this issue).
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
@@ -1134,7 +1134,7 @@ class ProposedApiController {
|
||||
|
||||
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
|
||||
|
||||
- this._envEnablesProposedApiForAll =
|
||||
+ this._envEnablesProposedApiForAll = true ||
|
||||
!_environmentService.isBuilt || // always allow proposed API when running out of sources
|
||||
(_environmentService.isExtensionDevelopment && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension
|
||||
(this._envEnabledExtensions.size === 0 && Array.isArray(_environmentService.extensionEnabledProposedApi)); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
@@ -135,10 +135,7 @@ export interface IExtensionHost {
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
- if (!extension.enabledApiProposals) {
|
||||
- return false;
|
||||
- }
|
||||
- return extension.enabledApiProposals.includes(proposal);
|
||||
+ return true
|
||||
}
|
||||
|
||||
export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
|
||||
@@ -1,104 +0,0 @@
|
||||
Add VSCODE_PROXY_URI environment variable
|
||||
|
||||
This can be used by extensions to open a port and access it through the proxy.
|
||||
|
||||
It is available in the terminal as well.
|
||||
|
||||
This can be tested using printenv in the terminal and by using the
|
||||
codeServerTest.proxyUri command through the test extension (copy it into your
|
||||
extensions, use --extensions-dir, or symlink it).
|
||||
|
||||
This has e2e tests.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -35,6 +35,7 @@ export interface IProductConfiguration {
|
||||
readonly rootEndpoint?: string
|
||||
readonly updateEndpoint?: string
|
||||
readonly logoutEndpoint?: string
|
||||
+ readonly proxyEndpointTemplate?: string
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { RemoteAuthorities } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
-import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
+import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
|
||||
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
|
||||
|
||||
@@ -20,7 +20,7 @@ export class RemoteAuthorityResolverServ
|
||||
private readonly _connectionToken: string | undefined;
|
||||
private readonly _connectionTokens: Map<string, string>;
|
||||
|
||||
- constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
|
||||
+ constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
|
||||
super();
|
||||
this._cache = new Map<string, ResolverResult>();
|
||||
this._connectionToken = connectionToken;
|
||||
@@ -59,12 +59,17 @@ export class RemoteAuthorityResolverServ
|
||||
|
||||
private _doResolveAuthority(authority: string): ResolverResult {
|
||||
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
|
||||
+ let options: ResolvedOptions | undefined
|
||||
+ if (this.proxyEndpointTemplate) {
|
||||
+ const proxyUrl = new URL(this.proxyEndpointTemplate, window.location.href);
|
||||
+ options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }}
|
||||
+ }
|
||||
if (authority.indexOf(':') >= 0) {
|
||||
const pieces = authority.split(':');
|
||||
- return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } };
|
||||
+ return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken }, options };
|
||||
}
|
||||
const port = (/^https:/.test(window.location.href) ? 443 : 80);
|
||||
- return { authority: { authority, host: authority, port: port, connectionToken } };
|
||||
+ return { authority: { authority, host: authority, port: port, connectionToken }, options };
|
||||
}
|
||||
|
||||
_clearResolvedAuthority(authority: string): void {
|
||||
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
|
||||
@@ -288,6 +288,7 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
|
||||
+ proxyEndpointTemplate: base + '/proxy/{{port}}',
|
||||
extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -179,7 +179,7 @@ export class BrowserMain extends Disposa
|
||||
|
||||
// Remote
|
||||
const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
|
||||
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider);
|
||||
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
|
||||
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
|
||||
|
||||
// Signing
|
||||
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/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
@@ -388,7 +388,7 @@ export function createTerminalEnvironmen
|
||||
|
||||
// Sanitize the environment, removing any undesirable VS Code and Electron environment
|
||||
// variables
|
||||
- sanitizeProcessEnvironment(env, 'VSCODE_IPC_HOOK_CLI');
|
||||
+ sanitizeProcessEnvironment(env, 'VSCODE_IPC_HOOK_CLI', 'VSCODE_PROXY_URI');
|
||||
|
||||
// Merge config (settings) and ShellLaunchConfig environments
|
||||
mergeEnvironments(env, allowedEnvFromConfig);
|
||||
@@ -1,20 +0,0 @@
|
||||
integration.diff
|
||||
node-version.diff
|
||||
base-path.diff
|
||||
proposed-api.diff
|
||||
marketplace.diff
|
||||
webview.diff
|
||||
insecure-notification.diff
|
||||
update-check.diff
|
||||
logout.diff
|
||||
store-socket.diff
|
||||
proxy-uri.diff
|
||||
display-language.diff
|
||||
github-auth.diff
|
||||
unique-db.diff
|
||||
post-install.diff
|
||||
log-level.diff
|
||||
local-storage.diff
|
||||
service-worker.diff
|
||||
last-opened.diff
|
||||
connection-type.diff
|
||||
@@ -1,67 +0,0 @@
|
||||
Add a service worker
|
||||
|
||||
To test try installing code-server as a PWA.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -36,6 +36,10 @@ export interface IProductConfiguration {
|
||||
readonly updateEndpoint?: string
|
||||
readonly logoutEndpoint?: string
|
||||
readonly proxyEndpointTemplate?: string
|
||||
+ readonly serviceWorker?: {
|
||||
+ readonly path: string;
|
||||
+ readonly scope: string;
|
||||
+ }
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
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
|
||||
@@ -296,6 +296,10 @@ export class WebClientServer {
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
|
||||
proxyEndpointTemplate: base + '/proxy/{{port}}',
|
||||
+ serviceWorker: {
|
||||
+ scope: vscodeBase + '/',
|
||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -90,6 +90,10 @@ export class CodeServerClient extends Di
|
||||
if (this.productService.logoutEndpoint) {
|
||||
this.addLogoutCommand(this.productService.logoutEndpoint);
|
||||
}
|
||||
+
|
||||
+ if (this.productService.serviceWorker) {
|
||||
+ await this.registerServiceWorker(this.productService.serviceWorker);
|
||||
+ }
|
||||
}
|
||||
|
||||
private checkUpdates(updateEndpoint: string) {
|
||||
@@ -162,4 +166,17 @@ export class CodeServerClient extends Di
|
||||
});
|
||||
}
|
||||
}
|
||||
+
|
||||
+ private async registerServiceWorker(serviceWorker: { path: string; scope: string }) {
|
||||
+ if (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) {
|
||||
+ try {
|
||||
+ await navigator.serviceWorker.register(serviceWorker.path, {
|
||||
+ scope: serviceWorker.scope,
|
||||
+ });
|
||||
+ this.logService.info('[Service Worker] registered');
|
||||
+ } catch (error: any) {
|
||||
+ this.logService.error('[Service Worker] registration', error as Error);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
Store a static reference to the IPC socket
|
||||
|
||||
This lets us use it to open files inside code-server from outside of
|
||||
code-server.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
@@ -2,7 +2,9 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
-
|
||||
+import { promises as fs } from 'fs';
|
||||
+import * as os from 'os'
|
||||
+import * as path from 'vs/base/common/path';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
|
||||
@@ -69,6 +71,10 @@ export class ExtHostExtensionService ext
|
||||
if (this._initData.remote.isRemote && this._initData.remote.authority) {
|
||||
const cliServer = this._instaService.createInstance(CLIServer);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
+
|
||||
+ fs.writeFile(path.join(os.tmpdir(), 'vscode-ipc'), cliServer.ipcHandlePath).catch((error) => {
|
||||
+ this._logService.error(error);
|
||||
+ });
|
||||
}
|
||||
|
||||
// Module loading tricks
|
||||
@@ -1,63 +0,0 @@
|
||||
Prevent state collisions
|
||||
|
||||
Previously if you opened different workspaces that had the same filesystem path
|
||||
(for example if you have /home/coder on two different machines that are both
|
||||
accessed through the same host) they would conflict with each other. This
|
||||
ensures that different browser paths will be unique (for example /workspace1 and
|
||||
/workspace2).
|
||||
|
||||
The easiest way to test is to open files in the same workspace using both / and
|
||||
/vscode and make sure they are not interacting with each other.
|
||||
|
||||
It should also migrate old databases which can be tested by opening in an old
|
||||
code-server.
|
||||
|
||||
This has e2e tests.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
@@ -13,6 +13,7 @@ import { InMemoryStorageDatabase, isStor
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { AbstractStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||||
+import { hash } from 'vs/base/common/hash';
|
||||
|
||||
export class BrowserStorageService extends AbstractStorageService {
|
||||
|
||||
@@ -36,7 +37,11 @@ export class BrowserStorageService exten
|
||||
}
|
||||
|
||||
private getId(scope: StorageScope): string {
|
||||
- return scope === StorageScope.GLOBAL ? 'global' : this.payload.id;
|
||||
+ // Add a unique ID based on the current path for per-workspace databases.
|
||||
+ // This prevents workspaces on different machines that share the same domain
|
||||
+ // and file path from colliding (since it does not appear IndexedDB can be
|
||||
+ // scoped to a path) as long as they are hosted on different paths.
|
||||
+ return scope === StorageScope.GLOBAL ? 'global' : (this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16));
|
||||
}
|
||||
|
||||
protected async doInitialize(): Promise<void> {
|
||||
@@ -75,6 +80,21 @@ export class BrowserStorageService exten
|
||||
const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY);
|
||||
if (firstWorkspaceOpen === undefined) {
|
||||
this.workspaceStorage.set(IS_NEW_KEY, true);
|
||||
+ // Migrate the old database.
|
||||
+ let db: IIndexedDBStorageDatabase | undefined
|
||||
+ try {
|
||||
+ db = await IndexedDBStorageDatabase.create({ id: this.payload.id }, this.logService)
|
||||
+ const items = await db.getItems()
|
||||
+ for (const [key, value] of items) {
|
||||
+ this.workspaceStorage.set(key, value);
|
||||
+ }
|
||||
+ } catch (error) {
|
||||
+ this.logService.error(`[IndexedDB Storage ${this.payload.id}] migrate error: ${toErrorMessage(error)}`);
|
||||
+ } finally {
|
||||
+ if (db) {
|
||||
+ db.close()
|
||||
+ }
|
||||
+ }
|
||||
} else if (firstWorkspaceOpen) {
|
||||
this.workspaceStorage.set(IS_NEW_KEY, false);
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
Add a notification that lets you know when an update is out
|
||||
|
||||
The easiest way to test this is probably to change the version in your
|
||||
package.json and delete the last notification storage item.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -1,10 +1,16 @@
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
+import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
+import { IProductService } from 'vs/platform/product/common/productService';
|
||||
+import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class CodeServerClient extends Disposable {
|
||||
constructor (
|
||||
+ @ILogService private logService: ILogService,
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
+ @IProductService private productService: IProductService,
|
||||
+ @IStorageService private storageService: IStorageService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -72,5 +78,59 @@ export class CodeServerClient extends Di
|
||||
},
|
||||
});
|
||||
}
|
||||
+
|
||||
+ if (this.productService.updateEndpoint) {
|
||||
+ this.checkUpdates(this.productService.updateEndpoint)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private checkUpdates(updateEndpoint: string) {
|
||||
+ const getUpdate = async (updateCheckEndpoint: string): Promise<void> => {
|
||||
+ this.logService.debug('Checking for update...');
|
||||
+
|
||||
+ const response = await fetch(updateCheckEndpoint, {
|
||||
+ headers: { Accept: 'application/json' },
|
||||
+ });
|
||||
+ if (!response.ok) {
|
||||
+ throw new Error(response.statusText);
|
||||
+ }
|
||||
+ const json = await response.json();
|
||||
+ if (json.error) {
|
||||
+ throw new Error(json.error);
|
||||
+ }
|
||||
+ if (json.isLatest) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const lastNoti = this.storageService.getNumber('csLastUpdateNotification', StorageScope.GLOBAL);
|
||||
+ if (lastNoti) {
|
||||
+ // Only remind them again after 1 week.
|
||||
+ const timeout = 1000 * 60 * 60 * 24 * 7;
|
||||
+ const threshold = lastNoti + timeout;
|
||||
+ if (Date.now() < threshold) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.storageService.store('csLastUpdateNotification', Date.now(), StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
+
|
||||
+ this.notificationService.notify({
|
||||
+ severity: Severity.Info,
|
||||
+ message: `[code-server v${json.latest}](https://github.com/cdr/code-server/releases/tag/v${json.latest}) has been released!`,
|
||||
+ });
|
||||
+ };
|
||||
+
|
||||
+ const updateLoop = (): void => {
|
||||
+ getUpdate(updateEndpoint)
|
||||
+ .catch(error => {
|
||||
+ this.logService.debug(`failed to check for update: ${error}`);
|
||||
+ })
|
||||
+ .finally(() => {
|
||||
+ // Check again every 6 hours.
|
||||
+ setTimeout(updateLoop, 1000 * 60 * 60 * 6);
|
||||
+ });
|
||||
+ };
|
||||
+
|
||||
+ updateLoop();
|
||||
}
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -33,6 +33,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
+ readonly updateEndpoint?: string
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
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
|
||||
@@ -286,6 +286,7 @@ export class WebClientServer {
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -11,6 +11,8 @@ import { refineServiceDecorator } from '
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
|
||||
+ /* ----- code-server ----- */
|
||||
+ 'disable-update-check': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -84,6 +86,8 @@ export const serverOptions: OptionDescri
|
||||
};
|
||||
|
||||
export interface ServerParsedArgs {
|
||||
+ /* ----- code-server ----- */
|
||||
+ 'disable-update-check'?: boolean;
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
Serve webviews from the same origin
|
||||
|
||||
Normally webviews are served from vscode-webview.net but we would rather them be
|
||||
self-hosted.
|
||||
|
||||
When doing this CSP will block resources (for example when viewing images) so
|
||||
add 'self' to the CSP to fix that.
|
||||
|
||||
Index: code-server/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
|
||||
@@ -240,7 +240,7 @@ export class BrowserWorkbenchEnvironment
|
||||
|
||||
@memoize
|
||||
get webviewExternalEndpoint(): string {
|
||||
- const endpoint = this.options.webviewEndpoint
|
||||
+ const endpoint = (this.options.webviewEndpoint && new URL(this.options.webviewEndpoint, window.location.toString()).toString())
|
||||
|| this.productService.webviewContentExternalBaseUrlTemplate
|
||||
|| 'https://{{uuid}}.vscode-webview.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
|
||||
|
||||
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
|
||||
@@ -280,6 +280,7 @@ export class WebClientServer {
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
+ webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
|
||||
@@ -25,7 +25,7 @@ export const webviewResourceBaseHost = '
|
||||
|
||||
export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
|
||||
|
||||
-export const webviewGenericCspSource = `https://*.${webviewResourceBaseHost}`;
|
||||
+export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
|
||||
|
||||
/**
|
||||
* Construct a uri that can load resources inside a webview
|
||||
@@ -1,14 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
self.addEventListener("install", () => {
|
||||
console.debug("[Service Worker] installed")
|
||||
})
|
||||
|
||||
self.addEventListener("activate", (event: any) => {
|
||||
event.waitUntil((self as any).clients.claim())
|
||||
console.debug("[Service Worker] activated")
|
||||
})
|
||||
|
||||
self.addEventListener("fetch", () => {
|
||||
// Without this event handler we won't be recognized as a PWA.
|
||||
})
|
||||
@@ -22,35 +22,40 @@ export interface App extends Disposable {
|
||||
server: http.Server
|
||||
}
|
||||
|
||||
export const listen = async (server: http.Server, { host, port, socket, "socket-mode": mode }: ListenOptions) => {
|
||||
if (socket) {
|
||||
try {
|
||||
await fs.unlink(socket)
|
||||
} catch (error: any) {
|
||||
handleArgsSocketCatchError(error)
|
||||
}
|
||||
}
|
||||
await new Promise<void>(async (resolve, reject) => {
|
||||
const listen = (server: http.Server, { host, port, socket, "socket-mode": mode }: ListenOptions) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
server.on("error", reject)
|
||||
|
||||
const onListen = () => {
|
||||
// Promise resolved earlier so this is an unrelated error.
|
||||
server.off("error", reject)
|
||||
server.on("error", (err) => util.logError(logger, "http server error", err))
|
||||
resolve()
|
||||
|
||||
if (socket && mode) {
|
||||
fs.chmod(socket, mode)
|
||||
.then(resolve)
|
||||
.catch((err) => {
|
||||
util.logError(logger, "socket chmod", err)
|
||||
reject(err)
|
||||
})
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
|
||||
if (socket) {
|
||||
try {
|
||||
await fs.unlink(socket)
|
||||
} catch (error: any) {
|
||||
handleArgsSocketCatchError(error)
|
||||
}
|
||||
|
||||
server.listen(socket, onListen)
|
||||
} else {
|
||||
// [] is the correct format when using :: but Node errors with them.
|
||||
server.listen(port, host.replace(/^\[|\]$/g, ""), onListen)
|
||||
}
|
||||
})
|
||||
|
||||
// NOTE@jsjoeio: we need to chmod after the server is finished
|
||||
// listening. Otherwise, the socket may not have been created yet.
|
||||
if (socket && mode) {
|
||||
await fs.chmod(socket, mode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +138,6 @@ export const handleServerError = (resolved: boolean, err: Error, reject: (err: E
|
||||
*/
|
||||
export const handleArgsSocketCatchError = (error: any) => {
|
||||
if (!isNodeJSErrnoException(error) || error.code !== "ENOENT") {
|
||||
throw Error(error.message ? error.message : error)
|
||||
logger.error(error.message ? error.message : error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,33 +31,13 @@ export enum LogLevel {
|
||||
|
||||
export class OptionalString extends Optional<string> {}
|
||||
|
||||
/**
|
||||
* Code flags provided by the user.
|
||||
*/
|
||||
export interface UserProvidedCodeArgs {
|
||||
"disable-telemetry"?: boolean
|
||||
force?: boolean
|
||||
"user-data-dir"?: string
|
||||
"enable-proposed-api"?: string[]
|
||||
"extensions-dir"?: string
|
||||
"builtin-extensions-dir"?: string
|
||||
"install-extension"?: string[]
|
||||
"uninstall-extension"?: string[]
|
||||
"list-extensions"?: boolean
|
||||
"locate-extension"?: string[]
|
||||
"show-versions"?: boolean
|
||||
category?: string
|
||||
"github-auth"?: string
|
||||
"disable-update-check"?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments that the user explicitly provided on the command line. All
|
||||
* arguments must be optional.
|
||||
*
|
||||
* For arguments with defaults see DefaultedArgs.
|
||||
*/
|
||||
export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
export interface UserProvidedArgs {
|
||||
config?: string
|
||||
auth?: AuthType
|
||||
password?: string
|
||||
@@ -65,6 +45,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
cert?: OptionalString
|
||||
"cert-host"?: string
|
||||
"cert-key"?: string
|
||||
"disable-update-check"?: boolean
|
||||
enable?: string[]
|
||||
help?: boolean
|
||||
host?: string
|
||||
@@ -85,6 +66,21 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
verbose?: boolean
|
||||
/* Positional arguments. */
|
||||
_?: string[]
|
||||
|
||||
// VS Code flags.
|
||||
"disable-telemetry"?: boolean
|
||||
force?: boolean
|
||||
"user-data-dir"?: string
|
||||
"enable-proposed-api"?: string[]
|
||||
"extensions-dir"?: string
|
||||
"builtin-extensions-dir"?: string
|
||||
"install-extension"?: string[]
|
||||
"uninstall-extension"?: string[]
|
||||
"list-extensions"?: boolean
|
||||
"locate-extension"?: string[]
|
||||
"show-versions"?: boolean
|
||||
category?: string
|
||||
"github-auth"?: string
|
||||
}
|
||||
|
||||
interface Option<T> {
|
||||
@@ -124,11 +120,11 @@ type OptionType<T> = T extends boolean
|
||||
? "string[]"
|
||||
: "unknown"
|
||||
|
||||
export type Options<T> = {
|
||||
type Options<T> = {
|
||||
[P in keyof T]: Option<OptionType<T[P]>>
|
||||
}
|
||||
|
||||
export const options: Options<Required<UserProvidedArgs>> = {
|
||||
const options: Options<Required<UserProvidedArgs>> = {
|
||||
auth: { type: AuthType, description: "The type of authentication to use." },
|
||||
password: {
|
||||
type: "string",
|
||||
@@ -239,8 +235,8 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
},
|
||||
}
|
||||
|
||||
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
|
||||
const entries = Object.entries(opts).filter(([, v]) => !!v.description)
|
||||
export const optionDescriptions = (): string[] => {
|
||||
const entries = Object.entries(options).filter(([, v]) => !!v.description)
|
||||
const widths = entries.reduce(
|
||||
(prev, [k, v]) => ({
|
||||
long: k.length > prev.long ? k.length : prev.long,
|
||||
@@ -765,37 +761,14 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for running Code's server.
|
||||
*
|
||||
* A subset of ../../lib/vscode/src/vs/server/node/serverEnvironmentService.ts:90
|
||||
*/
|
||||
export interface CodeArgs extends UserProvidedCodeArgs {
|
||||
"accept-server-license-terms"?: boolean
|
||||
"connection-token"?: string
|
||||
help: boolean
|
||||
port?: string
|
||||
version: boolean
|
||||
"without-connection-token"?: boolean
|
||||
"without-browser-env-var"?: boolean
|
||||
compatibility: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Types for ../../lib/vscode/src/vs/server/node/server.main.ts:65.
|
||||
*/
|
||||
export type SpawnCodeCli = (args: CodeArgs) => Promise<void>
|
||||
|
||||
/**
|
||||
* Convert our arguments to VS Code server arguments.
|
||||
*/
|
||||
export const toCodeArgs = async (args: DefaultedArgs): Promise<CodeArgs> => {
|
||||
export const toVsCodeArgs = async (args: DefaultedArgs): Promise<CodeServerLib.ServerParsedArgs> => {
|
||||
return {
|
||||
"connection-token": "0000",
|
||||
...args,
|
||||
"accept-server-license-terms": true,
|
||||
// This seems to be used to make the connection token flags optional (when
|
||||
// set to 1.63) but we have always included them.
|
||||
compatibility: "1.64",
|
||||
/** Type casting. */
|
||||
help: !!args.help,
|
||||
version: !!args.version,
|
||||
|
||||
@@ -16,14 +16,14 @@ export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJso
|
||||
return pkg
|
||||
}
|
||||
|
||||
export const rootPath = path.resolve(__dirname, "../..")
|
||||
export const vsRootPath = path.join(rootPath, "lib/vscode")
|
||||
const PACKAGE_JSON = "package.json"
|
||||
const pkg = getPackageJson(`${rootPath}/${PACKAGE_JSON}`)
|
||||
const codePkg = getPackageJson(`${vsRootPath}/${PACKAGE_JSON}`) || { version: "0.0.0" }
|
||||
const pkg = getPackageJson("../../package.json")
|
||||
const codePkg = getPackageJson("../../vendor/modules/code-oss-dev/package.json")
|
||||
|
||||
export const pkgName = pkg.name || "code-server"
|
||||
export const version = pkg.version || "development"
|
||||
export const commit = pkg.commit || "development"
|
||||
export const rootPath = path.resolve(__dirname, "../..")
|
||||
export const vsRootPath = path.join(rootPath, "vendor/modules/code-oss-dev")
|
||||
export const codeVersion = codePkg.version || "development"
|
||||
export const tmpdir = path.join(os.tmpdir(), "code-server")
|
||||
export const isDevMode = commit === "development"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import { optionDescriptions, parse, readConfigFile, setDefaults, shouldOpenInExistingInstance } from "./cli"
|
||||
import { getVersionString, getVersionJsonString } from "./constants"
|
||||
import { openInExistingInstance, runCodeServer, runCodeCli, shouldSpawnCliProcess } from "./main"
|
||||
import { openInExistingInstance, runCodeServer, runVsCodeCli, shouldSpawnCliProcess } from "./main"
|
||||
import { isChild, wrapper } from "./wrapper"
|
||||
|
||||
async function entry(): Promise<void> {
|
||||
@@ -48,7 +48,7 @@ async function entry(): Promise<void> {
|
||||
|
||||
if (shouldSpawnCliProcess(args)) {
|
||||
logger.debug("Found VS Code arguments; spawning VS Code CLI")
|
||||
return runCodeCli(args)
|
||||
return runVsCodeCli(args)
|
||||
}
|
||||
|
||||
const socketPath = await shouldOpenInExistingInstance(cliArgs)
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from "path"
|
||||
import { Disposable } from "../common/emitter"
|
||||
import { plural } from "../common/util"
|
||||
import { createApp, ensureAddress } from "./app"
|
||||
import { AuthType, DefaultedArgs, Feature, SpawnCodeCli, toCodeArgs, UserProvidedArgs } from "./cli"
|
||||
import { AuthType, DefaultedArgs, Feature, toVsCodeArgs, UserProvidedArgs } from "./cli"
|
||||
import { coderCloudBind } from "./coder_cloud"
|
||||
import { commit, version } from "./constants"
|
||||
import { register } from "./routes"
|
||||
@@ -24,46 +24,27 @@ export const shouldSpawnCliProcess = (args: UserProvidedArgs): boolean => {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is copy of OpenCommandPipeArgs from
|
||||
* ../../lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts:15
|
||||
*
|
||||
* Arguments supported by Code's socket. It can be used to perform actions from
|
||||
* the CLI in a running instance of Code (for example to open a file).
|
||||
*
|
||||
* TODO: Can we import this (and other types) directly?
|
||||
* This is useful when an CLI arg should be passed to VS Code directly,
|
||||
* such as when managing extensions.
|
||||
* @deprecated This should be removed when code-server merges with lib/vscode.
|
||||
*/
|
||||
export interface OpenCommandPipeArgs {
|
||||
type: "open"
|
||||
fileURIs?: string[]
|
||||
folderURIs: string[]
|
||||
forceNewWindow?: boolean
|
||||
diffMode?: boolean
|
||||
addMode?: boolean
|
||||
gotoLineMode?: boolean
|
||||
forceReuseWindow?: boolean
|
||||
waitMarkerFilePath?: string
|
||||
}
|
||||
export const runVsCodeCli = async (args: DefaultedArgs): Promise<void> => {
|
||||
logger.debug("Running VS Code CLI")
|
||||
|
||||
/**
|
||||
* Run Code's CLI for things like managing extensions.
|
||||
*/
|
||||
export const runCodeCli = async (args: DefaultedArgs): Promise<void> => {
|
||||
logger.debug("Running Code CLI")
|
||||
|
||||
// See ../../lib/vscode/src/vs/server/node/server.main.ts:65.
|
||||
const spawnCli = await loadAMDModule<SpawnCodeCli>("vs/server/node/server.main", "spawnCli")
|
||||
// See ../../vendor/modules/code-oss-dev/src/vs/server/main.js.
|
||||
const spawnCli = await loadAMDModule<CodeServerLib.SpawnCli>("vs/server/remoteExtensionHostAgent", "spawnCli")
|
||||
|
||||
try {
|
||||
await spawnCli(await toCodeArgs(args))
|
||||
await spawnCli(await toVsCodeArgs(args))
|
||||
} catch (error: any) {
|
||||
logger.error("Got error from Code", error)
|
||||
logger.error("Got error from VS Code", error)
|
||||
}
|
||||
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
export const openInExistingInstance = async (args: DefaultedArgs, socketPath: string): Promise<void> => {
|
||||
const pipeArgs: OpenCommandPipeArgs & { fileURIs: string[] } = {
|
||||
const pipeArgs: CodeServerLib.OpenCommandPipeArgs & { fileURIs: string[] } = {
|
||||
type: "open",
|
||||
folderURIs: [],
|
||||
fileURIs: [],
|
||||
@@ -95,12 +76,12 @@ export const openInExistingInstance = async (args: DefaultedArgs, socketPath: st
|
||||
},
|
||||
(response) => {
|
||||
response.on("data", (message) => {
|
||||
logger.debug("got message from Code", field("message", message.toString()))
|
||||
logger.debug("got message from VS Code", field("message", message.toString()))
|
||||
})
|
||||
},
|
||||
)
|
||||
vscode.on("error", (error: unknown) => {
|
||||
logger.error("got error from Code", field("error", error))
|
||||
logger.error("got error from VS Code", field("error", error))
|
||||
})
|
||||
vscode.write(JSON.stringify(pipeArgs))
|
||||
vscode.end()
|
||||
|
||||
@@ -129,14 +129,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||
express.static(rootPath, {
|
||||
cacheControl: commit !== "development",
|
||||
fallthrough: false,
|
||||
setHeaders: (res, path, stat) => {
|
||||
// The service worker is served from a sub-path on the static route so
|
||||
// this is required to allow it to register a higher scope (by default
|
||||
// the browser only allows it to register from its own path or lower).
|
||||
if (path.endsWith("/serviceWorker.js")) {
|
||||
res.setHeader("Service-Worker-Allowed", "/")
|
||||
}
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -1,34 +1,19 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import * as express from "express"
|
||||
import * as http from "http"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
import { WebsocketRequest } from "../../../typings/pluginapi"
|
||||
import { logError } from "../../common/util"
|
||||
import { CodeArgs, toCodeArgs } from "../cli"
|
||||
import { toVsCodeArgs } from "../cli"
|
||||
import { isDevMode } from "../constants"
|
||||
import { authenticated, ensureAuthenticated, redirect, replaceTemplates, self } from "../http"
|
||||
import { authenticated, ensureAuthenticated, redirect, self } from "../http"
|
||||
import { SocketProxyProvider } from "../socket"
|
||||
import { isFile, loadAMDModule } from "../util"
|
||||
import { Router as WsRouter } from "../wsRouter"
|
||||
|
||||
/**
|
||||
* This is the API of Code's web client server. code-server delegates requests
|
||||
* to Code here.
|
||||
*/
|
||||
export interface IServerAPI {
|
||||
handleRequest(req: http.IncomingMessage, res: http.ServerResponse): Promise<void>
|
||||
handleUpgrade(req: http.IncomingMessage, socket: net.Socket): void
|
||||
handleServerError(err: Error): void
|
||||
dispose(): void
|
||||
}
|
||||
|
||||
// Types for ../../../lib/vscode/src/vs/server/node/server.main.ts:72.
|
||||
export type CreateServer = (address: string | net.AddressInfo | null, args: CodeArgs) => Promise<IServerAPI>
|
||||
import { errorHandler } from "./errors"
|
||||
|
||||
export class CodeServerRouteWrapper {
|
||||
/** Assigned in `ensureCodeServerLoaded` */
|
||||
private _codeServerMain!: IServerAPI
|
||||
private _codeServerMain!: CodeServerLib.IServerAPI
|
||||
private _wsRouterWrapper = WsRouter()
|
||||
private _socketProxyProvider = new SocketProxyProvider()
|
||||
public router = express.Router()
|
||||
@@ -39,32 +24,6 @@ export class CodeServerRouteWrapper {
|
||||
|
||||
//#region Route Handlers
|
||||
|
||||
private manifest: express.Handler = async (req, res, next) => {
|
||||
res.writeHead(200, { "Content-Type": "application/manifest+json" })
|
||||
|
||||
return res.end(
|
||||
replaceTemplates(
|
||||
req,
|
||||
JSON.stringify(
|
||||
{
|
||||
name: "code-server",
|
||||
short_name: "code-server",
|
||||
start_url: ".",
|
||||
display: "fullscreen",
|
||||
description: "Run Code on a remote server.",
|
||||
icons: [192, 512].map((size) => ({
|
||||
src: `{{BASE}}/_static/src/browser/media/pwa-icon-${size}.png`,
|
||||
type: "image/png",
|
||||
sizes: `${size}x${size}`,
|
||||
})),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private $root: express.Handler = async (req, res, next) => {
|
||||
const isAuthenticated = await authenticated(req)
|
||||
const NO_FOLDER_OR_WORKSPACE_QUERY = !req.query.folder && !req.query.workspace
|
||||
@@ -122,6 +81,17 @@ export class CodeServerRouteWrapper {
|
||||
}
|
||||
|
||||
private $proxyRequest: express.Handler = async (req, res, next) => {
|
||||
// We allow certain errors to propagate so that other routers may handle requests
|
||||
// outside VS Code
|
||||
const requestErrorHandler = (error: any) => {
|
||||
if (error instanceof Error && ["EntryNotFound", "FileNotFound", "HttpError"].includes(error.message)) {
|
||||
next()
|
||||
}
|
||||
errorHandler(error, req, res, next)
|
||||
}
|
||||
|
||||
req.once("error", requestErrorHandler)
|
||||
|
||||
this._codeServerMain.handleRequest(req, res)
|
||||
}
|
||||
|
||||
@@ -147,14 +117,18 @@ export class CodeServerRouteWrapper {
|
||||
|
||||
const { args } = req
|
||||
|
||||
// See ../../../lib/vscode/src/vs/server/node/server.main.ts:72.
|
||||
const createVSServer = await loadAMDModule<CreateServer>("vs/server/node/server.main", "createServer")
|
||||
/**
|
||||
* @file ../../../vendor/modules/code-oss-dev/src/vs/server/main.js
|
||||
*/
|
||||
const createVSServer = await loadAMDModule<CodeServerLib.CreateServer>(
|
||||
"vs/server/remoteExtensionHostAgent",
|
||||
"createServer",
|
||||
)
|
||||
|
||||
try {
|
||||
this._codeServerMain = await createVSServer(null, {
|
||||
...(await toCodeArgs(args)),
|
||||
...(await toVsCodeArgs(args)),
|
||||
// TODO: Make the browser helper script work.
|
||||
"without-connection-token": true,
|
||||
"without-browser-env-var": true,
|
||||
})
|
||||
} catch (error) {
|
||||
@@ -170,7 +144,6 @@ export class CodeServerRouteWrapper {
|
||||
|
||||
constructor() {
|
||||
this.router.get("/", this.ensureCodeServerLoaded, this.$root)
|
||||
this.router.get(/manifest.json$/, this.manifest)
|
||||
this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
|
||||
this._wsRouterWrapper.ws("/", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ describe("code-server", true, [], {}, () => {
|
||||
expect(await codeServerPage.isEditorVisible()).toBe(true)
|
||||
})
|
||||
|
||||
test("should always have a connection", async ({ codeServerPage }) => {
|
||||
expect(await codeServerPage.isConnected()).toBe(true)
|
||||
})
|
||||
|
||||
test("should show the Integrated Terminal", async ({ codeServerPage }) => {
|
||||
await codeServerPage.focusTerminal()
|
||||
expect(await codeServerPage.page.isVisible("#terminal")).toBe(true)
|
||||
|
||||
@@ -20,14 +20,14 @@ class Context {
|
||||
public canceled(): boolean {
|
||||
return this._canceled
|
||||
}
|
||||
public finished(): boolean {
|
||||
return this._done
|
||||
public done(): void {
|
||||
this._done = true
|
||||
}
|
||||
public cancel(): void {
|
||||
this._canceled = true
|
||||
}
|
||||
public finish(): void {
|
||||
this._done = true
|
||||
public finish(): boolean {
|
||||
return this._done
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export class CodeServer {
|
||||
name: string,
|
||||
private readonly args: string[],
|
||||
private readonly env: NodeJS.ProcessEnv,
|
||||
private _workspaceDir: Promise<string> | string | undefined,
|
||||
private readonly _workspaceDir: Promise<string> | string | undefined,
|
||||
private readonly entry = process.env.CODE_SERVER_TEST_ENTRY || ".",
|
||||
) {
|
||||
this.logger = logger.named(name)
|
||||
@@ -64,7 +64,7 @@ export class CodeServer {
|
||||
/**
|
||||
* The workspace directory code-server opens with.
|
||||
*/
|
||||
get workspaceDir(): Promise<string> | string {
|
||||
get workspaceDir(): Promise<string> {
|
||||
if (!this._workspaceDir) {
|
||||
this._workspaceDir = tmpdir(workspaceDir)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ export class CodeServerPage {
|
||||
private readonly authenticated: boolean,
|
||||
) {
|
||||
this.page.on("console", (message) => {
|
||||
this.codeServer.logger.debug(message.text())
|
||||
this.codeServer.logger.debug(message)
|
||||
})
|
||||
this.page.on("pageerror", (error) => {
|
||||
logError(this.codeServer.logger, "page", error)
|
||||
@@ -241,13 +241,14 @@ export class CodeServerPage {
|
||||
this.codeServer.logger.debug("Waiting for editor to be ready...")
|
||||
|
||||
const editorIsVisible = await this.isEditorVisible()
|
||||
const editorIsConnected = await this.isConnected()
|
||||
let reloadCount = 0
|
||||
|
||||
// Occassionally code-server timeouts in Firefox
|
||||
// we're not sure why
|
||||
// but usually a reload or two fixes it
|
||||
// TODO@jsjoeio @oxy look into Firefox reconnection/timeout issues
|
||||
while (!editorIsVisible) {
|
||||
while (!editorIsVisible && !editorIsConnected) {
|
||||
// When a reload happens, we want to wait for all resources to be
|
||||
// loaded completely. Hence why we use that instead of DOMContentLoaded
|
||||
// Read more: https://thisthat.dev/dom-content-loaded-vs-load/
|
||||
@@ -255,7 +256,7 @@ export class CodeServerPage {
|
||||
// Give it an extra second just in case it's feeling extra slow
|
||||
await this.page.waitForTimeout(1000)
|
||||
reloadCount += 1
|
||||
if (await this.isEditorVisible()) {
|
||||
if ((await this.isEditorVisible()) && (await this.isConnected())) {
|
||||
this.codeServer.logger.debug(`editor became ready after ${reloadCount} reloads`)
|
||||
break
|
||||
}
|
||||
@@ -279,6 +280,23 @@ export class CodeServerPage {
|
||||
return visible
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the editor is visible
|
||||
*/
|
||||
async isConnected() {
|
||||
this.codeServer.logger.debug("Waiting for network idle...")
|
||||
|
||||
await this.page.waitForLoadState("networkidle")
|
||||
|
||||
const host = new URL(await this.codeServer.address()).host
|
||||
// NOTE: This seems to be pretty brittle between version changes.
|
||||
const hostSelector = `[aria-label="remote ${host}"]`
|
||||
this.codeServer.logger.debug(`Waiting selector: ${hostSelector}`)
|
||||
await this.page.waitForSelector(hostSelector)
|
||||
|
||||
return await this.page.isVisible(hostSelector)
|
||||
}
|
||||
|
||||
/**
|
||||
* Focuses Integrated Terminal
|
||||
* by using "Terminal: Focus Terminal"
|
||||
@@ -308,13 +326,13 @@ export class CodeServerPage {
|
||||
* Wait for a tab to open for the specified file.
|
||||
*/
|
||||
async waitForTab(file: string): Promise<void> {
|
||||
await this.page.waitForSelector(`.tab :text("${path.basename(file)}")`)
|
||||
return this.page.waitForSelector(`.tab :text("${path.basename(file)}")`)
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the specified tab is open.
|
||||
*/
|
||||
async tabIsVisible(file: string): Promise<boolean> {
|
||||
async tabIsVisible(file: string): Promise<void> {
|
||||
return this.page.isVisible(`.tab :text("${path.basename(file)}")`)
|
||||
}
|
||||
|
||||
@@ -350,8 +368,8 @@ export class CodeServerPage {
|
||||
try {
|
||||
await this.page.waitForSelector(`${selector}:not(:focus-within)`)
|
||||
} catch (error) {
|
||||
if (!ctx.finished()) {
|
||||
this.codeServer.logger.debug(`${selector} navigation: ${(error as any).message || error}`)
|
||||
if (!ctx.done()) {
|
||||
this.codeServer.logger.debug(`${selector} navigation: ${error.message || error}`)
|
||||
}
|
||||
}
|
||||
return false
|
||||
@@ -405,7 +423,7 @@ export class CodeServerPage {
|
||||
return false
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug(`navigation: ${(error as any).message || error}`)
|
||||
logger.debug(`navigation: ${error.message || error}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -418,7 +436,7 @@ export class CodeServerPage {
|
||||
// time we lose focus or there is an error.
|
||||
let attempts = 1
|
||||
let context = new Context()
|
||||
while (!(await Promise.race([openThenWaitClose(context), navigate(context)]))) {
|
||||
while (!(await Promise.race([openThenWaitClose(), navigate(context)]))) {
|
||||
++attempts
|
||||
logger.debug("closed, retrying (${attempt}/∞)")
|
||||
context.cancel()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { promises } from "fs"
|
||||
import * as http from "http"
|
||||
import * as https from "https"
|
||||
import * as path from "path"
|
||||
import { createApp, ensureAddress, handleArgsSocketCatchError, handleServerError, listen } from "../../../src/node/app"
|
||||
import { createApp, ensureAddress, handleArgsSocketCatchError, handleServerError } from "../../../src/node/app"
|
||||
import { OptionalString, setDefaults } from "../../../src/node/cli"
|
||||
import { generateCertificate } from "../../../src/node/util"
|
||||
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
|
||||
@@ -201,33 +201,31 @@ describe("handleArgsSocketCatchError", () => {
|
||||
})
|
||||
|
||||
it("should log an error if its not an NodeJS.ErrnoException", () => {
|
||||
const message = "other message"
|
||||
const error = new Error(message)
|
||||
const error = new Error()
|
||||
|
||||
expect(() => {
|
||||
handleArgsSocketCatchError(error)
|
||||
}).toThrowError(error)
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(error)
|
||||
})
|
||||
|
||||
it("should log an error if its not an NodeJS.ErrnoException (and the error has a message)", () => {
|
||||
const errorMessage = "handleArgsSocketCatchError Error"
|
||||
const error = new Error(errorMessage)
|
||||
|
||||
expect(() => {
|
||||
handleArgsSocketCatchError(error)
|
||||
}).toThrowError(error)
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(errorMessage)
|
||||
})
|
||||
|
||||
it("should not log an error if its a NodeJS.ErrnoException", () => {
|
||||
const code = "ENOENT"
|
||||
const error: NodeJS.ErrnoException = new Error(code)
|
||||
error.code = code
|
||||
it("should not log an error if its a iNodeJS.ErrnoException", () => {
|
||||
const error: NodeJS.ErrnoException = new Error()
|
||||
error.code = "ENOENT"
|
||||
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(() => {
|
||||
handleArgsSocketCatchError(error)
|
||||
}).not.toThrowError()
|
||||
expect(logger.error).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
|
||||
it("should log an error if the code is not ENOENT (and the error has a message)", () => {
|
||||
@@ -236,50 +234,19 @@ describe("handleArgsSocketCatchError", () => {
|
||||
error.code = "EACCESS"
|
||||
error.message = errorMessage
|
||||
|
||||
expect(() => {
|
||||
handleArgsSocketCatchError(error)
|
||||
}).toThrowError(error)
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(errorMessage)
|
||||
})
|
||||
|
||||
it("should log an error if the code is not ENOENT", () => {
|
||||
const code = "EACCESS"
|
||||
const error: NodeJS.ErrnoException = new Error(code)
|
||||
error.code = code
|
||||
const error: NodeJS.ErrnoException = new Error()
|
||||
error.code = "EACCESS"
|
||||
|
||||
expect(() => {
|
||||
handleArgsSocketCatchError(error)
|
||||
}).toThrowError(error)
|
||||
})
|
||||
})
|
||||
|
||||
describe("listen", () => {
|
||||
let tmpDirPath: string
|
||||
let mockServer: http.Server
|
||||
|
||||
const testName = "listen"
|
||||
|
||||
beforeEach(async () => {
|
||||
await clean(testName)
|
||||
mockLogger()
|
||||
tmpDirPath = await tmpdir(testName)
|
||||
mockServer = http.createServer()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mockServer.close()
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("should throw an error if a directory is passed in instead of a file", async () => {
|
||||
const errorMessage = "EISDIR: illegal operation on a directory, unlink"
|
||||
const port = await getAvailablePort()
|
||||
const mockArgs = { port, host: "0.0.0.0", socket: tmpDirPath }
|
||||
|
||||
try {
|
||||
await listen(mockServer, mockArgs)
|
||||
} catch (error) {
|
||||
expect(error).toBeInstanceOf(Error)
|
||||
expect((error as any).message).toMatch(errorMessage)
|
||||
}
|
||||
handleArgsSocketCatchError(error)
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
||||
expect(logger.error).toHaveBeenCalledWith(error)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,12 +12,7 @@ import {
|
||||
setDefaults,
|
||||
shouldOpenInExistingInstance,
|
||||
splitOnFirstEquals,
|
||||
toCodeArgs,
|
||||
optionDescriptions,
|
||||
options,
|
||||
Options,
|
||||
AuthType,
|
||||
OptionalString,
|
||||
toVsCodeArgs,
|
||||
} from "../../../src/node/cli"
|
||||
import { shouldSpawnCliProcess } from "../../../src/node/main"
|
||||
import { generatePassword, paths } from "../../../src/node/util"
|
||||
@@ -199,15 +194,6 @@ describe("parser", () => {
|
||||
expect(logger.level).toEqual(Level.Trace)
|
||||
})
|
||||
|
||||
it("should set valid log level env var", async () => {
|
||||
process.env.LOG_LEVEL = "error"
|
||||
const defaults = await setDefaults(parse([]))
|
||||
expect(defaults).toEqual({
|
||||
...defaults,
|
||||
log: "error",
|
||||
})
|
||||
})
|
||||
|
||||
it("should ignore invalid log level env var", async () => {
|
||||
process.env.LOG_LEVEL = "bogus"
|
||||
const defaults = await setDefaults(parse([]))
|
||||
@@ -727,11 +713,11 @@ describe("readSocketPath", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("toCodeArgs", () => {
|
||||
describe("toVsCodeArgs", () => {
|
||||
const vscodeDefaults = {
|
||||
...defaults,
|
||||
"connection-token": "0000",
|
||||
"accept-server-license-terms": true,
|
||||
compatibility: "1.64",
|
||||
help: false,
|
||||
port: "8080",
|
||||
version: false,
|
||||
@@ -744,7 +730,7 @@ describe("toCodeArgs", () => {
|
||||
})
|
||||
|
||||
it("should convert empty args", async () => {
|
||||
expect(await toCodeArgs(await setDefaults(parse([])))).toStrictEqual({
|
||||
expect(await toVsCodeArgs(await setDefaults(parse([])))).toStrictEqual({
|
||||
...vscodeDefaults,
|
||||
})
|
||||
})
|
||||
@@ -752,103 +738,9 @@ describe("toCodeArgs", () => {
|
||||
it("should ignore regular file", async () => {
|
||||
const file = path.join(await tmpdir(testName), "file")
|
||||
await fs.writeFile(file, "foobar")
|
||||
expect(await toCodeArgs(await setDefaults(parse([file])))).toStrictEqual({
|
||||
expect(await toVsCodeArgs(await setDefaults(parse([file])))).toStrictEqual({
|
||||
...vscodeDefaults,
|
||||
_: [file],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("optionDescriptions", () => {
|
||||
it("should return the descriptions of all the available options", () => {
|
||||
const expectedOptionDescriptions = Object.entries(options)
|
||||
.flat()
|
||||
.filter((item: any) => {
|
||||
if (item.description) {
|
||||
return item.description
|
||||
}
|
||||
})
|
||||
.map((item: any) => item.description)
|
||||
const actualOptionDescriptions = optionDescriptions()
|
||||
// We need both the expected and the actual
|
||||
// Both of these are string[]
|
||||
// We then loop through the expectedOptionDescriptions
|
||||
// and check that this expectedDescription exists in the
|
||||
// actualOptionDescriptions
|
||||
|
||||
// To do that we need to loop through actualOptionDescriptions
|
||||
// and make sure we have a substring match
|
||||
expectedOptionDescriptions.forEach((expectedDescription) => {
|
||||
const exists = actualOptionDescriptions.find((desc) => {
|
||||
if (
|
||||
desc.replace(/\n/g, " ").replace(/ /g, "").includes(expectedDescription.replace(/\n/g, " ").replace(/ /g, ""))
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
expect(exists).toBeTruthy()
|
||||
})
|
||||
})
|
||||
it("should visually align multiple options", () => {
|
||||
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
|
||||
"cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." },
|
||||
"cert-host": {
|
||||
type: "string",
|
||||
description: "Hostname to use when generating a self signed certificate.",
|
||||
},
|
||||
"disable-update-check": {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
|
||||
"then notifies you once every week that a new release is available.",
|
||||
},
|
||||
}
|
||||
expect(optionDescriptions(opts)).toStrictEqual([
|
||||
" --cert-key Path to certificate key when using non-generated cert.",
|
||||
" --cert-host Hostname to use when generating a self signed certificate.",
|
||||
` --disable-update-check Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and
|
||||
then notifies you once every week that a new release is available.`,
|
||||
])
|
||||
})
|
||||
it("should add all valid options for enumerated types", () => {
|
||||
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
|
||||
auth: { type: AuthType, description: "The type of authentication to use." },
|
||||
}
|
||||
expect(optionDescriptions(opts)).toStrictEqual([" --auth The type of authentication to use. [password, none]"])
|
||||
})
|
||||
|
||||
it("should show if an option is deprecated", () => {
|
||||
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
|
||||
link: {
|
||||
type: OptionalString,
|
||||
description: `
|
||||
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
|
||||
https://hostname-username.coder.co at which you can easily access your code-server instance.
|
||||
Authorization is done via GitHub.
|
||||
`,
|
||||
deprecated: true,
|
||||
},
|
||||
}
|
||||
expect(optionDescriptions(opts)).toStrictEqual([
|
||||
` --link (deprecated) Securely bind code-server via our cloud service with the passed name. You'll get a URL like
|
||||
https://hostname-username.coder.co at which you can easily access your code-server instance.
|
||||
Authorization is done via GitHub.`,
|
||||
])
|
||||
})
|
||||
|
||||
it("should show newlines in description", () => {
|
||||
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
|
||||
"install-extension": {
|
||||
type: "string[]",
|
||||
description:
|
||||
"Install or update a VS Code extension by id or vsix. The identifier of an extension is `${publisher}.${name}`.\n" +
|
||||
"To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.",
|
||||
},
|
||||
}
|
||||
expect(optionDescriptions(opts)).toStrictEqual([
|
||||
` --install-extension Install or update a VS Code extension by id or vsix. The identifier of an extension is \`\${publisher}.\${name}\`.
|
||||
To install a specific version provide \`@\${version}\`. For example: 'vscode.csharp@1.2.3'.`,
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import path from "path"
|
||||
import * as semver from "semver"
|
||||
import { mockLogger } from "../../utils/helpers"
|
||||
import * as semver from "semver"
|
||||
|
||||
describe("constants", () => {
|
||||
let constants: typeof import("../../../src/node/constants")
|
||||
@@ -16,21 +15,19 @@ describe("constants", () => {
|
||||
}
|
||||
|
||||
const mockCodePackageJson = {
|
||||
name: "mock-vscode",
|
||||
name: "mock-code-oss-dev",
|
||||
version: "1.2.3",
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
jest.clearAllMocks()
|
||||
mockLogger()
|
||||
jest.mock(path.resolve(__dirname, "../../../package.json"), () => mockPackageJson, { virtual: true })
|
||||
jest.mock(path.resolve(__dirname, "../../../lib/vscode/package.json"), () => mockCodePackageJson, {
|
||||
virtual: true,
|
||||
})
|
||||
jest.mock("../../../package.json", () => mockPackageJson, { virtual: true })
|
||||
jest.mock("../../../vendor/modules/code-oss-dev/package.json", () => mockCodePackageJson, { virtual: true })
|
||||
constants = require("../../../src/node/constants")
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
@@ -94,7 +91,7 @@ describe("constants", () => {
|
||||
const packageJson = constants.getPackageJson("../../package.json")
|
||||
expect(packageJson).toStrictEqual(mockPackageJson)
|
||||
|
||||
const codePackageJson = constants.getPackageJson("../../lib/vscode/package.json")
|
||||
const codePackageJson = constants.getPackageJson("../../vendor/modules/code-oss-dev/package.json")
|
||||
expect(codePackageJson).toStrictEqual(mockCodePackageJson)
|
||||
})
|
||||
})
|
||||
@@ -105,19 +102,17 @@ describe("constants", () => {
|
||||
name: "mock-code-server",
|
||||
}
|
||||
const mockCodePackageJson = {
|
||||
name: "mock-vscode",
|
||||
name: "mock-code-oss-dev",
|
||||
}
|
||||
|
||||
beforeAll(() => {
|
||||
jest.clearAllMocks()
|
||||
jest.mock(path.resolve(__dirname, "../../../package.json"), () => mockPackageJson, { virtual: true })
|
||||
jest.mock(path.resolve(__dirname, "../../../lib/vscode/package.json"), () => mockCodePackageJson, {
|
||||
virtual: true,
|
||||
})
|
||||
jest.mock("../../../package.json", () => mockPackageJson, { virtual: true })
|
||||
jest.mock("../../../vendor/modules/code-oss-dev/package.json", () => mockCodePackageJson, { virtual: true })
|
||||
constants = require("../../../src/node/constants")
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
jest.clearAllMocks()
|
||||
jest.resetModules()
|
||||
})
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ describe("vscode", () => {
|
||||
it("should do nothing when nothing is passed in", async () => {
|
||||
codeServer = await integration.setup(["--auth=none"], "")
|
||||
|
||||
const resp = await codeServer.fetch("/", undefined)
|
||||
let resp = await codeServer.fetch("/", undefined)
|
||||
|
||||
expect(resp.status).toBe(200)
|
||||
const url = new URL(resp.url)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"./node_modules/@types",
|
||||
"./typings",
|
||||
"./test/node_modules/@types",
|
||||
"./lib/vscode/src/vs/server/@types"
|
||||
"./vendor/modules/code-oss-dev/src/vs/server/@types"
|
||||
],
|
||||
"downlevelIteration": true
|
||||
},
|
||||
|
||||
12
vendor/package.json
vendored
Normal file
12
vendor/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "vendor",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"postinstall": "./postinstall.sh"
|
||||
},
|
||||
"devDependencies": {
|
||||
"code-oss-dev": "coder/vscode#94384412221f432c15bb679315c49964925090be"
|
||||
}
|
||||
}
|
||||
10
vendor/postinstall.sh
vendored
Executable file
10
vendor/postinstall.sh
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
main() {
|
||||
echo 'Installing VS Code dependencies...'
|
||||
cd modules/code-oss-dev
|
||||
yarn install --frozen-lockfile
|
||||
}
|
||||
|
||||
main "$@"
|
||||
1494
vendor/yarn.lock
vendored
Normal file
1494
vendor/yarn.lock
vendored
Normal file
File diff suppressed because it is too large
Load Diff
185
yarn.lock
185
yarn.lock
@@ -751,6 +751,15 @@ array.prototype.flat@^1.2.4:
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.18.0-next.1"
|
||||
|
||||
array.prototype.flatmap@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446"
|
||||
integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
define-properties "^1.1.3"
|
||||
es-abstract "^1.19.0"
|
||||
|
||||
arrify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
||||
@@ -768,19 +777,20 @@ astral-regex@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
|
||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||
|
||||
audit-ci@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/audit-ci/-/audit-ci-6.0.0.tgz#78b71ac2aa754218b16e224ef3aa649cfe3063f8"
|
||||
integrity sha512-ZoJxM4FQvaWdabQvqA44PTg64Bm/a8B9dnL/ft33lygoQuKh+Oa0hwdc/VLsq/zrhNCC12uSUnnfYvgxgZLurw==
|
||||
audit-ci@^5.0.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/audit-ci/-/audit-ci-5.1.2.tgz#2e9a6c23c8511d8f79f6fde18d042ebc1bdec881"
|
||||
integrity sha512-FNBbo4ycoHxcS7ruNNkq3LB+fZ4UWDd0QUNAva7Ae/F/Y45BBA7ZfHPSr5Fr+tS2+eqSwxToeFRRnw2Tp2PE8Q==
|
||||
dependencies:
|
||||
JSONStream "^1.3.5"
|
||||
array.prototype.flatmap "^1.2.5"
|
||||
cross-spawn "^7.0.3"
|
||||
escape-string-regexp "^4.0.0"
|
||||
event-stream "4.0.1"
|
||||
jju "^1.4.0"
|
||||
readline-transform "1.0.0"
|
||||
semver "^7.0.0"
|
||||
yargs "^17.0.0"
|
||||
yargs "^16.0.0"
|
||||
|
||||
autoprefixer@^9.8.6:
|
||||
version "9.8.6"
|
||||
@@ -1431,6 +1441,32 @@ es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2:
|
||||
string.prototype.trimstart "^1.0.4"
|
||||
unbox-primitive "^1.0.0"
|
||||
|
||||
es-abstract@^1.19.0:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
|
||||
integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.1.1"
|
||||
get-symbol-description "^1.0.0"
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.2"
|
||||
internal-slot "^1.0.3"
|
||||
is-callable "^1.2.4"
|
||||
is-negative-zero "^2.0.1"
|
||||
is-regex "^1.1.4"
|
||||
is-shared-array-buffer "^1.0.1"
|
||||
is-string "^1.0.7"
|
||||
is-weakref "^1.0.1"
|
||||
object-inspect "^1.11.0"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.2"
|
||||
string.prototype.trimend "^1.0.4"
|
||||
string.prototype.trimstart "^1.0.4"
|
||||
unbox-primitive "^1.0.1"
|
||||
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
@@ -1942,7 +1978,7 @@ get-caller-file@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.1:
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
|
||||
integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
|
||||
@@ -1956,6 +1992,14 @@ get-stdin@^8.0.0:
|
||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
|
||||
integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
|
||||
|
||||
get-symbol-description@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
|
||||
integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
get-intrinsic "^1.1.1"
|
||||
|
||||
get-uri@3:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
|
||||
@@ -2098,6 +2142,13 @@ has-symbols@^1.0.1, has-symbols@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||
integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==
|
||||
|
||||
has-tostringtag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
|
||||
integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
|
||||
dependencies:
|
||||
has-symbols "^1.0.2"
|
||||
|
||||
has-unicode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
@@ -2110,12 +2161,12 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hosted-git-info@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-5.0.0.tgz#df7a06678b4ebd722139786303db80fdf302ea56"
|
||||
integrity sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==
|
||||
hosted-git-info@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.0.tgz#9f06639a90beff66cacae6e77f8387b431d61ddc"
|
||||
integrity sha512-fqhGdjk4av7mT9fU/B01dUtZ+WZSc/XEXMoLXDVZukiQRXxeHSSz3AqbeWRJHtF8EQYHlAgB1NSAHU0Cm7aqZA==
|
||||
dependencies:
|
||||
lru-cache "^7.5.1"
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
html-tags@^3.1.0:
|
||||
version "3.1.0"
|
||||
@@ -2278,6 +2329,15 @@ ini@^1.3.5:
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||
|
||||
internal-slot@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
|
||||
integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.0"
|
||||
has "^1.0.3"
|
||||
side-channel "^1.0.4"
|
||||
|
||||
ip@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
|
||||
@@ -2333,6 +2393,11 @@ is-callable@^1.1.4, is-callable@^1.2.3:
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
|
||||
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
|
||||
|
||||
is-callable@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
||||
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
|
||||
|
||||
is-core-module@^2.2.0, is-core-module@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1"
|
||||
@@ -2340,13 +2405,6 @@ is-core-module@^2.2.0, is-core-module@^2.4.0:
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-core-module@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
|
||||
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
|
||||
dependencies:
|
||||
has "^1.0.3"
|
||||
|
||||
is-date-object@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e"
|
||||
@@ -2419,16 +2477,36 @@ is-regex@^1.1.2:
|
||||
call-bind "^1.0.2"
|
||||
has-symbols "^1.0.1"
|
||||
|
||||
is-regex@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
||||
integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-regexp@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d"
|
||||
integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==
|
||||
|
||||
is-shared-array-buffer@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6"
|
||||
integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==
|
||||
|
||||
is-string@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6"
|
||||
integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==
|
||||
|
||||
is-string@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
|
||||
integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
|
||||
dependencies:
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937"
|
||||
@@ -2446,6 +2524,13 @@ is-unicode-supported@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
|
||||
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
|
||||
|
||||
is-weakref@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2"
|
||||
integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.0"
|
||||
|
||||
is-whitespace-character@^1.0.0:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7"
|
||||
@@ -2655,11 +2740,6 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^7.5.1:
|
||||
version "7.5.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.5.1.tgz#660a134c2c3c015aa453b03df55d2a9f0c216a0f"
|
||||
integrity sha512-q1TS8IqKvcg3aScamKCHpepSrHF537Ww7nHahBOxhDu9D2YoBXAsj/7uFdZFj1xJr9LmyeJ62AdyofCHafUbIA==
|
||||
|
||||
make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
@@ -2826,10 +2906,10 @@ minimist-options@4.1.0:
|
||||
is-plain-obj "^1.1.0"
|
||||
kind-of "^6.0.3"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.5, "minimist@npm:minimist-lite@2.2.0", minimist@~1.2.5:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist-lite/-/minimist-lite-2.2.0.tgz#43992acac6bb17e78acb6eee784d1da2f7cc3216"
|
||||
integrity sha512-o9M0Iz5ELqCT4NzeaZHBBlV4+ruOGGWV6lVxFoghC6Wvp4W6ECbBBpmDRHdk72O/sMh3QT0c/0XDKhtGlztRZw==
|
||||
minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass@^3.0.0:
|
||||
version "3.1.3"
|
||||
@@ -2920,15 +3000,15 @@ nopt@^5.0.0:
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0, normalize-package-data@^3.0.0, normalize-package-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-4.0.0.tgz#1122d5359af21d4cd08718b92b058a658594177c"
|
||||
integrity sha512-m+GL22VXJKkKbw62ZaBBjv8u6IE3UI4Mh5QakIqs3fWiKe0Xyi6L97hakwZK41/LD4R/2ly71Bayx0NLMwLA/g==
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0, normalize-package-data@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.1.tgz#98dc56dfe6755d99b1c53f046e1e3d2dde55a1c7"
|
||||
integrity sha512-D/ttLdxo71msR4FF3VgSwK4blHfE3/vGByz1NCeE7/Dh8reQOKNJJjk5L10mLq9jxa+ZHzT1/HLgxljzbXE7Fw==
|
||||
dependencies:
|
||||
hosted-git-info "^5.0.0"
|
||||
is-core-module "^2.8.1"
|
||||
semver "^7.3.5"
|
||||
validate-npm-package-license "^3.0.4"
|
||||
hosted-git-info "^4.0.0"
|
||||
resolve "^1.17.0"
|
||||
semver "^7.3.2"
|
||||
validate-npm-package-license "^3.0.1"
|
||||
|
||||
normalize-range@^0.1.2:
|
||||
version "0.1.2"
|
||||
@@ -2960,6 +3040,11 @@ object-assign@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-inspect@^1.11.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
|
||||
integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
|
||||
|
||||
object-inspect@^1.9.0:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.2.tgz#b6385a3e2b7cae0b5eafcf90cddf85d128767f30"
|
||||
@@ -3603,7 +3688,7 @@ resolve-from@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
|
||||
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
|
||||
|
||||
resolve@^1.13.1, resolve@^1.20.0:
|
||||
resolve@^1.13.1, resolve@^1.17.0, resolve@^1.20.0:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
|
||||
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
|
||||
@@ -3670,7 +3755,7 @@ semver@^6.0.0, semver@^6.3.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
||||
semver@^7.0.0, semver@^7.1.3, semver@^7.2.1, semver@^7.3.5:
|
||||
semver@^7.0.0, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5:
|
||||
version "7.3.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
|
||||
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
|
||||
@@ -4262,7 +4347,7 @@ typescript@^4.4.0-dev.20210528:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86"
|
||||
integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==
|
||||
|
||||
unbox-primitive@^1.0.0:
|
||||
unbox-primitive@^1.0.0, unbox-primitive@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
|
||||
integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
|
||||
@@ -4408,7 +4493,7 @@ v8-compile-cache@^2.0.3, v8-compile-cache@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
||||
|
||||
validate-npm-package-license@^3.0.4:
|
||||
validate-npm-package-license@^3.0.1:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
||||
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
|
||||
@@ -4581,28 +4666,28 @@ yaml@^1.10.0:
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
|
||||
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
|
||||
|
||||
yargs-parser@^20.2.2:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||
|
||||
yargs-parser@^20.2.3:
|
||||
version "20.2.7"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
|
||||
integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
|
||||
|
||||
yargs-parser@^21.0.0:
|
||||
version "21.0.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
|
||||
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==
|
||||
|
||||
yargs@^17.0.0:
|
||||
version "17.3.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9"
|
||||
integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==
|
||||
yargs@^16.0.0:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||
dependencies:
|
||||
cliui "^7.0.2"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.3"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.0.0"
|
||||
yargs-parser "^20.2.2"
|
||||
|
||||
yarn@^1.22.4:
|
||||
version "1.22.11"
|
||||
|
||||
Reference in New Issue
Block a user