forked from PowerShell/vscode-powershell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExternalApi.ts
149 lines (126 loc) · 6.08 KB
/
ExternalApi.ts
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
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import * as vscode from "vscode";
import { v4 as uuidv4 } from 'uuid';
import { LanguageClient } from "vscode-languageclient";
import { LanguageClientConsumer } from "../languageClientConsumer";
import { Logger } from "../logging";
import { SessionManager } from "../session";
export interface IExternalPowerShellDetails {
exePath: string;
version: string;
displayName: string;
architecture: string;
}
export class ExternalApiFeature extends LanguageClientConsumer {
private commands: vscode.Disposable[];
private static readonly registeredExternalExtension: Map<string, IExternalExtension> = new Map<string, IExternalExtension>();
constructor(private sessionManager: SessionManager, private log: Logger) {
super();
this.commands = [
/*
DESCRIPTION:
Registers your extension to allow usage of the external API. The returns
a session UUID that will need to be passed in to subsequent API calls.
USAGE:
vscode.commands.executeCommand(
"PowerShell.RegisterExternalExtension",
"ms-vscode.PesterTestExplorer" // the name of the extension using us
"v1"); // API Version.
RETURNS:
string session uuid
*/
vscode.commands.registerCommand("PowerShell.RegisterExternalExtension", (id: string, apiVersion: string = 'v1'): string =>
this.registerExternalExtension(id, apiVersion)),
/*
DESCRIPTION:
Unregisters a session that an extension has. This returns
true if it succeeds or throws if it fails.
USAGE:
vscode.commands.executeCommand(
"PowerShell.UnregisterExternalExtension",
"uuid"); // the uuid from above for tracking purposes
RETURNS:
true if it worked, otherwise throws an error.
*/
vscode.commands.registerCommand("PowerShell.UnregisterExternalExtension", (uuid: string = ""): boolean =>
this.unregisterExternalExtension(uuid)),
/*
DESCRIPTION:
This will fetch the version details of the PowerShell used to start
PowerShell Editor Services in the PowerShell extension.
USAGE:
vscode.commands.executeCommand(
"PowerShell.GetPowerShellVersionDetails",
"uuid"); // the uuid from above for tracking purposes
RETURNS:
An IPowerShellVersionDetails which consists of:
{
version: string;
displayVersion: string;
edition: string;
architecture: string;
}
*/
vscode.commands.registerCommand("PowerShell.GetPowerShellVersionDetails", (uuid: string = ""): Promise<IExternalPowerShellDetails> =>
this.getPowerShellVersionDetails(uuid)),
]
}
private registerExternalExtension(id: string, apiVersion: string = 'v1'): string {
this.log.writeDiagnostic(`Registering extension '${id}' for use with API version '${apiVersion}'.`);
for (const [_, externalExtension] of ExternalApiFeature.registeredExternalExtension) {
if (externalExtension.id === id) {
const message = `The extension '${id}' is already registered.`;
this.log.writeWarning(message);
throw new Error(message);
}
}
if (!vscode.extensions.all.some(ext => ext.id === id)) {
throw new Error(`No extension installed with id '${id}'. You must use a valid extension id.`);
}
// If we're in development mode, we allow these to be used for testing purposes.
if (!this.sessionManager.InDevelopmentMode && (id === "ms-vscode.PowerShell" || id === "ms-vscode.PowerShell-Preview")) {
throw new Error("You can't use the PowerShell extension's id in this registration.");
}
const uuid = uuidv4();
ExternalApiFeature.registeredExternalExtension.set(uuid, {
id,
apiVersion
});
return uuid;
}
private unregisterExternalExtension(uuid: string = ""): boolean {
this.log.writeDiagnostic(`Unregistering extension with session UUID: ${uuid}`);
if (!ExternalApiFeature.registeredExternalExtension.delete(uuid)) {
throw new Error(`No extension registered with session UUID: ${uuid}`);
}
return true;
}
private async getPowerShellVersionDetails(uuid: string = ""): Promise<IExternalPowerShellDetails> {
if (!ExternalApiFeature.registeredExternalExtension.has(uuid)) {
throw new Error(
"UUID provided was invalid, make sure you execute the 'PowerShell.GetPowerShellVersionDetails' command and pass in the UUID that it returns to subsequent command executions.");
}
// TODO: When we have more than one API version, make sure to include a check here.
const extension = ExternalApiFeature.registeredExternalExtension.get(uuid);
this.log.writeDiagnostic(`Extension '${extension.id}' used command 'PowerShell.GetPowerShellVersionDetails'.`);
await this.sessionManager.waitUntilStarted();
const versionDetails = this.sessionManager.getPowerShellVersionDetails();
return {
exePath: this.sessionManager.PowerShellExeDetails.exePath,
version: versionDetails.version,
displayName: this.sessionManager.PowerShellExeDetails.displayName, // comes from the Session Menu
architecture: versionDetails.architecture
};
}
public dispose() {
for (const command of this.commands) {
command.dispose();
}
}
}
interface IExternalExtension {
readonly id: string;
readonly apiVersion: string;
}