-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement "headless plugins" in a new plugin host outside of frontend…
… connections (#13138) Define a 'theiaHeadlessPlugin' engine to identify headless plugins that support only the headless plugin host. Ordinary backend plugins that also run in the headless host can add a 'headless' entry-point in the 'theiaPlugin' object in package.json - update the Theia application webpack generator to handle packing the headless-plugin API init script - implement a headless entry-point in the PluginModel as a peer to frontend and backend entry-points - factor out common plugin manager behaviour into an abstract class - define distinct plugin manager (vscode/theia) and headless plugin manager implementations - similarly for the HostedPluginSupport - define the minimal TerminalExt/Main APIs for access to the default shell to support the 'env.shell' API - implement nested Inversify container for headless plugins to isolate them and their plugin host from the connection-scoped plugins - add examples for headless plugin - add a "Greeting of the Day" example custom API provider - add a plugin-gotd example headless plugin that uses the custom API example to greet the world on activation and also illustrates simple vscode API usage - Support headless entrypoint in VSCode plugins - support the headless entrypoint in an otherwise VS Code plugin - prefer the VS Code names for start/stop functions - update the example plugin to use be a dual VSCode/headless plugin using the vscode API in the usual backend entrypoint - Support distinct and application-specific headless activation events - extend the PluginPackage interface to add a "headless" property initially defining only an optional "activationEvents" string array property for headless mode. The idea being that eventually other things like "contributions" might also be defined, here - support application injection of activation events that it will trigger in its plugins via the HeadlessHostedPluginSupport class's activateByEvent(activationEvent: string) API - adapt the example GotD plugin's package manifest to use the new "headless" property - Differentiate provision of ext APIs to headless and backend plugin hosts - define a distinct headless ext API initialization function protocol and headless API initialization script path to target the headless plugin host specifically in the ext API provider - refactor the initialization of ext APIs in the plugin host to make use of this new distinction - update the Greeting-of-the-Day example API provider to support both headless and backend plugins - define the index for the common plugin-ext-headless API exports - fix up other minor details - Inversify injection in the Plugin Host - implement an Inversify container in the plugin hosts - inject Ext interfaces and the RPC framework - get container modules in plugin entrypoints to configure the container - the plugin container module can provide for API initialization in a simpler, more reusable way than the current initialization function, which is still supported for backwards compatibility Signed-off-by: Christian W. Damus <[email protected]> Co-authored-by: Martin Fleck <[email protected]> Co-authored-by: Mark Sujew <[email protected]>
- Loading branch information
1 parent
b4bbecd
commit 56cf3db
Showing
94 changed files
with
4,155 additions
and
794 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
extends: [ | ||
'../../configs/build.eslintrc.json' | ||
], | ||
parserOptions: { | ||
tsconfigRootDir: __dirname, | ||
project: 'tsconfig.json' | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<div align='center'> | ||
|
||
<br /> | ||
|
||
<img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' /> | ||
|
||
<h2>ECLIPSE THEIA - API PROVIDER SAMPLE</h2> | ||
|
||
<hr /> | ||
|
||
</div> | ||
|
||
## Description | ||
|
||
The `@theia/api-provider-sample` extension is a programming example showing how to define and provide a custom API object for _plugins_ to use. | ||
The purpose of the extension is to: | ||
- provide developers with realistic coding examples of providing custom API objects | ||
- provide easy-to-use and test examples for features when reviewing pull requests | ||
|
||
The extension is for reference and test purposes only and is not published on `npm` (`private: true`). | ||
|
||
### Greeting of the Day | ||
|
||
The sample defines a `gotd` API that plugins can import and use to obtain tailored messages with which to greet the world, for example in their activation function. | ||
|
||
The source code is laid out in the `src/` tree as follows: | ||
|
||
- `gotd.d.ts` — the TypeScript definition of the `gotd` API object that plugins import to interact with the "Greeting of the Day" service | ||
- `plugin/` — the API initialization script and the implementation of the API objects (`GreetingExt` and similar interfaces). | ||
All code in this directory runs exclusively in the separate plugin-host Node process, isolated from the main Theia process, together with either headless plugins or the backend of VS Code plugins. | ||
The `GreetingExtImpl` and similar classes communicate with the actual API implementation (`GreetingMainImpl` etc.) classes in the main Theia process via RPC | ||
- `node/` — the API classes implementing `GreetingMain` and similar interfaces and the Inversify bindings that register the API provider. | ||
All code in this directory runs in the main Theia Node process | ||
- `common/` — the RPC API Ext/Main interface definitions corresponding to the backend of the `gotd` plugin API | ||
|
||
## Additional Information | ||
|
||
- [Theia - GitHub](https://github.com/eclipse-theia/theia) | ||
- [Theia - Website](https://theia-ide.org/) | ||
|
||
## License | ||
|
||
- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/) | ||
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp) | ||
|
||
## Trademark | ||
"Theia" is a trademark of the Eclipse Foundation | ||
https://www.eclipse.org/theia |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{ | ||
"private": true, | ||
"name": "@theia/api-provider-sample", | ||
"version": "1.45.0", | ||
"description": "Theia - Example code to demonstrate Theia API Provider Extensions", | ||
"dependencies": { | ||
"@theia/core": "1.45.0", | ||
"@theia/plugin-ext-headless": "1.45.0", | ||
"@theia/plugin-ext": "1.45.0" | ||
}, | ||
"theiaExtensions": [ | ||
{ | ||
"backend": "lib/node/gotd-backend-module" | ||
} | ||
], | ||
"keywords": [ | ||
"theia-extension" | ||
], | ||
"license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/eclipse-theia/theia.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/eclipse-theia/theia/issues" | ||
}, | ||
"homepage": "https://github.com/eclipse-theia/theia", | ||
"files": [ | ||
"lib", | ||
"src" | ||
], | ||
"types": "src/gotd.d.ts", | ||
"scripts": { | ||
"lint": "theiaext lint", | ||
"build": "theiaext build", | ||
"watch": "theiaext watch", | ||
"clean": "theiaext clean" | ||
}, | ||
"devDependencies": { | ||
"@theia/ext-scripts": "1.45.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2024 EclipseSource and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// http://www.eclipse.org/legal/epl-2.0. | ||
// | ||
// This Source Code may also be made available under the following Secondary | ||
// Licenses when the conditions for such availability set forth in the Eclipse | ||
// Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
// with the GNU Classpath Exception which is available at | ||
// https://www.gnu.org/software/classpath/license.html. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 | ||
// ***************************************************************************** | ||
import { createProxyIdentifier } from '@theia/plugin-ext/lib/common/rpc-protocol'; | ||
import type { greeting } from '../gotd'; | ||
import { Event } from '@theia/core'; | ||
|
||
export enum GreetingKind { | ||
DIRECT = 1, | ||
QUIRKY = 2, | ||
SNARKY = 3, | ||
} | ||
|
||
export interface GreeterData { | ||
readonly uuid: string; | ||
greetingKinds: greeting.GreetingKind[]; | ||
}; | ||
|
||
export const GreetingMain = Symbol('GreetingMain'); | ||
export interface GreetingMain { | ||
$getMessage(greeterId: string): Promise<string>; | ||
|
||
$createGreeter(): Promise<GreeterData>; | ||
$destroyGreeter(greeterId: GreeterData['uuid']): Promise<void>; | ||
|
||
$updateGreeter(data: GreeterData): void; | ||
} | ||
|
||
export const GreetingExt = Symbol('GreetingExt'); | ||
export interface GreetingExt { | ||
|
||
// | ||
// External protocol | ||
// | ||
|
||
registerGreeter(): Promise<string>; | ||
unregisterGreeter(uuid: string): Promise<void>; | ||
|
||
getMessage(greeterId: string): Promise<string>; | ||
getGreetingKinds(greeterId: string): readonly greeting.GreetingKind[]; | ||
setGreetingKindEnabled(greeterId: string, greetingKind: greeting.GreetingKind, enable: boolean): void; | ||
onGreetingKindsChanged(greeterId: string): Event<readonly greeting.GreetingKind[]>; | ||
|
||
// | ||
// Internal protocol | ||
// | ||
|
||
$greeterUpdated(data: GreeterData): void; | ||
|
||
} | ||
|
||
export const PLUGIN_RPC_CONTEXT = { | ||
GREETING_MAIN: createProxyIdentifier<GreetingMain>('GreetingMain'), | ||
}; | ||
|
||
export const MAIN_RPC_CONTEXT = { | ||
GREETING_EXT: createProxyIdentifier<GreetingExt>('GreetingExt'), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2024 EclipseSource and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// http://www.eclipse.org/legal/epl-2.0. | ||
// | ||
// This Source Code may also be made available under the following Secondary | ||
// Licenses when the conditions for such availability set forth in the Eclipse | ||
// Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
// with the GNU Classpath Exception which is available at | ||
// https://www.gnu.org/software/classpath/license.html. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 | ||
// ***************************************************************************** | ||
|
||
// Strictly speaking, the 'greeting' namespace is an unnecessary level of organization | ||
// but it serves to illustrate how API namespaces are implemented in the backend. | ||
export namespace greeting { | ||
export function createGreeter(): Promise<greeting.Greeter>; | ||
|
||
export enum GreetingKind { | ||
DIRECT = 1, | ||
QUIRKY = 2, | ||
SNARKY = 3, | ||
} | ||
|
||
export interface Greeter extends Disposable { | ||
greetingKinds: readonly GreetingKind[]; | ||
|
||
getMessage(): Promise<string>; | ||
|
||
setGreetingKind(kind: GreetingKind, enable = true): void; | ||
|
||
onGreetingKindsChanged: Event<readonly GreetingKind[]>; | ||
} | ||
} | ||
|
||
export interface Event<T> { | ||
(listener: (e: T) => unknown, thisArg?: unknown): Disposable; | ||
} | ||
|
||
export interface Disposable { | ||
dispose(): void; | ||
} | ||
|
||
namespace Disposable { | ||
export function create(func: () => void): Disposable; | ||
} |
33 changes: 33 additions & 0 deletions
33
examples/api-provider-sample/src/node/ext-plugin-gotd-api-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2024 EclipseSource and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// http://www.eclipse.org/legal/epl-2.0. | ||
// | ||
// This Source Code may also be made available under the following Secondary | ||
// Licenses when the conditions for such availability set forth in the Eclipse | ||
// Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
// with the GNU Classpath Exception which is available at | ||
// https://www.gnu.org/software/classpath/license.html. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 | ||
// ***************************************************************************** | ||
import * as path from 'path'; | ||
import { injectable } from '@theia/core/shared/inversify'; | ||
import { ExtPluginApi, ExtPluginApiProvider } from '@theia/plugin-ext-headless'; | ||
|
||
@injectable() | ||
export class ExtPluginGotdApiProvider implements ExtPluginApiProvider { | ||
provideApi(): ExtPluginApi { | ||
// We can support both backend plugins and headless plugins, so we have only one | ||
// entry-point script. Moreover, the application build packages that script in | ||
// the `../backend/` directory from its source `../plugin/` location, alongside | ||
// the scripts for all other plugin API providers. | ||
const universalInitPath = path.join(__dirname, '../backend/gotd-api-init'); | ||
return { | ||
backendInitPath: universalInitPath, | ||
headlessInitPath: universalInitPath | ||
}; | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
examples/api-provider-sample/src/node/gotd-backend-module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2024 EclipseSource and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// http://www.eclipse.org/legal/epl-2.0. | ||
// | ||
// This Source Code may also be made available under the following Secondary | ||
// Licenses when the conditions for such availability set forth in the Eclipse | ||
// Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
// with the GNU Classpath Exception which is available at | ||
// https://www.gnu.org/software/classpath/license.html. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 | ||
// ***************************************************************************** | ||
import { ContainerModule } from '@theia/core/shared/inversify'; | ||
import { ExtPluginApiProvider } from '@theia/plugin-ext'; | ||
import { ExtPluginGotdApiProvider } from './ext-plugin-gotd-api-provider'; | ||
import { MainPluginApiProvider } from '@theia/plugin-ext/lib/common/plugin-ext-api-contribution'; | ||
import { GotdMainPluginApiProvider } from './gotd-main-plugin-provider'; | ||
import { GreetingMain } from '../common/plugin-api-rpc'; | ||
import { GreetingMainImpl } from './greeting-main-impl'; | ||
|
||
export default new ContainerModule(bind => { | ||
bind(Symbol.for(ExtPluginApiProvider)).to(ExtPluginGotdApiProvider).inSingletonScope(); | ||
bind(MainPluginApiProvider).to(GotdMainPluginApiProvider).inSingletonScope(); | ||
bind(GreetingMain).to(GreetingMainImpl).inSingletonScope(); | ||
}); |
29 changes: 29 additions & 0 deletions
29
examples/api-provider-sample/src/node/gotd-main-plugin-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// ***************************************************************************** | ||
// Copyright (C) 2024 EclipseSource and others. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Eclipse Public License v. 2.0 which is available at | ||
// http://www.eclipse.org/legal/epl-2.0. | ||
// | ||
// This Source Code may also be made available under the following Secondary | ||
// Licenses when the conditions for such availability set forth in the Eclipse | ||
// Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
// with the GNU Classpath Exception which is available at | ||
// https://www.gnu.org/software/classpath/license.html. | ||
// | ||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 | ||
// ***************************************************************************** | ||
import { MainPluginApiProvider } from '@theia/plugin-ext/lib/common/plugin-ext-api-contribution'; | ||
import { RPCProtocol } from '@theia/plugin-ext/lib/common/rpc-protocol'; | ||
import { inject, injectable } from '@theia/core/shared/inversify'; | ||
import { GreetingMain, PLUGIN_RPC_CONTEXT } from '../common/plugin-api-rpc'; | ||
|
||
@injectable() | ||
export class GotdMainPluginApiProvider implements MainPluginApiProvider { | ||
@inject(GreetingMain) | ||
protected readonly greetingMain: GreetingMain; | ||
|
||
initialize(rpc: RPCProtocol): void { | ||
rpc.set(PLUGIN_RPC_CONTEXT.GREETING_MAIN, this.greetingMain); | ||
} | ||
} |
Oops, something went wrong.