Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 140 additions & 89 deletions package-lock.json

Large diffs are not rendered by default.

47 changes: 23 additions & 24 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -867,25 +867,24 @@
"ws": "^7.2.3"
},
"devDependencies": {
"@types/chai": "^4.2.9",
"@types/analytics-node": "^3.1.4",
"@types/chai": "^4.2.14",
"@types/chai-fs": "^2.0.2",
"@types/chai-json-schema": "^1.4.5",
"@types/classnames": "^2.2.10",
"@types/chai-json-schema": "^1.4.6",
"@types/classnames": "^2.2.11",
"@types/debug": "^4.1.5",
"@types/enzyme": "^3.10.7",
"@types/glob": "^7.1.1",
"@types/jest": "^26.0.14",
"@types/keytar": "4.4.2",
"@types/mocha": "^8.0.3",
"@types/node": "^14.11.5",
"@types/react": "^16.9.25",
"@types/react-dom": "^16.9.5",
"@types/redux": "^3.6.0",
"@types/sinon": "^9.0.1",
"@types/enzyme": "^3.10.8",
"@types/glob": "^7.1.3",
"@types/jest": "^26.0.20",
"@types/mocha": "^8.2.0",
"@types/node": "^14.14.20",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/sinon": "^9.0.10",
"@types/vscode": "^1.49.0",
"@types/ws": "^7.2.4",
"@typescript-eslint/eslint-plugin": "^4.12.0",
"@typescript-eslint/parser": "^4.12.0",
"@types/ws": "^7.4.0",
"@typescript-eslint/eslint-plugin": "^4.13.0",
"@typescript-eslint/parser": "^4.13.0",
"autoprefixer": "^9.7.5",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
Expand All @@ -909,24 +908,24 @@
"meow": "^6.0.1",
"mkdirp": "^1.0.4",
"mocha": "^8.2.1",
"mocha-junit-reporter": "^1.23.3",
"mocha-junit-reporter": "^2.0.0",
"mocha-multi": "^1.1.3",
"mongodb-ace-autocompleter": "^0.4.13",
"mongodb-ace-autocompleter": "^0.4.14",
"mongodb-runner": "^4.8.0",
"node-loader": "^0.6.0",
"npm-run-all": "^4.1.5",
"ora": "^4.0.3",
"postcss-loader": "^3.0.0",
"pre-commit": "^1.2.2",
"sinon": "^9.0.0",
"sinon": "^9.2.3",
"sinon-chai": "^3.5.0",
"style-loader": "^1.1.3",
"ts-jest": "^26.4.1",
"ts-loader": "^6.2.2",
"ts-node": "^8.6.2",
"ts-jest": "^26.4.4",
"ts-loader": "^8.0.14",
"ts-node": "^9.1.1",
"typescript": "^4.1.3",
"vsce": "^1.81.1",
"vscode-test": "^1.3.0",
"vsce": "^1.83.0",
"vscode-test": "^1.4.1",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
"xvfb-maybe": "^0.2.1"
Expand Down
11 changes: 5 additions & 6 deletions src/connectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { StatusView } from './views';
import { EventEmitter } from 'events';
import { StorageController, StorageVariables } from './storage';
import { SavedConnection, StorageScope } from './storage/storageController';
import TelemetryController from './telemetry/telemetryController';
import TelemetryService from './telemetry/telemetryService';
import { ext } from './extensionConstants';
import { CONNECTION_STATUS } from './views/webview-app/extension-app-message-constants';
import SSH_TUNNEL_TYPES from './views/webview-app/connection-model/constants/ssh-tunnel-types';
Expand Down Expand Up @@ -72,19 +72,19 @@ export default class ConnectionController {

private _statusView: StatusView;
private _storageController: StorageController;
private _telemetryController: TelemetryController;
private _telemetryService: TelemetryService;

// Used by other parts of the extension that respond to changes in the connections.
private eventEmitter: EventEmitter = new EventEmitter();

constructor(
_statusView: StatusView,
storageController: StorageController,
telemetryController: TelemetryController
telemetryService: TelemetryService
) {
this._statusView = _statusView;
this._storageController = storageController;
this._telemetryController = telemetryController;
this._telemetryService = telemetryService;
}

_loadSavedConnection = async (
Expand Down Expand Up @@ -250,8 +250,7 @@ export default class ConnectionController {
newDataService: DataServiceType,
connectionType: ConnectionTypes
): void {
// Send metrics to Segment
this._telemetryController.trackNewConnection(
this._telemetryService.trackNewConnection(
newDataService,
connectionType
);
Expand Down
52 changes: 45 additions & 7 deletions src/editors/editDocumentCodeLensProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as vscode from 'vscode';
import EXTENSION_COMMANDS from '../commands';
import type { OutputItem, ResultCodeLensInfo } from '../utils/types';
import ConnectionController from '../connectionController';
import { DocumentSource } from '../telemetry/telemetryService';

export default class EditDocumentCodeLensProvider
implements vscode.CodeLensProvider {
Expand All @@ -22,20 +23,38 @@ implements vscode.CodeLensProvider {
});
}

updateCodeLensesPosition(playgroundResult: OutputItem): void {
updateCodeLensesForPlayground(playgroundResult: OutputItem) {
const source = DocumentSource.DOCUMENT_SOURCE_PLAYGROUND;

if (!playgroundResult || !playgroundResult.content) {
this._codeLensesInfo = [];

return;
}

const { content, namespace, type } = playgroundResult;
const connectionId = this._connectionController.getActiveConnectionId();
const codeLensesInfo: ResultCodeLensInfo[] = [];
const data = { content, namespace, source };

// Show code lenses only for the list of documents or a single document
// that are returned by the find() method.
if (type === 'Cursor' && Array.isArray(content)) {
if (type === 'Cursor') {
this._updateCodeLensesForCursor(data);
} else if (type === 'Document') {
this._updateCodeLensesForDocument(data);
}
}

_updateCodeLensesForCursor(data: {
content: any,
namespace: string | null,
source: string
}) {
const codeLensesInfo: ResultCodeLensInfo[] = [];

if (Array.isArray(data.content)) {
const connectionId = this._connectionController.getActiveConnectionId();
const { content, namespace, source } = data;

// When the playground result is the collection,
// show the first code lense after [{.
let line = 2;
Expand All @@ -45,23 +64,42 @@ implements vscode.CodeLensProvider {
// to be able to save the editable document.
if (item !== null && item._id && namespace) {
codeLensesInfo.push({
line,
documentId: item._id,
source,
line,
namespace,
connectionId
});

// To calculate the position of the next open curly bracket,
// we stringify the object and use a regular expression
// so we can count the number of lines.
line += JSON.stringify(item, null, 2).split(/\r\n|\r|\n/).length;
}
});
} else if (type === 'Document' && content._id && namespace) {
}

this._codeLensesInfo = codeLensesInfo;
this._onDidChangeCodeLenses.fire();
}

_updateCodeLensesForDocument(data: {
content: any,
namespace: string | null,
source: string
}): void {
const codeLensesInfo: ResultCodeLensInfo[] = [];
const { content, namespace, source } = data;

if (content._id && namespace) {
const connectionId = this._connectionController.getActiveConnectionId();

// When the playground result is the single document,
// show the single code lense after {.
codeLensesInfo.push({
line: 1,
documentId: content._id,
source,
line: 1,
namespace,
connectionId
});
Expand Down
18 changes: 11 additions & 7 deletions src/editors/editorsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ import PlaygroundController from './playgroundController';
import DocumentIdStore from './documentIdStore';
import MongoDBDocumentService, {
DOCUMENT_ID_URI_IDENTIFIER,
DOCUMENT_SOURCE_URI_IDENTIFIER,
VIEW_DOCUMENT_SCHEME
} from './mongoDBDocumentService';
import { MemoryFileSystemProvider } from './memoryFileSystemProvider';
import TelemetryController from '../telemetry/telemetryController';
import TelemetryService from '../telemetry/telemetryService';
import PlaygroundResultProvider, {
PLAYGROUND_RESULT_SCHEME
} from './playgroundResultProvider';
Expand All @@ -42,7 +43,7 @@ export default class EditorsController {
_memoryFileSystemProvider: MemoryFileSystemProvider;
_documentIdStore: DocumentIdStore;
_mongoDBDocumentService: MongoDBDocumentService;
_telemetryController: TelemetryController;
_telemetryService: TelemetryService;
_playgroundResultViewProvider: PlaygroundResultProvider;
_activeConnectionCodeLensProvider: ActiveConnectionCodeLensProvider;
_partialExecutionCodeLensProvider: PartialExecutionCodeLensProvider;
Expand All @@ -52,7 +53,7 @@ export default class EditorsController {
connectionController: ConnectionController,
playgroundController: PlaygroundController,
statusView: StatusView,
telemetryController: TelemetryController,
telemetryService: TelemetryService,
playgroundResultViewProvider: PlaygroundResultProvider,
activeConnectionCodeLensProvider: ActiveConnectionCodeLensProvider,
partialExecutionCodeLensProvider: PartialExecutionCodeLensProvider
Expand All @@ -63,15 +64,15 @@ export default class EditorsController {
this._playgroundController = playgroundController;
this._context = context;
this._statusView = statusView;
this._telemetryController = telemetryController;
this._telemetryService = telemetryService;
this._memoryFileSystemProvider = new MemoryFileSystemProvider();
this._documentIdStore = new DocumentIdStore();
this._mongoDBDocumentService = new MongoDBDocumentService(
this._context,
this._documentIdStore,
this._connectionController,
this._statusView,
this._telemetryController
this._telemetryService
);
this._collectionViewProvider = new CollectionDocumentsProvider(
connectionController,
Expand Down Expand Up @@ -123,8 +124,9 @@ export default class EditorsController {
const connectionIdUriQuery = `${CONNECTION_ID_URI_IDENTIFIER}=${activeConnectionId}`;
const documentIdReference = this._documentIdStore.add(data.documentId);
const documentIdUriQuery = `${DOCUMENT_ID_URI_IDENTIFIER}=${documentIdReference}`;
const documentSourceUriQuery = `${DOCUMENT_SOURCE_URI_IDENTIFIER}=${data.source}`;
const uri: vscode.Uri = vscode.Uri.parse(fileName).with({
query: `?${namespaceUriQuery}&${connectionIdUriQuery}&${documentIdUriQuery}`
query: `?${namespaceUriQuery}&${connectionIdUriQuery}&${documentIdUriQuery}&${documentSourceUriQuery}`
});
const document = await vscode.workspace.openTextDocument(uri);

Expand Down Expand Up @@ -154,6 +156,7 @@ export default class EditorsController {
const connectionId = uriParams.get(CONNECTION_ID_URI_IDENTIFIER);
const documentIdReference = uriParams.get(DOCUMENT_ID_URI_IDENTIFIER) || '';
const documentId = this._documentIdStore.get(documentIdReference);
const source = uriParams.get(DOCUMENT_SOURCE_URI_IDENTIFIER) || '';

// If not MongoDB document save to disk instead of MongoDB.
if (
Expand All @@ -176,7 +179,8 @@ export default class EditorsController {
namespace,
connectionId,
documentId,
newDocument
newDocument,
source
});

// Save document changes to active editor.
Expand Down
28 changes: 18 additions & 10 deletions src/editors/mongoDBDocumentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { EJSON } from 'bson';
import DocumentIdStore from './documentIdStore';
import ConnectionController from '../connectionController';
import { StatusView } from '../views';
import TelemetryController from '../telemetry/telemetryController';
import TelemetryService, { DocumentSource } from '../telemetry/telemetryService';
import { createLogger } from '../logging';
import util from 'util';
import type { ResultCodeLensInfo } from '../utils/types';

export const DOCUMENT_ID_URI_IDENTIFIER = 'documentId';

export const DOCUMENT_SOURCE_URI_IDENTIFIER = 'source';

export const VIEW_DOCUMENT_SCHEME = 'VIEW_DOCUMENT_SCHEME';

const log = createLogger('document controller');
Expand All @@ -19,20 +21,20 @@ export default class MongoDBDocumentService {
_documentIdStore: DocumentIdStore;
_connectionController: ConnectionController;
_statusView: StatusView;
_telemetryController: TelemetryController;
_telemetryService: TelemetryService;

constructor(
context: vscode.ExtensionContext,
documentIdStore: DocumentIdStore,
connectionController: ConnectionController,
statusView: StatusView,
telemetryController: TelemetryController
telemetryService: TelemetryService
) {
this._context = context;
this._documentIdStore = documentIdStore;
this._connectionController = connectionController;
this._statusView = statusView;
this._telemetryController = telemetryController;
this._telemetryService = telemetryService;
}

_fetchDocumentFailed(message: string): void {
Expand All @@ -44,8 +46,9 @@ export default class MongoDBDocumentService {
_saveDocumentFailed(message: string): void {
const errorMessage = `Unable to save document: ${message}`;

// Send a telemetry event that saving the document failed.
this._telemetryController.trackDocumentUpdated('treeview', false);
this._telemetryService.trackDocumentUpdated(
DocumentSource.DOCUMENT_SOURCE_TREEVIEW, false
);

throw new Error(errorMessage);
}
Expand All @@ -55,10 +58,11 @@ export default class MongoDBDocumentService {
namespace: string;
connectionId: string;
newDocument: EJSON.SerializableTypes;
source: string;
}): Promise<void> {
log.info('replace document in MongoDB', data);

const { documentId, namespace, connectionId, newDocument } = data;
const { documentId, namespace, connectionId, newDocument, source } = data;
const activeConnectionId = this._connectionController.getActiveConnectionId();
const connectionName = this._connectionController.getSavedConnectionName(
connectionId
Expand Down Expand Up @@ -97,11 +101,13 @@ export default class MongoDBDocumentService {
);

this._statusView.hideMessage();
this._telemetryController.trackDocumentUpdated('treeview', true);
this._telemetryService.trackDocumentUpdated(source, true);
} catch (error) {
const printableError = error as { message: string };

this._statusView.hideMessage();

return this._saveDocumentFailed(error.message);
return this._saveDocumentFailed(printableError.message);
}
}

Expand Down Expand Up @@ -155,9 +161,11 @@ export default class MongoDBDocumentService {
EJSON.stringify(documents[0])
) as EJSON.SerializableTypes;
} catch (error) {
const printableError = error as { message: string };

this._statusView.hideMessage();

return this._fetchDocumentFailed(error.message);
return this._fetchDocumentFailed(printableError.message);
}
}
}
Loading