-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathconnectFolderToServerNamespace.ts
More file actions
158 lines (156 loc) · 6.23 KB
/
Copy pathconnectFolderToServerNamespace.ts
File metadata and controls
158 lines (156 loc) · 6.23 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
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
150
151
152
153
154
155
156
157
158
import * as vscode from "vscode";
import { AtelierAPI } from "../api";
import {
panel,
resolveConnectionSpec,
getResolvedConnectionSpec,
serverManagerApi,
resolveUsernameAndPassword,
} from "../extension";
import { handleError, notIsfs, displayableUri } from "../utils";
interface ConnSettings {
server: string;
ns: string;
active: boolean;
}
export async function connectFolderToServerNamespace(): Promise<void> {
if (!vscode.workspace.workspaceFolders?.length) {
vscode.window.showErrorMessage("No folders in the workspace.", "Dismiss");
return;
}
if (!serverManagerApi) {
vscode.window.showErrorMessage(
"Connecting a folder to a server namespace requires the [InterSystems Server Manager extension](https://marketplace.visualstudio.com/items?itemName=intersystems-community.servermanager) to be installed and enabled.",
"Dismiss"
);
return;
}
// Which folder?
const items: vscode.QuickPickItem[] = vscode.workspace.workspaceFolders
.filter((folder) => notIsfs(folder.uri))
.map((folder) => {
const config = vscode.workspace.getConfiguration("objectscript", folder);
const conn: ConnSettings = config.get("conn");
return {
label: folder.name,
description: folder.uri.fsPath,
detail:
!conn.server || !conn.active
? "No active server connection"
: `Currently connected to ${conn.ns} on ${conn.server}`,
};
});
if (!items.length) {
vscode.window.showErrorMessage("No local folders in the workspace.", "Dismiss");
return;
}
const pick =
items.length == 1 && !items[0].detail.startsWith("Currently")
? items[0]
: await vscode.window.showQuickPick(items, { title: "Pick a folder" });
if (!pick) return;
const folder = vscode.workspace.workspaceFolders.find((el) => el.name === pick.label);
// Get user's choice of server
const options: vscode.QuickPickOptions = {};
const serverName: string = await serverManagerApi.pickServer(folder, options);
if (!serverName) {
return;
}
await resolveConnectionSpec(serverName, undefined, folder);
// Prepare a displayable form of its connection spec as a hint to the user
// This will never return the default value (second parameter) because we only just resolved the connection spec.
const connSpec = getResolvedConnectionSpec(serverName, undefined);
const connDisplayString = `${connSpec.webServer.scheme}://${connSpec.webServer.host}:${connSpec.webServer.port}/${connSpec.webServer.pathPrefix}`;
// Connect and fetch namespaces
const api = new AtelierAPI(vscode.Uri.parse(`isfs://${serverName}/?ns=%SYS`));
const serverConf = vscode.workspace
.getConfiguration("intersystems", folder)
.inspect<{ [key: string]: any }>("servers");
if (
serverConf.workspaceFolderValue &&
typeof serverConf.workspaceFolderValue[serverName] == "object" &&
!(serverConf.workspaceValue && typeof serverConf.workspaceValue[serverName] == "object")
) {
// Need to manually set connection info if the server is defined at the workspace folder level
api.setConnSpec(serverName, connSpec);
}
const allNamespaces: string[] = await api
.serverInfo(false)
.then((data) => data.result.content.namespaces)
.catch(async (error) => {
if (error?.statusCode == 401 && !api.config.auth.resolved()) {
// Attempt to resolve username and password and try again
const newSpec = await resolveUsernameAndPassword(api.config.serverName, connSpec);
if (newSpec) {
// We were able to resolve credentials, so try again
api.setConnSpec(api.config.serverName, newSpec);
return api
.serverInfo(false)
.then((data) => data.result.content.namespaces)
.catch(async (err) => {
handleError(err, `Failed to fetch namespace list from server at ${connDisplayString}.`);
return undefined;
});
} else {
handleError(
`Unauthenticated access rejected by '${api.serverId}'.`,
`Failed to fetch namespace list from server at ${connDisplayString}.`
);
return undefined;
}
}
handleError(error, `Failed to fetch namespace list from server at ${connDisplayString}.`);
return undefined;
});
// Clear the panel entry created by the connection
panel.text = "";
panel.tooltip = "";
// Handle serverInfo failure
if (!allNamespaces) {
return;
}
// Handle serverInfo having returned no namespaces
if (!allNamespaces.length) {
vscode.window.showErrorMessage(`No namespace list returned by server at ${connDisplayString}`, "Dismiss");
return;
}
// Get user's choice of namespace
const namespace = await vscode.window.showQuickPick(allNamespaces, {
title: `Pick a namespace on server '${serverName}' (${connDisplayString})`,
});
if (!namespace) {
return;
}
// Update folder's config object
const config = vscode.workspace.getConfiguration("objectscript", folder);
if (vscode.workspace.workspaceFile && items.length == 1) {
// Ask the user if they want to enable the connection at the workspace or folder level.
// Only allow this when there is a single client-side folder in the workspace because
// the server may be configured at the workspace folder level.
const answer = await vscode.window.showQuickPick(
[
{ label: `Workspace Folder ${folder.name}`, detail: displayableUri(folder.uri) },
{ label: "Workspace File", detail: displayableUri(vscode.workspace.workspaceFile) },
],
{ title: "Store the server connection at the workspace or folder level?" }
);
if (!answer) return;
if (answer.label == "Workspace File") {
// Enable the connection at the workspace level
const conn: any = config.inspect("conn").workspaceValue;
await config.update(
"conn",
{ ...conn, server: serverName, ns: namespace, active: true },
vscode.ConfigurationTarget.Workspace
);
return;
}
}
// Enable the connection at the workspace folder level
const conn: any = config.inspect("conn").workspaceFolderValue;
await config.update(
"conn",
{ ...conn, server: serverName, ns: namespace, active: true },
vscode.ConfigurationTarget.WorkspaceFolder
);
}