@theia/plugin-ext 1.27.0-next.37 → 1.27.0-next.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/lib/common/plugin-identifiers.d.ts +41 -0
  2. package/lib/common/plugin-identifiers.d.ts.map +1 -0
  3. package/lib/common/plugin-identifiers.js +81 -0
  4. package/lib/common/plugin-identifiers.js.map +1 -0
  5. package/lib/common/plugin-protocol.d.ts +28 -7
  6. package/lib/common/plugin-protocol.d.ts.map +1 -1
  7. package/lib/common/plugin-protocol.js +3 -1
  8. package/lib/common/plugin-protocol.js.map +1 -1
  9. package/lib/hosted/browser/hosted-plugin.d.ts +2 -2
  10. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  11. package/lib/hosted/browser/hosted-plugin.js +20 -13
  12. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  13. package/lib/hosted/browser/worker/plugin-manifest-loader.d.ts.map +1 -1
  14. package/lib/hosted/browser/worker/plugin-manifest-loader.js +4 -1
  15. package/lib/hosted/browser/worker/plugin-manifest-loader.js.map +1 -1
  16. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts +10 -5
  17. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts.map +1 -1
  18. package/lib/hosted/node/hosted-plugin-deployer-handler.js +54 -12
  19. package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
  20. package/lib/hosted/node/hosted-plugin-process.d.ts +2 -2
  21. package/lib/hosted/node/hosted-plugin-process.d.ts.map +1 -1
  22. package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
  23. package/lib/hosted/node/hosted-plugin.d.ts +2 -2
  24. package/lib/hosted/node/hosted-plugin.d.ts.map +1 -1
  25. package/lib/hosted/node/hosted-plugin.js.map +1 -1
  26. package/lib/hosted/node/metadata-scanner.d.ts +3 -2
  27. package/lib/hosted/node/metadata-scanner.d.ts.map +1 -1
  28. package/lib/hosted/node/metadata-scanner.js +8 -3
  29. package/lib/hosted/node/metadata-scanner.js.map +1 -1
  30. package/lib/hosted/node/plugin-manifest-loader.d.ts.map +1 -1
  31. package/lib/hosted/node/plugin-manifest-loader.js +3 -0
  32. package/lib/hosted/node/plugin-manifest-loader.js.map +1 -1
  33. package/lib/hosted/node/plugin-service.d.ts +18 -4
  34. package/lib/hosted/node/plugin-service.d.ts.map +1 -1
  35. package/lib/hosted/node/plugin-service.js +73 -18
  36. package/lib/hosted/node/plugin-service.js.map +1 -1
  37. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  38. package/lib/hosted/node/scanners/scanner-theia.js +4 -2
  39. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  40. package/lib/main/browser/main-context.d.ts.map +1 -1
  41. package/lib/main/browser/main-context.js +2 -1
  42. package/lib/main/browser/main-context.js.map +1 -1
  43. package/lib/main/browser/plugin-shared-style.d.ts +3 -1
  44. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  45. package/lib/main/browser/plugin-shared-style.js +15 -4
  46. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  47. package/lib/main/browser/theming-main.d.ts +2 -1
  48. package/lib/main/browser/theming-main.d.ts.map +1 -1
  49. package/lib/main/browser/theming-main.js +3 -6
  50. package/lib/main/browser/theming-main.js.map +1 -1
  51. package/lib/main/browser/webview/webview-theme-data-provider.d.ts +2 -0
  52. package/lib/main/browser/webview/webview-theme-data-provider.d.ts.map +1 -1
  53. package/lib/main/browser/webview/webview-theme-data-provider.js +5 -1
  54. package/lib/main/browser/webview/webview-theme-data-provider.js.map +1 -1
  55. package/lib/main/node/handlers/plugin-theia-directory-handler.d.ts +6 -1
  56. package/lib/main/node/handlers/plugin-theia-directory-handler.d.ts.map +1 -1
  57. package/lib/main/node/handlers/plugin-theia-directory-handler.js +61 -20
  58. package/lib/main/node/handlers/plugin-theia-directory-handler.js.map +1 -1
  59. package/lib/main/node/handlers/plugin-theia-file-handler.d.ts +4 -0
  60. package/lib/main/node/handlers/plugin-theia-file-handler.d.ts.map +1 -1
  61. package/lib/main/node/handlers/plugin-theia-file-handler.js +25 -4
  62. package/lib/main/node/handlers/plugin-theia-file-handler.js.map +1 -1
  63. package/lib/main/node/plugin-cli-contribution.d.ts +3 -0
  64. package/lib/main/node/plugin-cli-contribution.d.ts.map +1 -1
  65. package/lib/main/node/plugin-cli-contribution.js +13 -0
  66. package/lib/main/node/plugin-cli-contribution.js.map +1 -1
  67. package/lib/main/node/plugin-deployer-directory-handler-context-impl.d.ts +1 -0
  68. package/lib/main/node/plugin-deployer-directory-handler-context-impl.d.ts.map +1 -1
  69. package/lib/main/node/plugin-deployer-directory-handler-context-impl.js +17 -0
  70. package/lib/main/node/plugin-deployer-directory-handler-context-impl.js.map +1 -1
  71. package/lib/main/node/plugin-deployer-file-handler-context-impl.d.ts.map +1 -1
  72. package/lib/main/node/plugin-deployer-file-handler-context-impl.js +0 -1
  73. package/lib/main/node/plugin-deployer-file-handler-context-impl.js.map +1 -1
  74. package/lib/main/node/plugin-deployer-impl.d.ts +5 -2
  75. package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
  76. package/lib/main/node/plugin-deployer-impl.js +72 -28
  77. package/lib/main/node/plugin-deployer-impl.js.map +1 -1
  78. package/lib/main/node/plugin-ext-backend-module.d.ts.map +1 -1
  79. package/lib/main/node/plugin-ext-backend-module.js +2 -0
  80. package/lib/main/node/plugin-ext-backend-module.js.map +1 -1
  81. package/lib/main/node/plugin-server-handler.d.ts +3 -2
  82. package/lib/main/node/plugin-server-handler.d.ts.map +1 -1
  83. package/lib/main/node/plugin-server-handler.js +3 -0
  84. package/lib/main/node/plugin-server-handler.js.map +1 -1
  85. package/lib/main/node/plugin-uninstallation-manager.d.ts +12 -0
  86. package/lib/main/node/plugin-uninstallation-manager.d.ts.map +1 -0
  87. package/lib/main/node/plugin-uninstallation-manager.js +66 -0
  88. package/lib/main/node/plugin-uninstallation-manager.js.map +1 -0
  89. package/package.json +25 -24
  90. package/src/common/plugin-identifiers.ts +84 -0
  91. package/src/common/plugin-protocol.ts +32 -8
  92. package/src/hosted/browser/hosted-plugin.ts +22 -16
  93. package/src/hosted/browser/worker/plugin-manifest-loader.ts +4 -2
  94. package/src/hosted/node/hosted-plugin-deployer-handler.ts +64 -20
  95. package/src/hosted/node/hosted-plugin-process.ts +2 -2
  96. package/src/hosted/node/hosted-plugin.ts +2 -2
  97. package/src/hosted/node/metadata-scanner.ts +8 -6
  98. package/src/hosted/node/plugin-manifest-loader.ts +2 -0
  99. package/src/hosted/node/plugin-service.ts +79 -23
  100. package/src/hosted/node/scanners/scanner-theia.ts +5 -3
  101. package/src/main/browser/main-context.ts +2 -1
  102. package/src/main/browser/plugin-shared-style.ts +7 -4
  103. package/src/main/browser/theming-main.ts +3 -7
  104. package/src/main/browser/webview/webview-theme-data-provider.ts +5 -9
  105. package/src/main/node/handlers/plugin-theia-directory-handler.ts +56 -28
  106. package/src/main/node/handlers/plugin-theia-file-handler.ts +25 -4
  107. package/src/main/node/plugin-cli-contribution.ts +12 -0
  108. package/src/main/node/plugin-deployer-directory-handler-context-impl.ts +17 -1
  109. package/src/main/node/plugin-deployer-file-handler-context-impl.ts +0 -1
  110. package/src/main/node/plugin-deployer-impl.ts +75 -30
  111. package/src/main/node/plugin-ext-backend-module.ts +3 -0
  112. package/src/main/node/plugin-server-handler.ts +6 -2
  113. package/src/main/node/plugin-uninstallation-manager.ts +60 -0
