driftdetect-vscode 0.9.32 → 0.9.33
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 +1 -1
- package/.turbo/turbo-lint.log +44 -1
- package/.turbo/turbo-test.log +0 -34
- 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.map +1 -0
- package/dist/activation/index.d.ts.map +1 -0
- package/dist/client/connection-manager.d.ts.map +1 -0
- package/dist/client/connection-manager.js +216 -0
- package/dist/client/connection-manager.js.map +1 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/language-client-factory.d.ts.map +1 -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-router.d.ts.map +1 -0
- package/dist/commands/command-router.js +129 -0
- package/dist/commands/command-router.js.map +1 -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.map +1 -0
- package/dist/commands/handlers/constants-handlers.js +85 -0
- package/dist/commands/handlers/constants-handlers.js.map +1 -0
- package/dist/commands/handlers/index.d.ts.map +1 -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.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.map +1 -0
- package/dist/commands/handlers/violation-handlers.d.ts.map +1 -0
- package/dist/commands/handlers/violation-handlers.js +75 -0
- package/dist/commands/handlers/violation-handlers.js.map +1 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/middleware/connection-check-middleware.d.ts.map +1 -0
- package/dist/commands/middleware/index.d.ts.map +1 -0
- package/dist/commands/middleware/logging-middleware.d.ts.map +1 -0
- package/dist/commands/middleware/telemetry-middleware.d.ts.map +1 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +182 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/validator.d.ts.map +1 -0
- package/dist/config/validator.js +89 -0
- package/dist/config/validator.js.map +1 -0
- package/dist/extension.d.ts.map +1 -0
- package/dist/extension.js +51 -0
- package/dist/extension.js.map +1 -0
- package/dist/infrastructure/disposable-manager.d.ts.map +1 -0
- package/dist/infrastructure/disposable-manager.js +76 -0
- package/dist/infrastructure/disposable-manager.js.map +1 -0
- package/dist/infrastructure/index.d.ts.map +1 -0
- package/dist/infrastructure/logger.d.ts.map +1 -0
- package/dist/infrastructure/logger.js +82 -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 +92 -0
- package/dist/infrastructure/service-container.js.map +1 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/initial-state.d.ts.map +1 -0
- package/dist/state/selectors.d.ts.map +1 -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.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.map +1 -0
- package/dist/types/lsp-types.d.ts.map +1 -0
- package/dist/types/state-types.d.ts.map +1 -0
- package/dist/ui/decorations/decoration-controller.d.ts.map +1 -0
- package/dist/ui/decorations/decoration-controller.js +196 -0
- package/dist/ui/decorations/decoration-controller.js.map +1 -0
- package/dist/ui/decorations/decoration-types.d.ts.map +1 -0
- package/dist/ui/decorations/index.d.ts.map +1 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/notifications/index.d.ts.map +1 -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.map +1 -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.map +1 -0
- package/dist/ui/status-bar/status-bar-modes.js +112 -0
- package/dist/ui/status-bar/status-bar-modes.js.map +1 -0
- package/dist/views/constants-tree-provider.d.ts +111 -0
- package/dist/views/constants-tree-provider.d.ts.map +1 -0
- package/dist/views/constants-tree-provider.js +343 -0
- package/dist/views/constants-tree-provider.js.map +1 -0
- package/dist/views/files-tree-provider.d.ts +36 -0
- package/dist/views/files-tree-provider.d.ts.map +1 -0
- package/dist/views/files-tree-provider.js +95 -0
- package/dist/views/files-tree-provider.js.map +1 -0
- package/dist/views/index.d.ts.map +1 -0
- package/dist/views/patterns-tree-provider.d.ts.map +1 -0
- package/dist/views/violations-tree-provider.d.ts.map +1 -0
- package/dist/webview/index.d.ts.map +1 -0
- package/dist/webview/webview-manager.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/activation/activation-controller.ts +13 -13
- package/src/client/connection-manager.ts +11 -9
- package/src/client/request-middleware.ts +6 -6
- package/src/commands/command-router.ts +7 -5
- package/src/commands/handlers/connection-handlers.ts +5 -5
- package/src/commands/handlers/constants-handlers.ts +13 -12
- package/src/commands/handlers/pattern-handlers.ts +3 -3
- package/src/commands/handlers/scan-handlers.ts +1 -1
- package/src/commands/handlers/violation-handlers.ts +6 -3
- package/src/config/config-manager.ts +11 -2
- package/src/config/validator.ts +13 -17
- package/src/extension.ts +2 -1
- package/src/infrastructure/disposable-manager.ts +2 -1
- package/src/infrastructure/logger.ts +3 -8
- package/src/infrastructure/service-container.ts +6 -7
- package/src/state/state-manager.ts +8 -11
- package/src/types/extension-types.ts +1 -1
- package/src/ui/decorations/decoration-controller.ts +4 -5
- package/src/ui/notifications/notification-service.ts +5 -5
- package/src/ui/status-bar/status-bar-controller.ts +3 -3
- package/src/ui/status-bar/status-bar-modes.ts +24 -9
- package/src/views/constants-tree-provider.ts +17 -19
- package/src/views/files-tree-provider.ts +0 -4
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -149,7 +149,7 @@ export class ConnectionManager implements vscode.Disposable {
|
|
|
149
149
|
|
|
150
150
|
// Handle client errors
|
|
151
151
|
this.client.onDidChangeState((event: StateChangeEvent) => {
|
|
152
|
-
this.logger.debug(`Client state changed: ${event.oldState} -> ${event.newState}`);
|
|
152
|
+
this.logger.debug(`Client state changed: ${String(event.oldState)} -> ${String(event.newState)}`);
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -168,7 +168,7 @@ export class ConnectionManager implements vscode.Disposable {
|
|
|
168
168
|
await this.delay(100);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
throw new Error(`Server initialization timed out after ${timeout}ms`);
|
|
171
|
+
throw new Error(`Server initialization timed out after ${String(timeout)}ms`);
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
private async handleConnectionError(error: unknown): Promise<void> {
|
|
@@ -183,7 +183,7 @@ export class ConnectionManager implements vscode.Disposable {
|
|
|
183
183
|
|
|
184
184
|
if (this.restartCount >= CONNECTION_CONFIG.maxRestarts) {
|
|
185
185
|
this.setState('failed');
|
|
186
|
-
this.logger.error(`Max restart attempts (${CONNECTION_CONFIG.maxRestarts}) reached`);
|
|
186
|
+
this.logger.error(`Max restart attempts (${String(CONNECTION_CONFIG.maxRestarts)}) reached`);
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
189
|
|
|
@@ -191,7 +191,7 @@ export class ConnectionManager implements vscode.Disposable {
|
|
|
191
191
|
this.restartCount++;
|
|
192
192
|
|
|
193
193
|
this.logger.info(
|
|
194
|
-
`Reconnecting in ${delay}ms (attempt ${this.restartCount}/${CONNECTION_CONFIG.maxRestarts})`
|
|
194
|
+
`Reconnecting in ${String(delay)}ms (attempt ${String(this.restartCount)}/${String(CONNECTION_CONFIG.maxRestarts)})`
|
|
195
195
|
);
|
|
196
196
|
|
|
197
197
|
this.setState('reconnecting');
|
|
@@ -208,11 +208,13 @@ export class ConnectionManager implements vscode.Disposable {
|
|
|
208
208
|
private startHealthCheck(): void {
|
|
209
209
|
this.stopHealthCheck();
|
|
210
210
|
|
|
211
|
-
this.healthCheckTimer = setInterval(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
211
|
+
this.healthCheckTimer = setInterval(() => {
|
|
212
|
+
void this.isHealthy().then(healthy => {
|
|
213
|
+
if (!healthy) {
|
|
214
|
+
this.logger.warn('Health check failed, reconnecting...');
|
|
215
|
+
void this.reconnect();
|
|
216
|
+
}
|
|
217
|
+
});
|
|
216
218
|
}, CONNECTION_CONFIG.healthCheckInterval);
|
|
217
219
|
}
|
|
218
220
|
|
|
@@ -56,14 +56,14 @@ export class RequestMiddleware {
|
|
|
56
56
|
|
|
57
57
|
if (attempt < opts.retries) {
|
|
58
58
|
this.logger.warn(
|
|
59
|
-
`Request ${method} failed (attempt ${attempt + 1}/${opts.retries + 1}): ${lastError.message}`
|
|
59
|
+
`Request ${method} failed (attempt ${String(attempt + 1)}/${String(opts.retries + 1)}): ${lastError.message}`
|
|
60
60
|
);
|
|
61
61
|
await this.delay(opts.retryDelay * (attempt + 1));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
this.logger.error(`Request ${method} failed after ${opts.retries + 1} attempts`);
|
|
66
|
+
this.logger.error(`Request ${method} failed after ${String(opts.retries + 1)} attempts`);
|
|
67
67
|
throw lastError;
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -72,7 +72,7 @@ export class RequestMiddleware {
|
|
|
72
72
|
*/
|
|
73
73
|
notify(method: string, params?: unknown): void {
|
|
74
74
|
try {
|
|
75
|
-
this.client.sendNotification(method, params);
|
|
75
|
+
void this.client.sendNotification(method, params);
|
|
76
76
|
} catch (error) {
|
|
77
77
|
this.logger.error(`Notification ${method} failed:`, error);
|
|
78
78
|
}
|
|
@@ -85,7 +85,7 @@ export class RequestMiddleware {
|
|
|
85
85
|
): Promise<T> {
|
|
86
86
|
return new Promise<T>((resolve, reject) => {
|
|
87
87
|
const timer = setTimeout(() => {
|
|
88
|
-
reject(new Error(`Request ${method} timed out after ${timeout}ms`));
|
|
88
|
+
reject(new Error(`Request ${method} timed out after ${String(timeout)}ms`));
|
|
89
89
|
}, timeout);
|
|
90
90
|
|
|
91
91
|
this.client
|
|
@@ -94,9 +94,9 @@ export class RequestMiddleware {
|
|
|
94
94
|
clearTimeout(timer);
|
|
95
95
|
resolve(result);
|
|
96
96
|
})
|
|
97
|
-
.catch((error) => {
|
|
97
|
+
.catch((error: unknown) => {
|
|
98
98
|
clearTimeout(timer);
|
|
99
|
-
reject(error);
|
|
99
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
100
100
|
});
|
|
101
101
|
});
|
|
102
102
|
}
|
|
@@ -156,8 +156,10 @@ export class CommandRouter implements vscode.Disposable {
|
|
|
156
156
|
|
|
157
157
|
const next = async (): Promise<void> => {
|
|
158
158
|
if (index < this.middleware.length) {
|
|
159
|
-
const mw = this.middleware[index++]
|
|
160
|
-
|
|
159
|
+
const mw = this.middleware[index++];
|
|
160
|
+
if (mw) {
|
|
161
|
+
await mw(ctx, next);
|
|
162
|
+
}
|
|
161
163
|
} else {
|
|
162
164
|
await handler(ctx);
|
|
163
165
|
}
|
|
@@ -170,13 +172,13 @@ export class CommandRouter implements vscode.Disposable {
|
|
|
170
172
|
const message = error instanceof Error ? error.message : String(error);
|
|
171
173
|
this.logger.error(`Command ${command} failed:`, message);
|
|
172
174
|
|
|
173
|
-
vscode.window
|
|
175
|
+
void vscode.window
|
|
174
176
|
.showErrorMessage(`Drift: ${message}`, 'Retry', 'Show Logs')
|
|
175
177
|
.then((action) => {
|
|
176
178
|
if (action === 'Retry') {
|
|
177
|
-
vscode.commands.executeCommand(command);
|
|
179
|
+
void vscode.commands.executeCommand(command);
|
|
178
180
|
} else if (action === 'Show Logs') {
|
|
179
|
-
vscode.commands.executeCommand('drift.showLogs');
|
|
181
|
+
void vscode.commands.executeCommand('drift.showLogs');
|
|
180
182
|
}
|
|
181
183
|
});
|
|
182
184
|
}
|
|
@@ -44,10 +44,10 @@ export function createConnectionHandlers(
|
|
|
44
44
|
|
|
45
45
|
const items = [
|
|
46
46
|
`Connection: ${connection.status}`,
|
|
47
|
-
`Server Version: ${connection.serverVersion
|
|
48
|
-
`Patterns: ${patterns.total}`,
|
|
49
|
-
`Violations: ${violations.total}`,
|
|
50
|
-
`Last Scan: ${workspace.lastScanTime ? new Date(workspace.lastScanTime).toLocaleString() : 'Never'}`,
|
|
47
|
+
`Server Version: ${connection.serverVersion ?? 'Unknown'}`,
|
|
48
|
+
`Patterns: ${String(patterns.total)}`,
|
|
49
|
+
`Violations: ${String(violations.total)}`,
|
|
50
|
+
`Last Scan: ${workspace.lastScanTime !== null ? new Date(workspace.lastScanTime).toLocaleString() : 'Never'}`,
|
|
51
51
|
];
|
|
52
52
|
|
|
53
53
|
await notifications.info(items.join('\n'), [], { detail: 'Drift Status' });
|
|
@@ -61,7 +61,7 @@ export function createConnectionHandlers(
|
|
|
61
61
|
const state = stateManager.getState();
|
|
62
62
|
const error = state.connection.lastError;
|
|
63
63
|
|
|
64
|
-
if (error) {
|
|
64
|
+
if (error !== null && error !== '') {
|
|
65
65
|
await notifications.error(error, [
|
|
66
66
|
{ title: 'Retry', command: DRIFT_COMMANDS.reconnect },
|
|
67
67
|
{ title: 'Show Logs', command: 'drift.showLogs' },
|
|
@@ -18,7 +18,7 @@ export function createConstantsHandlers(
|
|
|
18
18
|
/**
|
|
19
19
|
* Show constants view by category
|
|
20
20
|
*/
|
|
21
|
-
'drift.showConstantsByCategory': async () => {
|
|
21
|
+
'drift.showConstantsByCategory': async (): Promise<void> => {
|
|
22
22
|
constantsProvider.setViewMode('category');
|
|
23
23
|
await vscode.commands.executeCommand('drift.constantsView.focus');
|
|
24
24
|
},
|
|
@@ -26,7 +26,7 @@ export function createConstantsHandlers(
|
|
|
26
26
|
/**
|
|
27
27
|
* Show constants view by language
|
|
28
28
|
*/
|
|
29
|
-
'drift.showConstantsByLanguage': async () => {
|
|
29
|
+
'drift.showConstantsByLanguage': async (): Promise<void> => {
|
|
30
30
|
constantsProvider.setViewMode('language');
|
|
31
31
|
await vscode.commands.executeCommand('drift.constantsView.focus');
|
|
32
32
|
},
|
|
@@ -34,7 +34,7 @@ export function createConstantsHandlers(
|
|
|
34
34
|
/**
|
|
35
35
|
* Show constant issues
|
|
36
36
|
*/
|
|
37
|
-
'drift.showConstantIssues': async () => {
|
|
37
|
+
'drift.showConstantIssues': async (): Promise<void> => {
|
|
38
38
|
constantsProvider.setViewMode('issues');
|
|
39
39
|
await vscode.commands.executeCommand('drift.constantsView.focus');
|
|
40
40
|
},
|
|
@@ -42,7 +42,7 @@ export function createConstantsHandlers(
|
|
|
42
42
|
/**
|
|
43
43
|
* Go to constant definition
|
|
44
44
|
*/
|
|
45
|
-
'drift.goToConstant': async (file: unknown, line: unknown) => {
|
|
45
|
+
'drift.goToConstant': async (file: unknown, line: unknown): Promise<void> => {
|
|
46
46
|
if (typeof file !== 'string' || typeof line !== 'number') {
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
@@ -58,30 +58,31 @@ export function createConstantsHandlers(
|
|
|
58
58
|
new vscode.Range(position, position),
|
|
59
59
|
vscode.TextEditorRevealType.InCenter
|
|
60
60
|
);
|
|
61
|
-
} catch
|
|
62
|
-
vscode.window.showErrorMessage(`Failed to open file: ${file}`);
|
|
61
|
+
} catch {
|
|
62
|
+
void vscode.window.showErrorMessage(`Failed to open file: ${file}`);
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Find constant usages
|
|
68
68
|
*/
|
|
69
|
-
'drift.findConstantUsages': async (constantName: unknown) => {
|
|
70
|
-
|
|
69
|
+
'drift.findConstantUsages': async (constantName: unknown): Promise<void> => {
|
|
70
|
+
let searchName = constantName;
|
|
71
|
+
if (typeof searchName !== 'string' || searchName === '') {
|
|
71
72
|
// If no constant name provided, prompt for one
|
|
72
73
|
const input = await vscode.window.showInputBox({
|
|
73
74
|
prompt: 'Enter constant name to search for',
|
|
74
75
|
placeHolder: 'CONSTANT_NAME',
|
|
75
76
|
});
|
|
76
|
-
if (
|
|
77
|
+
if (input === null || input === '') {
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
|
-
|
|
80
|
+
searchName = input;
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
// Use VSCode's built-in search
|
|
83
84
|
await vscode.commands.executeCommand('workbench.action.findInFiles', {
|
|
84
|
-
query:
|
|
85
|
+
query: searchName,
|
|
85
86
|
isRegex: false,
|
|
86
87
|
isCaseSensitive: true,
|
|
87
88
|
matchWholeWord: true,
|
|
@@ -91,7 +92,7 @@ export function createConstantsHandlers(
|
|
|
91
92
|
/**
|
|
92
93
|
* Show constants overview
|
|
93
94
|
*/
|
|
94
|
-
'drift.showConstants': async () => {
|
|
95
|
+
'drift.showConstants': async (): Promise<void> => {
|
|
95
96
|
constantsProvider.setViewMode('category');
|
|
96
97
|
await vscode.commands.executeCommand('drift.constantsView.focus');
|
|
97
98
|
},
|
|
@@ -48,7 +48,7 @@ export function createPatternHandlers(
|
|
|
48
48
|
|
|
49
49
|
const patternId = ctx.args[0] as string | undefined;
|
|
50
50
|
|
|
51
|
-
if (
|
|
51
|
+
if (patternId === null || patternId === '') {
|
|
52
52
|
// Show pattern picker
|
|
53
53
|
const patterns = await client.sendRequest<Array<{ id: string; name: string }>>(
|
|
54
54
|
'drift/patterns/list',
|
|
@@ -90,7 +90,7 @@ export function createPatternHandlers(
|
|
|
90
90
|
|
|
91
91
|
const patternId = ctx.args[0] as string | undefined;
|
|
92
92
|
|
|
93
|
-
if (
|
|
93
|
+
if (patternId === null || patternId === '') {
|
|
94
94
|
// Show pattern picker
|
|
95
95
|
const patterns = await client.sendRequest<Array<{ id: string; name: string }>>(
|
|
96
96
|
'drift/patterns/list',
|
|
@@ -133,7 +133,7 @@ export function createPatternHandlers(
|
|
|
133
133
|
const patternId = ctx.args[0] as string | undefined;
|
|
134
134
|
const violationId = ctx.args[1] as string | undefined;
|
|
135
135
|
|
|
136
|
-
if (
|
|
136
|
+
if (patternId === null || patternId === '') {
|
|
137
137
|
await notifications.warning('No pattern specified for variant creation.');
|
|
138
138
|
return;
|
|
139
139
|
}
|
|
@@ -67,7 +67,7 @@ export function createScanHandlers(
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
await notifications.info(
|
|
70
|
-
`Scan complete: ${result.patterns} patterns, ${result.violations} violations`
|
|
70
|
+
`Scan complete: ${String(result.patterns)} patterns, ${String(result.violations)} violations`
|
|
71
71
|
);
|
|
72
72
|
} catch (error) {
|
|
73
73
|
stateManager.update(draft => {
|
|
@@ -43,7 +43,7 @@ export function createViolationHandlers(
|
|
|
43
43
|
const uri = ctx.args[1] as string | undefined;
|
|
44
44
|
const line = ctx.args[2] as number | undefined;
|
|
45
45
|
|
|
46
|
-
if (
|
|
46
|
+
if (violationId === null || violationId === '' || uri === null || uri === '' || line === undefined) {
|
|
47
47
|
// Try to get from current editor position
|
|
48
48
|
const editor = vscode.window.activeTextEditor;
|
|
49
49
|
if (!editor) {
|
|
@@ -63,8 +63,11 @@ export function createViolationHandlers(
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Extract violation ID from diagnostic data
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
interface DiagnosticData {
|
|
67
|
+
violationId?: string;
|
|
68
|
+
}
|
|
69
|
+
const data = (driftDiagnostic as vscode.Diagnostic & { data?: DiagnosticData }).data;
|
|
70
|
+
if (data?.violationId === null || data?.violationId === undefined) {
|
|
68
71
|
await notifications.warning('Cannot identify violation.');
|
|
69
72
|
return;
|
|
70
73
|
}
|
|
@@ -139,11 +139,20 @@ export class ConfigManager implements vscode.Disposable {
|
|
|
139
139
|
try {
|
|
140
140
|
if (fs.existsSync(configPath)) {
|
|
141
141
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
142
|
-
|
|
142
|
+
interface ParsedTeamConfig {
|
|
143
|
+
enforceApproved?: boolean;
|
|
144
|
+
requiredCategories?: string[];
|
|
145
|
+
customRules?: Array<string | { id: string; severity: string }>;
|
|
146
|
+
}
|
|
147
|
+
const parsed: ParsedTeamConfig = JSON.parse(content) as ParsedTeamConfig;
|
|
148
|
+
// Map customRules objects to just their IDs if they're objects
|
|
149
|
+
const customRules = parsed.customRules
|
|
150
|
+
? parsed.customRules.map((rule) => (typeof rule === 'string' ? rule : rule.id))
|
|
151
|
+
: DEFAULT_CONFIG.team.customRules;
|
|
143
152
|
return {
|
|
144
153
|
enforceApproved: parsed.enforceApproved ?? DEFAULT_CONFIG.team.enforceApproved,
|
|
145
154
|
requiredCategories: parsed.requiredCategories ?? DEFAULT_CONFIG.team.requiredCategories,
|
|
146
|
-
customRules
|
|
155
|
+
customRules,
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
} catch (error) {
|
package/src/config/validator.ts
CHANGED
|
@@ -36,39 +36,35 @@ export function validateConfig(config: Partial<DriftConfig>): ValidationResult {
|
|
|
36
36
|
const errors: string[] = [];
|
|
37
37
|
|
|
38
38
|
// Validate server config
|
|
39
|
-
if (config.server) {
|
|
40
|
-
|
|
41
|
-
errors.push(`Invalid trace level: ${config.server.trace}`);
|
|
42
|
-
}
|
|
39
|
+
if (config.server?.trace !== undefined && !VALID_TRACE_LEVELS.includes(config.server.trace)) {
|
|
40
|
+
errors.push(`Invalid trace level: ${config.server.trace}`);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
// Validate scan config
|
|
46
|
-
if (config.scan) {
|
|
44
|
+
if (config.scan !== undefined) {
|
|
47
45
|
if (typeof config.scan.debounceMs === 'number' && config.scan.debounceMs < 0) {
|
|
48
46
|
errors.push('debounceMs must be non-negative');
|
|
49
47
|
}
|
|
50
|
-
if (config.scan.excludePatterns && !Array.isArray(config.scan.excludePatterns)) {
|
|
48
|
+
if (config.scan.excludePatterns !== undefined && !Array.isArray(config.scan.excludePatterns)) {
|
|
51
49
|
errors.push('excludePatterns must be an array');
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
// Validate display config
|
|
56
|
-
if (config.display) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
errors.push(`Invalid severity: ${severity}`);
|
|
61
|
-
}
|
|
54
|
+
if (config.display?.severityFilter !== undefined) {
|
|
55
|
+
for (const severity of config.display.severityFilter) {
|
|
56
|
+
if (!VALID_SEVERITIES.includes(severity)) {
|
|
57
|
+
errors.push(`Invalid severity: ${severity}`);
|
|
62
58
|
}
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
// Validate AI config
|
|
67
|
-
if (config.ai) {
|
|
68
|
-
if (config.ai.provider && !VALID_PROVIDERS.includes(config.ai.provider)) {
|
|
63
|
+
if (config.ai !== undefined) {
|
|
64
|
+
if (config.ai.provider !== undefined && !VALID_PROVIDERS.includes(config.ai.provider)) {
|
|
69
65
|
errors.push(`Invalid AI provider: ${config.ai.provider}`);
|
|
70
66
|
}
|
|
71
|
-
if (config.ai.enabled && config.ai.provider === 'none') {
|
|
67
|
+
if (config.ai.enabled === true && config.ai.provider === 'none') {
|
|
72
68
|
errors.push('AI enabled but provider is "none"');
|
|
73
69
|
}
|
|
74
70
|
}
|
|
@@ -99,14 +95,14 @@ export function validateConfigValue(
|
|
|
99
95
|
if (key === 'severityFilter' && Array.isArray(value)) {
|
|
100
96
|
for (const v of value) {
|
|
101
97
|
if (!VALID_SEVERITIES.includes(v as Severity)) {
|
|
102
|
-
errors.push(`Invalid severity: ${v}`);
|
|
98
|
+
errors.push(`Invalid severity: ${String(v)}`);
|
|
103
99
|
}
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
break;
|
|
107
103
|
case 'ai':
|
|
108
104
|
if (key === 'provider' && !VALID_PROVIDERS.includes(value as AIProvider)) {
|
|
109
|
-
errors.push(`Invalid AI provider: ${value}`);
|
|
105
|
+
errors.push(`Invalid AI provider: ${String(value)}`);
|
|
110
106
|
}
|
|
111
107
|
break;
|
|
112
108
|
}
|
package/src/extension.ts
CHANGED
|
@@ -15,7 +15,8 @@ import { createActivationController, type ActivationController } from './activat
|
|
|
15
15
|
*/
|
|
16
16
|
export function getVersion(): string {
|
|
17
17
|
const extension = vscode.extensions.getExtension('driftdetect.driftdetect-vscode');
|
|
18
|
-
|
|
18
|
+
const packageJSON = extension?.packageJSON as { version?: string } | undefined;
|
|
19
|
+
return packageJSON?.version ?? '0.0.0';
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
// For backwards compatibility
|
|
@@ -59,7 +59,8 @@ export class DisposableManager implements IDisposableManager, vscode.Disposable
|
|
|
59
59
|
try {
|
|
60
60
|
disposable?.dispose();
|
|
61
61
|
} catch (error) {
|
|
62
|
-
|
|
62
|
+
// Log error but continue disposing other resources
|
|
63
|
+
void error;
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
@@ -76,13 +76,13 @@ export class Logger implements ILogger {
|
|
|
76
76
|
const argsStr = args
|
|
77
77
|
.map(arg => {
|
|
78
78
|
if (arg instanceof Error) {
|
|
79
|
-
return `${arg.message}\n${arg.stack}`;
|
|
79
|
+
return `${arg.message}\n${arg.stack ?? ''}`;
|
|
80
80
|
}
|
|
81
|
-
if (typeof arg === 'object') {
|
|
81
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
82
82
|
try {
|
|
83
83
|
return JSON.stringify(arg, null, 2);
|
|
84
84
|
} catch {
|
|
85
|
-
return
|
|
85
|
+
return '[Object]';
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
return String(arg);
|
|
@@ -92,11 +92,6 @@ export class Logger implements ILogger {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
this.channel.appendLine(formattedMessage);
|
|
95
|
-
|
|
96
|
-
// Also log errors to console for debugging
|
|
97
|
-
if (level === 'error') {
|
|
98
|
-
console.error(`[Drift] ${message}`, ...args);
|
|
99
|
-
}
|
|
100
95
|
}
|
|
101
96
|
}
|
|
102
97
|
|
|
@@ -29,19 +29,19 @@ export class ServiceContainer implements IServiceContainer {
|
|
|
29
29
|
/**
|
|
30
30
|
* Register a service instance directly
|
|
31
31
|
*/
|
|
32
|
-
register
|
|
32
|
+
register(key: string, instance: unknown): void {
|
|
33
33
|
this.instances.set(key, instance);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Register a service factory for lazy instantiation
|
|
38
38
|
*/
|
|
39
|
-
registerFactory
|
|
39
|
+
registerFactory(
|
|
40
40
|
key: string,
|
|
41
|
-
factory: ServiceFactory<
|
|
41
|
+
factory: ServiceFactory<unknown>,
|
|
42
42
|
options: ServiceOptions = { singleton: true }
|
|
43
43
|
): void {
|
|
44
|
-
this.factories.set(key, factory
|
|
44
|
+
this.factories.set(key, factory);
|
|
45
45
|
this.options.set(key, options);
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -83,11 +83,10 @@ export class ServiceContainer implements IServiceContainer {
|
|
|
83
83
|
* Try to get a service, returning undefined if not found
|
|
84
84
|
*/
|
|
85
85
|
tryGet<T>(key: string): T | undefined {
|
|
86
|
-
|
|
86
|
+
if (this.has(key)) {
|
|
87
87
|
return this.get<T>(key);
|
|
88
|
-
} catch {
|
|
89
|
-
return undefined;
|
|
90
88
|
}
|
|
89
|
+
return undefined;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
/**
|
|
@@ -87,7 +87,7 @@ export class StateManager implements vscode.Disposable {
|
|
|
87
87
|
this.listeners.add(listener);
|
|
88
88
|
|
|
89
89
|
return {
|
|
90
|
-
dispose: () => {
|
|
90
|
+
dispose: (): void => {
|
|
91
91
|
this.listeners.delete(listener);
|
|
92
92
|
},
|
|
93
93
|
};
|
|
@@ -99,7 +99,7 @@ export class StateManager implements vscode.Disposable {
|
|
|
99
99
|
subscribeAll(callback: (state: ExtensionState) => void): vscode.Disposable {
|
|
100
100
|
this.listeners.add(callback);
|
|
101
101
|
return {
|
|
102
|
-
dispose: () => {
|
|
102
|
+
dispose: (): void => {
|
|
103
103
|
this.listeners.delete(callback);
|
|
104
104
|
},
|
|
105
105
|
};
|
|
@@ -130,8 +130,8 @@ export class StateManager implements vscode.Disposable {
|
|
|
130
130
|
for (const listener of this.listeners) {
|
|
131
131
|
try {
|
|
132
132
|
listener(this.state);
|
|
133
|
-
} catch
|
|
134
|
-
|
|
133
|
+
} catch {
|
|
134
|
+
// Listener error, continue with others
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -141,7 +141,7 @@ export class StateManager implements vscode.Disposable {
|
|
|
141
141
|
|
|
142
142
|
try {
|
|
143
143
|
const persisted = this.context.globalState.get<Partial<ExtensionState>>(PERSISTENCE_KEY);
|
|
144
|
-
if (persisted) {
|
|
144
|
+
if (persisted?.preferences !== undefined) {
|
|
145
145
|
// Only restore preferences, not transient state
|
|
146
146
|
return {
|
|
147
147
|
...initial,
|
|
@@ -151,8 +151,8 @@ export class StateManager implements vscode.Disposable {
|
|
|
151
151
|
},
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
|
-
} catch
|
|
155
|
-
|
|
154
|
+
} catch {
|
|
155
|
+
// Failed to load persisted state, use initial
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
return initial;
|
|
@@ -164,10 +164,7 @@ export class StateManager implements vscode.Disposable {
|
|
|
164
164
|
preferences: this.state.preferences,
|
|
165
165
|
};
|
|
166
166
|
|
|
167
|
-
this.context.globalState.update(PERSISTENCE_KEY, toPersist)
|
|
168
|
-
() => {},
|
|
169
|
-
(error) => { console.error('[Drift] Failed to persist state:', error); }
|
|
170
|
-
);
|
|
167
|
+
void this.context.globalState.update(PERSISTENCE_KEY, toPersist);
|
|
171
168
|
}
|
|
172
169
|
|
|
173
170
|
private shallowEqual(a: unknown, b: unknown): boolean {
|
|
@@ -33,8 +33,6 @@ export class DecorationController implements vscode.Disposable {
|
|
|
33
33
|
* Update decorations for the active editor
|
|
34
34
|
*/
|
|
35
35
|
updateDecorations(editor: vscode.TextEditor): void {
|
|
36
|
-
if (!editor) {return;}
|
|
37
|
-
|
|
38
36
|
const uri = editor.document.uri;
|
|
39
37
|
const diagnostics = vscode.languages.getDiagnostics(uri);
|
|
40
38
|
|
|
@@ -187,7 +185,7 @@ export class DecorationController implements vscode.Disposable {
|
|
|
187
185
|
|
|
188
186
|
for (const d of diagnostics) {
|
|
189
187
|
const severity = this.diagnosticSeverityToString(d.severity);
|
|
190
|
-
const group = groups.get(severity)
|
|
188
|
+
const group = groups.get(severity) ?? [];
|
|
191
189
|
group.push(d);
|
|
192
190
|
groups.set(severity, group);
|
|
193
191
|
}
|
|
@@ -216,8 +214,9 @@ export class DecorationController implements vscode.Disposable {
|
|
|
216
214
|
const icon = this.getSeverityIcon(diagnostic.severity);
|
|
217
215
|
md.appendMarkdown(`${icon} **${diagnostic.message}**\n\n`);
|
|
218
216
|
|
|
219
|
-
if (diagnostic.code) {
|
|
220
|
-
|
|
217
|
+
if (diagnostic.code !== null) {
|
|
218
|
+
const codeStr = typeof diagnostic.code === 'object' ? String(diagnostic.code.value) : String(diagnostic.code);
|
|
219
|
+
md.appendMarkdown(`Pattern: \`${codeStr}\`\n\n`);
|
|
221
220
|
}
|
|
222
221
|
|
|
223
222
|
md.appendMarkdown(`---\n\n`);
|
|
@@ -97,7 +97,7 @@ export class NotificationService {
|
|
|
97
97
|
const pickOptions: vscode.QuickPickOptions = {
|
|
98
98
|
...options,
|
|
99
99
|
};
|
|
100
|
-
if (options.title) {
|
|
100
|
+
if (options.title !== null && options.title !== '') {
|
|
101
101
|
pickOptions.title = `Drift: ${options.title}`;
|
|
102
102
|
}
|
|
103
103
|
return vscode.window.showQuickPick(items, pickOptions);
|
|
@@ -110,7 +110,7 @@ export class NotificationService {
|
|
|
110
110
|
const inputOptions: vscode.InputBoxOptions = {
|
|
111
111
|
...options,
|
|
112
112
|
};
|
|
113
|
-
if (options.title) {
|
|
113
|
+
if (options.title !== null && options.title !== '') {
|
|
114
114
|
inputOptions.title = `Drift: ${options.title}`;
|
|
115
115
|
}
|
|
116
116
|
return vscode.window.showInputBox(inputOptions);
|
|
@@ -134,7 +134,7 @@ export class NotificationService {
|
|
|
134
134
|
if (options.modal !== undefined) {
|
|
135
135
|
messageOptions.modal = options.modal;
|
|
136
136
|
}
|
|
137
|
-
if (options.detail !== undefined) {
|
|
137
|
+
if (options.detail !== null && options.detail !== '' && options.detail !== undefined) {
|
|
138
138
|
messageOptions.detail = options.detail;
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -144,13 +144,13 @@ export class NotificationService {
|
|
|
144
144
|
...actionTitles
|
|
145
145
|
);
|
|
146
146
|
|
|
147
|
-
if (selected) {
|
|
147
|
+
if (selected !== null && selected !== '') {
|
|
148
148
|
const action = actions.find(a => a.title === selected);
|
|
149
149
|
if (action) {
|
|
150
150
|
if (action.callback) {
|
|
151
151
|
await action.callback();
|
|
152
152
|
} else if (action.command) {
|
|
153
|
-
await vscode.commands.executeCommand(action.command, ...(action.args
|
|
153
|
+
await vscode.commands.executeCommand(action.command, ...(action.args ?? []));
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
}
|
|
@@ -89,15 +89,15 @@ export class StatusBarController implements vscode.Disposable {
|
|
|
89
89
|
// Add stats if connected
|
|
90
90
|
if (state.connection.status === 'connected') {
|
|
91
91
|
md.appendMarkdown(`---\n\n`);
|
|
92
|
-
md.appendMarkdown(`**Patterns:** ${state.patterns.total}\n\n`);
|
|
93
|
-
md.appendMarkdown(`**Violations:** ${state.violations.total}\n\n`);
|
|
92
|
+
md.appendMarkdown(`**Patterns:** ${String(state.patterns.total)}\n\n`);
|
|
93
|
+
md.appendMarkdown(`**Violations:** ${String(state.violations.total)}\n\n`);
|
|
94
94
|
|
|
95
95
|
if (state.violations.total > 0) {
|
|
96
96
|
md.appendMarkdown(`\n`);
|
|
97
97
|
for (const [severity, count] of Object.entries(state.violations.bySeverity)) {
|
|
98
98
|
if (count > 0) {
|
|
99
99
|
const icon = this.getSeverityIcon(severity);
|
|
100
|
-
md.appendMarkdown(`- ${icon} ${severity}: ${count}\n`);
|
|
100
|
+
md.appendMarkdown(`- ${icon} ${severity}: ${String(count)}\n`);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
}
|