Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser-only static extension support #14776

Open
wants to merge 30 commits into
base: master
Choose a base branch
from

Conversation

robertjndw
Copy link
Contributor

@robertjndw robertjndw commented Jan 27, 2025

What it does

This PR introduces support for static extension/plugin declaration in the Browser-Only mode. The required plugins can either be download and added manually to the respective directory or automatically through the theiaPlugins property. I've added a script which automatically unpacks the .vsix files in the theiaPluginsDir property and bundles them with the browser-only variant of Theia.
Currently, the metadata have to be specified by hand afterwards and will be injected at startup. An example of this can be found the in the respective directory.
Details on how to specify and craft those metadata are described in the file ADOPTING.md

How to test

As an example, I have chosen the Typescript Language tools as they run smoothly and represent a real world use case:

  1. Head to the browser-only example and run npm run download:plugins
  2. Change the corresponding paths in example-static-plugin-metadata.ts to the respective path on your system. Currently, it assumes /home/user/theia as path, just replace this part with your local theia location
  3. Run the npm run build command to build and package the plugins with the browser-only version
  4. Start the application with npm run start
  5. Head over to localhost:3000
  6. Verify that the plugins are installed (under the extensions tab, they should be listed as builtin)
  7. Create a Typescript file and while coding the autocompletion and syntax highlighting should work

Follow-ups

Unfortunately, there are some limitation which can/should be tackled in future work

  • The metadata configuration is currently done by hand. There are some methods in the node directory which would come in handy in automatic this. These should be outsourced into a independent package for handling Extension package.json files in both the node and browser-only variant
  • There is no dynamic installation of plugins. They have to be configured and bundled with Theia. In future work, there might be an option to install plugins at runtime from the OpenVSX registry.
  • Some VScode Web Extensions do not work. It seems that it has to do with the way they are bundled. An error message like module is undefined occurs when the plugin is executed and it happens in statements like module.export = i. This is strange as module is typically a Node.js thing. However, the general installation and bundling works and the error occurs directly in the plugin's bundled code when executed. To be investigated further ...

Breaking changes

  • This PR introduces breaking changes and requires careful review. If yes, the breaking changes section in the changelog has been updated.

Attribution

Review checklist

Reminder for reviewers

robertjndw and others added 30 commits September 28, 2024 22:22
@sdirix sdirix self-requested a review January 29, 2025 07:08
Copy link
Member

@sdirix sdirix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

Sadly I was not able to get the TS plugin working on my machine. It seems that some plugin storage directory was not creatable in opfs.

