@pooder/core 1.2.0 → 2.0.0
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/CHANGELOG.md +6 -0
- package/dist/index.d.mts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +33 -2
- package/dist/index.mjs +30 -1
- package/package.json +1 -1
- package/src/command.ts +10 -10
- package/src/context.ts +17 -17
- package/src/contribution/index.ts +12 -12
- package/src/contribution/registry.ts +118 -118
- package/src/disposable.ts +3 -3
- package/src/extension.ts +164 -164
- package/src/index.ts +145 -140
- package/src/run-test-full.ts +98 -98
- package/src/services/CommandService.ts +79 -79
- package/src/services/ConfigurationService.ts +107 -107
- package/src/services/WorkbenchService.ts +30 -0
- package/src/services/index.ts +2 -1
- package/src/test-extension-full.ts +79 -79
package/src/extension.ts
CHANGED
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
import { ExtensionContext } from "./context";
|
|
2
|
-
import { Contribution, ContributionPointIds } from "./contribution";
|
|
3
|
-
import Disposable from "./disposable";
|
|
4
|
-
import CommandService from "./services/CommandService";
|
|
5
|
-
import { ConfigurationService } from "./services";
|
|
6
|
-
|
|
7
|
-
interface ExtensionMetadata {
|
|
8
|
-
name: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface Extension {
|
|
12
|
-
id: string;
|
|
13
|
-
metadata?: Partial<ExtensionMetadata>;
|
|
14
|
-
|
|
15
|
-
activate(context: ExtensionContext): void;
|
|
16
|
-
deactivate(context: ExtensionContext): void;
|
|
17
|
-
contribute?(): Record<string, any[]>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class ExtensionRegistry extends Map<string, Extension> {}
|
|
21
|
-
|
|
22
|
-
class ExtensionManager {
|
|
23
|
-
private readonly context: ExtensionContext;
|
|
24
|
-
private extensionRegistry: ExtensionRegistry = new ExtensionRegistry();
|
|
25
|
-
private extensionDisposables: Map<string, Disposable[]> = new Map();
|
|
26
|
-
|
|
27
|
-
constructor(context: ExtensionContext) {
|
|
28
|
-
this.context = context;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
register(extension: Extension) {
|
|
32
|
-
if (this.extensionRegistry.has(extension.id)) {
|
|
33
|
-
console.warn(
|
|
34
|
-
`Plugin "${extension.id}" already registered. It will be overwritten.`,
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Initialize disposables for this extension
|
|
39
|
-
this.extensionDisposables.set(extension.id, []);
|
|
40
|
-
const disposables = this.extensionDisposables.get(extension.id)!;
|
|
41
|
-
|
|
42
|
-
// Process declarative contributions
|
|
43
|
-
if (extension.contribute) {
|
|
44
|
-
for (const [pointId, items] of Object.entries(extension.contribute())) {
|
|
45
|
-
if (Array.isArray(items)) {
|
|
46
|
-
items.forEach((item, index) => {
|
|
47
|
-
const contributionId =
|
|
48
|
-
item.id ||
|
|
49
|
-
(item.command
|
|
50
|
-
? item.command
|
|
51
|
-
: `${extension.id}.${pointId}.${index}`);
|
|
52
|
-
const contribution: Contribution = {
|
|
53
|
-
id: contributionId,
|
|
54
|
-
metadata: {
|
|
55
|
-
extensionId: extension.id,
|
|
56
|
-
...item?.metadata,
|
|
57
|
-
},
|
|
58
|
-
data: item,
|
|
59
|
-
};
|
|
60
|
-
const disposable = this.context.contributions.register(
|
|
61
|
-
pointId,
|
|
62
|
-
contribution,
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
// Track contribution registration to unregister later
|
|
66
|
-
disposables.push(disposable);
|
|
67
|
-
|
|
68
|
-
const dispose = this.collectContribution(pointId, contribution);
|
|
69
|
-
if (dispose) {
|
|
70
|
-
disposables.push(dispose);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
this.extensionRegistry.set(extension.id, extension);
|
|
79
|
-
this.context.eventBus.emit("extension:register", extension);
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error(
|
|
82
|
-
`Error in onCreate hook for plugin "${extension.id}":`,
|
|
83
|
-
error,
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
extension.activate(this.context);
|
|
89
|
-
} catch (error) {
|
|
90
|
-
console.error(
|
|
91
|
-
`Error in onActivate hook for plugin "${extension.id}":`,
|
|
92
|
-
error,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
console.log(`Plugin "${extension.id}" registered successfully`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
collectContribution(pointId: string, item: any): Disposable | undefined {
|
|
100
|
-
// If registering configurations, update ConfigurationService defaults
|
|
101
|
-
if (pointId === ContributionPointIds.CONFIGURATIONS) {
|
|
102
|
-
const configService = this.context.services.get<ConfigurationService>(
|
|
103
|
-
"ConfigurationService",
|
|
104
|
-
);
|
|
105
|
-
configService?.initializeDefaults([item.data]);
|
|
106
|
-
}
|
|
107
|
-
if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
|
|
108
|
-
const commandService =
|
|
109
|
-
this.context.services.get<CommandService>("CommandService")!;
|
|
110
|
-
|
|
111
|
-
return commandService.registerCommand(item.id, item.data.handler);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
unregister(name: string) {
|
|
116
|
-
const extension = this.extensionRegistry.get(name);
|
|
117
|
-
if (!extension) {
|
|
118
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
extension.deactivate(this.context);
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.error(`Error in deactivate for plugin "${name}":`, error);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Dispose all resources associated with this extension
|
|
129
|
-
const disposables = this.extensionDisposables.get(name);
|
|
130
|
-
if (disposables) {
|
|
131
|
-
disposables.forEach((d) => d.dispose());
|
|
132
|
-
this.extensionDisposables.delete(name);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
this.extensionRegistry.delete(name);
|
|
136
|
-
console.log(`Plugin "${name}" unregistered`);
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
enable(name: string) {
|
|
141
|
-
const extension = this.extensionRegistry.get(name);
|
|
142
|
-
if (!extension) {
|
|
143
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
disable(name: string) {
|
|
149
|
-
const extension = this.extensionRegistry.get(name);
|
|
150
|
-
if (!extension) {
|
|
151
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
update() {}
|
|
157
|
-
|
|
158
|
-
destroy() {
|
|
159
|
-
const extensionNames = Array.from(this.extensionRegistry.keys());
|
|
160
|
-
extensionNames.forEach((name) => this.unregister(name));
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export { Extension, ExtensionMetadata, ExtensionRegistry, ExtensionManager };
|
|
1
|
+
import { ExtensionContext } from "./context";
|
|
2
|
+
import { Contribution, ContributionPointIds } from "./contribution";
|
|
3
|
+
import Disposable from "./disposable";
|
|
4
|
+
import CommandService from "./services/CommandService";
|
|
5
|
+
import { ConfigurationService } from "./services";
|
|
6
|
+
|
|
7
|
+
interface ExtensionMetadata {
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Extension {
|
|
12
|
+
id: string;
|
|
13
|
+
metadata?: Partial<ExtensionMetadata>;
|
|
14
|
+
|
|
15
|
+
activate(context: ExtensionContext): void;
|
|
16
|
+
deactivate(context: ExtensionContext): void;
|
|
17
|
+
contribute?(): Record<string, any[]>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class ExtensionRegistry extends Map<string, Extension> {}
|
|
21
|
+
|
|
22
|
+
class ExtensionManager {
|
|
23
|
+
private readonly context: ExtensionContext;
|
|
24
|
+
private extensionRegistry: ExtensionRegistry = new ExtensionRegistry();
|
|
25
|
+
private extensionDisposables: Map<string, Disposable[]> = new Map();
|
|
26
|
+
|
|
27
|
+
constructor(context: ExtensionContext) {
|
|
28
|
+
this.context = context;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
register(extension: Extension) {
|
|
32
|
+
if (this.extensionRegistry.has(extension.id)) {
|
|
33
|
+
console.warn(
|
|
34
|
+
`Plugin "${extension.id}" already registered. It will be overwritten.`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Initialize disposables for this extension
|
|
39
|
+
this.extensionDisposables.set(extension.id, []);
|
|
40
|
+
const disposables = this.extensionDisposables.get(extension.id)!;
|
|
41
|
+
|
|
42
|
+
// Process declarative contributions
|
|
43
|
+
if (extension.contribute) {
|
|
44
|
+
for (const [pointId, items] of Object.entries(extension.contribute())) {
|
|
45
|
+
if (Array.isArray(items)) {
|
|
46
|
+
items.forEach((item, index) => {
|
|
47
|
+
const contributionId =
|
|
48
|
+
item.id ||
|
|
49
|
+
(item.command
|
|
50
|
+
? item.command
|
|
51
|
+
: `${extension.id}.${pointId}.${index}`);
|
|
52
|
+
const contribution: Contribution = {
|
|
53
|
+
id: contributionId,
|
|
54
|
+
metadata: {
|
|
55
|
+
extensionId: extension.id,
|
|
56
|
+
...item?.metadata,
|
|
57
|
+
},
|
|
58
|
+
data: item,
|
|
59
|
+
};
|
|
60
|
+
const disposable = this.context.contributions.register(
|
|
61
|
+
pointId,
|
|
62
|
+
contribution,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Track contribution registration to unregister later
|
|
66
|
+
disposables.push(disposable);
|
|
67
|
+
|
|
68
|
+
const dispose = this.collectContribution(pointId, contribution);
|
|
69
|
+
if (dispose) {
|
|
70
|
+
disposables.push(dispose);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
this.extensionRegistry.set(extension.id, extension);
|
|
79
|
+
this.context.eventBus.emit("extension:register", extension);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(
|
|
82
|
+
`Error in onCreate hook for plugin "${extension.id}":`,
|
|
83
|
+
error,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
extension.activate(this.context);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error(
|
|
91
|
+
`Error in onActivate hook for plugin "${extension.id}":`,
|
|
92
|
+
error,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(`Plugin "${extension.id}" registered successfully`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
collectContribution(pointId: string, item: any): Disposable | undefined {
|
|
100
|
+
// If registering configurations, update ConfigurationService defaults
|
|
101
|
+
if (pointId === ContributionPointIds.CONFIGURATIONS) {
|
|
102
|
+
const configService = this.context.services.get<ConfigurationService>(
|
|
103
|
+
"ConfigurationService",
|
|
104
|
+
);
|
|
105
|
+
configService?.initializeDefaults([item.data]);
|
|
106
|
+
}
|
|
107
|
+
if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
|
|
108
|
+
const commandService =
|
|
109
|
+
this.context.services.get<CommandService>("CommandService")!;
|
|
110
|
+
|
|
111
|
+
return commandService.registerCommand(item.id, item.data.handler);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
unregister(name: string) {
|
|
116
|
+
const extension = this.extensionRegistry.get(name);
|
|
117
|
+
if (!extension) {
|
|
118
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
extension.deactivate(this.context);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error(`Error in deactivate for plugin "${name}":`, error);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Dispose all resources associated with this extension
|
|
129
|
+
const disposables = this.extensionDisposables.get(name);
|
|
130
|
+
if (disposables) {
|
|
131
|
+
disposables.forEach((d) => d.dispose());
|
|
132
|
+
this.extensionDisposables.delete(name);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.extensionRegistry.delete(name);
|
|
136
|
+
console.log(`Plugin "${name}" unregistered`);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
enable(name: string) {
|
|
141
|
+
const extension = this.extensionRegistry.get(name);
|
|
142
|
+
if (!extension) {
|
|
143
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
disable(name: string) {
|
|
149
|
+
const extension = this.extensionRegistry.get(name);
|
|
150
|
+
if (!extension) {
|
|
151
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
update() {}
|
|
157
|
+
|
|
158
|
+
destroy() {
|
|
159
|
+
const extensionNames = Array.from(this.extensionRegistry.keys());
|
|
160
|
+
extensionNames.forEach((name) => this.unregister(name));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export { Extension, ExtensionMetadata, ExtensionRegistry, ExtensionManager };
|
package/src/index.ts
CHANGED
|
@@ -1,140 +1,145 @@
|
|
|
1
|
-
import { Service, ServiceRegistry } from "./service";
|
|
2
|
-
import EventBus from "./event";
|
|
3
|
-
import { ExtensionManager } from "./extension";
|
|
4
|
-
import Disposable from "./disposable";
|
|
5
|
-
import {
|
|
6
|
-
Contribution,
|
|
7
|
-
ContributionPoint,
|
|
8
|
-
ContributionPointIds,
|
|
9
|
-
ContributionRegistry,
|
|
10
|
-
} from "./contribution";
|
|
11
|
-
import { CommandService, ConfigurationService } from "./services";
|
|
12
|
-
import { ExtensionContext } from "./context";
|
|
13
|
-
|
|
14
|
-
export * from "./extension";
|
|
15
|
-
export * from "./context";
|
|
16
|
-
export * from "./contribution";
|
|
17
|
-
export * from "./service";
|
|
18
|
-
export * from "./services";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
private readonly
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.registerContributionPoint({
|
|
61
|
-
id: ContributionPointIds.
|
|
62
|
-
description: "Contribution point for
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
this.registerContributionPoint({
|
|
66
|
-
id: ContributionPointIds.
|
|
67
|
-
description: "Contribution point for
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
this.registerContributionPoint({
|
|
71
|
-
id: ContributionPointIds.
|
|
72
|
-
description: "Contribution point for
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
this.registerContributionPoint({
|
|
76
|
-
id: ContributionPointIds.
|
|
77
|
-
description: "Contribution point for
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
contribution:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
1
|
+
import { Service, ServiceRegistry } from "./service";
|
|
2
|
+
import EventBus from "./event";
|
|
3
|
+
import { ExtensionManager } from "./extension";
|
|
4
|
+
import Disposable from "./disposable";
|
|
5
|
+
import {
|
|
6
|
+
Contribution,
|
|
7
|
+
ContributionPoint,
|
|
8
|
+
ContributionPointIds,
|
|
9
|
+
ContributionRegistry,
|
|
10
|
+
} from "./contribution";
|
|
11
|
+
import { CommandService, ConfigurationService, WorkbenchService } from "./services";
|
|
12
|
+
import { ExtensionContext } from "./context";
|
|
13
|
+
|
|
14
|
+
export * from "./extension";
|
|
15
|
+
export * from "./context";
|
|
16
|
+
export * from "./contribution";
|
|
17
|
+
export * from "./service";
|
|
18
|
+
export * from "./services";
|
|
19
|
+
export { default as EventBus } from "./event";
|
|
20
|
+
|
|
21
|
+
export class Pooder {
|
|
22
|
+
readonly eventBus: EventBus = new EventBus();
|
|
23
|
+
private readonly services: ServiceRegistry = new ServiceRegistry();
|
|
24
|
+
private readonly contributions: ContributionRegistry =
|
|
25
|
+
new ContributionRegistry();
|
|
26
|
+
readonly extensionManager: ExtensionManager;
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
// Initialize default contribution points
|
|
30
|
+
this.initDefaultContributionPoints();
|
|
31
|
+
|
|
32
|
+
const commandService = new CommandService();
|
|
33
|
+
this.registerService(commandService, "CommandService");
|
|
34
|
+
|
|
35
|
+
const configurationService = new ConfigurationService();
|
|
36
|
+
this.registerService(configurationService, "ConfigurationService");
|
|
37
|
+
|
|
38
|
+
const workbenchService = new WorkbenchService();
|
|
39
|
+
workbenchService.setEventBus(this.eventBus);
|
|
40
|
+
this.registerService(workbenchService, "WorkbenchService");
|
|
41
|
+
|
|
42
|
+
// Create a restricted context for extensions
|
|
43
|
+
const context: ExtensionContext = {
|
|
44
|
+
eventBus: this.eventBus,
|
|
45
|
+
services: {
|
|
46
|
+
get: <T extends Service>(serviceName: string) =>
|
|
47
|
+
this.services.get<T>(serviceName),
|
|
48
|
+
},
|
|
49
|
+
contributions: {
|
|
50
|
+
get: <T>(pointId: string) => this.getContributions<T>(pointId),
|
|
51
|
+
register: <T>(pointId: string, contribution: Contribution<T>) =>
|
|
52
|
+
this.registerContribution(pointId, contribution),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
this.extensionManager = new ExtensionManager(context);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private initDefaultContributionPoints() {
|
|
60
|
+
this.registerContributionPoint({
|
|
61
|
+
id: ContributionPointIds.CONTRIBUTIONS,
|
|
62
|
+
description: "Contribution point for contribution points",
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
this.registerContributionPoint({
|
|
66
|
+
id: ContributionPointIds.COMMANDS,
|
|
67
|
+
description: "Contribution point for commands",
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
this.registerContributionPoint({
|
|
71
|
+
id: ContributionPointIds.TOOLS,
|
|
72
|
+
description: "Contribution point for tools",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
this.registerContributionPoint({
|
|
76
|
+
id: ContributionPointIds.VIEWS,
|
|
77
|
+
description: "Contribution point for UI views",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this.registerContributionPoint({
|
|
81
|
+
id: ContributionPointIds.CONFIGURATIONS,
|
|
82
|
+
description: "Contribution point for configurations",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// --- Service Management ---
|
|
87
|
+
|
|
88
|
+
registerService(service: Service, id?: string) {
|
|
89
|
+
const serviceId = id || service.constructor.name;
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
service?.init?.();
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error(`Error initializing service ${serviceId}:`, e);
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.services.register(serviceId, service);
|
|
99
|
+
this.eventBus.emit("service:register", service);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
unregisterService(service: Service, id?: string) {
|
|
104
|
+
const serviceId = id || service.constructor.name;
|
|
105
|
+
if (!this.services.has(serviceId)) {
|
|
106
|
+
console.warn(`Service ${serviceId} is not registered.`);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
service?.dispose?.();
|
|
112
|
+
} catch (e) {
|
|
113
|
+
console.error(`Error disposing service ${serviceId}:`, e);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.services.delete(serviceId);
|
|
118
|
+
this.eventBus.emit("service:unregister", service);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
getService<T extends Service>(id: string): T | undefined {
|
|
123
|
+
return this.services.get<T>(id);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// --- Contribution Management ---
|
|
127
|
+
|
|
128
|
+
registerContributionPoint<T>(point: ContributionPoint<T>): void {
|
|
129
|
+
this.contributions.registerPoint(point);
|
|
130
|
+
this.eventBus.emit("contribution:point:register", point);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
registerContribution<T>(
|
|
134
|
+
pointId: string,
|
|
135
|
+
contribution: Contribution<T>,
|
|
136
|
+
): Disposable {
|
|
137
|
+
const disposable = this.contributions.register(pointId, contribution);
|
|
138
|
+
this.eventBus.emit("contribution:register", { ...contribution, pointId });
|
|
139
|
+
return disposable;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getContributions<T>(pointId: string): Contribution<T>[] {
|
|
143
|
+
return this.contributions.get<T>(pointId);
|
|
144
|
+
}
|
|
145
|
+
}
|