-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathcommandManager.ts
More file actions
97 lines (84 loc) · 2.46 KB
/
Copy pathcommandManager.ts
File metadata and controls
97 lines (84 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import * as vscode from "vscode";
import { type TelemetryService } from "../telemetry/service";
/**
* Every `coder.*` command id contributed by this extension. Kept in sync with
* `contributes.commands` in package.json by a unit test.
*/
export const CODER_COMMAND_IDS = [
"coder.login",
"coder.logout",
"coder.switchDeployment",
"coder.open",
"coder.openDevContainer",
"coder.openFromSidebar",
"coder.openAppStatus",
"coder.workspace.update",
"coder.createWorkspace",
"coder.navigateToWorkspace",
"coder.navigateToWorkspaceSettings",
"coder.refreshWorkspaces",
"coder.viewLogs",
"coder.exportTelemetry",
"coder.searchMyWorkspaces",
"coder.searchAllWorkspaces",
"coder.manageCredentials",
"coder.applyRecommendedSettings",
"coder.pingWorkspace",
"coder.pingWorkspace:views",
"coder.speedTest",
"coder.speedTest:views",
"coder.supportBundle",
"coder.supportBundle:views",
"coder.tasks.refresh",
] as const;
export type CoderCommandId = (typeof CODER_COMMAND_IDS)[number];
const VALID_IDS: ReadonlySet<string> = new Set(CODER_COMMAND_IDS);
const COMMAND_INVOKED_EVENT = "command.invoked";
// `never[]` accepts any concrete handler shape (function-parameter contravariance).
type CommandHandler = (...args: never[]) => unknown;
/**
* Single registration point for `coder.*` commands. Wraps every handler in
* `TelemetryService.trace("command.invoked", ...)` so duration plus
* success/error are captured uniformly.
*/
export class CommandManager implements vscode.Disposable {
private readonly registrations = new Set<vscode.Disposable>();
public constructor(private readonly telemetry: TelemetryService) {}
public register(
id: CoderCommandId,
handler: CommandHandler,
): vscode.Disposable {
if (!VALID_IDS.has(id)) {
throw new Error(`Unknown coder command id: ${id}`);
}
const invoke = handler as (...args: unknown[]) => unknown;
const properties = { command_id: id };
const wrapped = (...args: unknown[]): Thenable<unknown> =>
this.telemetry.trace(
COMMAND_INVOKED_EVENT,
() => Promise.resolve(invoke(...args)),
properties,
);
let live: vscode.Disposable | null = vscode.commands.registerCommand(
id,
wrapped,
);
this.registrations.add(live);
return {
dispose: () => {
if (!live) {
return;
}
this.registrations.delete(live);
live.dispose();
live = null;
},
};
}
public dispose(): void {
for (const inner of this.registrations) {
inner.dispose();
}
this.registrations.clear();
}
}