failed to load plugins: Unknown (FileSystemError): Error while accessing resource file:///globalStorage
    at createFileSystemProviderError (http://localhost:3000/bundle.js:381479:27)
    at OPFSFileSystemProvider.stat (http://localhost:3000/packages_filesystem_lib_browser-only_browser-only-filesystem-frontend-module_js.js:235:61)
    at async FileService.mkdirp (http://localhost:3000/bundle.js:378429:30)
    at async FileService.createFolder (http://localhost:3000/bundle.js:378413:9)
    at async HostedPluginSupport.getHostGlobalStoragePath (http://localhost:3000/packages_plugin-ext_lib_hosted_browser_hosted-plugin_js.js:732:13)
    at async Promise.all (index 2)
    at async HostedPluginSupport.startPlugins (http://localhost:3000/packages_plugin-ext_lib_hosted_browser_hosted-plugin_js.js:1401:71)
    at async HostedPluginSupport.doLoad (http://localhost:3000/packages_plugin-ext_lib_hosted_browser_hosted-plugin_js.js:1265:9)
    at async ProgressService.withProgress (http://localhost:3000/bundle.js:357799:20)
    at async http://localhost:3000/packages_plugin-ext_lib_hosted_browser_hosted-plugin_js.js:1214:17

There are two ways to retrieve extensions:
1. VSIX packages: Copy the `.vsix` files to the directory specified in the `package.json` file by the `theiaPluginsDir` property. (e.g. `"theiaPluginsDir": "plugins"`)
2. Open VSX Link: Specify a list of `id:link` mappings in the `package.json` file by the `theiaPlugins` property (e.g. `"theiaPlugins": { "vscodevim.vim": "https://open-vsx.org/api/vscodevim/vim/1.29.0/file/vscodevim.vim-1.29.0.vsix" }`). Extensions can be found on the [Open VSX Registry](https://open-vsx.org/) by searching for the extension and copying the link linked to the Download button.
When using the command `npm run download:plugins`, Theia will download the `.vsix` files from the specified links and install them in the directory specified by the `theiaPluginsDir` property.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When using the command `npm run download:plugins`, Theia will download the `.vsix` files from the specified links and install them in the directory specified by the `theiaPluginsDir` property.
When using the Theia CLI command `theia download:plugins`, the Theia CLI will download the `.vsix` files from the specified links and install them in the directory specified by the `theiaPluginsDir` property.

2. Open VSX Link: Specify a list of `id:link` mappings in the `package.json` file by the `theiaPlugins` property (e.g. `"theiaPlugins": { "vscodevim.vim": "https://open-vsx.org/api/vscodevim/vim/1.29.0/file/vscodevim.vim-1.29.0.vsix" }`). Extensions can be found on the [Open VSX Registry](https://open-vsx.org/) by searching for the extension and copying the link linked to the Download button.
When using the command `npm run download:plugins`, Theia will download the `.vsix` files from the specified links and install them in the directory specified by the `theiaPluginsDir` property.

After the extensions are downloaded, they need be packaged into the Theia Browser-Only application. To do this, run the command `npm run package:plugins` which in turn will run the [script](examples/browser-only/prepare-plugins.js) to unpack the `.vsix` files and copy the contents to the `lib/frontend/hostedPlugin` directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
After the extensions are downloaded, they need be packaged into the Theia Browser-Only application. To do this, run the command `npm run package:plugins` which in turn will run the [script](examples/browser-only/prepare-plugins.js) to unpack the `.vsix` files and copy the contents to the `lib/frontend/hostedPlugin` directory.
After the extensions are downloaded, they need to be packaged into the Theia Browser-Only application. To do this, run the command `npm run package:plugins` which in turn will run the [script](examples/browser-only/prepare-plugins.js) to unpack the `.vsix` files and copy the contents to the `lib/frontend/hostedPlugin` directory.

2. Open VSX Link: Specify a list of `id:link` mappings in the `package.json` file by the `theiaPlugins` property (e.g. `"theiaPlugins": { "vscodevim.vim": "https://open-vsx.org/api/vscodevim/vim/1.29.0/file/vscodevim.vim-1.29.0.vsix" }`). Extensions can be found on the [Open VSX Registry](https://open-vsx.org/) by searching for the extension and copying the link linked to the Download button.
When using the command `npm run download:plugins`, Theia will download the `.vsix` files from the specified links and install them in the directory specified by the `theiaPluginsDir` property.

After the extensions are downloaded, they need be packaged into the Theia Browser-Only application. To do this, run the command `npm run package:plugins` which in turn will run the [script](examples/browser-only/prepare-plugins.js) to unpack the `.vsix` files and copy the contents to the `lib/frontend/hostedPlugin` directory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ADOPTING.md is meant for downstream consumers. They don't have access to the npm run package:plugins script in their code base.

Suggestion: Describe first what needs to be done, i.e. unpacking vsix files to which specific directory, and then link to the prepare-plugins.js script as an example on how this can be done automatically.

metadata: {
'host': 'main', // Should always be set to 'main'
'model': {
'packagePath': '/home/user/theia/examples/browser-only/plugins/theia.helloworld-web-sample/extension', // Deprecated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean with "Deprecated"?

'stopMethod': 'deactivate', // the method to call when the extension is deactivated; typically 'deactivate' for VS Code extensions and 'stop' for Theia plugins
'frontendModuleName': 'theia_helloworld_web_sample', // the id specified above but with underscores instead of dots and dashes similar to iconUrl, readmeUrl, and licenseUrl
'frontendInitPath': 'plugin-vscode-init-fe.js', // the path to the frontend initialization script; only required for VS Code extensions
'backendInitPath': '/Users/user/theia/examples/browser/lib/backend/plugin-vscode-init' // the path to the backend initialization script; for Theia plugins, this path ends with 'backend-init-theia'
Copy link
Member

@sdirix sdirix Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this path needed? As we don't have a backend. If yes then we must make sure that we are self-contained and don't rely on browser build artifacts.

@@ -0,0 +1,42 @@
const { promisify } = require('util');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a copyright

Comment on lines +17 to +18
import '../../src/browser/style/terminal.css';
import 'xterm/css/xterm.css';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import '../../src/browser/style/terminal.css';
import 'xterm/css/xterm.css';

@@ -0,0 +1,27 @@
// *****************************************************************************
// Copyright (C) 2017 TypeFox and others.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be your copyright?

@@ -0,0 +1,65 @@
// *****************************************************************************
// Copyright (C) 2017 TypeFox and others.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your copyright?

const targetDir = path.join('lib', 'frontend', 'hostedPlugin', pluginName);

// Ensure the target directory exists.
await fs.mkdir(targetDir, { recursive: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the target directory already exists we should skip copying, or at least only copy missing files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Waiting on author
Development

Successfully merging this pull request may close these issues.

2 participants