driftdetect-vscode 0.8.2
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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-test.log +138 -0
- package/.vscode/launch.json +17 -0
- package/.vscode/tasks.json +15 -0
- package/LICENSE +121 -0
- package/dist/activation/activation-controller.d.ts +61 -0
- package/dist/activation/activation-controller.d.ts.map +1 -0
- package/dist/activation/activation-controller.js +235 -0
- package/dist/activation/activation-controller.js.map +1 -0
- package/dist/activation/activation-phases.d.ts +28 -0
- package/dist/activation/activation-phases.d.ts.map +1 -0
- package/dist/activation/activation-phases.js +80 -0
- package/dist/activation/activation-phases.js.map +1 -0
- package/dist/activation/index.d.ts +6 -0
- package/dist/activation/index.d.ts.map +1 -0
- package/dist/activation/index.js +6 -0
- package/dist/activation/index.js.map +1 -0
- package/dist/client/connection-config.d.ts +50 -0
- package/dist/client/connection-config.d.ts.map +1 -0
- package/dist/client/connection-config.js +56 -0
- package/dist/client/connection-config.js.map +1 -0
- package/dist/client/connection-manager.d.ts +70 -0
- package/dist/client/connection-manager.d.ts.map +1 -0
- package/dist/client/connection-manager.js +214 -0
- package/dist/client/connection-manager.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/language-client-factory.d.ts +29 -0
- package/dist/client/language-client-factory.d.ts.map +1 -0
- package/dist/client/language-client-factory.js +76 -0
- package/dist/client/language-client-factory.js.map +1 -0
- package/dist/client/request-middleware.d.ts +38 -0
- package/dist/client/request-middleware.d.ts.map +1 -0
- package/dist/client/request-middleware.js +85 -0
- package/dist/client/request-middleware.js.map +1 -0
- package/dist/commands/command-definitions.d.ts +53 -0
- package/dist/commands/command-definitions.d.ts.map +1 -0
- package/dist/commands/command-definitions.js +212 -0
- package/dist/commands/command-definitions.js.map +1 -0
- package/dist/commands/command-router.d.ts +80 -0
- package/dist/commands/command-router.d.ts.map +1 -0
- package/dist/commands/command-router.js +127 -0
- package/dist/commands/command-router.js.map +1 -0
- package/dist/commands/handlers/connection-handlers.d.ts +14 -0
- package/dist/commands/handlers/connection-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/connection-handlers.js +57 -0
- package/dist/commands/handlers/connection-handlers.js.map +1 -0
- package/dist/commands/handlers/constants-handlers.d.ts +11 -0
- package/dist/commands/handlers/constants-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/constants-handlers.js +84 -0
- package/dist/commands/handlers/constants-handlers.js.map +1 -0
- package/dist/commands/handlers/index.d.ts +10 -0
- package/dist/commands/handlers/index.d.ts.map +1 -0
- package/dist/commands/handlers/index.js +10 -0
- package/dist/commands/handlers/index.js.map +1 -0
- package/dist/commands/handlers/pattern-handlers.d.ts +13 -0
- package/dist/commands/handlers/pattern-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/pattern-handlers.js +127 -0
- package/dist/commands/handlers/pattern-handlers.js.map +1 -0
- package/dist/commands/handlers/scan-handlers.d.ts +15 -0
- package/dist/commands/handlers/scan-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/scan-handlers.js +74 -0
- package/dist/commands/handlers/scan-handlers.js.map +1 -0
- package/dist/commands/handlers/ui-handlers.d.ts +12 -0
- package/dist/commands/handlers/ui-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/ui-handlers.js +74 -0
- package/dist/commands/handlers/ui-handlers.js.map +1 -0
- package/dist/commands/handlers/violation-handlers.d.ts +13 -0
- package/dist/commands/handlers/violation-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/violation-handlers.js +76 -0
- package/dist/commands/handlers/violation-handlers.js.map +1 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/middleware/connection-check-middleware.d.ts +12 -0
- package/dist/commands/middleware/connection-check-middleware.d.ts.map +1 -0
- package/dist/commands/middleware/connection-check-middleware.js +34 -0
- package/dist/commands/middleware/connection-check-middleware.js.map +1 -0
- package/dist/commands/middleware/index.d.ts +7 -0
- package/dist/commands/middleware/index.d.ts.map +1 -0
- package/dist/commands/middleware/index.js +7 -0
- package/dist/commands/middleware/index.js.map +1 -0
- package/dist/commands/middleware/logging-middleware.d.ts +12 -0
- package/dist/commands/middleware/logging-middleware.d.ts.map +1 -0
- package/dist/commands/middleware/logging-middleware.js +24 -0
- package/dist/commands/middleware/logging-middleware.js.map +1 -0
- package/dist/commands/middleware/telemetry-middleware.d.ts +22 -0
- package/dist/commands/middleware/telemetry-middleware.d.ts.map +1 -0
- package/dist/commands/middleware/telemetry-middleware.js +30 -0
- package/dist/commands/middleware/telemetry-middleware.js.map +1 -0
- package/dist/config/config-manager.d.ts +53 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +178 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/defaults.d.ts +11 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +43 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/validator.d.ts +22 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +93 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/extension.d.ts +32 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +50 -0
- package/dist/extension.js.map +1 -0
- package/dist/infrastructure/disposable-manager.d.ts +43 -0
- package/dist/infrastructure/disposable-manager.d.ts.map +1 -0
- package/dist/infrastructure/disposable-manager.js +75 -0
- package/dist/infrastructure/disposable-manager.js.map +1 -0
- package/dist/infrastructure/event-bus.d.ts +85 -0
- package/dist/infrastructure/event-bus.d.ts.map +1 -0
- package/dist/infrastructure/event-bus.js +74 -0
- package/dist/infrastructure/event-bus.js.map +1 -0
- package/dist/infrastructure/index.d.ts +10 -0
- package/dist/infrastructure/index.d.ts.map +1 -0
- package/dist/infrastructure/index.js +10 -0
- package/dist/infrastructure/index.js.map +1 -0
- package/dist/infrastructure/logger.d.ts +37 -0
- package/dist/infrastructure/logger.d.ts.map +1 -0
- package/dist/infrastructure/logger.js +86 -0
- package/dist/infrastructure/logger.js.map +1 -0
- package/dist/infrastructure/service-container.d.ts +68 -0
- package/dist/infrastructure/service-container.d.ts.map +1 -0
- package/dist/infrastructure/service-container.js +94 -0
- package/dist/infrastructure/service-container.js.map +1 -0
- package/dist/state/index.d.ts +7 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +7 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/initial-state.d.ts +11 -0
- package/dist/state/initial-state.d.ts.map +1 -0
- package/dist/state/initial-state.js +58 -0
- package/dist/state/initial-state.js.map +1 -0
- package/dist/state/selectors.d.ts +41 -0
- package/dist/state/selectors.d.ts.map +1 -0
- package/dist/state/selectors.js +61 -0
- package/dist/state/selectors.js.map +1 -0
- package/dist/state/state-manager.d.ts +54 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +166 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/types/config-types.d.ts +69 -0
- package/dist/types/config-types.d.ts.map +1 -0
- package/dist/types/config-types.js +5 -0
- package/dist/types/config-types.js.map +1 -0
- package/dist/types/extension-types.d.ts +45 -0
- package/dist/types/extension-types.d.ts.map +1 -0
- package/dist/types/extension-types.js +5 -0
- package/dist/types/extension-types.js.map +1 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +12 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lsp-types.d.ts +70 -0
- package/dist/types/lsp-types.d.ts.map +1 -0
- package/dist/types/lsp-types.js +5 -0
- package/dist/types/lsp-types.js.map +1 -0
- package/dist/types/state-types.d.ts +82 -0
- package/dist/types/state-types.d.ts.map +1 -0
- package/dist/types/state-types.js +5 -0
- package/dist/types/state-types.js.map +1 -0
- package/dist/types/vscode-types.d.ts +36 -0
- package/dist/types/vscode-types.d.ts.map +1 -0
- package/dist/types/vscode-types.js +7 -0
- package/dist/types/vscode-types.js.map +1 -0
- package/dist/ui/decorations/decoration-controller.d.ts +45 -0
- package/dist/ui/decorations/decoration-controller.d.ts.map +1 -0
- package/dist/ui/decorations/decoration-controller.js +198 -0
- package/dist/ui/decorations/decoration-controller.js.map +1 -0
- package/dist/ui/decorations/decoration-types.d.ts +28 -0
- package/dist/ui/decorations/decoration-types.d.ts.map +1 -0
- package/dist/ui/decorations/decoration-types.js +98 -0
- package/dist/ui/decorations/decoration-types.js.map +1 -0
- package/dist/ui/decorations/index.d.ts +7 -0
- package/dist/ui/decorations/index.d.ts.map +1 -0
- package/dist/ui/decorations/index.js +6 -0
- package/dist/ui/decorations/index.js.map +1 -0
- package/dist/ui/index.d.ts +7 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +7 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/notifications/index.d.ts +5 -0
- package/dist/ui/notifications/index.d.ts.map +1 -0
- package/dist/ui/notifications/index.js +5 -0
- package/dist/ui/notifications/index.js.map +1 -0
- package/dist/ui/notifications/notification-service.d.ts +66 -0
- package/dist/ui/notifications/notification-service.d.ts.map +1 -0
- package/dist/ui/notifications/notification-service.js +103 -0
- package/dist/ui/notifications/notification-service.js.map +1 -0
- package/dist/ui/status-bar/index.d.ts +6 -0
- package/dist/ui/status-bar/index.d.ts.map +1 -0
- package/dist/ui/status-bar/index.js +6 -0
- package/dist/ui/status-bar/index.js.map +1 -0
- package/dist/ui/status-bar/status-bar-controller.d.ts +37 -0
- package/dist/ui/status-bar/status-bar-controller.d.ts.map +1 -0
- package/dist/ui/status-bar/status-bar-controller.js +111 -0
- package/dist/ui/status-bar/status-bar-controller.js.map +1 -0
- package/dist/ui/status-bar/status-bar-modes.d.ts +26 -0
- package/dist/ui/status-bar/status-bar-modes.d.ts.map +1 -0
- package/dist/ui/status-bar/status-bar-modes.js +97 -0
- package/dist/ui/status-bar/status-bar-modes.js.map +1 -0
- package/dist/views/base-tree-provider.d.ts +74 -0
- package/dist/views/base-tree-provider.d.ts.map +1 -0
- package/dist/views/base-tree-provider.js +95 -0
- package/dist/views/base-tree-provider.js.map +1 -0
- package/dist/views/constants-tree-provider.d.ts +112 -0
- package/dist/views/constants-tree-provider.d.ts.map +1 -0
- package/dist/views/constants-tree-provider.js +344 -0
- package/dist/views/constants-tree-provider.js.map +1 -0
- package/dist/views/files-tree-provider.d.ts +37 -0
- package/dist/views/files-tree-provider.d.ts.map +1 -0
- package/dist/views/files-tree-provider.js +98 -0
- package/dist/views/files-tree-provider.js.map +1 -0
- package/dist/views/index.d.ts +10 -0
- package/dist/views/index.d.ts.map +1 -0
- package/dist/views/index.js +10 -0
- package/dist/views/index.js.map +1 -0
- package/dist/views/patterns-tree-provider.d.ts +39 -0
- package/dist/views/patterns-tree-provider.d.ts.map +1 -0
- package/dist/views/patterns-tree-provider.js +139 -0
- package/dist/views/patterns-tree-provider.js.map +1 -0
- package/dist/views/violations-tree-provider.d.ts +46 -0
- package/dist/views/violations-tree-provider.d.ts.map +1 -0
- package/dist/views/violations-tree-provider.js +158 -0
- package/dist/views/violations-tree-provider.js.map +1 -0
- package/dist/webview/index.d.ts +7 -0
- package/dist/webview/index.d.ts.map +1 -0
- package/dist/webview/index.js +7 -0
- package/dist/webview/index.js.map +1 -0
- package/dist/webview/webview-manager.d.ts +57 -0
- package/dist/webview/webview-manager.d.ts.map +1 -0
- package/dist/webview/webview-manager.js +167 -0
- package/dist/webview/webview-manager.js.map +1 -0
- package/package.json +405 -0
- package/resources/drift-icon.png +0 -0
- package/resources/drift-icon.svg +5 -0
- package/resources/icons/error.svg +4 -0
- package/resources/icons/info.svg +4 -0
- package/resources/icons/lightbulb.svg +4 -0
- package/resources/icons/warning.svg +4 -0
- package/src/activation/activation-controller.ts +320 -0
- package/src/activation/activation-phases.ts +96 -0
- package/src/activation/index.ts +6 -0
- package/src/client/connection-config.ts +64 -0
- package/src/client/connection-manager.ts +263 -0
- package/src/client/index.ts +8 -0
- package/src/client/language-client-factory.ts +111 -0
- package/src/client/request-middleware.ts +117 -0
- package/src/commands/command-definitions.ts +243 -0
- package/src/commands/command-router.ts +194 -0
- package/src/commands/handlers/connection-handlers.ts +74 -0
- package/src/commands/handlers/constants-handlers.ts +99 -0
- package/src/commands/handlers/index.ts +10 -0
- package/src/commands/handlers/pattern-handlers.ts +167 -0
- package/src/commands/handlers/scan-handlers.ts +107 -0
- package/src/commands/handlers/ui-handlers.ts +88 -0
- package/src/commands/handlers/violation-handlers.ts +97 -0
- package/src/commands/index.ts +7 -0
- package/src/commands/middleware/connection-check-middleware.ts +46 -0
- package/src/commands/middleware/index.ts +7 -0
- package/src/commands/middleware/logging-middleware.ts +28 -0
- package/src/commands/middleware/telemetry-middleware.ts +46 -0
- package/src/config/config-manager.ts +213 -0
- package/src/config/defaults.ts +45 -0
- package/src/config/index.ts +7 -0
- package/src/config/validator.ts +118 -0
- package/src/extension.ts +57 -0
- package/src/infrastructure/disposable-manager.ts +87 -0
- package/src/infrastructure/event-bus.ts +121 -0
- package/src/infrastructure/index.ts +10 -0
- package/src/infrastructure/logger.ts +108 -0
- package/src/infrastructure/service-container.ts +123 -0
- package/src/state/index.ts +7 -0
- package/src/state/initial-state.ts +60 -0
- package/src/state/selectors.ts +126 -0
- package/src/state/state-manager.ts +198 -0
- package/src/types/config-types.ts +77 -0
- package/src/types/extension-types.ts +58 -0
- package/src/types/index.ts +12 -0
- package/src/types/lsp-types.ts +77 -0
- package/src/types/state-types.ts +92 -0
- package/src/types/vscode-types.ts +40 -0
- package/src/ui/decorations/decoration-controller.ts +252 -0
- package/src/ui/decorations/decoration-types.ts +129 -0
- package/src/ui/decorations/index.ts +7 -0
- package/src/ui/index.ts +7 -0
- package/src/ui/notifications/index.ts +5 -0
- package/src/ui/notifications/notification-service.ts +167 -0
- package/src/ui/status-bar/index.ts +6 -0
- package/src/ui/status-bar/status-bar-controller.ts +135 -0
- package/src/ui/status-bar/status-bar-modes.ts +119 -0
- package/src/views/base-tree-provider.ts +127 -0
- package/src/views/constants-tree-provider.ts +525 -0
- package/src/views/files-tree-provider.ts +140 -0
- package/src/views/index.ts +10 -0
- package/src/views/patterns-tree-provider.ts +179 -0
- package/src/views/violations-tree-provider.ts +210 -0
- package/src/webview/index.ts +7 -0
- package/src/webview/webview-manager.ts +238 -0
- package/tsconfig.json +22 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigManager - Configuration management with change detection
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: Load, validate, and watch configuration.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
|
|
10
|
+
import * as vscode from 'vscode';
|
|
11
|
+
|
|
12
|
+
import { DEFAULT_CONFIG } from './defaults.js';
|
|
13
|
+
import { validateConfig } from './validator.js';
|
|
14
|
+
|
|
15
|
+
import type { Logger } from '../infrastructure/index.js';
|
|
16
|
+
import type { DriftConfig, ConfigChangeEvent, TeamConfig } from '../types/index.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Configuration manager with reactive updates
|
|
20
|
+
*/
|
|
21
|
+
export class ConfigManager implements vscode.Disposable {
|
|
22
|
+
private config: DriftConfig;
|
|
23
|
+
private readonly disposables: vscode.Disposable[] = [];
|
|
24
|
+
private readonly changeEmitter = new vscode.EventEmitter<ConfigChangeEvent>();
|
|
25
|
+
|
|
26
|
+
readonly onConfigChange = this.changeEmitter.event;
|
|
27
|
+
|
|
28
|
+
constructor(private readonly logger: Logger) {
|
|
29
|
+
this.config = this.loadConfig();
|
|
30
|
+
this.watchConfig();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get a configuration section
|
|
35
|
+
*/
|
|
36
|
+
get<K extends keyof DriftConfig>(section: K): DriftConfig[K] {
|
|
37
|
+
return this.config[section];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the full configuration
|
|
42
|
+
*/
|
|
43
|
+
getAll(): Readonly<DriftConfig> {
|
|
44
|
+
return this.config;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Update a configuration section
|
|
49
|
+
*/
|
|
50
|
+
async update<K extends keyof DriftConfig>(
|
|
51
|
+
section: K,
|
|
52
|
+
value: Partial<DriftConfig[K]>,
|
|
53
|
+
target: vscode.ConfigurationTarget = vscode.ConfigurationTarget.Workspace
|
|
54
|
+
): Promise<void> {
|
|
55
|
+
const vsConfig = vscode.workspace.getConfiguration('drift');
|
|
56
|
+
const current = vsConfig.get<DriftConfig[K]>(section);
|
|
57
|
+
const merged = { ...current, ...value };
|
|
58
|
+
|
|
59
|
+
// Validate before updating
|
|
60
|
+
const validation = validateConfig({ [section]: merged });
|
|
61
|
+
if (!validation.valid) {
|
|
62
|
+
this.logger.error('Invalid configuration:', validation.errors);
|
|
63
|
+
throw new Error(`Invalid configuration: ${validation.errors.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await vsConfig.update(section, merged, target);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Reset configuration to defaults
|
|
71
|
+
*/
|
|
72
|
+
async reset(target: vscode.ConfigurationTarget = vscode.ConfigurationTarget.Workspace): Promise<void> {
|
|
73
|
+
const vsConfig = vscode.workspace.getConfiguration('drift');
|
|
74
|
+
|
|
75
|
+
for (const [section, value] of Object.entries(DEFAULT_CONFIG)) {
|
|
76
|
+
if (section !== 'team') {
|
|
77
|
+
await vsConfig.update(section, value, target);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Reload configuration from VS Code settings
|
|
84
|
+
*/
|
|
85
|
+
reload(): void {
|
|
86
|
+
const oldConfig = this.config;
|
|
87
|
+
this.config = this.loadConfig();
|
|
88
|
+
this.emitChanges(oldConfig, this.config);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Dispose resources
|
|
93
|
+
*/
|
|
94
|
+
dispose(): void {
|
|
95
|
+
this.changeEmitter.dispose();
|
|
96
|
+
for (const d of this.disposables) {
|
|
97
|
+
d.dispose();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private loadConfig(): DriftConfig {
|
|
102
|
+
const vsConfig = vscode.workspace.getConfiguration('drift');
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
server: {
|
|
106
|
+
path: vsConfig.get('server.path', DEFAULT_CONFIG.server.path),
|
|
107
|
+
args: vsConfig.get('server.args', DEFAULT_CONFIG.server.args),
|
|
108
|
+
trace: vsConfig.get('server.trace', DEFAULT_CONFIG.server.trace),
|
|
109
|
+
},
|
|
110
|
+
scan: {
|
|
111
|
+
onSave: vsConfig.get('scan.onSave', DEFAULT_CONFIG.scan.onSave),
|
|
112
|
+
onOpen: vsConfig.get('scan.onOpen', DEFAULT_CONFIG.scan.onOpen),
|
|
113
|
+
debounceMs: vsConfig.get('scan.debounceMs', DEFAULT_CONFIG.scan.debounceMs),
|
|
114
|
+
excludePatterns: vsConfig.get('scan.excludePatterns', DEFAULT_CONFIG.scan.excludePatterns),
|
|
115
|
+
},
|
|
116
|
+
display: {
|
|
117
|
+
showStatusBar: vsConfig.get('display.showStatusBar', DEFAULT_CONFIG.display.showStatusBar),
|
|
118
|
+
showInlineHints: vsConfig.get('display.showInlineHints', DEFAULT_CONFIG.display.showInlineHints),
|
|
119
|
+
showGutterIcons: vsConfig.get('display.showGutterIcons', DEFAULT_CONFIG.display.showGutterIcons),
|
|
120
|
+
severityFilter: vsConfig.get('display.severityFilter', DEFAULT_CONFIG.display.severityFilter),
|
|
121
|
+
},
|
|
122
|
+
ai: {
|
|
123
|
+
enabled: vsConfig.get('ai.enabled', DEFAULT_CONFIG.ai.enabled),
|
|
124
|
+
provider: vsConfig.get('ai.provider', DEFAULT_CONFIG.ai.provider),
|
|
125
|
+
model: vsConfig.get('ai.model', DEFAULT_CONFIG.ai.model),
|
|
126
|
+
},
|
|
127
|
+
team: this.loadTeamConfig(),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private loadTeamConfig(): TeamConfig {
|
|
132
|
+
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
|
133
|
+
if (!workspaceFolder) {
|
|
134
|
+
return DEFAULT_CONFIG.team;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const configPath = path.join(workspaceFolder.uri.fsPath, '.drift', 'config.json');
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
if (fs.existsSync(configPath)) {
|
|
141
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
142
|
+
const parsed = JSON.parse(content);
|
|
143
|
+
return {
|
|
144
|
+
enforceApproved: parsed.enforceApproved ?? DEFAULT_CONFIG.team.enforceApproved,
|
|
145
|
+
requiredCategories: parsed.requiredCategories ?? DEFAULT_CONFIG.team.requiredCategories,
|
|
146
|
+
customRules: parsed.customRules ?? DEFAULT_CONFIG.team.customRules,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
} catch (error) {
|
|
150
|
+
this.logger.warn('Failed to load team config:', error);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return DEFAULT_CONFIG.team;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private watchConfig(): void {
|
|
157
|
+
// Watch VS Code settings
|
|
158
|
+
this.disposables.push(
|
|
159
|
+
vscode.workspace.onDidChangeConfiguration((event) => {
|
|
160
|
+
if (event.affectsConfiguration('drift')) {
|
|
161
|
+
this.reload();
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// Watch .drift/config.json
|
|
167
|
+
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
|
168
|
+
if (workspaceFolder) {
|
|
169
|
+
const pattern = new vscode.RelativePattern(workspaceFolder, '.drift/config.json');
|
|
170
|
+
const watcher = vscode.workspace.createFileSystemWatcher(pattern);
|
|
171
|
+
|
|
172
|
+
watcher.onDidChange(() => { this.reloadTeamConfig(); });
|
|
173
|
+
watcher.onDidCreate(() => { this.reloadTeamConfig(); });
|
|
174
|
+
watcher.onDidDelete(() => { this.reloadTeamConfig(); });
|
|
175
|
+
|
|
176
|
+
this.disposables.push(watcher);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private reloadTeamConfig(): void {
|
|
181
|
+
const oldTeam = this.config.team;
|
|
182
|
+
this.config = { ...this.config, team: this.loadTeamConfig() };
|
|
183
|
+
|
|
184
|
+
if (JSON.stringify(oldTeam) !== JSON.stringify(this.config.team)) {
|
|
185
|
+
this.changeEmitter.fire({
|
|
186
|
+
section: 'team',
|
|
187
|
+
oldValue: oldTeam,
|
|
188
|
+
newValue: this.config.team,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private emitChanges(oldConfig: DriftConfig, newConfig: DriftConfig): void {
|
|
194
|
+
const sections: (keyof DriftConfig)[] = ['server', 'scan', 'display', 'ai', 'team'];
|
|
195
|
+
|
|
196
|
+
for (const section of sections) {
|
|
197
|
+
if (JSON.stringify(oldConfig[section]) !== JSON.stringify(newConfig[section])) {
|
|
198
|
+
this.changeEmitter.fire({
|
|
199
|
+
section,
|
|
200
|
+
oldValue: oldConfig[section],
|
|
201
|
+
newValue: newConfig[section],
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Factory function for creating config manager
|
|
210
|
+
*/
|
|
211
|
+
export function createConfigManager(logger: Logger): ConfigManager {
|
|
212
|
+
return new ConfigManager(logger);
|
|
213
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configuration values
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: Provide default config values.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DriftConfig } from '../types/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default configuration
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_CONFIG: DriftConfig = {
|
|
13
|
+
server: {
|
|
14
|
+
path: '',
|
|
15
|
+
args: [],
|
|
16
|
+
trace: 'off',
|
|
17
|
+
},
|
|
18
|
+
scan: {
|
|
19
|
+
onSave: true,
|
|
20
|
+
onOpen: true,
|
|
21
|
+
debounceMs: 200,
|
|
22
|
+
excludePatterns: [
|
|
23
|
+
'**/node_modules/**',
|
|
24
|
+
'**/dist/**',
|
|
25
|
+
'**/.git/**',
|
|
26
|
+
'**/coverage/**',
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
display: {
|
|
30
|
+
showStatusBar: true,
|
|
31
|
+
showInlineHints: true,
|
|
32
|
+
showGutterIcons: true,
|
|
33
|
+
severityFilter: ['error', 'warning'],
|
|
34
|
+
},
|
|
35
|
+
ai: {
|
|
36
|
+
enabled: false,
|
|
37
|
+
provider: 'none',
|
|
38
|
+
model: '',
|
|
39
|
+
},
|
|
40
|
+
team: {
|
|
41
|
+
enforceApproved: false,
|
|
42
|
+
requiredCategories: [],
|
|
43
|
+
customRules: [],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration validator
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: Validate configuration values.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { DriftConfig, Severity, AIProvider } from '../types/index.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Validation result
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
errors: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Valid severity values
|
|
19
|
+
*/
|
|
20
|
+
const VALID_SEVERITIES: Severity[] = ['error', 'warning', 'info', 'hint'];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Valid AI providers
|
|
24
|
+
*/
|
|
25
|
+
const VALID_PROVIDERS: AIProvider[] = ['openai', 'anthropic', 'ollama', 'none'];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Valid trace levels
|
|
29
|
+
*/
|
|
30
|
+
const VALID_TRACE_LEVELS = ['off', 'messages', 'verbose'] as const;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Validate configuration
|
|
34
|
+
*/
|
|
35
|
+
export function validateConfig(config: Partial<DriftConfig>): ValidationResult {
|
|
36
|
+
const errors: string[] = [];
|
|
37
|
+
|
|
38
|
+
// Validate server config
|
|
39
|
+
if (config.server) {
|
|
40
|
+
if (config.server.trace && !VALID_TRACE_LEVELS.includes(config.server.trace)) {
|
|
41
|
+
errors.push(`Invalid trace level: ${config.server.trace}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Validate scan config
|
|
46
|
+
if (config.scan) {
|
|
47
|
+
if (typeof config.scan.debounceMs === 'number' && config.scan.debounceMs < 0) {
|
|
48
|
+
errors.push('debounceMs must be non-negative');
|
|
49
|
+
}
|
|
50
|
+
if (config.scan.excludePatterns && !Array.isArray(config.scan.excludePatterns)) {
|
|
51
|
+
errors.push('excludePatterns must be an array');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Validate display config
|
|
56
|
+
if (config.display) {
|
|
57
|
+
if (config.display.severityFilter) {
|
|
58
|
+
for (const severity of config.display.severityFilter) {
|
|
59
|
+
if (!VALID_SEVERITIES.includes(severity)) {
|
|
60
|
+
errors.push(`Invalid severity: ${severity}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Validate AI config
|
|
67
|
+
if (config.ai) {
|
|
68
|
+
if (config.ai.provider && !VALID_PROVIDERS.includes(config.ai.provider)) {
|
|
69
|
+
errors.push(`Invalid AI provider: ${config.ai.provider}`);
|
|
70
|
+
}
|
|
71
|
+
if (config.ai.enabled && config.ai.provider === 'none') {
|
|
72
|
+
errors.push('AI enabled but provider is "none"');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
valid: errors.length === 0,
|
|
78
|
+
errors,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Validate a single config value
|
|
84
|
+
*/
|
|
85
|
+
export function validateConfigValue(
|
|
86
|
+
section: keyof DriftConfig,
|
|
87
|
+
key: string,
|
|
88
|
+
value: unknown
|
|
89
|
+
): ValidationResult {
|
|
90
|
+
const errors: string[] = [];
|
|
91
|
+
|
|
92
|
+
switch (section) {
|
|
93
|
+
case 'scan':
|
|
94
|
+
if (key === 'debounceMs' && (typeof value !== 'number' || value < 0)) {
|
|
95
|
+
errors.push('debounceMs must be a non-negative number');
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
case 'display':
|
|
99
|
+
if (key === 'severityFilter' && Array.isArray(value)) {
|
|
100
|
+
for (const v of value) {
|
|
101
|
+
if (!VALID_SEVERITIES.includes(v as Severity)) {
|
|
102
|
+
errors.push(`Invalid severity: ${v}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case 'ai':
|
|
108
|
+
if (key === 'provider' && !VALID_PROVIDERS.includes(value as AIProvider)) {
|
|
109
|
+
errors.push(`Invalid AI provider: ${value}`);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
valid: errors.length === 0,
|
|
116
|
+
errors,
|
|
117
|
+
};
|
|
118
|
+
}
|
package/src/extension.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @drift/vscode - VS Code Extension Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for the Drift VS Code extension.
|
|
5
|
+
* It delegates all work to the ActivationController for proper
|
|
6
|
+
* lifecycle management and phased activation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as vscode from 'vscode';
|
|
10
|
+
|
|
11
|
+
import { createActivationController, type ActivationController } from './activation/index.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extension version - read from package.json at runtime
|
|
15
|
+
*/
|
|
16
|
+
export function getVersion(): string {
|
|
17
|
+
const extension = vscode.extensions.getExtension('driftdetect.driftdetect-vscode');
|
|
18
|
+
return extension?.packageJSON?.version ?? '0.0.0';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// For backwards compatibility
|
|
22
|
+
export const VERSION = '0.4.4';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Activation controller instance
|
|
26
|
+
*/
|
|
27
|
+
let controller: ActivationController | null = null;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Activates the Drift extension
|
|
31
|
+
*
|
|
32
|
+
* This function is called by VS Code when the extension is activated.
|
|
33
|
+
* Activation is phased for optimal startup performance:
|
|
34
|
+
*
|
|
35
|
+
* 1. Immediate phase (<100ms): Infrastructure, state, config, status bar
|
|
36
|
+
* 2. Deferred phase: LSP connection, commands, decorations
|
|
37
|
+
* 3. Lazy phase: Tree views, webviews (on-demand)
|
|
38
|
+
*/
|
|
39
|
+
export async function activate(context: vscode.ExtensionContext): Promise<void> {
|
|
40
|
+
controller = createActivationController(context);
|
|
41
|
+
context.subscriptions.push(controller);
|
|
42
|
+
|
|
43
|
+
await controller.activate();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Deactivates the Drift extension
|
|
48
|
+
*
|
|
49
|
+
* This function is called by VS Code when the extension is deactivated.
|
|
50
|
+
* It ensures proper cleanup of all resources.
|
|
51
|
+
*/
|
|
52
|
+
export async function deactivate(): Promise<void> {
|
|
53
|
+
if (controller) {
|
|
54
|
+
await controller.deactivate();
|
|
55
|
+
controller = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DisposableManager - Centralized resource cleanup
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: Track and dispose VS Code disposables.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as vscode from 'vscode';
|
|
8
|
+
|
|
9
|
+
import type { DisposableManager as IDisposableManager } from '../types/index.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Manages disposable resources for proper cleanup
|
|
13
|
+
*/
|
|
14
|
+
export class DisposableManager implements IDisposableManager, vscode.Disposable {
|
|
15
|
+
private readonly disposables: vscode.Disposable[] = [];
|
|
16
|
+
private disposed = false;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Add a disposable to be managed
|
|
20
|
+
*/
|
|
21
|
+
add(disposable: vscode.Disposable): void {
|
|
22
|
+
if (this.disposed) {
|
|
23
|
+
// If already disposed, dispose the new item immediately
|
|
24
|
+
disposable.dispose();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.disposables.push(disposable);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Add multiple disposables
|
|
32
|
+
*/
|
|
33
|
+
addAll(...disposables: vscode.Disposable[]): void {
|
|
34
|
+
for (const d of disposables) {
|
|
35
|
+
this.add(d);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Create a disposable from a cleanup function
|
|
41
|
+
*/
|
|
42
|
+
addCallback(cleanup: () => void): void {
|
|
43
|
+
this.add({ dispose: cleanup });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Dispose all managed resources
|
|
48
|
+
*/
|
|
49
|
+
dispose(): void {
|
|
50
|
+
if (this.disposed) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.disposed = true;
|
|
55
|
+
|
|
56
|
+
// Dispose in reverse order (LIFO)
|
|
57
|
+
while (this.disposables.length > 0) {
|
|
58
|
+
const disposable = this.disposables.pop();
|
|
59
|
+
try {
|
|
60
|
+
disposable?.dispose();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('[Drift] Error disposing resource:', error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check if already disposed
|
|
69
|
+
*/
|
|
70
|
+
isDisposed(): boolean {
|
|
71
|
+
return this.disposed;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get count of managed disposables
|
|
76
|
+
*/
|
|
77
|
+
get count(): number {
|
|
78
|
+
return this.disposables.length;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Factory function for creating disposable managers
|
|
84
|
+
*/
|
|
85
|
+
export function createDisposableManager(): DisposableManager {
|
|
86
|
+
return new DisposableManager();
|
|
87
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EventBus - Decoupled event communication
|
|
3
|
+
*
|
|
4
|
+
* Single responsibility: Enable pub/sub communication between components.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as vscode from 'vscode';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Event types for the extension
|
|
11
|
+
*/
|
|
12
|
+
export type ExtensionEventType =
|
|
13
|
+
| 'connection:changed'
|
|
14
|
+
| 'connection:error'
|
|
15
|
+
| 'patterns:updated'
|
|
16
|
+
| 'violations:updated'
|
|
17
|
+
| 'scan:started'
|
|
18
|
+
| 'scan:completed'
|
|
19
|
+
| 'config:changed'
|
|
20
|
+
| 'workspace:changed';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Event payload types
|
|
24
|
+
*/
|
|
25
|
+
export interface ExtensionEvents {
|
|
26
|
+
'connection:changed': { status: string; previousStatus: string };
|
|
27
|
+
'connection:error': { error: Error; recoverable: boolean };
|
|
28
|
+
'patterns:updated': { total: number; categories: string[] };
|
|
29
|
+
'violations:updated': { total: number; file?: string };
|
|
30
|
+
'scan:started': { files: number };
|
|
31
|
+
'scan:completed': { duration: number; patterns: number; violations: number };
|
|
32
|
+
'config:changed': { section: string; oldValue: unknown; newValue: unknown };
|
|
33
|
+
'workspace:changed': { folders: string[] };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Event listener type
|
|
38
|
+
*/
|
|
39
|
+
type EventListener<T> = (data: T) => void;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Type-safe event bus for extension-wide communication
|
|
43
|
+
*/
|
|
44
|
+
export class EventBus implements vscode.Disposable {
|
|
45
|
+
private readonly emitters = new Map<string, vscode.EventEmitter<unknown>>();
|
|
46
|
+
private readonly disposables: vscode.Disposable[] = [];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to an event
|
|
50
|
+
*/
|
|
51
|
+
on<K extends ExtensionEventType>(
|
|
52
|
+
event: K,
|
|
53
|
+
listener: EventListener<ExtensionEvents[K]>
|
|
54
|
+
): vscode.Disposable {
|
|
55
|
+
const emitter = this.getOrCreateEmitter(event);
|
|
56
|
+
return emitter.event(listener as EventListener<unknown>);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Subscribe to an event once
|
|
61
|
+
*/
|
|
62
|
+
once<K extends ExtensionEventType>(
|
|
63
|
+
event: K,
|
|
64
|
+
listener: EventListener<ExtensionEvents[K]>
|
|
65
|
+
): vscode.Disposable {
|
|
66
|
+
const disposable = this.on(event, (data) => {
|
|
67
|
+
disposable.dispose();
|
|
68
|
+
listener(data);
|
|
69
|
+
});
|
|
70
|
+
return disposable;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Emit an event
|
|
75
|
+
*/
|
|
76
|
+
emit<K extends ExtensionEventType>(event: K, data: ExtensionEvents[K]): void {
|
|
77
|
+
const emitter = this.emitters.get(event);
|
|
78
|
+
if (emitter) {
|
|
79
|
+
emitter.fire(data);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if event has listeners
|
|
85
|
+
*/
|
|
86
|
+
hasListeners(event: ExtensionEventType): boolean {
|
|
87
|
+
return this.emitters.has(event);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Dispose all emitters
|
|
92
|
+
*/
|
|
93
|
+
dispose(): void {
|
|
94
|
+
for (const emitter of this.emitters.values()) {
|
|
95
|
+
emitter.dispose();
|
|
96
|
+
}
|
|
97
|
+
this.emitters.clear();
|
|
98
|
+
|
|
99
|
+
for (const d of this.disposables) {
|
|
100
|
+
d.dispose();
|
|
101
|
+
}
|
|
102
|
+
this.disposables.length = 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private getOrCreateEmitter(event: string): vscode.EventEmitter<unknown> {
|
|
106
|
+
let emitter = this.emitters.get(event);
|
|
107
|
+
if (!emitter) {
|
|
108
|
+
emitter = new vscode.EventEmitter<unknown>();
|
|
109
|
+
this.emitters.set(event, emitter);
|
|
110
|
+
this.disposables.push(emitter);
|
|
111
|
+
}
|
|
112
|
+
return emitter;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Factory function for creating event bus
|
|
118
|
+
*/
|
|
119
|
+
export function createEventBus(): EventBus {
|
|
120
|
+
return new EventBus();
|
|
121
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure module exports
|
|
3
|
+
*
|
|
4
|
+
* Core utilities and services used across the extension.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { Logger, createLogger } from './logger.js';
|
|
8
|
+
export { DisposableManager, createDisposableManager } from './disposable-manager.js';
|
|
9
|
+
export { ServiceContainer, ServiceKeys, createServiceContainer } from './service-container.js';
|
|
10
|
+
export { EventBus, createEventBus } from './event-bus.js';
|