You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# This document describes how to add new plugin api namespace
1
+
# How to add a new plugin API namespace
2
2
3
-
New Plugin API namespace should be packaged as Theia extension
3
+
This document describes how to add new plugin API namespace in the plugin host.
4
+
Depending on the plugin host we can either provide a frontend or backend API extension:
4
5
5
-
## Provide your API or namespace
6
+
- In the backend plugin host that runs in the Node environment in a separate process, we adapt the module loading to return a custom API object instead of loading a module with a particular name.
7
+
- In the frontend plugin host that runs in the browser environment via a web worker, we import the API scripts and put it in the global context.
6
8
7
-
This API developed in the way that you provide your API as separate npm package.
8
-
In that package you can declare your api.
9
-
Example `foo.d.ts`:
9
+
In this document we focus on the implementation of a backend plugin API.
10
+
However, both APIs can be provided by implementing and binding an `ExtPluginApiProvider` which should be packaged as a Theia extension.
10
11
11
-
```typescript
12
-
declaremodule'@bar/foo' {
13
-
exportnamespacefooBar {
14
-
exportfunction getFoo():Foo;
15
-
}
16
-
}
17
-
```
12
+
## Declare your plugin API provider
13
+
14
+
The plugin API provider is executed on the respective plugin host to add your custom API namespace.
To ease the usage of your API, it should be developed as separate npm package that can be easily imported without any additional dependencies, cf, the VS Code API or the Theia Plugin API.
## Next you need to implement `ExtPluginApiBackendInitializationFn`, which should handle `@bar/foo` module loading and instantiate `@foo/bar` API object, `path/to/backend/foo/implementation.js` example :
55
+
## Implement your plugin API provider
56
+
57
+
In our example, we aim to provide a new API object for the backend.
58
+
Theia expects that the `backendInitPath` that we specified in our API provider is a function called `provideApi` that follows the `ExtPluginApiBackendInitializationFn` signature.
## Next you need to implement `createAPIFactory` factory function
125
+
## Implement your API object
126
+
127
+
We create a dedicated API object for each individual plugin as part of the module loading process.
128
+
Each API object is returned as part of the module loading process if a script imports `@bar/foo` and should therefore match the API definition that we provided in the `*.d.ts` file.
129
+
Multiple imports will not lead to the creation of multiple API objects as we cache it in our custom `overrideInternalLoad` function.
In the example above the API object creates a local object that will fulfill the API contract.
150
+
The implementation details are hidden by the object and it could be a local implementation that only lives inside the plugin host but it could also be an implementation that uses the `RPCProtocol` to communicate with the main application to retrieve additional information.
151
+
152
+
### Implementing Main-Ext communication
153
+
154
+
In this document, we will only highlight the individual parts needed to establish the communication between the main application and the external plugin host.
155
+
For a more elaborate example of an API that communicates with the main application, please have a look at the definition of the [Theia Plugin API](https://github.com/eclipse-theia/theia/blob/master/doc/Plugin-API.md).
156
+
157
+
First, we need to establish the communication on the RPC protocol by providing an implementation for our own side and generating a proxy for the opposite side.
158
+
Proxies are identified using dedicated identifiers so we set them up first, together with the expected interfaces.
159
+
`Ext` and `Main` interfaces contain the functions called over RCP and must start with `$`.
160
+
Due to the asynchronous nature of the communication over RPC, the result should always be a `Promise` or `PromiseLike`.
161
+
162
+
Example `common/foo-api-rpc.ts`:
163
+
164
+
```typescript
165
+
exportinterfaceFooMain {
166
+
$getFooImpl():Promise<Foo>;
167
+
}
168
+
169
+
exportinterfaceFooExt {
170
+
// placeholder for callbacks for the main application to the extension
171
+
}
172
+
173
+
// Plugin host will obtain a proxy using these IDs, main application will register an implementation for it.
On the main side we need to implement the counterpart of the ExtPluginApiProvider, the `MainPluginApiProvider`, and expose it in a browser frontend module:
In this example, we can already see the big advantage of going to the main application side as we have full access to our Theia services.
242
+
243
+
## Usage in a plugin
244
+
245
+
When using the API in a plugin the user can simply use the API as follows:
246
+
247
+
```typescript
248
+
import*asfoofrom'@bar/foo';
249
+
250
+
foo.fooBar.getFoo();
251
+
```
252
+
253
+
## Packaging
254
+
255
+
When bundling our application with the generated `gen-webpack.node.config.js` we need to make sure that our initialization function is bundled as a `commonjs2` library so it can be dynamically loaded.
0 commit comments