Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
a1acc25dc3 Bump typescript-eslint from 8.69.0 to 8.71.1
Bumps [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) from 8.69.0 to 8.71.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.71.1/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.70.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-14 01:05:40 +00:00
dependabot[bot]
c5fee2d2f9 Bump brace-expansion from 1.1.18 to 1.1.21 (#8044) 2026-10-13 17:02:46 -08:00
Harsh Bhanushali
83670e50c6 Fix false booleans in config file being parsed as true (#8053)
Options like `enable-remote-storage: false` in config.yaml are converted to
`--enable-remote-storage=false`, but the parser set any boolean option to
true regardless of its value. Booleans set to false are now ignored, the
same way optional strings set to false already are.
2026-10-13 17:01:10 -08:00
KeuqS
41cf6f7eaf Add Turkish locale (#8050) 2026-10-09 22:50:17 +00:00
cdrci
78aad47ce6 Update Helm chart and changelog with 4.141.0 (#8045) 2026-10-08 02:35:52 -08:00
cdrci
8b41915d25 Update Code to 1.141.0 (#8040)
* Update Code to 1.141.0
* Allow pull_request_target
* Add e2e tests for remote storage
* Fix Typescript extension not loading
* Remove unused imports
2026-10-07 22:54:47 -08:00
25 changed files with 453 additions and 133 deletions

View File

@@ -79,6 +79,9 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with: with:
submodules: true submodules: true
# When an update/ branch is merged, a release is automatically created
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a - run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with: with:
@@ -173,6 +176,9 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with: with:
submodules: true submodules: true
# When an update/ branch is merged, a release is automatically created
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a - run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with: with:
@@ -233,6 +239,9 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
with: with:
submodules: true submodules: true
# When an update/ branch is merged, a release is automatically created
# which requires secrets.
allow-unsafe-pr-checkout: true
# quilt has no windows build. The patches are ordinary -p1 diffs # quilt has no windows build. The patches are ordinary -p1 diffs
# against the repository root, so git applies them in series order. # against the repository root, so git applies them in series order.

View File

@@ -22,6 +22,25 @@ Code v99.99.999
## Unreleased ## Unreleased
## [4.141.0](https://github.com/coder/code-server/releases/tag/v4.141.0) - 2026-10-08
Code v1.141.0
### Added
- A new `--enable-remote-storage` flag can be used to make code-server persist
workbench storage on the remote server instead of browser storage. Use this if
you want to share storage between multiple devices.
### Fixed
- The Typescript extension was trying to load as a browser extension even though
we build the remote server version, causing it to fail to activate.
### Changed
- Update to Code 1.141.0
## [4.140.0](https://github.com/coder/code-server/releases/tag/v4.140.0) - 2026-10-02 ## [4.140.0](https://github.com/coder/code-server/releases/tag/v4.140.0) - 2026-10-02
Code v1.140.0 Code v1.140.0

View File

@@ -58,10 +58,17 @@ main() {
exit 1 exit 1
fi fi
# Add the date, our name, links, enable telemetry (this just makes telemetry # Modify the product.json:
# available; telemetry can still be disabled by flag or setting), and # - Add the date
# configure trusted extensions (since some, like github.copilot-chat, never # - Set the code-server name.
# ask to be trusted and this is the only way to get auth working). # - Add our links
# - Enable telemetry (this just makes telemetry available; telemetry can still
# be disabled by flag or setting)
# - Configure trusted extensions (since some, like github.copilot-chat, never
# ask to be trusted and this is the only way to get auth working).
# - Make Typescript server plugins run in the workspace. We build the remote
# server version, so there is no browser distribution, and this key is not
# added automatically.
# #
# This needs to be done before building as Code will read this file and embed # This needs to be done before building as Code will read this file and embed
# it into the client-side code. # it into the client-side code.
@@ -103,6 +110,9 @@ main() {
], ],
"aiConfig": { "aiConfig": {
"ariaKey": "code-server" "ariaKey": "code-server"
},
"extensionPointExtensionKind": {
"typescriptServerPlugins": ["workspace"]
} }
} }
EOF EOF

View File

@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.55.0 version: 3.56.0
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using. # follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.140.0 appVersion: 4.141.0

View File

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

140
package-lock.json generated
View File

@@ -857,17 +857,17 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.1.tgz",
"integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==", "integrity": "sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.12.2", "@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.69.0", "@typescript-eslint/scope-manager": "8.71.1",
"@typescript-eslint/type-utils": "8.69.0", "@typescript-eslint/type-utils": "8.71.1",
"@typescript-eslint/utils": "8.69.0", "@typescript-eslint/utils": "8.71.1",
"@typescript-eslint/visitor-keys": "8.69.0", "@typescript-eslint/visitor-keys": "8.71.1",
"ignore": "^7.0.5", "ignore": "^7.0.5",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.5.0"
@@ -880,15 +880,15 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.69.0", "@typescript-eslint/parser": "^8.71.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0" "typescript": ">=4.8.4 <6.1.0"
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.8", "version": "7.0.12",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz",
"integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==", "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -896,16 +896,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.1.tgz",
"integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==", "integrity": "sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.69.0", "@typescript-eslint/scope-manager": "8.71.1",
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"@typescript-eslint/typescript-estree": "8.69.0", "@typescript-eslint/typescript-estree": "8.71.1",
"@typescript-eslint/visitor-keys": "8.69.0", "@typescript-eslint/visitor-keys": "8.71.1",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -921,14 +921,14 @@
} }
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.1.tgz",
"integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==", "integrity": "sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.69.0", "@typescript-eslint/tsconfig-utils": "^8.71.1",
"@typescript-eslint/types": "^8.69.0", "@typescript-eslint/types": "^8.71.1",
"debug": "^4.4.3" "debug": "^4.4.3"
}, },
"engines": { "engines": {
@@ -943,14 +943,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.1.tgz",
"integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==", "integrity": "sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"@typescript-eslint/visitor-keys": "8.69.0" "@typescript-eslint/visitor-keys": "8.71.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -961,9 +961,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.1.tgz",
"integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==", "integrity": "sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -978,15 +978,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.1.tgz",
"integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==", "integrity": "sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"@typescript-eslint/typescript-estree": "8.69.0", "@typescript-eslint/typescript-estree": "8.71.1",
"@typescript-eslint/utils": "8.69.0", "@typescript-eslint/utils": "8.71.1",
"debug": "^4.4.3", "debug": "^4.4.3",
"ts-api-utils": "^2.5.0" "ts-api-utils": "^2.5.0"
}, },
@@ -1003,9 +1003,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.1.tgz",
"integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==", "integrity": "sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -1017,16 +1017,16 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.1.tgz",
"integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==", "integrity": "sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.69.0", "@typescript-eslint/project-service": "8.71.1",
"@typescript-eslint/tsconfig-utils": "8.69.0", "@typescript-eslint/tsconfig-utils": "8.71.1",
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"@typescript-eslint/visitor-keys": "8.69.0", "@typescript-eslint/visitor-keys": "8.71.1",
"debug": "^4.4.3", "debug": "^4.4.3",
"minimatch": "^10.2.2", "minimatch": "^10.2.2",
"semver": "^7.7.3", "semver": "^7.7.3",
@@ -1055,9 +1055,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.9", "version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1084,16 +1084,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.1.tgz",
"integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==", "integrity": "sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.9.1", "@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.69.0", "@typescript-eslint/scope-manager": "8.71.1",
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"@typescript-eslint/typescript-estree": "8.69.0" "@typescript-eslint/typescript-estree": "8.71.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1108,13 +1108,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.1.tgz",
"integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==", "integrity": "sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.69.0", "@typescript-eslint/types": "8.71.1",
"eslint-visitor-keys": "^5.0.0" "eslint-visitor-keys": "^5.0.0"
}, },
"engines": { "engines": {
@@ -1779,9 +1779,9 @@
"license": "BSD-2-Clause" "license": "BSD-2-Clause"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.18", "version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -6373,16 +6373,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.69.0", "version": "8.71.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.69.0.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.1.tgz",
"integrity": "sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==", "integrity": "sha512-oiNVPC3/NbV1FpaHU07l8O6ynqG9v4PAiW2WvTrAmZdR0f2HI/gE668ElMLCK7Xbsu5k2fK5C4fXNiq05j7/nQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.69.0", "@typescript-eslint/eslint-plugin": "8.71.1",
"@typescript-eslint/parser": "8.69.0", "@typescript-eslint/parser": "8.71.1",
"@typescript-eslint/typescript-estree": "8.69.0", "@typescript-eslint/typescript-estree": "8.71.1",
"@typescript-eslint/utils": "8.69.0" "@typescript-eslint/utils": "8.71.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

@@ -48,8 +48,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" /> + <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
<style id="vscode-css-modules" type="text/css" media="screen"></style> <style id="vscode-css-modules" type="text/css" media="screen"></style>
</head> <!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
@@ -41,7 +41,7 @@ @@ -92,7 +92,7 @@
<!-- Startup (do not modify order of script tags!) --> <!-- Startup (do not modify order of script tags!) -->
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}"> <script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
@@ -85,8 +85,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" /> + <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css"> <link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
</head> <!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
@@ -37,7 +37,7 @@ @@ -88,7 +88,7 @@
<!-- Startup (do not modify order of script tags!) --> <!-- Startup (do not modify order of script tags!) -->
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}"> <script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
@@ -281,8 +281,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
- -
(function () { (function () {
// Find config by checking for DOM // This script running at all means the page scripts were not blocked or rewritten.
@@ -610,8 +600,8 @@ function readCookie(name: string): strin @@ -614,8 +604,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) { if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element'); throw new Error('Missing web configuration element');
} }

View File

@@ -272,7 +272,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
@@ -475,9 +475,6 @@ export class InstallAction extends Exten @@ -479,9 +479,6 @@ export class InstallAction extends Exten
if (this.extension.isBuiltin) { if (this.extension.isBuiltin) {
return; return;
} }
@@ -282,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
if (this.extension.state !== ExtensionState.Uninstalled) { if (this.extension.state !== ExtensionState.Uninstalled) {
return; return;
} }
@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ @@ -786,7 +783,7 @@ export abstract class InstallInOtherServ
} }
if (isLanguagePackExtension(this.extension.local.manifest)) { if (isLanguagePackExtension(this.extension.local.manifest)) {
@@ -291,7 +291,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
} }
// Prefers to run on UI // Prefers to run on UI
@@ -2281,17 +2278,6 @@ export class SetLanguageAction extends E @@ -2285,17 +2282,6 @@ export class SetLanguageAction extends E
update(): void { update(): void {
this.enabled = false; this.enabled = false;
this.class = SetLanguageAction.DisabledClass; this.class = SetLanguageAction.DisabledClass;
@@ -309,7 +309,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
} }
override async run(): Promise<any> { override async run(): Promise<any> {
@@ -2308,7 +2294,6 @@ export class ClearLanguageAction extends @@ -2312,7 +2298,6 @@ export class ClearLanguageAction extends
private static readonly DisabledClass = `${this.EnabledClass} disabled`; private static readonly DisabledClass = `${this.EnabledClass} disabled`;
constructor( constructor(
@@ -317,7 +317,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
@ILocaleService private readonly localeService: ILocaleService, @ILocaleService private readonly localeService: ILocaleService,
) { ) {
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false); super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
@@ -2318,17 +2303,6 @@ export class ClearLanguageAction extends @@ -2322,17 +2307,6 @@ export class ClearLanguageAction extends
update(): void { update(): void {
this.enabled = false; this.enabled = false;
this.class = ClearLanguageAction.DisabledClass; this.class = ClearLanguageAction.DisabledClass;

View File

@@ -225,7 +225,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" /> + <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<style id="vscode-css-modules" type="text/css" media="screen"></style> <style id="vscode-css-modules" type="text/css" media="screen"></style>
</head> <!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html 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.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@@ -251,7 +251,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" /> + <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css"> <link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
</head> <!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts

View File

@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js'; import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js'; import { create } from '../../../workbench/workbench.web.main.internal.js';
@@ -612,6 +613,44 @@ class WorkspaceProvider implements IWork @@ -616,6 +617,44 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined, settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config), workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute), urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
@@ -159,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts --- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
@@ -99,8 +99,8 @@ export class ForwardedPortsView extends @@ -100,8 +100,8 @@ export class ForwardedPortsView extends
private async enableForwardedPortsFeatures() { private async enableForwardedPortsFeatures() {
this.contextKeyListener.clear(); this.contextKeyListener.clear();

View File

@@ -3,10 +3,10 @@ Index: code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/secrets/common/secrets.ts --- code-server.orig/lib/vscode/src/vs/platform/secrets/common/secrets.ts
+++ code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts +++ code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
@@ -139,8 +139,13 @@ export class BaseSecretStorageService ex @@ -144,8 +144,13 @@ export class BaseSecretStorageService ex
return await readEncryptedSecret( return await readEncryptedSecret(
key, key,
(fullKey) => this.getValueFromStorage(key, fullKey, storageService), (fullKey) => this.getValueFromStorage(key, fullKey, storageService),
- // If the storage service is in-memory, we don't need to decrypt - // If the storage service is in-memory, we don't need to decrypt
- this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.decrypt(v), - this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.decrypt(v),
+ // Don't decrypt if storage is in-memory or if encryption service is not available + // Don't decrypt if storage is in-memory or if encryption service is not available
@@ -19,10 +19,10 @@ Index: code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
this._logService, this._logService,
); );
} catch (e) { } catch (e) {
@@ -160,8 +165,13 @@ export class BaseSecretStorageService ex @@ -168,8 +173,13 @@ export class BaseSecretStorageService ex
key, key,
value, value,
(fullKey, encrypted) => this.setValueInStorage(key, fullKey, encrypted, storageService), (fullKey, encrypted) => this.setValueInStorage(key, fullKey, encrypted, storageService),
- // If the storage service is in-memory, we don't need to encrypt - // If the storage service is in-memory, we don't need to encrypt
- this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.encrypt(v), - this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.encrypt(v),
+ // Don't encrypt if storage is in-memory or if encryption service is not available + // Don't encrypt if storage is in-memory or if encryption service is not available
@@ -35,7 +35,7 @@ Index: code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
this._logService, this._logService,
); );
} catch (e) { } catch (e) {
@@ -194,8 +204,9 @@ export class BaseSecretStorageService ex @@ -224,8 +234,9 @@ export class BaseSecretStorageService ex
private async initialize(): Promise<IStorageService> { private async initialize(): Promise<IStorageService> {
let storageService; let storageService;
@@ -47,7 +47,7 @@ Index: code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
this._type = 'persisted'; this._type = 'persisted';
storageService = this._storageService; storageService = this._storageService;
} else { } else {
@@ -203,7 +214,7 @@ export class BaseSecretStorageService ex @@ -233,7 +244,7 @@ export class BaseSecretStorageService ex
if (this._type === 'in-memory') { if (this._type === 'in-memory') {
return this._storageService; return this._storageService;
} }
@@ -77,10 +77,14 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts --- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts +++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -625,2 +625,2 @@ @@ -655,8 +655,8 @@ class WorkspaceProvider implements IWork
})
}
},
- secretStorageProvider: config.remoteAuthority && !secretStorageKeyPath - secretStorageProvider: config.remoteAuthority && !secretStorageKeyPath
- ? undefined /* with a remote without embedder-preferred storage, store on the remote */ - ? undefined /* with a remote without embedder-preferred storage, store on the remote */
+ secretStorageProvider: config.remoteStorageEnabled || (config.remoteAuthority && !secretStorageKeyPath) + secretStorageProvider: config.remoteStorageEnabled || (config.remoteAuthority && !secretStorageKeyPath)
+ ? undefined /* with remote storage enabled, or without embedder-prefered storage, store on the remote */ + ? undefined /* with remote storage enabled, or without embedder-prefered storage, store on the remote */
: new LocalStorageSecretStorageProvider(secretStorageCrypto),
}); });
})(); })();

