Skip to content

Commit 9cd5c36

Browse files
authored
fix: Use connected connection model options VSCODE-234 (#255)
1 parent 34eca98 commit 9cd5c36

14 files changed

+356
-116
lines changed

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/editors/playgroundController.ts

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,29 @@ import playgroundSearchTemplate from '../templates/playgroundSearchTemplate';
1919
import playgroundTemplate from '../templates/playgroundTemplate';
2020
import { StatusView } from '../views';
2121
import TelemetryService from '../telemetry/telemetryService';
22+
import { ConnectionOptions } from '../types/connectionOptionsType';
2223

2324
const log = createLogger('playground controller');
2425

26+
const getSSLFilePathsFromConnectionModel = (
27+
connectionModelDriverOptions: ConnectionOptions
28+
): {
29+
sslCA?: string | string[];
30+
sslCert?: string | string[];
31+
sslKey?: string | string[];
32+
} => {
33+
const sslFilePaths = {};
34+
['sslCA', 'sslCert', 'sslKey'].forEach((key) => {
35+
if (connectionModelDriverOptions[key]) {
36+
sslFilePaths[key] = connectionModelDriverOptions[key] as (
37+
string | string[]
38+
);
39+
}
40+
});
41+
42+
return sslFilePaths;
43+
};
44+
2545
/**
2646
* This controller manages playground.
2747
*/
@@ -36,7 +56,6 @@ export default class PlaygroundController {
3656
_partialExecutionCodeLensProvider: PartialExecutionCodeLensProvider;
3757
_outputChannel: OutputChannel;
3858
_connectionString?: string;
39-
_connectionOptions?: EJSON.SerializableTypes;
4059
_selectedText?: string;
4160
_codeToEvaluate = '';
4261
_isPartialRun: boolean;
@@ -135,11 +154,11 @@ export default class PlaygroundController {
135154
selectedText.length > 0 &&
136155
selectedText.length >= lastSelectedLine.length
137156
) {
138-
this._partialExecutionCodeLensProvider?.refresh(
157+
this._partialExecutionCodeLensProvider.refresh(
139158
new vscode.Range(firstLine, 0, firstLine, 0)
140159
);
141160
} else {
142-
this._partialExecutionCodeLensProvider?.refresh();
161+
this._partialExecutionCodeLensProvider.refresh();
143162
}
144163
}
145164

@@ -148,26 +167,40 @@ export default class PlaygroundController {
148167
}
149168

150169
async _connectToServiceProvider(): Promise<void> {
151-
const model = this._connectionController
152-
.getActiveConnectionModel()
153-
?.getAttributes({ derived: true });
154-
155-
this._connectionString = undefined;
156-
this._connectionOptions = undefined;
157-
158170
await this._languageServerController.disconnectFromServiceProvider();
159171

160-
if (model && model.driverUrlWithSsh) {
161-
this._connectionString = model.driverUrlWithSsh;
162-
this._connectionOptions = model.driverOptions ? model.driverOptions : {};
172+
const dataService = this._connectionController.getActiveDataService();
173+
const connectionId = this._connectionController.getActiveConnectionId();
174+
const connectionModel = this._connectionController
175+
.getActiveConnectionModel();
176+
if (!dataService || !connectionId || !connectionModel) {
177+
this._activeConnectionCodeLensProvider.refresh();
163178

164-
await this._languageServerController.connectToServiceProvider({
165-
connectionString: this._connectionString,
166-
connectionOptions: this._connectionOptions
167-
});
179+
return;
168180
}
169181

170-
this._activeConnectionCodeLensProvider?.refresh();
182+
const connectionDetails = dataService.getConnectionOptions();
183+
const connectionString = connectionDetails.url;
184+
// We pass file paths to the language server since it doesn't
185+
// handle being passsed buffers well.
186+
// With driver version 4.0 we should be able to remove any use
187+
// of buffers and just pass file paths.
188+
const sslOptionsFilePaths = getSSLFilePathsFromConnectionModel(
189+
connectionModel.getAttributes({ derived: true }).driverOptions
190+
);
191+
192+
const connectionOptions: ConnectionOptions = {
193+
...connectionDetails.options,
194+
...sslOptionsFilePaths
195+
};
196+
197+
await this._languageServerController.connectToServiceProvider({
198+
connectionId,
199+
connectionString,
200+
connectionOptions
201+
});
202+
203+
this._activeConnectionCodeLensProvider.refresh();
171204
}
172205

173206
async _createPlaygroundFileWithContent(
@@ -241,12 +274,21 @@ export default class PlaygroundController {
241274
}
242275

243276
async _evaluate(codeToEvaluate: string): Promise<ShellExecuteAllResult> {
277+
const connectionId = this._connectionController.getActiveConnectionId();
278+
279+
if (!connectionId) {
280+
return Promise.reject(
281+
new Error('Please connect to a database before running a playground.')
282+
);
283+
}
284+
244285
this._statusView.showMessage('Getting results...');
245286

246287
// Send a request to the language server to execute scripts from a playground.
247-
const result: ShellExecuteAllResult = await this._languageServerController.executeAll(
248-
codeToEvaluate
249-
);
288+
const result: ShellExecuteAllResult = await this._languageServerController.executeAll({
289+
codeToEvaluate,
290+
connectionId
291+
});
250292

251293
this._statusView.hideMessage();
252294
this._telemetryService.trackPlaygroundCodeExecuted(
@@ -267,7 +309,7 @@ export default class PlaygroundController {
267309
}
268310

269311
_evaluateWithCancelModal(): Promise<ShellExecuteAllResult> {
270-
if (!this._connectionString) {
312+
if (!this._connectionController.isCurrentlyConnected()) {
271313
return Promise.reject(
272314
new Error('Please connect to a database before running a playground.')
273315
);
@@ -372,7 +414,7 @@ export default class PlaygroundController {
372414
.getConfiguration('mdb')
373415
.get('confirmRunAll');
374416

375-
if (!this._connectionString) {
417+
if (!this._connectionController.isCurrentlyConnected()) {
376418
vscode.window.showErrorMessage(
377419
'Please connect to a database before running a playground.'
378420
);

src/language/languageServerController.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as vscode from 'vscode';
22
import * as path from 'path';
3-
import { EJSON } from 'bson';
43
import {
54
LanguageClient,
65
LanguageClientOptions,
@@ -15,6 +14,7 @@ import { createLogger } from '../logging';
1514
import { PlaygroundExecuteParameters } from '../types/playgroundType';
1615
import { ServerCommands } from './serverCommands';
1716
import type { ShellExecuteAllResult } from '../types/playgroundType';
17+
import { ConnectionOptions } from '../types/connectionOptionsType';
1818

1919
const log = createLogger('LanguageServerController');
2020
let socket: WebSocket | null;
@@ -123,11 +123,11 @@ export default class LanguageServerController {
123123
this._context.extensionPath
124124
);
125125

126-
this._client.onNotification('showInformationMessage', (messsage) => {
126+
this._client.onNotification(ServerCommands.SHOW_INFO_MESSAGE, (messsage) => {
127127
vscode.window.showInformationMessage(messsage);
128128
});
129129

130-
this._client.onNotification('showErrorMessage', (messsage) => {
130+
this._client.onNotification(ServerCommands.SHOW_ERROR_MESSAGE, (messsage) => {
131131
vscode.window.showErrorMessage(messsage);
132132
});
133133
}
@@ -141,7 +141,9 @@ export default class LanguageServerController {
141141
this._client.stop();
142142
}
143143

144-
async executeAll(codeToEvaluate: string): Promise<ShellExecuteAllResult> {
144+
async executeAll(
145+
playgroundExecuteParameters: PlaygroundExecuteParameters
146+
): Promise<ShellExecuteAllResult> {
145147
this._isExecutingInProgress = true;
146148

147149
await this._client.onReady();
@@ -154,9 +156,7 @@ export default class LanguageServerController {
154156
// and return results to the playground controller when ready
155157
const result: ShellExecuteAllResult = await this._client.sendRequest(
156158
ServerCommands.EXECUTE_ALL_FROM_PLAYGROUND,
157-
{
158-
codeToEvaluate
159-
} as PlaygroundExecuteParameters,
159+
playgroundExecuteParameters,
160160
this._source.token
161161
);
162162

@@ -166,8 +166,9 @@ export default class LanguageServerController {
166166
}
167167

168168
async connectToServiceProvider(params: {
169-
connectionString?: string;
170-
connectionOptions?: EJSON.SerializableTypes;
169+
connectionId: string,
170+
connectionString: string;
171+
connectionOptions: ConnectionOptions
171172
}): Promise<void> {
172173
await this._client.onReady();
173174
await this._client.sendRequest(

src/language/mongoDBService.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type ShellCompletionItem = {
2020

2121
export default class MongoDBService {
2222
_connection: Connection;
23+
_connectionId?: string;
2324
_connectionString?: string;
2425
_connectionOptions?: ConnectionOptions;
2526
_cachedDatabases: CompletionItem[] | [] = [];
@@ -92,16 +93,18 @@ export default class MongoDBService {
9293
}
9394

9495
async connectToServiceProvider(params: {
95-
connectionString?: string;
96-
connectionOptions?: ConnectionOptions;
96+
connectionId: string;
97+
connectionString: string;
98+
connectionOptions: ConnectionOptions;
9799
}): Promise<boolean> {
98100
this._clearCurrentSessionConnection();
99101
this._clearCurrentSessionFields();
100102
this._clearCurrentSessionDatabases();
101103
this._clearCurrentSessionCollections();
102104

105+
this._connectionId = params.connectionId;
103106
this._connectionString = params.connectionString;
104-
this._connectionOptions = params.connectionOptions || {};
107+
this._connectionOptions = params.connectionOptions;
105108

106109
if (!this._connectionString) {
107110
return Promise.resolve(false);
@@ -153,6 +156,15 @@ export default class MongoDBService {
153156
return resolve(undefined);
154157
}
155158

159+
if (this._connectionId !== executionParameters.connectionId) {
160+
this._connection.sendNotification(
161+
ServerCommands.SHOW_ERROR_MESSAGE,
162+
'The playground\'s active connection does not match the extension\'s active connection. Please reconnect and try again.'
163+
);
164+
165+
return resolve(undefined);
166+
}
167+
156168
try {
157169
// Use Node worker threads to run a playground to be able to cancel infinite loops.
158170
//
@@ -192,7 +204,10 @@ export default class MongoDBService {
192204
this._connection.console.log(
193205
`MONGOSH execute all error: ${util.inspect(error)}`
194206
);
195-
this._connection.sendNotification('showErrorMessage', printableError.message);
207+
this._connection.sendNotification(
208+
ServerCommands.SHOW_ERROR_MESSAGE,
209+
printableError.message
210+
);
196211
}
197212

198213
worker.terminate().then(() => {
@@ -204,7 +219,7 @@ export default class MongoDBService {
204219
token.onCancellationRequested(async () => {
205220
this._connection.console.log('PLAYGROUND cancellation requested');
206221
this._connection.sendNotification(
207-
'showInformationMessage',
222+
ServerCommands.SHOW_INFO_MESSAGE,
208223
'The running playground operation was canceled.'
209224
);
210225

src/language/serverCommands.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ export enum ServerCommands {
66
GET_FIELDS_FROM_SCHEMA = 'GET_FIELDS_FROM_SCHEMA',
77
GET_LIST_DATABASES = 'GET_LIST_DATABASES',
88
GET_LIST_COLLECTIONS = 'GET_LIST_COLLECTIONS',
9-
SET_EXTENSION_PATH = 'SET_EXTENSION_PATH'
9+
SET_EXTENSION_PATH = 'SET_EXTENSION_PATH',
10+
SHOW_ERROR_MESSAGE = 'SHOW_ERROR_MESSAGE',
11+
SHOW_INFO_MESSAGE = 'SHOW_INFO_MESSAGE'
1012
}
1113

1214
export type PlaygroundRunParameters = {

0 commit comments

Comments
 (0)