@@ -17,11 +17,12 @@
17
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
18
 
19
19
  import { injectable, optional, multiInject, inject, named } from '@theia/core/shared/inversify';
20
+ import * as semver from 'semver';
20
21
  import {
21
22
  PluginDeployerResolver, PluginDeployerFileHandler, PluginDeployerDirectoryHandler,
22
23
  PluginDeployerEntry, PluginDeployer, PluginDeployerParticipant, PluginDeployerStartContext,
23
24
  PluginDeployerResolverInit, PluginDeployerFileHandlerContext,
24
- PluginDeployerDirectoryHandlerContext, PluginDeployerEntryType, PluginDeployerHandler, PluginType, UnresolvedPluginEntry
25
+ PluginDeployerDirectoryHandlerContext, PluginDeployerEntryType, PluginDeployerHandler, PluginType, UnresolvedPluginEntry, PluginIdentifiers
25
26
  } from '../../common/plugin-protocol';
26
27
  import { PluginDeployerEntryImpl } from './plugin-deployer-entry-impl';
27
28
  import {
@@ -135,7 +136,11 @@ export class PluginDeployerImpl implements PluginDeployer {
135
136
  deployPlugins.log('Deploy plugins list');
136
137
  }
137
138
 
138
- async undeploy(pluginId: string): Promise<void> {
139
+ async uninstall(pluginId: PluginIdentifiers.VersionedId): Promise<void> {
140
+ await this.pluginDeployerHandler.uninstallPlugin(pluginId);
141
+ }
142
+
143
+ async undeploy(pluginId: PluginIdentifiers.VersionedId): Promise<void> {
139
144
  if (await this.pluginDeployerHandler.undeployPlugin(pluginId)) {
140
145
  this.onDidDeployEmitter.fire();
141
146
  }
@@ -163,49 +168,49 @@ export class PluginDeployerImpl implements PluginDeployer {
163
168
  */
164
169
  async resolvePlugins(plugins: UnresolvedPluginEntry[]): Promise<PluginDeployerEntry[]> {
165
170
  const visited = new Set<string>();
166
- const pluginsToDeploy = new Map<string, PluginDeployerEntry>();
171
+ const hasBeenVisited = (id: string) => visited.has(id) || (visited.add(id), false);
172
+ const pluginsToDeploy = new Map<PluginIdentifiers.VersionedId, PluginDeployerEntry>();
173
+ const unversionedIdsHandled = new Map<PluginIdentifiers.UnversionedId, string[]>();
167
174
 
168
- let queue: UnresolvedPluginEntry[] = [...plugins];
175
+ const queue: UnresolvedPluginEntry[] = [...plugins];
169
176
  while (queue.length) {
170
- const dependenciesChunk: Array<{
177
+ const pendingDependencies: Array<{
171
178
  dependencies: Map<string, string>
172
179
  type: PluginType
173
180
  }> = [];
174
- const workload: UnresolvedPluginEntry[] = [];
175
- while (queue.length) {
176
- const current = queue.shift()!;
177
- if (visited.has(current.id)) {
178
- continue;
179
- } else {
180
- workload.push(current);
181
- }
182
- visited.add(current.id);
183
- }
184
- queue = [];
185
- await Promise.all(workload.map(async ({ id, type }) => {
186
- if (type === undefined) {
187
- type = PluginType.System;
181
+ await Promise.all(queue.map(async entry => {
182
+ if (hasBeenVisited(entry.id)) {
183
+ return;
188
184
  }
185
+ const type = entry.type ?? PluginType.System;
189
186
  try {
190
- const pluginDeployerEntries = await this.resolvePlugin(id, type);
191
- await this.applyFileHandlers(pluginDeployerEntries);
192
- await this.applyDirectoryFileHandlers(pluginDeployerEntries);
187
+ const pluginDeployerEntries = await this.resolveAndHandle(entry.id, type);
193
188
  for (const deployerEntry of pluginDeployerEntries) {
194
- const dependencies = await this.pluginDeployerHandler.getPluginDependencies(deployerEntry);
195
- if (dependencies && !pluginsToDeploy.has(dependencies.metadata.model.id)) {
196
- pluginsToDeploy.set(dependencies.metadata.model.id, deployerEntry);
197
- if (dependencies.mapping) {
198
- dependenciesChunk.push({ dependencies: dependencies.mapping, type });
189
+ const pluginData = await this.pluginDeployerHandler.getPluginDependencies(deployerEntry);
190
+ const versionedId = pluginData && PluginIdentifiers.componentsToVersionedId(pluginData.metadata.model);
191
+ const unversionedId = versionedId && PluginIdentifiers.componentsToUnversionedId(pluginData.metadata.model);
192
+ if (unversionedId && !pluginsToDeploy.has(versionedId)) {
193
+ pluginsToDeploy.set(versionedId, deployerEntry);
194
+ if (pluginData.mapping) {
195
+ pendingDependencies.push({ dependencies: pluginData.mapping, type });
196
+ }
197
+ const otherVersions = unversionedIdsHandled.get(unversionedId) ?? [];
198
+ otherVersions.push(pluginData.metadata.model.version);
199
+ if (otherVersions.length === 1) {
200
+ unversionedIdsHandled.set(unversionedId, otherVersions);
201
+ } else {
202
+ this.findBestVersion(unversionedId, otherVersions, pluginsToDeploy);
199
203
  }
200
204
  }
201
205
  }
202
206
  } catch (e) {
203
- console.error(`Failed to resolve plugins from '${id}'`, e);
207
+ console.error(`Failed to resolve plugins from '${entry.id}'`, e);
204
208
  }
205
209
  }));
206
- for (const { dependencies, type } of dependenciesChunk) {
210
+ queue.length = 0;
211
+ for (const { dependencies, type } of pendingDependencies) {
207
212
  for (const [dependency, deployableDependency] of dependencies) {
208
- if (!pluginsToDeploy.has(dependency)) {
213
+ if (!unversionedIdsHandled.has(dependency as PluginIdentifiers.UnversionedId)) {
209
214
  queue.push({
210
215
  id: deployableDependency,
211
216
  type
@@ -217,6 +222,46 @@ export class PluginDeployerImpl implements PluginDeployer {
217
222
  return [...pluginsToDeploy.values()];
218
223
  }
219
224
 
225
+ protected async resolveAndHandle(id: string, type: PluginType): Promise<PluginDeployerEntry[]> {
226
+ const entries = await this.resolvePlugin(id, type);
227
+ await this.applyFileHandlers(entries);
228
+ await this.applyDirectoryFileHandlers(entries);
229
+ return entries;
230
+ }
231
+
232
+ protected findBestVersion(unversionedId: PluginIdentifiers.UnversionedId, versions: string[], knownPlugins: Map<PluginIdentifiers.VersionedId, PluginDeployerEntry>): void {
233
+ // If left better, return negative. Then best is index 0.
234
+ versions.map(version => ({ version, plugin: knownPlugins.get(PluginIdentifiers.idAndVersionToVersionedId({ version, id: unversionedId })) }))
235
+ .sort((left, right) => {
236
+ const leftPlugin = left.plugin;
237
+ const rightPlugin = right.plugin;
238
+ if (!leftPlugin && !rightPlugin) {
239
+ return 0;
240
+ }
241
+ if (!rightPlugin) {
242
+ return -1;
243
+ }
244
+ if (!leftPlugin) {
245
+ return 1;
246
+ }
247
+ if (leftPlugin.type === PluginType.System && rightPlugin.type === PluginType.User) {
248
+ return -1;
249
+ }
250
+ if (leftPlugin.type === PluginType.User && rightPlugin.type === PluginType.System) {
251
+ return 1;
252
+ }
253
+ if (semver.gtr(left.version, right.version)) {
254
+ return -1;
255
+ }
256
+ return 1;
257
+ }).forEach((versionedEntry, index) => {
258
+ if (index !== 0) {
259
+ // Mark as not accepted to prevent deployment of all but the winner.
260
+ versionedEntry.plugin?.accept();
261
+ }
262
+ });
263
+ }
264
+
220
265
  /**
221
266
  * deploy all plugins that have been accepted
222
267
  */
@@ -39,6 +39,7 @@ import { PluginCliContribution } from './plugin-cli-contribution';
39
39
  import { PluginTheiaEnvironment } from '../common/plugin-theia-environment';
40
40
  import { PluginTheiaDeployerParticipant } from './plugin-theia-deployer-participant';
41
41
  import { WebviewBackendSecurityWarnings } from './webview-backend-security-warnings';
42
+ import { PluginUninstallationManager } from './plugin-uninstallation-manager';
42
43
 
43
44
  export function bindMainBackend(bind: interfaces.Bind): void {
44
45
  bind(PluginApiContribution).toSelf().inSingletonScope();
@@ -50,6 +51,8 @@ export function bindMainBackend(bind: interfaces.Bind): void {
50
51
  bind(PluginDeployerContribution).toSelf().inSingletonScope();
51
52
  bind(BackendApplicationContribution).toService(PluginDeployerContribution);
52
53
 
54
+ bind(PluginUninstallationManager).toSelf().inSingletonScope();
55
+
53
56
  bind(PluginDeployerResolver).to(LocalDirectoryPluginDeployerResolver).inSingletonScope();
54
57
  bind(PluginDeployerResolver).to(LocalFilePluginDeployerResolver).inSingletonScope();
55
58
  bind(PluginDeployerResolver).to(GithubPluginDeployerResolver).inSingletonScope();
@@ -18,7 +18,7 @@ import { injectable, inject } from '@theia/core/shared/inversify';
18
18
  import { CancellationToken } from '@theia/core/lib/common/cancellation';
19
19
  import { PluginDeployerImpl } from './plugin-deployer-impl';
20
20
  import { PluginsKeyValueStorage } from './plugins-key-value-storage';
21
- import { PluginServer, PluginDeployer, PluginStorageKind, PluginType, UnresolvedPluginEntry } from '../../common/plugin-protocol';
21
+ import { PluginServer, PluginDeployer, PluginStorageKind, PluginType, UnresolvedPluginEntry, PluginIdentifiers } from '../../common/plugin-protocol';
22
22
  import { KeysToAnyValues, KeysToKeysToAnyValue } from '../../common/types';
23
23
 
24
24
  @injectable()
@@ -42,7 +42,11 @@ export class PluginServerHandler implements PluginServer {
42
42
  return this.pluginDeployer.deploy(pluginEntry);
43
43
  }
44
44
 
45
- undeploy(pluginId: string): Promise<void> {
45
+ uninstall(pluginId: PluginIdentifiers.VersionedId): Promise<void> {
46
+ return this.pluginDeployer.uninstall(pluginId);
47
+ }
48
+
49
+ undeploy(pluginId: PluginIdentifiers.VersionedId): Promise<void> {
46
50
  return this.pluginDeployer.undeploy(pluginId);
47
51
  }
48
52
 
@@ -0,0 +1,60 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2022 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { Emitter, Event } from '@theia/core';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { PluginIdentifiers } from '../../common';
20
+
21
+ @injectable()
22
+ export class PluginUninstallationManager {
23
+ protected readonly onDidChangeUninstalledPluginsEmitter = new Emitter<readonly PluginIdentifiers.VersionedId[]>();
24
+
25
+ get onDidChangeUninstalledPlugins(): Event<readonly PluginIdentifiers.VersionedId[]> {
26
+ return this.onDidChangeUninstalledPluginsEmitter.event;
27
+ }
28
+
29
+ protected uninstalledPlugins: PluginIdentifiers.VersionedId[] = [];
30
+
31
+ markAsUninstalled(pluginId: PluginIdentifiers.VersionedId): boolean {
32
+ if (!this.uninstalledPlugins.includes(pluginId)) {
33
+ this.uninstalledPlugins.push(pluginId);
34
+ this.onDidChangeUninstalledPluginsEmitter.fire(Object.freeze(this.uninstalledPlugins.slice()));
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+
40
+ markAsInstalled(pluginId: PluginIdentifiers.VersionedId): boolean {
41
+ let index: number;
42
+ let didChange = false;
43
+ while ((index = this.uninstalledPlugins.indexOf(pluginId)) !== -1) {
44
+ this.uninstalledPlugins.splice(index, 1);
45
+ didChange = true;
46
+ }
47
+ if (didChange) {
48
+ this.onDidChangeUninstalledPluginsEmitter.fire(Object.freeze(this.uninstalledPlugins.slice()));
49
+ }
50
+ return didChange;
51
+ }
52
+
53
+ isUninstalled(pluginId: PluginIdentifiers.VersionedId): boolean {
54
+ return this.uninstalledPlugins.includes(pluginId);
55
+ }
56
+
57
+ getUninstalledPluginIds(): readonly PluginIdentifiers.VersionedId[] {
58
+ return Object.freeze(this.uninstalledPlugins.slice());
59
+ }
60
+ }