View File

@@ -1,8 +1,13 @@
Reuse VS Code's Electron storage service for remote persistence Reuse VS Code's Electron storage service for remote persistence
Index: code-server/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts --- code-server.orig/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
+++ code-server/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts +++ code-server/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
@@ -14 +14,6 @@ @@ -11,7 +11,12 @@ import { IStorage } from '../../../base/
import { INativeEnvironmentService } from '../../environment/common/environment.js';
import { IFileService } from '../../files/common/files.js';
import { createDecorator } from '../../instantiation/common/instantiation.js';
-import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js'; -import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js';
+import type { ILifecycleMainService, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js'; +import type { ILifecycleMainService, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js';
+ +
@@ -10,44 +15,110 @@ Reuse VS Code's Electron storage service for remote persistence
+// that module imports Electron, which is not present in the code-server server image. +// that module imports Electron, which is not present in the code-server server image.
+const LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN = 3; +const LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN = 3;
+const SHUTDOWN_REASON_KILL = 2; +const SHUTDOWN_REASON_KILL = 2;
@@ -101 +101 @@ import { ILogService } from '../../log/common/log.js';
import { AbstractStorageService, isProfileUsingDefaultStorage, IStorageService, StorageScope, StorageTarget } from '../common/storage.js';
import { ApplicationStorageMain, ApplicationSharedStorageMain, ProfileStorageMain, InMemoryStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain, IStorageChangeEvent } from './storageMain.js';
@@ -92,7 +97,7 @@ export class StorageMainService extends
@ILogService private readonly logService: ILogService,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@IUserDataProfilesMainService private readonly userDataProfilesService: IUserDataProfilesMainService,
- @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, - @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
+ private readonly lifecycleMainService: ILifecycleMainService, + private readonly lifecycleMainService: ILifecycleMainService,
@@ -117 +117 @@ @IFileService private readonly fileService: IFileService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
) {
@@ -114,7 +119,7 @@ export class StorageMainService extends
// Application Storage: Warmup when any window opens
(async () => {
- await this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen); - await this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen);
+ await this.lifecycleMainService.when(LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN); + await this.lifecycleMainService.when(LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN);
@@ -256 +256 @@
this.applicationStorage.init();
this.applicationSharedStorage.init();
@@ -253,7 +258,7 @@ export class StorageMainService extends
}
private createProfileStorage(profile: IUserDataProfile): IStorageMain {
- if (this.shutdownReason === ShutdownReason.KILL) { - if (this.shutdownReason === ShutdownReason.KILL) {
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) { + if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
@@ -295 +295 @@
// Workaround for native crashes that we see when
// SQLite DBs are being created even after shutdown
@@ -292,7 +297,7 @@ export class StorageMainService extends
}
private createWorkspaceStorage(workspace: IAnyWorkspaceIdentifier): IStorageMain {
- if (this.shutdownReason === ShutdownReason.KILL) { - if (this.shutdownReason === ShutdownReason.KILL) {
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) { + if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
// Workaround for native crashes that we see when
// SQLite DBs are being created even after shutdown
Index: code-server/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts --- code-server.orig/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts +++ code-server/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
@@ -6 +6 @@ @@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js'; -import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js';
+import { IRemoteService } from '../../../../platform/ipc/common/services.js'; +import { IRemoteService } from '../../../../platform/ipc/common/services.js';
@@ -22 +22 @@ import { IStorage, Storage, MigratingStorage } from '../../../../base/parts/storage/common/storage.js';
import { RemoteStorageService } from '../../../../platform/storage/common/storageService.js';
import { FallbackApplicationStorageDatabaseClient, ApplicationSharedStorageDatabaseClient } from '../../../../platform/storage/common/storageIpc.js';
@@ -19,10 +19,10 @@ export class NativeWorkbenchStorageServi
workspace: IAnyWorkspaceIdentifier | undefined,
private readonly userDataProfileService: IUserDataProfileService,
userDataProfilesService: IUserDataProfilesService,
- mainProcessService: IMainProcessService, - mainProcessService: IMainProcessService,
+ remoteService: Pick<IRemoteService, 'getChannel'>, + remoteService: Pick<IRemoteService, 'getChannel'>,
@@ -25 +25 @@ private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
) {
- super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, mainProcessService, workbenchEnvironmentService); - super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, mainProcessService, workbenchEnvironmentService);
+ super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, remoteService as IRemoteService, workbenchEnvironmentService); + super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, remoteService as IRemoteService, workbenchEnvironmentService);
this.registerListeners();
}
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts --- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -68,0 +69 @@ @@ -66,6 +66,7 @@ export const serverOptions: OptionDescri
'disable-experiments': OPTIONS['disable-experiments'],
'disable-workspace-trust': OPTIONS['disable-workspace-trust'],
'file-watcher-polling': { type: 'string', deprecates: ['fileWatcherPolling'] },
+ 'enable-remote-storage': { type: 'boolean', cat: 'o', description: nls.localize('enable-remote-storage', 'Persist browser storage (settings, state, etc.) on the server instead of browser IndexedDB. Enables state portability across browsers/devices.') }, + 'enable-remote-storage': { type: 'boolean', cat: 'o', description: nls.localize('enable-remote-storage', 'Persist browser storage (settings, state, etc.) on the server instead of browser IndexedDB. Enables state portability across browsers/devices.') },
@@ -214,0 +216 @@ 'log': OPTIONS['log'],
'logsPath': OPTIONS['logsPath'],
'force-disable-user-env': OPTIONS['force-disable-user-env'],
@@ -212,6 +213,7 @@ export interface ServerParsedArgs {
'logsPath'?: string;
'force-disable-user-env'?: boolean;
+ 'enable-remote-storage'?: boolean; + 'enable-remote-storage'?: boolean;
'enable-proposed-api'?: string[];
/* ----- vs code web options ----- */
Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
===================================================================
--- code-server.orig/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 +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -107,0 +108,4 @@ @@ -105,6 +105,10 @@ import { McpManagementChannel } from '..
import { AllowedMcpServersService } from '../../platform/mcp/common/allowedMcpServersService.js';
import { IMcpGalleryManifestService } from '../../platform/mcp/common/mcpGalleryManifest.js';
import { McpGalleryManifestIPCService } from '../../platform/mcp/common/mcpGalleryManifestServiceIpc.js';
+import { StorageDatabaseChannel } from '../../platform/storage/electron-main/storageIpc.js'; +import { StorageDatabaseChannel } from '../../platform/storage/electron-main/storageIpc.js';
+import { StorageMainService } from '../../platform/storage/electron-main/storageMainService.js'; +import { StorageMainService } from '../../platform/storage/electron-main/storageMainService.js';
+import type { ILifecycleMainService } from '../../platform/lifecycle/electron-main/lifecycleMainService.js'; +import type { ILifecycleMainService } from '../../platform/lifecycle/electron-main/lifecycleMainService.js';
+import type { IUserDataProfilesMainService } from '../../platform/userDataProfile/electron-main/userDataProfile.js'; +import type { IUserDataProfilesMainService } from '../../platform/userDataProfile/electron-main/userDataProfile.js';
@@ -240,0 +245,15 @@ import { SANDBOX_HELPER_CHANNEL_NAME, SandboxHelperChannel } from '../../platform/sandbox/common/sandboxHelperIpc.js';
import { SandboxHelperService } from '../../platform/sandbox/node/sandboxHelper.js';
@@ -238,6 +242,21 @@ export async function setupServerService
services.set(IMcpGatewayService, new SyncDescriptor(McpGatewayService));
const instantiationService: IInstantiationService = new InstantiationService(services);
+ // Reuse the Electron storage service on the remote. The server has no + // Reuse the Electron storage service on the remote. The server has no
+ // windows, so its lifecycle is always ready and never loads a window. + // windows, so its lifecycle is always ready and never loads a window.
+ const storageMainService = disposables.add(new StorageMainService( + const storageMainService = disposables.add(new StorageMainService(
@@ -63,7 +134,10 @@ Reuse VS Code's Electron storage service for remote persistence
+ uriIdentityService, + uriIdentityService,
+ )); + ));
+ +
@@ -419,6 +439,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken services.set(ILanguagePackService, instantiationService.createInstance(NativeLanguagePackService));
const ptyHostStarter = instantiationService.createInstance(
@@ -420,6 +439,7 @@ export async function setupServerService
const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables); const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables);
socketServer.registerChannel('languagePacks', languagePackChannel); socketServer.registerChannel('languagePacks', languagePackChannel);
@@ -71,28 +145,61 @@ Reuse VS Code's Electron storage service for remote persistence
// clean up extensions folder // clean up extensions folder
remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp()); remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp());
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -411 +411,2 @@ @@ -451,7 +451,8 @@ export class WebClientServer {
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration,
- callbackRoute: callbackRoute - callbackRoute: callbackRoute
+ callbackRoute: callbackRoute, + callbackRoute: callbackRoute,
+ remoteStorageEnabled: this._environmentService.args['enable-remote-storage'] ? true : undefined + remoteStorageEnabled: this._environmentService.args['enable-remote-storage'] ? true : undefined
};
const cookies = cookie.parse(req.headers.cookie || '');
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.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -413,0 +414,5 @@ @@ -411,6 +411,11 @@ export interface IWorkbenchConstructionO
readonly authenticationProviders?: readonly IAuthenticationProvider[];
//#endregion
+ /** + /**
+ * Persist workbench storage on the remote server instead of browser IndexedDB. + * Persist workbench storage on the remote server instead of browser IndexedDB.
+ */ + */
+ readonly remoteStorageEnabled?: boolean; + readonly remoteStorageEnabled?: boolean;
+ +
//#region Development options
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.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -35,0 +36 @@ @@ -33,6 +33,7 @@ import { ISignService } from '../../plat
import { SignService } from '../../platform/sign/browser/signService.js';
import { IWorkbenchConstructionOptions, IWorkbench, IWorkspace, ITunnel } from './web.api.js';
import { BrowserStorageService } from '../services/storage/browser/storageService.js';
+import { NativeWorkbenchStorageService } from '../services/storage/electron-browser/storageService.js'; +import { NativeWorkbenchStorageService } from '../services/storage/electron-browser/storageService.js';
@@ -479 +480 @@ import { IStorageService } from '../../platform/storage/common/storage.js';
import { toLocalISOString } from '../../base/common/date.js';
import { isWorkspaceToOpen, isFolderToOpen } from '../../platform/window/common/window.js';
@@ -482,7 +483,7 @@ export class BrowserMain extends Disposa
serviceCollection.set(IWorkbenchConfigurationService, service);
return service;
}),
- this.createStorageService(workspace, logService, userDataProfileService).then(service => { - this.createStorageService(workspace, logService, userDataProfileService).then(service => {
+ this.createStorageService(workspace, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService).then(service => { + this.createStorageService(workspace, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService).then(service => {
@@ -601 +602,15 @@ serviceCollection.set(IStorageService, service);
return service;
})
@@ -604,7 +605,21 @@ export class BrowserMain extends Disposa
}));
}
- protected async createStorageService(workspace: IAnyWorkspaceIdentifier, logService: ILogService, userDataProfileService: IUserDataProfileService): Promise<IStorageService> { - protected async createStorageService(workspace: IAnyWorkspaceIdentifier, logService: ILogService, userDataProfileService: IUserDataProfileService): Promise<IStorageService> {
+ protected async createStorageService(workspace: IAnyWorkspaceIdentifier, environmentService: IBrowserWorkbenchEnvironmentService, logService: ILogService, userDataProfileService: IUserDataProfileService, userDataProfilesService: IUserDataProfilesService, remoteAgentService: IRemoteAgentService): Promise<IStorageService> { + protected async createStorageService(workspace: IAnyWorkspaceIdentifier, environmentService: IBrowserWorkbenchEnvironmentService, logService: ILogService, userDataProfileService: IUserDataProfileService, userDataProfilesService: IUserDataProfilesService, remoteAgentService: IRemoteAgentService): Promise<IStorageService> {
+ const connection = remoteAgentService.getConnection(); + const connection = remoteAgentService.getConnection();
@@ -109,14 +216,31 @@ Reuse VS Code's Electron storage service for remote persistence
+ } + }
+ } + }
+ +
const storageService = new BrowserStorageService(workspace, userDataProfileService, logService);
try {
Index: code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/sessions/browser/web.main.ts --- code-server.orig/lib/vscode/src/vs/sessions/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/sessions/browser/web.main.ts +++ code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
@@ -42 +42 @@ @@ -39,9 +39,9 @@ export class SessionsBrowserMain extends
_workspace: IAnyWorkspaceIdentifier,
environmentService: IBrowserWorkbenchEnvironmentService,
userDataProfileService: IUserDataProfileService,
- _userDataProfilesService: BrowserUserDataProfilesService, - _userDataProfilesService: BrowserUserDataProfilesService,
+ userDataProfilesService: BrowserUserDataProfilesService, + userDataProfilesService: BrowserUserDataProfilesService,
@@ -44 +44 @@ fileService: FileService,
- _remoteAgentService: IRemoteAgentService, - _remoteAgentService: IRemoteAgentService,
+ remoteAgentService: IRemoteAgentService, + remoteAgentService: IRemoteAgentService,
@@ -85 +85 @@ uriIdentityService: IUriIdentityService,
policyService: IPolicyService,
logService: ILogService,
@@ -82,7 +82,7 @@ export class SessionsBrowserMain extends
serviceCollection.set(IWorkbenchConfigurationService, configurationService);
// Storage
- const storageService = await this.createStorageService(workspaceIdentifier, logService, userDataProfileService); - const storageService = await this.createStorageService(workspaceIdentifier, logService, userDataProfileService);
+ const storageService = await this.createStorageService(workspaceIdentifier, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService); + const storageService = await this.createStorageService(workspaceIdentifier, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService);
serviceCollection.set(IStorageService, storageService);
// Workspace Trust Service

View File

@@ -24,6 +24,6 @@ trusted-domains.diff
signature-verification.diff signature-verification.diff
copilot.diff copilot.diff
app-name.diff app-name.diff
csp-hashes.diff
remote-storage.diff remote-storage.diff
remote-secret-storage.diff remote-secret-storage.diff
csp-hashes.diff

View File

@@ -436,7 +436,11 @@ export const parse = (
const option = options[key] const option = options[key]
if (option.type === "boolean") { if (option.type === "boolean") {
;(args[key] as boolean) = true // Booleans set to false (for example `--flag=false`, which is also how
// false values from the config file are passed in) are ignored.
if (value !== "false") {
;(args[key] as boolean) = true
}
continue continue
} }

View File

@@ -3,6 +3,7 @@ import i18next, { init } from "i18next"
import * as en from "./locales/en.json" import * as en from "./locales/en.json"
import * as ja from "./locales/ja.json" import * as ja from "./locales/ja.json"
import * as th from "./locales/th.json" import * as th from "./locales/th.json"
import * as tr from "./locales/tr.json"
import * as ur from "./locales/ur.json" import * as ur from "./locales/ur.json"
import * as zhCn from "./locales/zh-cn.json" import * as zhCn from "./locales/zh-cn.json"
@@ -16,6 +17,9 @@ const defaultResources = {
th: { th: {
translation: th, translation: th,
}, },
tr: {
translation: tr,
},
ja: { ja: {
translation: ja, translation: ja,
}, },

View File

@@ -0,0 +1,13 @@
{
"LOGIN_TITLE": "{{app}} girişi",
"LOGIN_BELOW": "Lütfen aşağıdan giriş yapın.",
"WELCOME": "{{app}} uygulamasına hoş geldiniz",
"LOGIN_PASSWORD": "Parola için yapılandırma dosyasını kontrol edin.",
"LOGIN_USING_ENV_PASSWORD": "Parola $PASSWORD ortam değişkeninden ayarlandı.",
"LOGIN_USING_HASHED_PASSWORD": "Parola $HASHED_PASSWORD ortam değişkeninden ayarlandı.",
"SUBMIT": "GÖNDER",
"PASSWORD_PLACEHOLDER": "PAROLA",
"LOGIN_RATE_LIMIT": "Giriş denemesi sınırına ulaşıldı!",
"MISS_PASSWORD": "Parola eksik",
"INCORRECT_PASSWORD": "Parola yanlış."
}

View File

@@ -2,7 +2,8 @@ import * as vscode from "vscode"
export function activate(context: vscode.ExtensionContext) { export function activate(context: vscode.ExtensionContext) {
vscode.window.showInformationMessage("test extension loaded") vscode.window.showInformationMessage("test extension loaded")
// Test extension
// Prints the current proxy URI into a notification.
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("codeServerTest.proxyUri", () => { vscode.commands.registerCommand("codeServerTest.proxyUri", () => {
if (process.env.VSCODE_PROXY_URI) { if (process.env.VSCODE_PROXY_URI) {
@@ -13,7 +14,8 @@ export function activate(context: vscode.ExtensionContext) {
}), }),
) )
// asExternalUri extension // Asks for a URI, then runs it through asExternalUri and prints the result
// into a notification.
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("codeServerTest.asExternalUri", async () => { vscode.commands.registerCommand("codeServerTest.asExternalUri", async () => {
const input = await vscode.window.showInputBox({ const input = await vscode.window.showInputBox({
@@ -28,4 +30,29 @@ export function activate(context: vscode.ExtensionContext) {
} }
}), }),
) )
const secretKey = "code-server-test-secret"
// Asks for a string, then stores it as a secret.
context.subscriptions.push(
vscode.commands.registerCommand("codeServerTest.setSecret", async () => {
const input = await vscode.window.showInputBox({
prompt: "Secret to store",
})
if (input) {
await context.secrets.store(secretKey, input)
vscode.window.showInformationMessage(`set secret: ${input}`)
} else {
vscode.window.showErrorMessage(`Failed to run test case. No input provided.`)
}
}),
)
// Prints the current secret, if any.
context.subscriptions.push(
vscode.commands.registerCommand("codeServerTest.getSecret", async () => {
vscode.window.showInformationMessage(`get secret: ${await context.secrets.get(secretKey)}`)
}),
)
} }

View File

@@ -22,6 +22,16 @@
"command": "codeServerTest.asExternalUri", "command": "codeServerTest.asExternalUri",
"title": "asExternalUri test", "title": "asExternalUri test",
"category": "code-server" "category": "code-server"
},
{
"command": "codeServerTest.setSecret",
"title": "Set test secret",
"category": "code-server"
},
{
"command": "codeServerTest.getSecret",
"title": "Get test secret",
"category": "code-server"
} }
] ]
}, },

View File

@@ -363,13 +363,14 @@ export class CodeServerPage {
} }
/** /**
* Checks if the test extension loaded * Checks if the test extension loaded by waiting for its notification. Once
* it appears, dismiss the notification.
*/ */
async waitForTestExtensionLoaded(): Promise<void> { async waitForTestExtensionLoaded(): Promise<void> {
const selector = "text=test extension loaded"
this.codeServer.logger.debug("Waiting for test extension to load...") this.codeServer.logger.debug("Waiting for test extension to load...")
const locator = this.page.getByRole("dialog", { name: "Info: test extension loaded" })
await this.page.waitForSelector(selector) await locator.hover()
await locator.getByLabel("Clear Notification (Del)").click()
} }
/** /**

View File

@@ -1,5 +1,3 @@
import { promises as fs } from "fs"
import * as path from "path"
import { clean } from "../utils/helpers" import { clean } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture" import { describe, test, expect } from "./baseFixture"

61
test/e2e/storage.test.ts Normal file
View File

@@ -0,0 +1,61 @@
import { promises as fs } from "fs"
import * as path from "path"
import { describe, test, expect } from "./baseFixture"
const tests = [
{
name: "browser storage",
args: [],
},
{
name: "remote storage",
args: ["--enable-remote-storage"],
},
]
for (const tc of tests) {
const args = ["--disable-workspace-trust", "--extensions-dir", path.join(__dirname, "./extensions"), ...tc.args]
describe(tc.name, args, {}, () => {
test("should store workbench state and secrets", async ({ codeServerPage }) => {
// Create and open a file.
const dir = await codeServerPage.workspaceDir
const file = path.join(dir, "foo")
await fs.writeFile(file, "bar")
await codeServerPage.openFile(file)
// Store a secret.
const secret = "foo-bar-baz"
await codeServerPage.waitForTestExtensionLoaded()
await codeServerPage.executeCommandViaMenus("code-server: Set test secret")
await codeServerPage.page.waitForSelector(".quick-input-widget:focus-within")
await codeServerPage.page.keyboard.type(secret)
await codeServerPage.page.keyboard.press("Enter")
await expect(codeServerPage.page.getByText(`Info: set secret: ${secret}`)).toBeVisible()
// There should be a workspace storage directory.
const userDir = path.join(dir, "User/workspaceStorage")
const dirs = await fs.readdir(userDir)
expect(dirs.length).toBe(1)
const storageFile = path.join(userDir, dirs[0], "state.vscdb")
if (tc.args.includes("--enable-remote-storage")) {
// The sqlite database should exist.
fs.stat(storageFile)
} else {
// But no sqlite database.
expect(() => fs.stat(storageFile)).rejects.toThrow("ENOENT")
}
// Reload using a command so it has a chance to flush storage.
await codeServerPage.executeCommandViaMenus("Developer: Reload Window")
await codeServerPage.waitForTestExtensionLoaded()
// Should see the same file.
await codeServerPage.waitForTab(file)
// Should be able to retrieve the secret.
await codeServerPage.executeCommandViaMenus("code-server: Get test secret")
await expect(codeServerPage.page.getByText(`Info: get secret: ${secret}`)).toBeVisible()
})
})
}

View File

@@ -0,0 +1,19 @@
import { promises as fs } from "fs"
import * as path from "path"
import { describe, test, expect } from "./baseFixture"
const args = ["--disable-workspace-trust"]
describe("typescript extension", args, {}, () => {
test("should load as a workspace extension", async ({ codeServerPage }) => {
const dir = await codeServerPage.workspaceDir
const file = path.join(dir, "foo.ts")
await fs.writeFile(file, 'const n: number = "x"')
await codeServerPage.openFile(file)
await codeServerPage.executeCommandViaMenus("Developer: Show Running Extensions")
await expect(
codeServerPage.page.getByLabel("typescript-language-features").getByText(/localhost:\d+/),
).toBeVisible()
})
})

View File

@@ -578,6 +578,19 @@ describe("parser", () => {
it("should ignore optional strings set to false", async () => { it("should ignore optional strings set to false", async () => {
expect(parse(["--cert=false"])).toEqual({}) expect(parse(["--cert=false"])).toEqual({})
}) })
it("should ignore booleans set to false", async () => {
expect(parse(["--disable-telemetry=false"])).toEqual({})
})
it("should parse booleans set to false in the config file", () => {
const configContents = `
disable-telemetry: false
disable-update-check: true
`
expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({
config: "/fake-config-path",
"disable-update-check": true,
})
})
it("should use last flag", async () => { it("should use last flag", async () => {
expect(parse(["--port", "8081", "--port", "8082"])).toEqual({ expect(parse(["--port", "8081", "--port", "8082"])).toEqual({
port: 8082, port: 8082,

View File

@@ -1,9 +1,13 @@
import { promises as fs } from "fs" import { promises as fs } from "fs"
import * as os from "os" import * as os from "os"
import * as path from "path" import * as path from "path"
import { loadCustomStrings } from "../../../src/node/i18n" import i18n, { loadCustomStrings } from "../../../src/node/i18n"
describe("i18n", () => { describe("i18n", () => {
it("includes Turkish translations", () => {
expect(i18n.getResource("tr", "translation", "WELCOME")).toBe("{{app}} uygulamasına hoş geldiniz")
})
let tempDir: string let tempDir: string
let validJsonFile: string let validJsonFile: string
let invalidJsonFile: string let invalidJsonFile: string