@flowscripter/dynamic-plugin-framework 1.3.18 → 1.4.1
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.
- package/.github/workflows/release-bun-library.yml +1 -0
- package/README.md +4 -7
- package/bun.lock +6 -7
- package/package.json +12 -12
- package/src/api/plugin_manager/PluginManager.ts +2 -7
- package/src/plugin_manager/DefaultPluginManager.ts +13 -30
- package/src/plugin_manager/plugin_repository/PluginRepository.ts +2 -4
- package/src/plugin_manager/plugin_repository/UrlListPluginRepository.ts +11 -29
- package/src/plugin_manager/plugin_repository/UrlPluginSource.ts +2 -7
- package/src/plugin_manager/registry/ExtensionRegistry.ts +2 -7
- package/src/plugin_manager/registry/InMemoryExtensionPointRegistry.ts +1 -2
- package/src/plugin_manager/registry/InMemoryExtensionRegistry.ts +9 -26
- package/src/plugin_manager/util/PluginLoader.ts +12 -22
- package/tests/fixtures/InvalidPlugin2.ts +5 -3
- package/tests/fixtures/InvalidPlugin3.ts +5 -3
- package/tests/fixtures/InvalidPlugin4.ts +6 -4
- package/tests/fixtures/InvalidPlugin5.ts +7 -5
- package/tests/fixtures/ValidPlugin1.ts +1 -3
- package/tests/plugin_manager/DefaultPluginManager_test.ts +14 -35
- package/tests/plugin_manager/plugin_repository/UrlListPluginRepository_test.ts +8 -23
- package/tests/plugin_manager/plugin_repository/UrlPluginSource_test.ts +8 -16
- package/tests/plugin_manager/registry/InMemoryExtensionPointRegistry_test.ts +4 -10
- package/tests/plugin_manager/registry/InMemoryExtensionRegistry_test.ts +6 -16
- package/tests/plugin_manager/util/PluginLoader_test.ts +13 -39
- package/tsconfig.json +2 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
> Dynamic plugin framework for Bun based on Javascript Modules and import()
|
|
10
10
|
> function
|
|
11
11
|
|
|
12
|
-
[//]: #
|
|
12
|
+
[//]: # "TODO: Remove this when plugin indexing and discovery available."
|
|
13
13
|
|
|
14
14
|
**STILL IN DEVELOPMENT**
|
|
15
15
|
|
|
@@ -242,20 +242,17 @@ Test:
|
|
|
242
242
|
|
|
243
243
|
`bun test`
|
|
244
244
|
|
|
245
|
-
**NOTE**: The following tasks use Deno as it excels at these and Bun does not
|
|
246
|
-
currently provide such functionality:
|
|
247
|
-
|
|
248
245
|
Format:
|
|
249
246
|
|
|
250
|
-
`
|
|
247
|
+
`bunx oxfmt`
|
|
251
248
|
|
|
252
249
|
Lint:
|
|
253
250
|
|
|
254
|
-
`
|
|
251
|
+
`bunx oxlint index.ts src/ tests/`
|
|
255
252
|
|
|
256
253
|
Generate HTML API Documentation:
|
|
257
254
|
|
|
258
|
-
`
|
|
255
|
+
`bunx typedoc --readme none index.ts`
|
|
259
256
|
|
|
260
257
|
The following diagram provides an overview of the main internal classes:
|
|
261
258
|
|
package/bun.lock
CHANGED
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 0,
|
|
3
4
|
"workspaces": {
|
|
4
5
|
"": {
|
|
5
6
|
"name": "@flowscripter/dynamic-plugin-framework",
|
|
6
7
|
"devDependencies": {
|
|
7
|
-
"@types/bun": "^1.
|
|
8
|
+
"@types/bun": "^1.3.14",
|
|
8
9
|
},
|
|
9
10
|
"peerDependencies": {
|
|
10
|
-
"typescript": "^
|
|
11
|
+
"typescript": "^6.0.3",
|
|
11
12
|
},
|
|
12
13
|
},
|
|
13
14
|
},
|
|
14
15
|
"packages": {
|
|
15
|
-
"@types/bun": ["@types/bun@1.
|
|
16
|
+
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
|
16
17
|
|
|
17
18
|
"@types/node": ["@types/node@22.13.4", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg=="],
|
|
18
19
|
|
|
19
|
-
"
|
|
20
|
+
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
|
20
21
|
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
|
22
|
+
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
|
24
23
|
|
|
25
24
|
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
|
26
25
|
}
|
package/package.json
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowscripter/dynamic-plugin-framework",
|
|
3
|
+
"version": "1.4.1",
|
|
3
4
|
"description": "Dynamic plugin framework for Bun based on Javascript Modules and import() function",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bun",
|
|
7
|
+
"dynamic",
|
|
8
|
+
"framework",
|
|
9
|
+
"import",
|
|
10
|
+
"plugin"
|
|
11
|
+
],
|
|
4
12
|
"homepage": "https://github.com/flowscripter/dynamic-plugin-framework#readme",
|
|
13
|
+
"license": "MIT",
|
|
5
14
|
"repository": {
|
|
6
15
|
"type": "git",
|
|
7
16
|
"url": "git+https://github.com/flowscripter/dynamic-plugin-framework.git"
|
|
8
17
|
},
|
|
9
|
-
"license": "MIT",
|
|
10
|
-
"keywords": [
|
|
11
|
-
"bun",
|
|
12
|
-
"plugin",
|
|
13
|
-
"framework",
|
|
14
|
-
"dynamic",
|
|
15
|
-
"import"
|
|
16
|
-
],
|
|
17
|
-
"module": "index.ts",
|
|
18
18
|
"type": "module",
|
|
19
|
-
"
|
|
19
|
+
"module": "index.ts",
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@types/bun": "^1.
|
|
24
|
+
"@types/bun": "^1.3.14"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"typescript": "^
|
|
27
|
+
"typescript": "^6.0.3"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -18,9 +18,7 @@ export default interface PluginManager {
|
|
|
18
18
|
*
|
|
19
19
|
* @return array of {@link ExtensionInfo}
|
|
20
20
|
*/
|
|
21
|
-
getRegisteredExtensions(
|
|
22
|
-
extensionPoint: string,
|
|
23
|
-
): Promise<ReadonlyArray<ExtensionInfo>>;
|
|
21
|
+
getRegisteredExtensions(extensionPoint: string): Promise<ReadonlyArray<ExtensionInfo>>;
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Instantiate a specific Extension.
|
|
@@ -31,8 +29,5 @@ export default interface PluginManager {
|
|
|
31
29
|
*
|
|
32
30
|
* @return an Extension instance implementing an Extension Point.
|
|
33
31
|
*/
|
|
34
|
-
instantiate(
|
|
35
|
-
extensionHandle: string,
|
|
36
|
-
hostData?: Map<string, string>,
|
|
37
|
-
): Promise<unknown>;
|
|
32
|
+
instantiate(extensionHandle: string, hostData?: Map<string, string>): Promise<unknown>;
|
|
38
33
|
}
|
|
@@ -12,30 +12,25 @@ import type PluginRepository from "./plugin_repository/PluginRepository.ts";
|
|
|
12
12
|
export default class DefaultPluginManager implements PluginManager {
|
|
13
13
|
private readonly extensionPointRegistry: ExtensionPointRegistry;
|
|
14
14
|
private readonly extensionRegistry: ExtensionRegistry;
|
|
15
|
-
private readonly pluginRepositoriesByExtensionHandle = new Map<
|
|
16
|
-
string,
|
|
17
|
-
PluginRepository
|
|
18
|
-
>();
|
|
15
|
+
private readonly pluginRepositoriesByExtensionHandle = new Map<string, PluginRepository>();
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Constructor configures the instance using the optionally specified
|
|
22
19
|
* {@link ExtensionPointRegistry} and {@link ExtensionRegistry}.
|
|
23
20
|
*
|
|
24
21
|
* @param pluginRepositories One or more {@link PluginRepository} instances to use for plugin discovery.
|
|
25
|
-
* @param extensionPointRegistry optional {@link ExtensionPointRegistry
|
|
26
|
-
*
|
|
22
|
+
* @param extensionPointRegistry optional {@link ExtensionPointRegistry} implementation. Defaults to using
|
|
23
|
+
* InMemoryExtensionPointRegistry.
|
|
27
24
|
* @param extensionRegistry optional {@link ExtensionRegistry} implementation. Defaults to using
|
|
28
|
-
*
|
|
25
|
+
* InMemoryExtensionRegistry
|
|
29
26
|
*/
|
|
30
27
|
public constructor(
|
|
31
28
|
private readonly pluginRepositories: Array<PluginRepository>,
|
|
32
29
|
extensionPointRegistry?: ExtensionPointRegistry,
|
|
33
30
|
extensionRegistry?: ExtensionRegistry,
|
|
34
31
|
) {
|
|
35
|
-
this.extensionPointRegistry = extensionPointRegistry ||
|
|
36
|
-
|
|
37
|
-
this.extensionRegistry = extensionRegistry ||
|
|
38
|
-
new InMemoryExtensionRegistry();
|
|
32
|
+
this.extensionPointRegistry = extensionPointRegistry || new InMemoryExtensionPointRegistry();
|
|
33
|
+
this.extensionRegistry = extensionRegistry || new InMemoryExtensionRegistry();
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
public async registerExtensions(extensionPoint: string): Promise<void> {
|
|
@@ -47,18 +42,10 @@ export default class DefaultPluginManager implements PluginManager {
|
|
|
47
42
|
|
|
48
43
|
for (let i = 0; i < this.pluginRepositories.length; i++) {
|
|
49
44
|
const pluginRepository = this.pluginRepositories[i];
|
|
50
|
-
for await (
|
|
51
|
-
const
|
|
52
|
-
extensionPoint,
|
|
53
|
-
)
|
|
54
|
-
) {
|
|
55
|
-
const extensionHandle =
|
|
56
|
-
`${i}:${extensionEntry.pluginId}:${extensionEntry.extensionId}`;
|
|
45
|
+
for await (const extensionEntry of pluginRepository.scanForExtensions(extensionPoint)) {
|
|
46
|
+
const extensionHandle = `${i}:${extensionEntry.pluginId}:${extensionEntry.extensionId}`;
|
|
57
47
|
|
|
58
|
-
this.pluginRepositoriesByExtensionHandle.set(
|
|
59
|
-
extensionHandle,
|
|
60
|
-
pluginRepository,
|
|
61
|
-
);
|
|
48
|
+
this.pluginRepositoriesByExtensionHandle.set(extensionHandle, pluginRepository);
|
|
62
49
|
await this.extensionRegistry.register(extensionHandle, extensionEntry);
|
|
63
50
|
}
|
|
64
51
|
}
|
|
@@ -67,9 +54,7 @@ export default class DefaultPluginManager implements PluginManager {
|
|
|
67
54
|
public async getRegisteredExtensions(
|
|
68
55
|
extensionPoint: string,
|
|
69
56
|
): Promise<ReadonlyArray<ExtensionInfo>> {
|
|
70
|
-
const extensionMap = await this.extensionRegistry.getExtensions(
|
|
71
|
-
extensionPoint,
|
|
72
|
-
);
|
|
57
|
+
const extensionMap = await this.extensionRegistry.getExtensions(extensionPoint);
|
|
73
58
|
const registeredExtensions = new Array<ExtensionInfo>();
|
|
74
59
|
|
|
75
60
|
extensionMap.forEach((entry, handle) => {
|
|
@@ -96,16 +81,14 @@ export default class DefaultPluginManager implements PluginManager {
|
|
|
96
81
|
const extensionEntry = await this.extensionRegistry.get(extensionHandle);
|
|
97
82
|
|
|
98
83
|
// Get the Plugin Repository for the Extension Handle
|
|
99
|
-
const pluginRepository = this.pluginRepositoriesByExtensionHandle.get(
|
|
100
|
-
extensionHandle,
|
|
101
|
-
);
|
|
84
|
+
const pluginRepository = this.pluginRepositoriesByExtensionHandle.get(extensionHandle);
|
|
102
85
|
|
|
103
86
|
if (!pluginRepository) {
|
|
104
87
|
return Promise.reject(`Extension handle ${extensionHandle} is unknown`);
|
|
105
88
|
}
|
|
106
89
|
// Get the Extension Descriptor from the Plugin Repository
|
|
107
|
-
const extensionDescriptor =
|
|
108
|
-
.getExtensionDescriptorFromExtensionEntry(extensionEntry);
|
|
90
|
+
const extensionDescriptor =
|
|
91
|
+
await pluginRepository.getExtensionDescriptorFromExtensionEntry(extensionEntry);
|
|
109
92
|
|
|
110
93
|
return extensionDescriptor.factory.create(hostData);
|
|
111
94
|
}
|
|
@@ -13,14 +13,12 @@ export default interface PluginRepository {
|
|
|
13
13
|
*
|
|
14
14
|
* @return an async iterable of {@link ExtensionEntry} instances for all matching Extensions.
|
|
15
15
|
*/
|
|
16
|
-
scanForExtensions(
|
|
17
|
-
extensionPoint: string,
|
|
18
|
-
): AsyncIterable<Readonly<ExtensionEntry>>;
|
|
16
|
+
scanForExtensions(extensionPoint: string): AsyncIterable<Readonly<ExtensionEntry>>;
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
19
|
* Return the {@link ExtensionDescriptor} for the Extension identified by the specified {@link ExtensionEntry}.
|
|
22
20
|
*
|
|
23
|
-
* @param extensionEntry the {@link
|
|
21
|
+
* @param extensionEntry the {@link ExtensionEntry} for the desired Extension.
|
|
24
22
|
*
|
|
25
23
|
* @return an {@link ExtensionDescriptor} instance.
|
|
26
24
|
*/
|
|
@@ -18,28 +18,22 @@ export default class UrlListPluginRepository implements PluginRepository {
|
|
|
18
18
|
* @throws *Error* if the URL set contains a non-valid URL.
|
|
19
19
|
*/
|
|
20
20
|
public constructor(
|
|
21
|
-
private readonly urlsAndExtensionPoints: Set<
|
|
22
|
-
{ url: string; extensionPoints: string[] }
|
|
23
|
-
>,
|
|
21
|
+
private readonly urlsAndExtensionPoints: Set<{ url: string; extensionPoints: string[] }>,
|
|
24
22
|
) {
|
|
25
|
-
if (!urlsAndExtensionPoints ||
|
|
26
|
-
throw new Error(
|
|
27
|
-
`Undefined or empty set of URL and extension points provided`,
|
|
28
|
-
);
|
|
23
|
+
if (!urlsAndExtensionPoints || urlsAndExtensionPoints.size === 0) {
|
|
24
|
+
throw new Error(`Undefined or empty set of URL and extension points provided`);
|
|
29
25
|
}
|
|
30
26
|
this.urlsAndExtensionPoints.forEach((urlAndExtensionPoint) => {
|
|
31
27
|
try {
|
|
32
28
|
new URL(urlAndExtensionPoint.url);
|
|
33
29
|
} catch (err) {
|
|
34
30
|
throw new Error(
|
|
35
|
-
`Cannot parse ${urlAndExtensionPoint.url} as a URL: ${
|
|
36
|
-
(err as Error).message
|
|
37
|
-
}`,
|
|
31
|
+
`Cannot parse ${urlAndExtensionPoint.url} as a URL: ${(err as Error).message}`,
|
|
38
32
|
);
|
|
39
33
|
}
|
|
40
34
|
if (
|
|
41
35
|
!urlAndExtensionPoint.extensionPoints ||
|
|
42
|
-
|
|
36
|
+
urlAndExtensionPoint.extensionPoints.length === 0
|
|
43
37
|
) {
|
|
44
38
|
throw new Error(`Undefined or empty set of extension points provided`);
|
|
45
39
|
}
|
|
@@ -54,9 +48,7 @@ export default class UrlListPluginRepository implements PluginRepository {
|
|
|
54
48
|
if (!urlAndExtensionPoints.extensionPoints.includes(extensionPoint)) {
|
|
55
49
|
continue;
|
|
56
50
|
}
|
|
57
|
-
const plugin = await this.pluginSource.loadPlugin(
|
|
58
|
-
new URL(urlAndExtensionPoints.url),
|
|
59
|
-
);
|
|
51
|
+
const plugin = await this.pluginSource.loadPlugin(new URL(urlAndExtensionPoints.url));
|
|
60
52
|
|
|
61
53
|
if (plugin) {
|
|
62
54
|
// Once we have loaded the plugin, double check on the extension points in the plugin
|
|
@@ -79,9 +71,7 @@ export default class UrlListPluginRepository implements PluginRepository {
|
|
|
79
71
|
}
|
|
80
72
|
}
|
|
81
73
|
|
|
82
|
-
public scanForExtensions(
|
|
83
|
-
extensionPoint: string,
|
|
84
|
-
): AsyncIterable<ExtensionEntry> {
|
|
74
|
+
public scanForExtensions(extensionPoint: string): AsyncIterable<ExtensionEntry> {
|
|
85
75
|
return this.getExtensionEntryAsyncIterable(extensionPoint);
|
|
86
76
|
}
|
|
87
77
|
|
|
@@ -93,9 +83,7 @@ export default class UrlListPluginRepository implements PluginRepository {
|
|
|
93
83
|
public async getExtensionDescriptorFromExtensionEntry(
|
|
94
84
|
extensionEntry: ExtensionEntry,
|
|
95
85
|
): Promise<Readonly<ExtensionDescriptor>> {
|
|
96
|
-
const plugin = await this.pluginSource.loadPlugin(
|
|
97
|
-
new URL(extensionEntry.pluginId),
|
|
98
|
-
);
|
|
86
|
+
const plugin = await this.pluginSource.loadPlugin(new URL(extensionEntry.pluginId));
|
|
99
87
|
|
|
100
88
|
if (!plugin) {
|
|
101
89
|
return Promise.reject(`Plugin ID ${extensionEntry.pluginId} is unknown`);
|
|
@@ -106,17 +94,11 @@ export default class UrlListPluginRepository implements PluginRepository {
|
|
|
106
94
|
try {
|
|
107
95
|
extensionId = parseInt(extensionEntry.extensionId);
|
|
108
96
|
} catch (_e) {
|
|
109
|
-
return Promise.reject(
|
|
110
|
-
`Extension ID ${extensionEntry.extensionId} is unknown`,
|
|
111
|
-
);
|
|
97
|
+
return Promise.reject(`Extension ID ${extensionEntry.extensionId} is unknown`);
|
|
112
98
|
}
|
|
113
99
|
|
|
114
|
-
if (
|
|
115
|
-
(
|
|
116
|
-
) {
|
|
117
|
-
return Promise.reject(
|
|
118
|
-
`Extension ID ${extensionEntry.extensionId} is unknown`,
|
|
119
|
-
);
|
|
100
|
+
if (extensionId < 0 || extensionId >= plugin.extensionDescriptors.length) {
|
|
101
|
+
return Promise.reject(`Extension ID ${extensionEntry.extensionId} is unknown`);
|
|
120
102
|
}
|
|
121
103
|
|
|
122
104
|
return Promise.resolve(plugin.extensionDescriptors[extensionId]);
|
|
@@ -21,17 +21,12 @@ export default class UrlPluginSource {
|
|
|
21
21
|
|
|
22
22
|
if (!plugin) {
|
|
23
23
|
const pluginLoadResult = await loadPlugin(url.toString());
|
|
24
|
-
if (
|
|
25
|
-
pluginLoadResult.isValidPlugin &&
|
|
26
|
-
(pluginLoadResult.plugin !== undefined)
|
|
27
|
-
) {
|
|
24
|
+
if (pluginLoadResult.isValidPlugin && pluginLoadResult.plugin !== undefined) {
|
|
28
25
|
plugin = pluginLoadResult.plugin;
|
|
29
26
|
this.pluginsByUrl.set(url, plugin);
|
|
30
27
|
}
|
|
31
28
|
if (pluginLoadResult.error) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Failed to load plugin from ${url}: ${pluginLoadResult.error.message}`,
|
|
34
|
-
);
|
|
29
|
+
throw new Error(`Failed to load plugin from ${url}: ${pluginLoadResult.error.message}`);
|
|
35
30
|
}
|
|
36
31
|
}
|
|
37
32
|
return Promise.resolve(this.pluginsByUrl.get(url));
|
|
@@ -10,10 +10,7 @@ export default interface ExtensionRegistry {
|
|
|
10
10
|
* @param extensionHandle a unique identifier under which to register the {@link ExtensionEntry}
|
|
11
11
|
* @param extensionEntry the {@link ExtensionEntry} for the Extension to register
|
|
12
12
|
*/
|
|
13
|
-
register(
|
|
14
|
-
extensionHandle: string,
|
|
15
|
-
extensionEntry: ExtensionEntry,
|
|
16
|
-
): Promise<void>;
|
|
13
|
+
register(extensionHandle: string, extensionEntry: ExtensionEntry): Promise<void>;
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
16
|
* Return the specified registered {@link ExtensionEntry} instance.
|
|
@@ -32,7 +29,5 @@ export default interface ExtensionRegistry {
|
|
|
32
29
|
* @return a map of extension handle to {@link ExtensionEntry} for all matching
|
|
33
30
|
* registered {@link ExtensionEntry} instances
|
|
34
31
|
*/
|
|
35
|
-
getExtensions(
|
|
36
|
-
extensionPoint: string,
|
|
37
|
-
): Promise<ReadonlyMap<string, ExtensionEntry>>;
|
|
32
|
+
getExtensions(extensionPoint: string): Promise<ReadonlyMap<string, ExtensionEntry>>;
|
|
38
33
|
}
|
|
@@ -3,8 +3,7 @@ import type ExtensionPointRegistry from "./ExtensionPointRegistry.ts";
|
|
|
3
3
|
/**
|
|
4
4
|
* Simple implementation of an {@link ExtensionPointRegistry} using an in-memory Set.
|
|
5
5
|
*/
|
|
6
|
-
export default class InMemoryExtensionPointRegistry
|
|
7
|
-
implements ExtensionPointRegistry {
|
|
6
|
+
export default class InMemoryExtensionPointRegistry implements ExtensionPointRegistry {
|
|
8
7
|
private readonly extensionPoints: Set<string> = new Set();
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -5,40 +5,27 @@ import type ExtensionEntry from "../plugin_repository/ExtensionEntry.ts";
|
|
|
5
5
|
* Simple implementation of an {@link ExtensionRegistry} using an in-memory map.
|
|
6
6
|
*/
|
|
7
7
|
export default class InMemoryExtensionRegistry implements ExtensionRegistry {
|
|
8
|
-
private readonly extensionEntriesByHandle: Map<string, ExtensionEntry> =
|
|
9
|
-
new Map();
|
|
8
|
+
private readonly extensionEntriesByHandle: Map<string, ExtensionEntry> = new Map();
|
|
10
9
|
|
|
11
|
-
private readonly extensionEntriesByExtensionPoint: Map<
|
|
12
|
-
|
|
13
|
-
Map<string, ExtensionEntry>
|
|
14
|
-
> = new Map();
|
|
10
|
+
private readonly extensionEntriesByExtensionPoint: Map<string, Map<string, ExtensionEntry>> =
|
|
11
|
+
new Map();
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* @inheritDoc
|
|
18
15
|
*
|
|
19
16
|
* @throws *Error* if the specified Extension handle has already been registered
|
|
20
17
|
*/
|
|
21
|
-
public register(
|
|
22
|
-
extensionHandle: string,
|
|
23
|
-
extensionEntry: ExtensionEntry,
|
|
24
|
-
): Promise<void> {
|
|
18
|
+
public register(extensionHandle: string, extensionEntry: ExtensionEntry): Promise<void> {
|
|
25
19
|
if (this.extensionEntriesByHandle.has(extensionHandle)) {
|
|
26
|
-
return Promise.reject(
|
|
27
|
-
`Extension handle ${extensionHandle} has already been registered`,
|
|
28
|
-
);
|
|
20
|
+
return Promise.reject(`Extension handle ${extensionHandle} has already been registered`);
|
|
29
21
|
}
|
|
30
22
|
this.extensionEntriesByHandle.set(extensionHandle, extensionEntry);
|
|
31
23
|
|
|
32
|
-
let extensionEntries = this.extensionEntriesByExtensionPoint.get(
|
|
33
|
-
extensionEntry.extensionPoint,
|
|
34
|
-
);
|
|
24
|
+
let extensionEntries = this.extensionEntriesByExtensionPoint.get(extensionEntry.extensionPoint);
|
|
35
25
|
|
|
36
26
|
if (extensionEntries === undefined) {
|
|
37
27
|
extensionEntries = new Map();
|
|
38
|
-
this.extensionEntriesByExtensionPoint.set(
|
|
39
|
-
extensionEntry.extensionPoint,
|
|
40
|
-
extensionEntries,
|
|
41
|
-
);
|
|
28
|
+
this.extensionEntriesByExtensionPoint.set(extensionEntry.extensionPoint, extensionEntries);
|
|
42
29
|
}
|
|
43
30
|
extensionEntries.set(extensionHandle, extensionEntry);
|
|
44
31
|
|
|
@@ -59,11 +46,7 @@ export default class InMemoryExtensionRegistry implements ExtensionRegistry {
|
|
|
59
46
|
return Promise.resolve(Object.freeze(extensionEntry));
|
|
60
47
|
}
|
|
61
48
|
|
|
62
|
-
public getExtensions(
|
|
63
|
-
extensionPoint
|
|
64
|
-
): Promise<ReadonlyMap<string, ExtensionEntry>> {
|
|
65
|
-
return Promise.resolve(
|
|
66
|
-
this.extensionEntriesByExtensionPoint.get(extensionPoint) || new Map(),
|
|
67
|
-
);
|
|
49
|
+
public getExtensions(extensionPoint: string): Promise<ReadonlyMap<string, ExtensionEntry>> {
|
|
50
|
+
return Promise.resolve(this.extensionEntriesByExtensionPoint.get(extensionPoint) || new Map());
|
|
68
51
|
}
|
|
69
52
|
}
|
|
@@ -56,9 +56,7 @@ async function getLocalUrl(remoteUrl: string) {
|
|
|
56
56
|
*
|
|
57
57
|
* @param url the URL of the module to import.
|
|
58
58
|
*/
|
|
59
|
-
export default async function loadPlugin(
|
|
60
|
-
url: string,
|
|
61
|
-
): Promise<Readonly<PluginLoadResult>> {
|
|
59
|
+
export default async function loadPlugin(url: string): Promise<Readonly<PluginLoadResult>> {
|
|
62
60
|
const result: PluginLoadResult = {
|
|
63
61
|
isValidPlugin: false,
|
|
64
62
|
plugin: undefined,
|
|
@@ -71,10 +69,9 @@ export default async function loadPlugin(
|
|
|
71
69
|
module = await import(url);
|
|
72
70
|
} catch (err) {
|
|
73
71
|
if (
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
(!url.toLowerCase().startsWith("http://") &&
|
|
77
|
-
!url.toLowerCase().startsWith("https://"))
|
|
72
|
+
(err as { message: string }).message === undefined ||
|
|
73
|
+
!(err as { message: string }).message.startsWith("ENOENT") ||
|
|
74
|
+
(!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
|
|
78
75
|
) {
|
|
79
76
|
result.error = err as Error;
|
|
80
77
|
return result;
|
|
@@ -93,25 +90,19 @@ export default async function loadPlugin(
|
|
|
93
90
|
|
|
94
91
|
// check the assumed Plugin has an array of extension descriptors
|
|
95
92
|
if (!Array.isArray(potentialPlugin.extensionDescriptors)) {
|
|
96
|
-
result.error = new Error(
|
|
97
|
-
`Plugin from ${url} does not provide an extensionDescriptors array`,
|
|
98
|
-
);
|
|
93
|
+
result.error = new Error(`Plugin from ${url} does not provide an extensionDescriptors array`);
|
|
99
94
|
return result;
|
|
100
95
|
}
|
|
101
96
|
|
|
102
97
|
// At this point assume it is a valid plugin and then disprove this
|
|
103
98
|
result.isValidPlugin = true;
|
|
104
99
|
|
|
105
|
-
for (
|
|
106
|
-
const potentialExtensionDescriptor of potentialPlugin
|
|
107
|
-
.extensionDescriptors
|
|
108
|
-
) {
|
|
100
|
+
for (const potentialExtensionDescriptor of potentialPlugin.extensionDescriptors) {
|
|
109
101
|
// check for valid {@link ExtensionDescriptor.extensionPoint}
|
|
110
102
|
if (
|
|
111
|
-
|
|
112
|
-
(!(potentialExtensionDescriptor.extensionPoint as unknown instanceof
|
|
113
|
-
|
|
114
|
-
(typeof potentialExtensionDescriptor.extensionPoint !== "string"))
|
|
103
|
+
potentialExtensionDescriptor.extensionPoint === undefined ||
|
|
104
|
+
(!((potentialExtensionDescriptor.extensionPoint as unknown) instanceof String) &&
|
|
105
|
+
typeof potentialExtensionDescriptor.extensionPoint !== "string")
|
|
115
106
|
) {
|
|
116
107
|
result.isValidPlugin = false;
|
|
117
108
|
result.error = new Error(
|
|
@@ -121,10 +112,9 @@ export default async function loadPlugin(
|
|
|
121
112
|
}
|
|
122
113
|
// check for valid {@link ExtensionDescriptor.factory.create function}
|
|
123
114
|
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
!(potentialExtensionDescriptor.factory.create as unknown instanceof
|
|
127
|
-
Function)
|
|
115
|
+
potentialExtensionDescriptor.factory === undefined ||
|
|
116
|
+
potentialExtensionDescriptor.factory.create === undefined ||
|
|
117
|
+
!((potentialExtensionDescriptor.factory.create as unknown) instanceof Function)
|
|
128
118
|
) {
|
|
129
119
|
result.isValidPlugin = false;
|
|
130
120
|
result.error = new Error(
|
|
@@ -26,9 +26,7 @@ export const extensionDescriptor1: ExtensionDescriptor = {
|
|
|
26
26
|
const plugin1: Plugin = {
|
|
27
27
|
pluginData: new Map([["foo", "bar"]]),
|
|
28
28
|
|
|
29
|
-
extensionDescriptors: [
|
|
30
|
-
extensionDescriptor1,
|
|
31
|
-
],
|
|
29
|
+
extensionDescriptors: [extensionDescriptor1],
|
|
32
30
|
};
|
|
33
31
|
|
|
34
32
|
export default plugin1;
|
|
@@ -2,16 +2,11 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import DefaultPluginManager from "../../src/plugin_manager/DefaultPluginManager.ts";
|
|
4
4
|
import UrlListPluginRepository from "../../src/plugin_manager/plugin_repository/UrlListPluginRepository.ts";
|
|
5
|
-
import {
|
|
6
|
-
EXTENSION_POINT_1,
|
|
7
|
-
type ExtensionPoint1,
|
|
8
|
-
} from "../fixtures/Constants.ts";
|
|
5
|
+
import { EXTENSION_POINT_1, type ExtensionPoint1 } from "../fixtures/Constants.ts";
|
|
9
6
|
|
|
10
|
-
const PLUGIN_1_URL =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"../fixtures/ValidPlugin1.ts",
|
|
14
|
-
);
|
|
7
|
+
const PLUGIN_1_URL =
|
|
8
|
+
"file://" +
|
|
9
|
+
path.join(path.dirname(Bun.fileURLToPath(import.meta.url)), "../fixtures/ValidPlugin1.ts");
|
|
15
10
|
|
|
16
11
|
describe("DefaultPluginManager Tests", () => {
|
|
17
12
|
test("Register without a plugin repository does not fail", async () => {
|
|
@@ -24,21 +19,15 @@ describe("DefaultPluginManager Tests", () => {
|
|
|
24
19
|
const urlListPluginRepository = new UrlListPluginRepository(
|
|
25
20
|
new Set([{ url: PLUGIN_1_URL, extensionPoints: [EXTENSION_POINT_1] }]),
|
|
26
21
|
);
|
|
27
|
-
const defaultPluginManager = new DefaultPluginManager([
|
|
28
|
-
urlListPluginRepository,
|
|
29
|
-
]);
|
|
22
|
+
const defaultPluginManager = new DefaultPluginManager([urlListPluginRepository]);
|
|
30
23
|
|
|
31
|
-
let extensions = await defaultPluginManager.getRegisteredExtensions(
|
|
32
|
-
EXTENSION_POINT_1,
|
|
33
|
-
);
|
|
24
|
+
let extensions = await defaultPluginManager.getRegisteredExtensions(EXTENSION_POINT_1);
|
|
34
25
|
|
|
35
26
|
expect(extensions.length).toEqual(0);
|
|
36
27
|
|
|
37
28
|
await defaultPluginManager.registerExtensions(EXTENSION_POINT_1);
|
|
38
29
|
|
|
39
|
-
extensions = await defaultPluginManager.getRegisteredExtensions(
|
|
40
|
-
EXTENSION_POINT_1,
|
|
41
|
-
);
|
|
30
|
+
extensions = await defaultPluginManager.getRegisteredExtensions(EXTENSION_POINT_1);
|
|
42
31
|
|
|
43
32
|
expect(extensions.length).toEqual(1);
|
|
44
33
|
});
|
|
@@ -47,23 +36,17 @@ describe("DefaultPluginManager Tests", () => {
|
|
|
47
36
|
const urlListPluginRepository = new UrlListPluginRepository(
|
|
48
37
|
new Set([{ url: PLUGIN_1_URL, extensionPoints: [EXTENSION_POINT_1] }]),
|
|
49
38
|
);
|
|
50
|
-
const defaultPluginManager = new DefaultPluginManager([
|
|
51
|
-
urlListPluginRepository,
|
|
52
|
-
]);
|
|
39
|
+
const defaultPluginManager = new DefaultPluginManager([urlListPluginRepository]);
|
|
53
40
|
|
|
54
41
|
await defaultPluginManager.registerExtensions(EXTENSION_POINT_1);
|
|
55
42
|
|
|
56
|
-
let extensions = await defaultPluginManager.getRegisteredExtensions(
|
|
57
|
-
EXTENSION_POINT_1,
|
|
58
|
-
);
|
|
43
|
+
let extensions = await defaultPluginManager.getRegisteredExtensions(EXTENSION_POINT_1);
|
|
59
44
|
|
|
60
45
|
expect(extensions.length).toEqual(1);
|
|
61
46
|
|
|
62
47
|
await defaultPluginManager.registerExtensions(EXTENSION_POINT_1);
|
|
63
48
|
|
|
64
|
-
extensions = await defaultPluginManager.getRegisteredExtensions(
|
|
65
|
-
EXTENSION_POINT_1,
|
|
66
|
-
);
|
|
49
|
+
extensions = await defaultPluginManager.getRegisteredExtensions(EXTENSION_POINT_1);
|
|
67
50
|
|
|
68
51
|
expect(extensions.length).toEqual(1);
|
|
69
52
|
});
|
|
@@ -72,24 +55,20 @@ describe("DefaultPluginManager Tests", () => {
|
|
|
72
55
|
const urlListPluginRepository = new UrlListPluginRepository(
|
|
73
56
|
new Set([{ url: PLUGIN_1_URL, extensionPoints: [EXTENSION_POINT_1] }]),
|
|
74
57
|
);
|
|
75
|
-
const defaultPluginManager = new DefaultPluginManager([
|
|
76
|
-
urlListPluginRepository,
|
|
77
|
-
]);
|
|
58
|
+
const defaultPluginManager = new DefaultPluginManager([urlListPluginRepository]);
|
|
78
59
|
|
|
79
60
|
await defaultPluginManager.registerExtensions(EXTENSION_POINT_1);
|
|
80
61
|
|
|
81
|
-
const extensionInfos = await defaultPluginManager.getRegisteredExtensions(
|
|
82
|
-
EXTENSION_POINT_1,
|
|
83
|
-
);
|
|
62
|
+
const extensionInfos = await defaultPluginManager.getRegisteredExtensions(EXTENSION_POINT_1);
|
|
84
63
|
|
|
85
64
|
const extensionInfo = extensionInfos[0];
|
|
86
65
|
|
|
87
66
|
expect(extensionInfo.pluginData?.get("foo"), "bar");
|
|
88
67
|
expect(extensionInfo.extensionData?.get("foo"), "bar");
|
|
89
68
|
|
|
90
|
-
const instance = await defaultPluginManager.instantiate(
|
|
69
|
+
const instance = (await defaultPluginManager.instantiate(
|
|
91
70
|
extensionInfo.extensionHandle,
|
|
92
|
-
) as ExtensionPoint1;
|
|
71
|
+
)) as ExtensionPoint1;
|
|
93
72
|
|
|
94
73
|
expect(instance.sayHello()).toEqual("hello");
|
|
95
74
|
});
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import UrlListPluginRepository from "../../../src/plugin_manager/plugin_repository/UrlListPluginRepository.ts";
|
|
4
|
-
import {
|
|
5
|
-
EXTENSION_POINT_1,
|
|
6
|
-
EXTENSION_POINT_2,
|
|
7
|
-
} from "../../fixtures/Constants.ts";
|
|
4
|
+
import { EXTENSION_POINT_1, EXTENSION_POINT_2 } from "../../fixtures/Constants.ts";
|
|
8
5
|
|
|
9
|
-
const PLUGIN_1_URL =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"../../fixtures/ValidPlugin1.ts",
|
|
13
|
-
);
|
|
6
|
+
const PLUGIN_1_URL =
|
|
7
|
+
"file://" +
|
|
8
|
+
path.join(path.dirname(Bun.fileURLToPath(import.meta.url)), "../../fixtures/ValidPlugin1.ts");
|
|
14
9
|
|
|
15
10
|
describe("UrlPluginSource Tests", () => {
|
|
16
11
|
test("Throws on empty set of URLs", () => {
|
|
@@ -18,10 +13,8 @@ describe("UrlPluginSource Tests", () => {
|
|
|
18
13
|
});
|
|
19
14
|
|
|
20
15
|
test("Throws on invalid URL", () => {
|
|
21
|
-
expect(
|
|
22
|
-
new UrlListPluginRepository(
|
|
23
|
-
new Set([{ url: "foo", extensionPoints: ["bar"] }]),
|
|
24
|
-
)
|
|
16
|
+
expect(
|
|
17
|
+
() => new UrlListPluginRepository(new Set([{ url: "foo", extensionPoints: ["bar"] }])),
|
|
25
18
|
).toThrow();
|
|
26
19
|
});
|
|
27
20
|
|
|
@@ -32,11 +25,7 @@ describe("UrlPluginSource Tests", () => {
|
|
|
32
25
|
const pluginRepository = new UrlListPluginRepository(urlSet);
|
|
33
26
|
|
|
34
27
|
let count = 0;
|
|
35
|
-
for await (
|
|
36
|
-
const extensionEntry of pluginRepository.scanForExtensions(
|
|
37
|
-
EXTENSION_POINT_1,
|
|
38
|
-
)
|
|
39
|
-
) {
|
|
28
|
+
for await (const extensionEntry of pluginRepository.scanForExtensions(EXTENSION_POINT_1)) {
|
|
40
29
|
expect(extensionEntry.pluginId).toEqual(PLUGIN_1_URL);
|
|
41
30
|
expect(extensionEntry.extensionPoint).toEqual(EXTENSION_POINT_1);
|
|
42
31
|
count += 1;
|
|
@@ -51,11 +40,7 @@ describe("UrlPluginSource Tests", () => {
|
|
|
51
40
|
const pluginRepository = new UrlListPluginRepository(urlSet);
|
|
52
41
|
|
|
53
42
|
let count = 0;
|
|
54
|
-
for await (
|
|
55
|
-
const extensionEntry of pluginRepository.scanForExtensions(
|
|
56
|
-
EXTENSION_POINT_2,
|
|
57
|
-
)
|
|
58
|
-
) {
|
|
43
|
+
for await (const extensionEntry of pluginRepository.scanForExtensions(EXTENSION_POINT_2)) {
|
|
59
44
|
// this should not be called
|
|
60
45
|
expect(extensionEntry.pluginId, "not good");
|
|
61
46
|
count += 1;
|
|
@@ -2,27 +2,19 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import UrlPluginSource from "../../../src/plugin_manager/plugin_repository/UrlPluginSource.ts";
|
|
4
4
|
|
|
5
|
-
const PLUGIN_1_URL =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
path.join(
|
|
13
|
-
path.dirname(Bun.fileURLToPath(import.meta.url)),
|
|
14
|
-
"../../fixtures/InvalidPlugin1.ts",
|
|
15
|
-
);
|
|
5
|
+
const PLUGIN_1_URL =
|
|
6
|
+
"file://" +
|
|
7
|
+
path.join(path.dirname(Bun.fileURLToPath(import.meta.url)), "../../fixtures/ValidPlugin1.ts");
|
|
8
|
+
|
|
9
|
+
const INVALID_PLUGIN_URL =
|
|
10
|
+
"file://" +
|
|
11
|
+
path.join(path.dirname(Bun.fileURLToPath(import.meta.url)), "../../fixtures/InvalidPlugin1.ts");
|
|
16
12
|
|
|
17
13
|
describe("UrlPluginSource Tests", () => {
|
|
18
14
|
test("Throws on invalid plugin", () => {
|
|
19
15
|
const urlPluginSource = new UrlPluginSource();
|
|
20
16
|
|
|
21
|
-
expect(
|
|
22
|
-
urlPluginSource.loadPlugin(
|
|
23
|
-
new URL(INVALID_PLUGIN_URL),
|
|
24
|
-
),
|
|
25
|
-
).rejects.toThrow();
|
|
17
|
+
expect(urlPluginSource.loadPlugin(new URL(INVALID_PLUGIN_URL))).rejects.toThrow();
|
|
26
18
|
});
|
|
27
19
|
|
|
28
20
|
test("Loads a plugin", async () => {
|
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import InMemoryExtensionPointRegistry from "../../../src/plugin_manager/registry/InMemoryExtensionPointRegistry.ts";
|
|
3
|
-
import {
|
|
4
|
-
EXTENSION_POINT_1,
|
|
5
|
-
EXTENSION_POINT_2,
|
|
6
|
-
} from "../../fixtures/Constants.ts";
|
|
3
|
+
import { EXTENSION_POINT_1, EXTENSION_POINT_2 } from "../../fixtures/Constants.ts";
|
|
7
4
|
|
|
8
5
|
describe("InMemoryExtensionPointRegistry Tests", () => {
|
|
9
6
|
test("Register extension point", async () => {
|
|
10
7
|
const extensionPointRegistry = new InMemoryExtensionPointRegistry();
|
|
11
8
|
|
|
12
|
-
expect(await extensionPointRegistry.isRegistered(EXTENSION_POINT_1))
|
|
13
|
-
.toBeFalse();
|
|
9
|
+
expect(await extensionPointRegistry.isRegistered(EXTENSION_POINT_1)).toBeFalse();
|
|
14
10
|
|
|
15
11
|
await extensionPointRegistry.register(EXTENSION_POINT_1);
|
|
16
12
|
|
|
17
|
-
expect(await extensionPointRegistry.isRegistered(EXTENSION_POINT_1))
|
|
18
|
-
.toBeTrue();
|
|
13
|
+
expect(await extensionPointRegistry.isRegistered(EXTENSION_POINT_1)).toBeTrue();
|
|
19
14
|
});
|
|
20
15
|
|
|
21
16
|
test("Cannot register extension point twice", async () => {
|
|
@@ -23,8 +18,7 @@ describe("InMemoryExtensionPointRegistry Tests", () => {
|
|
|
23
18
|
|
|
24
19
|
await extensionPointRegistry.register(EXTENSION_POINT_1);
|
|
25
20
|
|
|
26
|
-
expect(extensionPointRegistry.register(EXTENSION_POINT_1))
|
|
27
|
-
.rejects.toThrow();
|
|
21
|
+
expect(extensionPointRegistry.register(EXTENSION_POINT_1)).rejects.toThrow();
|
|
28
22
|
});
|
|
29
23
|
|
|
30
24
|
test("Get registered extension points", async () => {
|
|
@@ -28,8 +28,7 @@ describe("InMemoryExtensionRegistry Tests", () => {
|
|
|
28
28
|
test("Register extension", async () => {
|
|
29
29
|
const extensionRegistry = new InMemoryExtensionRegistry();
|
|
30
30
|
|
|
31
|
-
expect(extensionRegistry.get(EXTENSION_1_HANDLE)).rejects
|
|
32
|
-
.toThrow();
|
|
31
|
+
expect(extensionRegistry.get(EXTENSION_1_HANDLE)).rejects.toThrow();
|
|
33
32
|
|
|
34
33
|
await extensionRegistry.register(EXTENSION_1_HANDLE, extensionEntry1);
|
|
35
34
|
|
|
@@ -41,8 +40,7 @@ describe("InMemoryExtensionRegistry Tests", () => {
|
|
|
41
40
|
|
|
42
41
|
await extensionRegistry.register(EXTENSION_1_HANDLE, extensionEntry1);
|
|
43
42
|
|
|
44
|
-
expect(extensionRegistry.register(EXTENSION_1_HANDLE, extensionEntry1))
|
|
45
|
-
.rejects.toThrow();
|
|
43
|
+
expect(extensionRegistry.register(EXTENSION_1_HANDLE, extensionEntry1)).rejects.toThrow();
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
test("Get registered extensions", async () => {
|
|
@@ -51,22 +49,14 @@ describe("InMemoryExtensionRegistry Tests", () => {
|
|
|
51
49
|
await extensionRegistry.register(EXTENSION_1_HANDLE, extensionEntry1);
|
|
52
50
|
await extensionRegistry.register(EXTENSION_2_HANDLE, extensionEntry2);
|
|
53
51
|
|
|
54
|
-
const extensionEntries1 = await extensionRegistry.getExtensions(
|
|
55
|
-
EXTENSION_POINT_1,
|
|
56
|
-
);
|
|
52
|
+
const extensionEntries1 = await extensionRegistry.getExtensions(EXTENSION_POINT_1);
|
|
57
53
|
|
|
58
54
|
expect(extensionEntries1.size).toEqual(1);
|
|
59
|
-
expect(
|
|
60
|
-
extensionEntries1.get(EXTENSION_1_HANDLE)?.extensionId,
|
|
61
|
-
).toEqual(EXTENSION_1_ID);
|
|
55
|
+
expect(extensionEntries1.get(EXTENSION_1_HANDLE)?.extensionId).toEqual(EXTENSION_1_ID);
|
|
62
56
|
|
|
63
|
-
const extensionEntries2 = await extensionRegistry.getExtensions(
|
|
64
|
-
EXTENSION_POINT_2,
|
|
65
|
-
);
|
|
57
|
+
const extensionEntries2 = await extensionRegistry.getExtensions(EXTENSION_POINT_2);
|
|
66
58
|
|
|
67
59
|
expect(extensionEntries2.size).toEqual(1);
|
|
68
|
-
expect(
|
|
69
|
-
extensionEntries2.get(EXTENSION_2_HANDLE)?.extensionId,
|
|
70
|
-
).toEqual(EXTENSION_2_ID);
|
|
60
|
+
expect(extensionEntries2.get(EXTENSION_2_HANDLE)?.extensionId).toEqual(EXTENSION_2_ID);
|
|
71
61
|
});
|
|
72
62
|
});
|
|
@@ -10,84 +10,58 @@ describe("PluginLoader Tests", () => {
|
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
test("Rejects invalid modules", async () => {
|
|
13
|
-
const pluginLoadResult = await loadPlugin(
|
|
14
|
-
"../plugin_repository/UrlListPluginRepository.ts",
|
|
15
|
-
);
|
|
13
|
+
const pluginLoadResult = await loadPlugin("../plugin_repository/UrlListPluginRepository.ts");
|
|
16
14
|
|
|
17
15
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
18
|
-
expect(
|
|
19
|
-
pluginLoadResult.error?.message,
|
|
20
|
-
).toEqual(
|
|
16
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
21
17
|
"Plugin from ../plugin_repository/UrlListPluginRepository.ts does not provide an extensionDescriptors array",
|
|
22
18
|
);
|
|
23
19
|
});
|
|
24
20
|
|
|
25
21
|
test("Rejects invalid plugins", async () => {
|
|
26
|
-
let pluginLoadResult = await loadPlugin(
|
|
27
|
-
"../../../tests/fixtures/InvalidPlugin1.ts",
|
|
28
|
-
);
|
|
22
|
+
let pluginLoadResult = await loadPlugin("../../../tests/fixtures/InvalidPlugin1.ts");
|
|
29
23
|
|
|
30
24
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
31
25
|
expect(pluginLoadResult.error?.name).toEqual("Error");
|
|
32
|
-
expect(
|
|
33
|
-
pluginLoadResult.error?.message,
|
|
34
|
-
).toEqual(
|
|
26
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
35
27
|
"Plugin from ../../../tests/fixtures/InvalidPlugin1.ts does not provide an extensionDescriptors array",
|
|
36
28
|
);
|
|
37
29
|
|
|
38
|
-
pluginLoadResult = await loadPlugin(
|
|
39
|
-
"../../../tests/fixtures/InvalidPlugin2.ts",
|
|
40
|
-
);
|
|
30
|
+
pluginLoadResult = await loadPlugin("../../../tests/fixtures/InvalidPlugin2.ts");
|
|
41
31
|
|
|
42
32
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
43
33
|
expect(pluginLoadResult.error?.name).toEqual("Error");
|
|
44
|
-
expect(
|
|
45
|
-
pluginLoadResult.error?.message,
|
|
46
|
-
).toEqual(
|
|
34
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
47
35
|
"Plugin from ../../../tests/fixtures/InvalidPlugin2.ts does not provide an extensionPoint string in one of the extensionDescriptors",
|
|
48
36
|
);
|
|
49
37
|
|
|
50
|
-
pluginLoadResult = await loadPlugin(
|
|
51
|
-
"../../../tests/fixtures/InvalidPlugin3.ts",
|
|
52
|
-
);
|
|
38
|
+
pluginLoadResult = await loadPlugin("../../../tests/fixtures/InvalidPlugin3.ts");
|
|
53
39
|
|
|
54
40
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
55
41
|
expect(pluginLoadResult.error?.name).toEqual("Error");
|
|
56
|
-
expect(
|
|
57
|
-
pluginLoadResult.error?.message,
|
|
58
|
-
).toEqual(
|
|
42
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
59
43
|
"Plugin from ../../../tests/fixtures/InvalidPlugin3.ts does not provide a factory with a create function in one of the extensionDescriptors",
|
|
60
44
|
);
|
|
61
45
|
|
|
62
|
-
pluginLoadResult = await loadPlugin(
|
|
63
|
-
"../../../tests/fixtures/InvalidPlugin4.ts",
|
|
64
|
-
);
|
|
46
|
+
pluginLoadResult = await loadPlugin("../../../tests/fixtures/InvalidPlugin4.ts");
|
|
65
47
|
|
|
66
48
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
67
49
|
expect(pluginLoadResult.error?.name).toEqual("Error");
|
|
68
|
-
expect(
|
|
69
|
-
pluginLoadResult.error?.message,
|
|
70
|
-
).toEqual(
|
|
50
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
71
51
|
"Plugin from ../../../tests/fixtures/InvalidPlugin4.ts does not provide a factory with a create function in one of the extensionDescriptors",
|
|
72
52
|
);
|
|
73
53
|
|
|
74
|
-
pluginLoadResult = await loadPlugin(
|
|
75
|
-
"../../../tests/fixtures/InvalidPlugin5.ts",
|
|
76
|
-
);
|
|
54
|
+
pluginLoadResult = await loadPlugin("../../../tests/fixtures/InvalidPlugin5.ts");
|
|
77
55
|
|
|
78
56
|
expect(pluginLoadResult.isValidPlugin).toBeFalse();
|
|
79
57
|
expect(pluginLoadResult.error?.name).toEqual("Error");
|
|
80
|
-
expect(
|
|
81
|
-
pluginLoadResult.error?.message,
|
|
82
|
-
).toEqual(
|
|
58
|
+
expect(pluginLoadResult.error?.message).toEqual(
|
|
83
59
|
"Plugin from ../../../tests/fixtures/InvalidPlugin5.ts does not provide a factory with a create function in one of the extensionDescriptors",
|
|
84
60
|
);
|
|
85
61
|
});
|
|
86
62
|
|
|
87
63
|
test("Returns valid plugin", async () => {
|
|
88
|
-
const pluginLoadResult = await loadPlugin(
|
|
89
|
-
"../../../tests/fixtures/ValidPlugin1.ts",
|
|
90
|
-
);
|
|
64
|
+
const pluginLoadResult = await loadPlugin("../../../tests/fixtures/ValidPlugin1.ts");
|
|
91
65
|
|
|
92
66
|
expect(pluginLoadResult.isValidPlugin).toBeTrue();
|
|
93
67
|
expect(pluginLoadResult.error).toBeUndefined();
|