diff --git a/package.json b/package.json index 074b090370..31ab8560d0 100644 --- a/package.json +++ b/package.json @@ -191,8 +191,9 @@ } }, "scripts": { - "compile": "node ./node_modules/vscode/bin/compile -p ./", + "compile": "npm run lint && node ./node_modules/vscode/bin/compile -p ./", "compile_watch": "node ./node_modules/vscode/bin/compile -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install" + "postinstall": "node ./node_modules/vscode/bin/install", + "lint": "tslint src/**/*.ts" } } diff --git a/src/controllers/connectionManager.ts b/src/controllers/connectionManager.ts index a7acdbe0e9..8906728f6b 100644 --- a/src/controllers/connectionManager.ts +++ b/src/controllers/connectionManager.ts @@ -2,23 +2,20 @@ import vscode = require('vscode'); import Constants = require('../models/constants'); import Utils = require('../models/utils'); -import { RecentConnections } from '../models/recentConnections'; import Interfaces = require('../models/interfaces'); -import { ConnectionUI } from '../views/connectionUI' +import { ConnectionUI } from '../views/connectionUI'; import StatusView from '../views/statusView'; -var mssql = require('mssql'); +const mssql = require('mssql'); -export default class ConnectionManager -{ +export default class ConnectionManager { private _context: vscode.ExtensionContext; private _statusView: StatusView; private _connection; private _connectionCreds: Interfaces.IConnectionCredentials; private _connectionUI: ConnectionUI; - constructor(context: vscode.ExtensionContext, statusView: StatusView) - { + constructor(context: vscode.ExtensionContext, statusView: StatusView) { this._context = context; this._statusView = statusView; this._connectionUI = new ConnectionUI(); @@ -32,51 +29,44 @@ export default class ConnectionManager return this._connection; } - private get connectionUI() { + private get connectionUI(): ConnectionUI { return this._connectionUI; } - private get statusView() { + private get statusView(): StatusView { return this._statusView; } - get isConnected() { + get isConnected(): boolean { return this._connection && this._connection.connected; } // close active connection, if any - public onDisconnect() - { - return new Promise((resolve, reject) => - { - if(this.isConnected) { + public onDisconnect(): Promise { + return new Promise((resolve, reject) => { + if (this.isConnected) { this._connection.close(); } - this._connection = null; - this._connectionCreds = null; + this._connection = undefined; + this._connectionCreds = undefined; this.statusView.notConnected(); resolve(true); }); } // let users pick from a picklist of connections - public onNewConnection() - { + public onNewConnection(): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { // show connection picklist self.connectionUI.showConnections() - .then(function(connectionCreds) - { + .then(function(connectionCreds): void { // close active connection - self.onDisconnect().then(function() - { + self.onDisconnect().then(function(): void { // connect to the server/database self.connect(connectionCreds) - .then(function() - { + .then(function(): void { resolve(true); }); }); @@ -85,25 +75,23 @@ export default class ConnectionManager } // create a new connection with the connectionCreds provided - public connect(connectionCreds: Interfaces.IConnectionCredentials) - { + public connect(connectionCreds: Interfaces.IConnectionCredentials): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { const connection = new mssql.Connection(connectionCreds); self.statusView.connecting(connectionCreds); connection.connect() - .then(function() { + .then(function(): void { self._connectionCreds = connectionCreds; self._connection = connection; self.statusView.connectSuccess(connectionCreds); resolve(); }) - .catch(function(err) { + .catch(function(err): void { self.statusView.connectError(connectionCreds, err); Utils.showErrorMsg(Constants.gMsgError + err); reject(err); }); }); } -} \ No newline at end of file +} diff --git a/src/controllers/controller.ts b/src/controllers/controller.ts index 46c626d708..103cef460c 100644 --- a/src/controllers/controller.ts +++ b/src/controllers/controller.ts @@ -16,33 +16,28 @@ export default class MainController implements vscode.Disposable { private _statusview: StatusView; private _connectionMgr: ConnectionManager; - constructor(context: vscode.ExtensionContext) - { + constructor(context: vscode.ExtensionContext) { this._context = context; } - private registerCommand(command: string) - { + private registerCommand(command: string): void { const self = this; this._context.subscriptions.push(vscode.commands.registerCommand(command, () => { self._event.emit(command); })); } - dispose() - { + dispose(): void { this.deactivate(); } - public deactivate() - { + public deactivate(): void { Utils.logDebug(Constants.gExtensionDeactivated); this.onDisconnect(); this._statusview.dispose(); } - public activate() - { + public activate(): void { const self = this; // register VS Code commands @@ -68,29 +63,23 @@ export default class MainController implements vscode.Disposable { } // Close active connection, if any - private onDisconnect() - { + private onDisconnect(): Promise { return this._connectionMgr.onDisconnect(); } // Let users pick from a list of connections - public onNewConnection() - { + public onNewConnection(): Promise { return this._connectionMgr.onNewConnection(); } // get the T-SQL query from the editor, run it and show output - public onRunQuery() - { - if(!Utils.isEditingSqlFile()) - { + public onRunQuery(): void { + if (!Utils.isEditingSqlFile()) { Utils.showWarnMsg(Constants.gMsgOpenSqlFile); - } - else - { + } else { const self = this; let qr = new QueryRunner(self._connectionMgr, self._statusview, self._outputContentProvider); qr.onRunQuery(); } } -} \ No newline at end of file +} diff --git a/src/controllers/localWebService.ts b/src/controllers/localWebService.ts index e5f72ce1f1..ad31ca5084 100644 --- a/src/controllers/localWebService.ts +++ b/src/controllers/localWebService.ts @@ -1,22 +1,18 @@ 'use strict'; -import vscode = require('vscode'); import path = require('path'); -import fs = require('fs'); import Utils = require('../models/utils'); import Constants = require('../models/constants'); import Interfaces = require('../models/interfaces'); -var express = require('express'); +const express = require('express'); -export default class LocalWebService -{ +export default class LocalWebService { private app = express(); static _servicePort: string; static _vscodeExtensionPath: string; - static _htmlContentLocation = "src/views/htmlcontent"; + static _htmlContentLocation = 'src/views/htmlcontent'; static _staticContentPath: string; - constructor(extensionPath: string) - { + constructor(extensionPath: string) { // add static content for express web server to serve LocalWebService._vscodeExtensionPath = extensionPath; LocalWebService._staticContentPath = path.join(extensionPath, LocalWebService._htmlContentLocation); @@ -37,20 +33,18 @@ export default class LocalWebService return LocalWebService._vscodeExtensionPath; } - static getEndpointUri(type: Interfaces.ContentType): string - { - return this.serviceUrl + "/" + Interfaces.ContentTypes[type]; + static getEndpointUri(type: Interfaces.ContentType): string { + return this.serviceUrl + '/' + Interfaces.ContentTypes[type]; } - addHandler(type: Interfaces.ContentType, handler: (req, res) => void) { - let segment = "/" + Interfaces.ContentTypes[type]; + addHandler(type: Interfaces.ContentType, handler: (req, res) => void): void { + let segment = '/' + Interfaces.ContentTypes[type]; this.app.get(segment, handler); } - start() - { + start(): void { const port = this.app.listen(0).address().port; // 0 = listen on a random port Utils.logDebug(Constants.gMsgLocalWebserviceStarted + port); LocalWebService._servicePort = port.toString(); } -} \ No newline at end of file +} diff --git a/src/controllers/queryRunner.ts b/src/controllers/queryRunner.ts index d861d278a9..b41c7fed77 100644 --- a/src/controllers/queryRunner.ts +++ b/src/controllers/queryRunner.ts @@ -1,5 +1,4 @@ 'use strict'; -import * as events from 'events'; import vscode = require('vscode'); import Constants = require('../models/constants'); @@ -9,11 +8,10 @@ import Interfaces = require('../models/interfaces'); import ConnectionManager from './connectionManager'; import StatusView from '../views/statusView'; -var async = require("async"); -var mssql = require('mssql'); +const async = require('async'); +const mssql = require('mssql'); -export default class QueryRunner -{ +export default class QueryRunner { private _connectionMgr: ConnectionManager; private _outputProvider: SqlOutputContentProvider; private _errorEncountered = false; @@ -21,8 +19,7 @@ export default class QueryRunner private _resultsets: Interfaces.ISqlResultset[] = []; private _statusView: StatusView; - constructor(connectionMgr: ConnectionManager, statusView: StatusView, outputProvider: SqlOutputContentProvider) - { + constructor(connectionMgr: ConnectionManager, statusView: StatusView, outputProvider: SqlOutputContentProvider) { this._connectionMgr = connectionMgr; this._statusView = statusView; this._outputProvider = outputProvider; @@ -40,39 +37,33 @@ export default class QueryRunner return this._connectionMgr; } - private get statusView() { + private get statusView(): any { return this._statusView; } - private get outputProvider() { + private get outputProvider(): any { return this._outputProvider; } // get T-SQL text from the editor window, run it and show output - public onRunQuery() - { + public onRunQuery(): void { const self = this; - if(self.connectionManager.isConnected) - { + if (self.connectionManager.isConnected) { // already connected - run query - Utils.logDebug(Constants.gMsgRunQueryConnectionActive) + Utils.logDebug(Constants.gMsgRunQueryConnectionActive); self.runQuery(); - } - else if(self.connectionManager.connectionCredentials) - { + } else if (self.connectionManager.connectionCredentials) { // connected previously but not connected now - reconnect with saved connection info - Utils.logDebug(Constants.gMsgRunQueryConnectionDisconnected) + Utils.logDebug(Constants.gMsgRunQueryConnectionDisconnected); self.connectionManager.connect(self.connectionManager.connectionCredentials) - .then(function() { + .then(function(): void { self.runQuery(); }); - } - else - { + } else { // not connected - prompt for a new connection - Utils.logDebug(Constants.gMsgRunQueryNoConnection) + Utils.logDebug(Constants.gMsgRunQueryNoConnection); self.connectionManager.onNewConnection() - .then(function() { + .then(function(): void { self.runQuery(); }); } @@ -80,37 +71,31 @@ export default class QueryRunner // Helper to execute selected T-SQL text in the editor or the entire contents if no selection // Executes queries in batches separated by "GO;" - private runQuery() - { + private runQuery(): void { const self = this; // Good info on sync vs. async in node: http://book.mixu.net/node/ch7.html // http://www.sebastianseilund.com/nodejs-async-in-practice let sqlBatches = self.getSqlBatches(); - if(sqlBatches && sqlBatches.length > 0) - { + if (sqlBatches && sqlBatches.length > 0) { // called by async.js when all batches have finished executing - var done = function(err) - { + let done = function(err): void { // all batches executed Utils.logDebug(Constants.gMsgRunQueryAllBatchesExecuted); self.statusView.executedQuery(); - if(err) - { + if (err) { Utils.logDebug(Constants.gMsgRunQueryError + err.toString()); return; } self.outputProvider.updateContent(self.messages, self.resultSets); - } + }; // called by async.js for each sqlBatch - var iterator = function(sqlBatch, callback) - { + let iterator = function(sqlBatch, callback): void { self.executeBatch(sqlBatch, self.connectionManager.connection) - .then(function(resolution) - { + .then(function(resolution): void { Utils.logDebug(Constants.gMsgRunQueryAddBatchResultsets + sqlBatch); let recordsets = resolution.recordsets; let requestRowsAffected = resolution.requestRowsAffected; @@ -118,15 +103,14 @@ export default class QueryRunner callback(); // call 'callback' to indicate this iteration is done and to proceed to the next one }) - .catch(function(err) - { + .catch(function(err): void { self._errorEncountered = true; Utils.logDebug(Constants.gMsgRunQueryAddBatchError + sqlBatch); self.addError(err); callback(); // call 'callback' to indicate this iteration is done and to proceed to the next one }); - } + }; self._errorEncountered = false; self._messages = []; @@ -139,15 +123,13 @@ export default class QueryRunner } // Helper to execute T-SQL (selected text or the entire contents of the editor) - private executeBatch(sqlText, connection) - { - return new Promise((resolve, reject) => - { + private executeBatch(sqlText, connection): Promise { + return new Promise((resolve, reject) => { Utils.logDebug(Constants.gMsgRunQueryExecutingBatch + sqlText); const request = new mssql.Request(connection); request.multiple = true; // enable multiple recordsets - request.batch(sqlText, function(err, recordsets, rowsAffected) { - if(err) { + request.batch(sqlText, function(err, recordsets, rowsAffected): void { + if (err) { reject (err); } @@ -160,16 +142,12 @@ export default class QueryRunner // Simple "GO" parser // Looks at text in the active document and produces batches of T-SQL statements delimited by 'GO' // GO needs to be on a separate line by itself and may have an optional ';' after it - private getSqlBatches() - { + private getSqlBatches(): string[] { let editor = vscode.window.activeTextEditor; - let textInEditor = ""; - if(editor.selection.isEmpty) - { + let textInEditor = ''; + if (editor.selection.isEmpty) { textInEditor = editor.document.getText(); - } - else - { + } else { textInEditor = editor.document.getText(editor.selection); } @@ -184,20 +162,19 @@ export default class QueryRunner // /igm = ignore case, global, multi0line // start by assuming no "GO"s exist - let sqlBatches = []; + let sqlBatches: string[] = []; textInEditor = textInEditor.trim(); - if(textInEditor) { + if (textInEditor) { sqlBatches.push(textInEditor); } // Select all lines not containing "GO" on a line by itself let matches = textInEditor.split(/^\s*GO;*\s*$/igm); - if(matches && matches.length > 0) - { + if (matches && matches.length > 0) { // Found some "GO"s sqlBatches = matches.filter( (element) => { element.trim; - return element != ""; + return element !== ''; }); } @@ -205,100 +182,87 @@ export default class QueryRunner return sqlBatches; } - private addError(error: any) - { + private addError(error: any): void { const self = this; - if(!error) { + if (!error) { return; } - let errMsg = ""; - errMsg += error.number ? "Msg " + error.number + ", " : ""; - errMsg += error.class ? "Level " + error.class + ", " : ""; - errMsg += error.state ? "State " + error.state + ", " : ""; - errMsg += error.lineNumber ? "Line " + error.lineNumber : ""; - errMsg += " : " + error.message; + let errMsg = ''; + errMsg += error.number ? 'Msg ' + error.number + ', ' : ''; + errMsg += error.class ? 'Level ' + error.class + ', ' : ''; + errMsg += error.state ? 'State ' + error.state + ', ' : ''; + errMsg += error.lineNumber ? 'Line ' + error.lineNumber : ''; + errMsg += ' : ' + error.message; self.addMessage(errMsg); } - public addMessage(message: string) - { + public addMessage(message: string): void { const self = this; self._messages.push( { messageText: message.toString() }); } - private addResultsets(recordsets, requestRowsAffected) - { + private addResultsets(recordsets, requestRowsAffected): void { const self = this; - if(!recordsets || recordsets.length === 0) - { - if(requestRowsAffected) - { - self.addMessage( "(" + requestRowsAffected + Constants.gExecuteQueryRowsAffected + ")" ); - } - else - { + if (!recordsets || recordsets.length === 0) { + if (requestRowsAffected) { + self.addMessage( '(' + requestRowsAffected + Constants.gExecuteQueryRowsAffected + ')' ); + } else { self.addMessage(Constants.gExecuteQueryCommandCompleted); } return; } // process recordsets - for(let recordsetIndex in recordsets) - { - let currentRecordset = recordsets[recordsetIndex]; + for (let i = 0; i < recordsets.length; i++) { + let currentRecordset = recordsets[i]; let rowsAffected = self.getRowsAffected(currentRecordset); - self.addMessage( "(" + rowsAffected + Constants.gExecuteQueryRowsAffected + ")" ); + self.addMessage( '(' + rowsAffected + Constants.gExecuteQueryRowsAffected + ')' ); let columnMetadata = self.getColumnMetadata(currentRecordset); let rowsInResultset = self.getRowsInResultset(currentRecordset); - self._resultsets.push( { columns: columnMetadata, rows: rowsInResultset, executionPlanXml: "" } ); + self._resultsets.push( { columns: columnMetadata, rows: rowsInResultset, executionPlanXml: '' } ); } } // return rowsAffected for recordset - private getRowsAffected(recordset: any) - { + private getRowsAffected(recordset: any): any { let rowsAffected = 0; - if(recordset.rowsAffected) { + if (recordset.rowsAffected) { rowsAffected = recordset.rowsAffected; } - if(!rowsAffected) { + if (!rowsAffected) { rowsAffected = recordset.length; } return rowsAffected; } // return column metadata for recordset - private getColumnMetadata(recordset: any) - { + private getColumnMetadata(recordset: any): any[] { let columnMetadata = []; - for(let columnIndex in recordset.columns) - { - let columnName = recordset.columns[columnIndex].name; - if(!columnName) { - columnName = ""; + for (let i = 0; i < recordset.columns.length; i++) { + let columnName = recordset.columns[i].name; + if (!columnName) { + columnName = ''; } let columnMetadataRender = { name: columnName, label: columnName, - cell: "string" // format all columns as string for display in backgrid - } + cell: 'string' // format all columns as string for display in backgrid + }; columnMetadata.push(columnMetadataRender); } return columnMetadata; } // return column metadata for recordset - private getRowsInResultset(recordset: any) - { + private getRowsInResultset(recordset: any): any[] { const self = this; let rowsInResultset = []; - for(let row of recordset) - { + for (let row of recordset) { self.formatRowData(row); rowsInResultset.push(row); } @@ -306,27 +270,20 @@ export default class QueryRunner } // convert data in row to string values that can be displayed - private formatRowData(row: any) - { - for (let col in row) - { - let value = row[col]; - if (value instanceof Date) - { - row[col] = value.toISOString(); - } - else if ((value instanceof Buffer) || (value instanceof Object)) - { - let formattedValue = "0x" + value.toString('hex'); - if(formattedValue.length > 128) { + private formatRowData(row: any): void { + for (let i = 0; i < row.length; i++) { + let value = row[i]; + if (value instanceof Date) { + row[i] = value.toISOString(); + } else if ((value instanceof Buffer) || (value instanceof Object)) { + let formattedValue = '0x' + value.toString('hex'); + if (formattedValue.length > 128) { formattedValue = formattedValue.slice(0, 128); } - row[col] = formattedValue; - } - else if(value === null) - { - row[col] = "NULL"; + row[i] = formattedValue; + } else if (value === undefined) { + row[i] = 'NULL'; } } } -} \ No newline at end of file +} diff --git a/src/extension.ts b/src/extension.ts index 6d2bba5905..61a3476ed3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,17 +6,15 @@ let controller: MainController = undefined; // this method is called when your extension is activated // your extension is activated the very first time the command is executed -export function activate(context: vscode.ExtensionContext) -{ +export function activate(context: vscode.ExtensionContext): void { controller = new MainController(context); - context.subscriptions.push(controller); - controller.activate(); + context.subscriptions.push(controller); + controller.activate(); } // this method is called when your extension is deactivated -export function deactivate() -{ - if(controller) { +export function deactivate(): void { + if (controller) { controller.deactivate(); } -} \ No newline at end of file +} diff --git a/src/models/connectionInfo.ts b/src/models/connectionInfo.ts index a271779169..e7aaa38117 100644 --- a/src/models/connectionInfo.ts +++ b/src/models/connectionInfo.ts @@ -3,121 +3,114 @@ import Constants = require('./constants'); import Interfaces = require('./interfaces'); // Fix up connection settings if we're connecting to Azure SQL -export function fixupConnectionCredentials(connCreds: Interfaces.IConnectionCredentials): Interfaces.IConnectionCredentials -{ - if(!connCreds.server) { - connCreds.server = ""; +export function fixupConnectionCredentials(connCreds: Interfaces.IConnectionCredentials): Interfaces.IConnectionCredentials { + if (!connCreds.server) { + connCreds.server = ''; } - if(!connCreds.database) { - connCreds.database = ""; + if (!connCreds.database) { + connCreds.database = ''; } - if(!connCreds.user) { - connCreds.user = ""; + if (!connCreds.user) { + connCreds.user = ''; } - if(!connCreds.password) { - connCreds.password = ""; + if (!connCreds.password) { + connCreds.password = ''; } - if(!connCreds.connectionTimeout) { + if (!connCreds.connectionTimeout) { connCreds.connectionTimeout = Constants.gDefaultConnectionTimeout; } - if(!connCreds.requestTimeout) { + if (!connCreds.requestTimeout) { connCreds.requestTimeout = Constants.gDefaultRequestTimeout; } // default values for advanced options - if(!connCreds.options) { - connCreds.options = {encrypt: false, appName: Constants.gExtensionName} + if (!connCreds.options) { + connCreds.options = {encrypt: false, appName: Constants.gExtensionName}; } // default value for encrypt - if(!connCreds.options.encrypt) { + if (!connCreds.options.encrypt) { connCreds.options.encrypt = false; } // default value for appName - if(!connCreds.options.appName) { + if (!connCreds.options.appName) { connCreds.options.appName = Constants.gExtensionName; } - if(isAzureDatabase(connCreds.server)) - { + if (isAzureDatabase(connCreds.server)) { // always encrypt connection if connecting to Azure SQL connCreds.options.encrypt = true; // Ensure minumum connection timeout if connecting to Azure SQL - if(connCreds.connectionTimeout < Constants.gAzureSqlDbConnectionTimeout) { + if (connCreds.connectionTimeout < Constants.gAzureSqlDbConnectionTimeout) { connCreds.connectionTimeout = Constants.gAzureSqlDbConnectionTimeout; } // Ensure minumum request timeout if connecting to Azure SQL - if(connCreds.requestTimeout < Constants.gAzureSqlDbRequestTimeout) { + if (connCreds.requestTimeout < Constants.gAzureSqlDbRequestTimeout) { connCreds.requestTimeout = Constants.gAzureSqlDbRequestTimeout; } } return connCreds; } -// return true if server name ends with ".database.windows.net" -function isAzureDatabase(server: string) { +// return true if server name ends with '.database.windows.net' +function isAzureDatabase(server: string): boolean { return (server ? server.endsWith(Constants.gSqlDbPrefix) : false); } export function dump(connCreds: Interfaces.IConnectionCredentials): string { - let contents = "server=" + (connCreds.server ? connCreds.server : "null") + - " | database=" + (connCreds.database ? connCreds.database : "null") + - " | username=" + (connCreds.user ? connCreds.user : "null") + - " | encrypt=" + connCreds.options.encrypt + - " | connectionTimeout=" + connCreds.connectionTimeout + - " | connectionTimeout=" + connCreds.requestTimeout; + let contents = 'server=' + (connCreds.server ? connCreds.server : 'null') + + ' | database=' + (connCreds.database ? connCreds.database : 'null') + + ' | username=' + (connCreds.user ? connCreds.user : 'null') + + ' | encrypt=' + connCreds.options.encrypt + + ' | connectionTimeout=' + connCreds.connectionTimeout + + ' | connectionTimeout=' + connCreds.requestTimeout; return contents; } // compare connections porperties, except for password -export function equals(connCreds: Interfaces.IConnectionCredentials, theOther: Interfaces.IConnectionCredentials): boolean -{ - let equal = (connCreds.server == theOther.server) && - (connCreds.database == theOther.database) && - (connCreds.user == theOther.user) && - (connCreds.options.encrypt == theOther.options.encrypt) && - (connCreds.connectionTimeout == theOther.connectionTimeout) && - (connCreds.requestTimeout == theOther.requestTimeout); +export function equals(connCreds: Interfaces.IConnectionCredentials, theOther: Interfaces.IConnectionCredentials): boolean { + let equal = (connCreds.server === theOther.server) && + (connCreds.database === theOther.database) && + (connCreds.user === theOther.user) && + (connCreds.options.encrypt === theOther.options.encrypt) && + (connCreds.connectionTimeout === theOther.connectionTimeout) && + (connCreds.requestTimeout === theOther.requestTimeout); return equal; } -export function getPicklistLabel(connCreds: Interfaces.IConnectionCredentials): string -{ +export function getPicklistLabel(connCreds: Interfaces.IConnectionCredentials): string { return connCreds.server; } -export function getPicklistDescription(connCreds: Interfaces.IConnectionCredentials): string -{ - return "[" + - "database: " + (connCreds.database ? connCreds.database : "") + - ", username: " + (connCreds.user ? connCreds.user : "") + - "]"; +export function getPicklistDescription(connCreds: Interfaces.IConnectionCredentials): string { + return '[' + + 'database: ' + (connCreds.database ? connCreds.database : '') + + ', username: ' + (connCreds.user ? connCreds.user : '') + + ']'; } -export function getPicklistDetails(connCreds: Interfaces.IConnectionCredentials): string -{ - return "[" + - "encrypt connection: " + (connCreds.options.encrypt ? "true" : "false") + - ", connection timeout: " + connCreds.connectionTimeout + " ms" + - ", request timeout: " + connCreds.requestTimeout + " ms" + - "]"; +export function getPicklistDetails(connCreds: Interfaces.IConnectionCredentials): string { + return '[' + + 'encrypt connection: ' + (connCreds.options.encrypt ? 'true' : 'false') + + ', connection timeout: ' + connCreds.connectionTimeout + ' ms' + + ', request timeout: ' + connCreds.requestTimeout + ' ms' + + ']'; } -export function getTooltip(connCreds: Interfaces.IConnectionCredentials): string -{ - return "server: " + connCreds.server + "\r\n" + - "database: " + (connCreds.database ? connCreds.database : "") + "\r\n" + - "username: " + connCreds.user + "\r\n" + - "encrypt connection: " + (connCreds.options.encrypt ? "true" : "false") + "\r\n" + - "connection timeout: " + connCreds.connectionTimeout + " ms\r\n" + - "request timeout: " + connCreds.requestTimeout + " ms\r\n" + - "appName: " + connCreds.options.appName; -} \ No newline at end of file +export function getTooltip(connCreds: Interfaces.IConnectionCredentials): string { + return 'server: ' + connCreds.server + '\r\n' + + 'database: ' + (connCreds.database ? connCreds.database : '') + '\r\n' + + 'username: ' + connCreds.user + '\r\n' + + 'encrypt connection: ' + (connCreds.options.encrypt ? 'true' : 'false') + '\r\n' + + 'connection timeout: ' + connCreds.connectionTimeout + ' ms\r\n' + + 'request timeout: ' + connCreds.requestTimeout + ' ms\r\n' + + 'appName: ' + connCreds.options.appName; +} diff --git a/src/models/constants.ts b/src/models/constants.ts index 7a5a134204..b328e66e7d 100644 --- a/src/models/constants.ts +++ b/src/models/constants.ts @@ -1,87 +1,89 @@ // constants -export const gLanguageId = "sql"; -export const gExtensionName = "vscode-mssql"; -export const gOutputChannelName = "MSSQL"; +export const gLanguageId = 'sql'; +export const gExtensionName = 'vscode-mssql'; +export const gOutputChannelName = 'MSSQL'; export const gCmdRunQuery = 'extension.runQuery'; export const gCmdConnect = 'extension.connect'; export const gCmdDisconnect = 'extension.disconnect'; -export const gSqlDbPrefix = ".database.windows.net"; +export const gSqlDbPrefix = '.database.windows.net'; export const gDefaultConnectionTimeout = 15000; export const gDefaultRequestTimeout = 15000; export const gAzureSqlDbConnectionTimeout = 30000; export const gAzureSqlDbRequestTimeout = 30000; -export const gAzureDatabase = "Azure"; +export const gAzureDatabase = 'Azure'; export const gOutputContentTypeRoot = 'root'; -export const gOutputContentTypeMessages = "messages"; +export const gOutputContentTypeMessages = 'messages'; export const gOutputContentTypeResultsetMeta = 'resultsetsMeta'; -export const gOutputContentTypeColumns = 'columns' -export const gOutputContentTypeRows = 'rows' -export const gOutputServiceLocalhost = "http://localhost:"; +export const gOutputContentTypeColumns = 'columns'; +export const gOutputContentTypeRows = 'rows'; +export const gOutputServiceLocalhost = 'http://localhost:'; export const gMsgContentProviderSqlOutputHtml = 'sqlOutput.ejs'; -export const gConfigLogDebugInfo = "logDebugInfo"; -export const gConfigMyConnections = "connections"; +export const gConfigLogDebugInfo = 'logDebugInfo'; +export const gConfigMyConnections = 'connections'; // localizable strings -export const gConfigMyConnectionsNoServerName = "Missing server name in user preferences connection: "; +export const gConfigMyConnectionsNoServerName = 'Missing server name in user preferences connection: '; -export const gMsgLocalWebserviceStaticContent = "LocalWebService: added static html content path: "; +export const gMsgLocalWebserviceStaticContent = 'LocalWebService: added static html content path: '; export const gMsgLocalWebserviceStarted = 'LocalWebService listening on port '; export const gMsgRunQueryAllBatchesExecuted = 'runQuery: all batches executed'; export const gMsgRunQueryError = 'runQuery: error: '; -export const gMsgRunQueryExecutingBatch = 'runQuery: executeBatch called with SQL: ' -export const gMsgRunQueryAddBatchResultsets = 'runQuery: adding resultsets for batch: ' -export const gMsgRunQueryAddBatchError = 'runQuery: adding error message for batch: ' +export const gMsgRunQueryExecutingBatch = 'runQuery: executeBatch called with SQL: '; +export const gMsgRunQueryAddBatchResultsets = 'runQuery: adding resultsets for batch: '; +export const gMsgRunQueryAddBatchError = 'runQuery: adding error message for batch: '; export const gMsgRunQueryConnectionActive = 'runQuery: active connection is connected, using it to run query'; export const gMsgRunQueryConnectionDisconnected = 'runQuery: active connection is disconnected, reconnecting'; export const gMsgRunQueryNoConnection = 'runQuery: no active connection - prompting for user'; -export const gMsgContentProviderOnContentUpdated = "Content provider: onContentUpdated called"; +export const gMsgContentProviderOnContentUpdated = 'Content provider: onContentUpdated called'; export const gMsgContentProviderOnRootEndpoint = 'LocalWebService: Root end-point called'; -export const gMsgContentProviderOnResultsEndpoint = "LocalWebService: ResultsetsMeta endpoint called"; +export const gMsgContentProviderOnResultsEndpoint = 'LocalWebService: ResultsetsMeta endpoint called'; export const gMsgContentProviderOnMessagesEndpoint = 'LocalWebService: Messages end-point called'; -export const gMsgContentProviderOnColumnsEndpoint = "LocalWebService: Columns end-point called for index = "; -export const gMsgContentProviderOnRowsEndpoint = "LocalWebService: Rows end-point called for index = "; -export const gMsgContentProviderOnClear = "Content provider: clear called"; +export const gMsgContentProviderOnColumnsEndpoint = 'LocalWebService: Columns end-point called for index = '; +export const gMsgContentProviderOnRowsEndpoint = 'LocalWebService: Rows end-point called for index = '; +export const gMsgContentProviderOnClear = 'Content provider: clear called'; export const gMsgContentProviderOnUpdateContent = 'Content provider: updateContent called'; export const gMsgContentProviderProvideContent = 'Content provider: provideTextDocumentContent called: '; -export const gExtensionActivated = "activated."; -export const gExtensionDeactivated = "de-activated."; -export const gMsgOpenSqlFile = "To use this command, Open a .sql file -or- Change editor language to 'SQL' -or- Select some T-SQL text in the active SQL editor."; +export const gExtensionActivated = 'activated.'; +export const gExtensionDeactivated = 'de-activated.'; +export const gMsgOpenSqlFile = `To use this command, Open a .sql file -or- + Change editor language to "SQL" -or- + Select some T-SQL text in the active SQL editor.`; -export const gRecentConnectionsPlaceholder = "Choose a connection from the list below"; -export const gMsgNoConnectionsInSettings = "To use this command, add connection information to VS Code User or Workspace settings."; -export const gLabelOpenGlobalSettings = "Open Global Settings"; -export const gLabelOpenWorkspaceSettings = "Open Workspace Settings"; +export const gRecentConnectionsPlaceholder = 'Choose a connection from the list below'; +export const gMsgNoConnectionsInSettings = 'To use this command, add connection information to VS Code User or Workspace settings.'; +export const gLabelOpenGlobalSettings = 'Open Global Settings'; +export const gLabelOpenWorkspaceSettings = 'Open Workspace Settings'; -export const gServerPrompt = "Server name"; -export const gServerPlaceholder = "hostname\\instance or .database.windows.net"; -export const gDatabasePrompt = "Database name"; -export const gDatabasePlaceholder = "optional database to connect to (default depends on server configuration, typically 'master')"; -export const gUsernamePrompt = "Username"; -export const gUsernamePlaceholder = "username (SQL Authentication)"; -export const gPasswordPrompt = "Password"; -export const gPasswordPlaceholder = "Password (SQL Authentication)"; +export const gServerPrompt = 'Server name'; +export const gServerPlaceholder = 'hostname\\instance or .database.windows.net'; +export const gDatabasePrompt = 'Database name'; +export const gDatabasePlaceholder = 'optional database to connect to (default depends on server configuration, typically "master")'; +export const gUsernamePrompt = 'Username'; +export const gUsernamePlaceholder = 'username (SQL Authentication)'; +export const gPasswordPrompt = 'Password'; +export const gPasswordPlaceholder = 'Password (SQL Authentication)'; -export const gMsgIsRequired = " is required."; -export const gMsgRetry = "Retry"; -export const gMsgError = "Error: "; +export const gMsgIsRequired = ' is required.'; +export const gMsgRetry = 'Retry'; +export const gMsgError = 'Error: '; -export const gNotConnectedLabel = "Not connected"; -export const gNotConnectedTooltip = "Click to connect to a database"; -export const gConnectingLabel = "Connecting"; -export const gConnectingTooltip = "Connecting to: "; -export const gConnectedLabel = "Connected."; -export const gConnectErrorLabel = "Connection error!"; -export const gConnectErrorTooltip = "Error connecting to: "; -export const gConnectErrorCode = "Errorcode: "; -export const gConnectErrorMessage = "ErrorMessage: "; -export const gExecuteQueryLabel = "Executing query "; -export const gExecuteQueryErrorLabel = "Query completed with errors"; -export const gExecuteQuerySuccessLabel = "Query executed successfully"; -export const gExecuteQueryRowsAffected = " row(s) affected"; -export const gExecuteQueryCommandCompleted = "Command(s) completed successfully."; \ No newline at end of file +export const gNotConnectedLabel = 'Not connected'; +export const gNotConnectedTooltip = 'Click to connect to a database'; +export const gConnectingLabel = 'Connecting'; +export const gConnectingTooltip = 'Connecting to: '; +export const gConnectedLabel = 'Connected.'; +export const gConnectErrorLabel = 'Connection error!'; +export const gConnectErrorTooltip = 'Error connecting to: '; +export const gConnectErrorCode = 'Errorcode: '; +export const gConnectErrorMessage = 'ErrorMessage: '; +export const gExecuteQueryLabel = 'Executing query '; +export const gExecuteQueryErrorLabel = 'Query completed with errors'; +export const gExecuteQuerySuccessLabel = 'Query executed successfully'; +export const gExecuteQueryRowsAffected = ' row(s) affected'; +export const gExecuteQueryCommandCompleted = 'Command(s) completed successfully.'; diff --git a/src/models/interfaces.ts b/src/models/interfaces.ts index 011ed2ff34..a024f4d8f7 100644 --- a/src/models/interfaces.ts +++ b/src/models/interfaces.ts @@ -3,8 +3,7 @@ import vscode = require('vscode'); import Constants = require('./constants'); // interfaces -export enum ContentType -{ +export enum ContentType { Root = 0, Messages = 1, ResultsetsMeta = 2, @@ -18,50 +17,44 @@ Constants.gOutputContentTypeColumns, Constants.gOutputContentTypeRows]; // mssql.config wrapped into an interface for us to use more easily // Provided by the user when creating a new database connection // See this for more info: http://pekim.github.io/tedious/api-connection.html -export interface IConnectionCredentials -{ - server: string; - database: string; - user: string; - password: string; - connectionTimeout: number; - requestTimeout: number; - options: { encrypt: boolean, appName: string } +export interface IConnectionCredentials { + server: string; + database: string; + user: string; + password: string; + connectionTimeout: number; + requestTimeout: number; + options: { encrypt: boolean, appName: string }; }; export interface IConnectionCredentialsQuickPickItem extends vscode.QuickPickItem { - connectionCreds: IConnectionCredentials; -} + connectionCreds: IConnectionCredentials; +}; // Obtained from an active connection to show in the status bar -export interface IConnectionProperties -{ - serverVersion: string; - currentUser: string; - currentDatabase: string; +export interface IConnectionProperties { + serverVersion: string; + currentUser: string; + currentDatabase: string; }; -export interface IBackgridColumnMetadata -{ - name: string, - label: string, - cell: string +export interface IBackgridColumnMetadata { + name: string; + label: string; + cell: string; } -export interface ISqlResultsetMeta -{ - columnsUri: string, - rowsUri: string +export interface ISqlResultsetMeta { + columnsUri: string; + rowsUri: string; }; -export interface ISqlMessage -{ - messageText: string +export interface ISqlMessage { + messageText: string; }; -export interface ISqlResultset -{ - columns: any[], - rows: any[], - executionPlanXml: string -}; \ No newline at end of file +export interface ISqlResultset { + columns: any[]; + rows: any[]; + executionPlanXml: string; +}; diff --git a/src/models/recentConnections.ts b/src/models/recentConnections.ts index e2d7179a47..12c709692d 100644 --- a/src/models/recentConnections.ts +++ b/src/models/recentConnections.ts @@ -5,16 +5,13 @@ import ConnInfo = require('./connectionInfo'); import Interfaces = require('./interfaces'); import Utils = require('../models/utils'); -export class RecentConnections -{ +export class RecentConnections { // Load connections from user preferences and return them as a formatted picklist - public getPickListItems() - { + public getPickListItems(): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { self.loadConnections() - .then(function(connections) + .then(function(connections): void { const pickListItems = connections.map( (item: Interfaces.IConnectionCredentials) => { return { @@ -22,7 +19,7 @@ export class RecentConnections description: ConnInfo.getPicklistDescription(item), detail: ConnInfo.getPicklistDetails(item), connectionCreds: item - } + }; }); resolve(pickListItems); }); @@ -30,31 +27,24 @@ export class RecentConnections } // Load connections from user preferences - private loadConnections() - { - const self = this; - return new Promise((resolve, reject) => - { + private loadConnections(): Promise { + return new Promise((resolve, reject) => { // Load connections from user preferences // Per this https://code.visualstudio.com/Docs/customization/userandworkspace // Settings defined in workspace scope overwrite the settings defined in user scope let connections: Interfaces.IConnectionCredentials[] = []; let config = vscode.workspace.getConfiguration(Constants.gExtensionName); let configValues = config[Constants.gConfigMyConnections]; - for (var index = 0; index < configValues.length; index++) - { + for (let index = 0; index < configValues.length; index++) { let element = configValues[index]; - if(element.server && element.server.trim() && !element.server.trim().startsWith("{{")) - { + if (element.server && element.server.trim() && !element.server.trim().startsWith('{{')) { let connection = ConnInfo.fixupConnectionCredentials(element); connections.push(connection); - } - else - { - Utils.logDebug(Constants.gConfigMyConnectionsNoServerName + " index (" + index + "): " + element.toString()); + } else { + Utils.logDebug(Constants.gConfigMyConnectionsNoServerName + ' index (' + index + '): ' + element.toString()); } } resolve(connections); }); } -} \ No newline at end of file +} diff --git a/src/models/sqlOutputContentProvider.ts b/src/models/sqlOutputContentProvider.ts index c731c9022c..f389cc47ca 100644 --- a/src/models/sqlOutputContentProvider.ts +++ b/src/models/sqlOutputContentProvider.ts @@ -10,14 +10,13 @@ class QueryResultSet { public messages: string[] = []; public resultsets: Interfaces.ISqlResultset[] = []; - constructor(messages : string[], resultsets : Interfaces.ISqlResultset[]){ + constructor(messages: string[], resultsets: Interfaces.ISqlResultset[]) { this.messages = messages; this.resultsets = resultsets; } } -export class SqlOutputContentProvider implements vscode.TextDocumentContentProvider -{ +export class SqlOutputContentProvider implements vscode.TextDocumentContentProvider { private _queryResultsMap: Map = new Map(); public static providerName = 'tsqloutput'; public static providerUri = vscode.Uri.parse('tsqloutput://'); @@ -28,101 +27,93 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi return this._onDidChange.event; } - public onContentUpdated() { + public onContentUpdated(): void { Utils.logDebug(Constants.gMsgContentProviderOnContentUpdated); this._onDidChange.fire(SqlOutputContentProvider.providerUri); } - constructor(context: vscode.ExtensionContext) - { + constructor(context: vscode.ExtensionContext) { const self = this; // create local express server this._service = new LocalWebService(context.extensionPath); // add http handler for '/' - this._service.addHandler(Interfaces.ContentType.Root, function(req, res) { + this._service.addHandler(Interfaces.ContentType.Root, function(req, res): void { Utils.logDebug(Constants.gMsgContentProviderOnRootEndpoint); - let uri : string = req.query.uri; - res.render(path.join(LocalWebService.staticContentPath, Constants.gMsgContentProviderSqlOutputHtml), {uri:uri}); + let uri: string = req.query.uri; + res.render(path.join(LocalWebService.staticContentPath, Constants.gMsgContentProviderSqlOutputHtml), {uri: uri}); }); // add http handler for '/resultsetsMeta' - return metadata about columns & rows in multiple resultsets - this._service.addHandler(Interfaces.ContentType.ResultsetsMeta, function(req, res) { + this._service.addHandler(Interfaces.ContentType.ResultsetsMeta, function(req, res): void { Utils.logDebug(Constants.gMsgContentProviderOnResultsEndpoint); let resultsetsMeta: Interfaces.ISqlResultsetMeta[] = []; - let uri : string = req.query.uri; - for (var index = 0; index < self._queryResultsMap.get(uri).resultsets.length; index ++) - { + let uri: string = req.query.uri; + for (let index = 0; index < self._queryResultsMap.get(uri).resultsets.length; index ++) { resultsetsMeta.push( { - columnsUri: "/" + Constants.gOutputContentTypeColumns + "?id=" + index.toString(), - rowsUri: "/" + Constants.gOutputContentTypeRows + "?id=" + index.toString() + columnsUri: '/' + Constants.gOutputContentTypeColumns + '?id=' + index.toString(), + rowsUri: '/' + Constants.gOutputContentTypeRows + '?id=' + index.toString() }); } let json = JSON.stringify(resultsetsMeta); - //Utils.logDebug(json); + // Utils.logDebug(json); res.send(json); }); // add http handler for '/messages' - return all messages as a JSON string - this._service.addHandler(Interfaces.ContentType.Messages, function(req, res) { + this._service.addHandler(Interfaces.ContentType.Messages, function(req, res): void { Utils.logDebug(Constants.gMsgContentProviderOnMessagesEndpoint); - let uri : string = req.query.uri; + let uri: string = req.query.uri; let json = JSON.stringify(self._queryResultsMap.get(uri).messages); - //Utils.logDebug(json); + // Utils.logDebug(json); res.send(json); }); // add http handler for '/columns' - return column metadata as a JSON string - this._service.addHandler(Interfaces.ContentType.Columns, function(req, res) { - var id = req.query.id; + this._service.addHandler(Interfaces.ContentType.Columns, function(req, res): void { + let id = req.query.id; Utils.logDebug(Constants.gMsgContentProviderOnColumnsEndpoint + id); - let uri : string = req.query.uri; + let uri: string = req.query.uri; let columnMetadata = self._queryResultsMap.get(uri).resultsets[id].columns; let json = JSON.stringify(columnMetadata); - //Utils.logDebug(json); + // Utils.logDebug(json); res.send(json); }); // add http handler for '/rows' - return rows end-point for a specific resultset - this._service.addHandler(Interfaces.ContentType.Rows, function(req, res) { - var id = req.query.id; + this._service.addHandler(Interfaces.ContentType.Rows, function(req, res): void { + let id = req.query.id; Utils.logDebug(Constants.gMsgContentProviderOnRowsEndpoint + id); - let uri : string = req.query.uri; + let uri: string = req.query.uri; let json = JSON.stringify(self._queryResultsMap.get(uri).resultsets[id].rows); - //Utils.logDebug(json); + // Utils.logDebug(json); res.send(json); }); // start express server on localhost and listen on a random port - try - { + try { this._service.start(); - } - catch (error) - { + } catch (error) { Utils.showErrorMsg(error); throw(error); } } - private clear(uri:string) - { + private clear(uri: string): void { Utils.logDebug(Constants.gMsgContentProviderOnClear); this._queryResultsMap.delete(uri); } - public show(uri : string, title : string) - { - vscode.commands.executeCommand('vscode.previewHtml', uri, vscode.ViewColumn.Two, "SQL Query Results: " + title); + public show(uri: string, title: string): void { + vscode.commands.executeCommand('vscode.previewHtml', uri, vscode.ViewColumn.Two, 'SQL Query Results: ' + title); } - public updateContent(messages, resultsets) - { + public updateContent(messages, resultsets): string { Utils.logDebug(Constants.gMsgContentProviderOnUpdateContent); - let title : string = Utils.getActiveTextEditor().document.fileName; - let uri : string = SqlOutputContentProvider.providerUri + title; + let title: string = Utils.getActiveTextEditor().document.fileName; + let uri: string = SqlOutputContentProvider.providerUri + title; this.clear(uri); this.show(uri, title); this._queryResultsMap.set(uri, new QueryResultSet(messages, resultsets)); @@ -131,8 +122,7 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi } // Called by VS Code exactly once to load html content in the preview window - public provideTextDocumentContent(uri: vscode.Uri): string - { + public provideTextDocumentContent(uri: vscode.Uri): string { Utils.logDebug(Constants.gMsgContentProviderProvideContent + uri.toString()); // return dummy html content that redirects to 'http://localhost:' after the page loads @@ -149,4 +139,4 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi `; } -} \ No newline at end of file +} diff --git a/src/models/utils.ts b/src/models/utils.ts index c9bb46752c..c3755a2bb2 100644 --- a/src/models/utils.ts +++ b/src/models/utils.ts @@ -3,14 +3,11 @@ import vscode = require('vscode'); import Constants = require('./constants'); // Return 'true' if the active editor window has a .sql file, false otherwise -export function isEditingSqlFile() -{ +export function isEditingSqlFile(): boolean { let sqlFile = false; let editor = getActiveTextEditor(); - if(editor) - { - if (editor.document.languageId == Constants.gLanguageId) - { + if (editor) { + if (editor.document.languageId === Constants.gLanguageId) { sqlFile = true; } } @@ -18,60 +15,49 @@ export function isEditingSqlFile() } // Return the active text editor if there's one -export function getActiveTextEditor() -{ +export function getActiveTextEditor(): vscode.TextEditor { let editor = undefined; - if(vscode.window && vscode.window.activeTextEditor) - { + if (vscode.window && vscode.window.activeTextEditor) { editor = vscode.window.activeTextEditor; } return editor; } // Helper to log messages to "MSSQL" output channel -export function logToOutputChannel(msg: any) -{ +export function logToOutputChannel(msg: any): void { let outputChannel = vscode.window.createOutputChannel(Constants.gOutputChannelName); outputChannel.show(); - if(msg instanceof Array) - { + if (msg instanceof Array) { msg.forEach(element => { outputChannel.appendLine(element.toString()); }); - } - else - { + } else { outputChannel.appendLine(msg.toString()); } } // Helper to log debug messages -export function logDebug(msg: any) -{ +export function logDebug(msg: any): void { let config = vscode.workspace.getConfiguration(Constants.gExtensionName); let logDebugInfo = config[Constants.gConfigLogDebugInfo]; - if(logDebugInfo == true) - { + if (logDebugInfo === true) { let currentTime = new Date().toLocaleTimeString(); - let outputMsg = "[" + currentTime + "]: " + msg ? msg.toString() : ""; + let outputMsg = '[' + currentTime + ']: ' + msg ? msg.toString() : ''; console.log(outputMsg); } } // Helper to show an info message -export function showInfoMsg(msg: string) -{ - vscode.window.showInformationMessage(Constants.gExtensionName + ": " + msg ); +export function showInfoMsg(msg: string): void { + vscode.window.showInformationMessage(Constants.gExtensionName + ': ' + msg ); } // Helper to show an warn message -export function showWarnMsg(msg: string) -{ - vscode.window.showWarningMessage(Constants.gExtensionName + ": " + msg ); +export function showWarnMsg(msg: string): void { + vscode.window.showWarningMessage(Constants.gExtensionName + ': ' + msg ); } // Helper to show an error message -export function showErrorMsg(msg: string) -{ - vscode.window.showErrorMessage(Constants.gExtensionName + ": " + msg ); -} \ No newline at end of file +export function showErrorMsg(msg: string): void { + vscode.window.showErrorMessage(Constants.gExtensionName + ': ' + msg ); +} diff --git a/src/views/connectionUI.ts b/src/views/connectionUI.ts index a8279e705f..322a550d24 100644 --- a/src/views/connectionUI.ts +++ b/src/views/connectionUI.ts @@ -1,39 +1,29 @@ 'use strict'; import vscode = require('vscode'); -import ConnInfo = require('../models/connectionInfo'); import Constants = require('../models/constants'); -import Utils = require('../models/utils'); import { RecentConnections } from '../models/recentConnections'; import Interfaces = require('../models/interfaces'); -var async = require("async"); +let async = require('async'); -export class ConnectionUI -{ +export class ConnectionUI { // Helper to let user choose a connection from a picklist // Return the ConnectionInfo for the user's choice - public showConnections() - { + public showConnections(): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { let recentConnections = new RecentConnections(); recentConnections.getPickListItems() - .then((picklist: Interfaces.IConnectionCredentialsQuickPickItem[]) => - { - if(picklist.length == 0) - { + .then((picklist: Interfaces.IConnectionCredentialsQuickPickItem[]) => { + if (picklist.length === 0) { // No recent connections - prompt to open user settings or workspace settings to add a connection self.openUserOrWorkspaceSettings(); return false; - } - else - { + } else { // We have recent connections - show them in a picklist self.showConnectionsPickList(picklist) - .then(selection => - { - if(!selection) { + .then(selection => { + if (!selection) { return false; } resolve(selection); @@ -44,36 +34,31 @@ export class ConnectionUI } // Helper to prompt user to open VS Code user settings or workspace settings - private openUserOrWorkspaceSettings() - { + private openUserOrWorkspaceSettings(): void { let openGlobalSettingsItem: vscode.MessageItem = { - "title": Constants.gLabelOpenGlobalSettings + 'title': Constants.gLabelOpenGlobalSettings }; let openWorkspaceSettingsItem: vscode.MessageItem = { - "title": Constants.gLabelOpenWorkspaceSettings + 'title': Constants.gLabelOpenWorkspaceSettings }; - vscode.window.showWarningMessage(Constants.gExtensionName + ": " + Constants.gMsgNoConnectionsInSettings, openGlobalSettingsItem, openWorkspaceSettingsItem) - .then((selectedItem: vscode.MessageItem) => - { - if (selectedItem === openGlobalSettingsItem) - { - vscode.commands.executeCommand("workbench.action.openGlobalSettings"); - } - else if (selectedItem === openWorkspaceSettingsItem) - { - vscode.commands.executeCommand("workbench.action.openWorkspaceSettings"); + vscode.window.showWarningMessage(Constants.gExtensionName + + ': ' + + Constants.gMsgNoConnectionsInSettings, openGlobalSettingsItem, openWorkspaceSettingsItem) + .then((selectedItem: vscode.MessageItem) => { + if (selectedItem === openGlobalSettingsItem) { + vscode.commands.executeCommand('workbench.action.openGlobalSettings'); + } else if (selectedItem === openWorkspaceSettingsItem) { + vscode.commands.executeCommand('workbench.action.openWorkspaceSettings'); } }); } // Helper to let user choose a connection from a picklist - private showConnectionsPickList(pickList: Interfaces.IConnectionCredentialsQuickPickItem[]) - { + private showConnectionsPickList(pickList: Interfaces.IConnectionCredentialsQuickPickItem[]): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { // init picklist options let opts: vscode.QuickPickOptions = { matchOnDescription: true, @@ -82,15 +67,12 @@ export class ConnectionUI // show picklist vscode.window.showQuickPick(pickList, opts) - .then(selection => - { - if(selection != null) - { + .then(selection => { + if (selection !== undefined) { // user chose a connection from picklist. Prompt for mandatory info that's missing (e.g. username and/or password) let connectionCreds = selection.connectionCreds; - self.promptForMissingInfo(connectionCreds).then((resolvedConnectionCreds) => - { - if(!resolvedConnectionCreds) { + self.promptForMissingInfo(connectionCreds).then((resolvedConnectionCreds) => { + if (!resolvedConnectionCreds) { return false; } resolve(resolvedConnectionCreds); @@ -101,21 +83,17 @@ export class ConnectionUI } // Prompt user for missing details in the given IConnectionCredentials - private promptForMissingInfo(connectionCreds: Interfaces.IConnectionCredentials) - { + private promptForMissingInfo(connectionCreds: Interfaces.IConnectionCredentials): Promise { const self = this; - return new Promise((resolve, reject) => - { + return new Promise((resolve, reject) => { // called by async.js when all functions have finished executing - var final = function(err, self, results) - { - if(err) { + let final = function(err, object, results): boolean { + if (err) { return false; - } - else { + } else { resolve(results); // final connectionCreds with all the missing inputs filled in } - } + }; // call each of these functions in a waterfall and pass parameters from one to the next // See this for more info: https://github.com/caolan/async#waterfall @@ -127,27 +105,19 @@ export class ConnectionUI } // Helper to prompt for username - private promptForUsername(self, connectionCreds: Interfaces.IConnectionCredentials, callback) - { - if(connectionCreds.user) - { + private promptForUsername(self, connectionCreds: Interfaces.IConnectionCredentials, callback): void { + if (connectionCreds.user) { // we already have a username - tell async.js to proceed to the next function - callback(null, self, connectionCreds); - } - else - { + callback(undefined, self, connectionCreds); + } else { // we don't have a username, prompt the user to enter it let usernameInputOptions: vscode.InputBoxOptions = {placeHolder: Constants.gUsernamePlaceholder, prompt: Constants.gUsernamePrompt}; self.promptUser(usernameInputOptions) - .then((input) => - { - if(input) - { + .then((input) => { + if (input) { connectionCreds.user = input; - callback(null, self, connectionCreds); // tell async.js to proceed to the next function - } - else - { + callback(undefined, self, connectionCreds); // tell async.js to proceed to the next function + } else { // user cancelled - raise an error and abort the wizard callback(true, self, connectionCreds); } @@ -156,27 +126,19 @@ export class ConnectionUI } // Helper to prompt for password - private promptForPassword(self, connectionCreds: Interfaces.IConnectionCredentials, callback) - { - if(connectionCreds.password) - { + private promptForPassword(self, connectionCreds: Interfaces.IConnectionCredentials, callback): void { + if (connectionCreds.password) { // we already have a password - tell async.js to proceed to the next function - callback(null, self, connectionCreds); - } - else - { + callback(undefined, self, connectionCreds); + } else { // we don't have a password, prompt the user to enter it let passwordInputOptions: vscode.InputBoxOptions = {placeHolder: Constants.gPasswordPlaceholder, prompt: Constants.gPasswordPrompt, password: true}; self.promptUser(passwordInputOptions) - .then((input) => - { - if(input) - { + .then((input) => { + if (input) { connectionCreds.password = input; - callback(null, self, connectionCreds); // tell async.js to proceed to the next function - } - else - { + callback(undefined, self, connectionCreds); // tell async.js to proceed to the next function + } else { // user cancelled - raise an error and abort the wizard callback(true, self, connectionCreds); } @@ -186,32 +148,24 @@ export class ConnectionUI // Helper to prompt user for input // If the input is a mandatory inout then keeps prompting the user until cancelled - private promptUser(options: vscode.InputBoxOptions, mandatoryInput = true) - { - return new Promise((resolve, reject) => - { - var prompt = () => - { - vscode.window.showInputBox(options).then((input) => - { - if ((!input || !input.trim()) && mandatoryInput) - { - // Prompt user to re-enter if this is a mandatory input - vscode.window.showWarningMessage(options.prompt + Constants.gMsgIsRequired, Constants.gMsgRetry).then((choice) => - { - if (choice === Constants.gMsgRetry) { - prompt(); - } - }); - return false; - } - else - { - resolve(input); - } - }); - } - prompt(); - }); - } -} \ No newline at end of file + // private promptUser(options: vscode.InputBoxOptions, mandatoryInput = true): Promise { + // return new Promise((resolve, reject) => { + // let prompt = () => { + // vscode.window.showInputBox(options).then((input) => { + // if ((!input || !input.trim()) && mandatoryInput) { + // // Prompt user to re-enter if this is a mandatory input + // vscode.window.showWarningMessage(options.prompt + Constants.gMsgIsRequired, Constants.gMsgRetry).then((choice) => { + // if (choice === Constants.gMsgRetry) { + // prompt(); + // } + // }); + // return false; + // } else { + // resolve(input); + // } + // }); + // }; + // prompt(); + // }); + // } +} diff --git a/src/views/statusView.ts b/src/views/statusView.ts index 46eac0981a..a6d7250d1d 100644 --- a/src/views/statusView.ts +++ b/src/views/statusView.ts @@ -2,31 +2,26 @@ import vscode = require('vscode'); import Constants = require('../models/constants'); import ConnInfo = require('../models/connectionInfo'); import Interfaces = require('../models/interfaces'); -import Utils = require('../models/utils'); -export default class StatusView implements vscode.Disposable -{ +export default class StatusView implements vscode.Disposable { private _statusConnection: vscode.StatusBarItem; private _statusQuery: vscode.StatusBarItem; private tm; - constructor() - { + constructor() { this.createStatusBar(); } - dispose() - { + dispose(): void { this._statusConnection.dispose(); - this._statusConnection = null; + this._statusConnection = undefined; this._statusQuery.dispose(); - this._statusQuery = null; + this._statusQuery = undefined; clearInterval(this.tm); } // Create status bar item if needed - private createStatusBar() - { + private createStatusBar(): void { if (!this._statusConnection) { this._statusConnection = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); } @@ -35,39 +30,35 @@ export default class StatusView implements vscode.Disposable this._statusQuery = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); } - if(this.tm) { + if (this.tm) { clearInterval(this.tm); } } - public show() - { - if(this._statusConnection) { + public show(): void { + if (this._statusConnection) { this._statusConnection.show(); } - if(this._statusQuery) { + if (this._statusQuery) { this._statusQuery.show(); } } - public notConnected() - { + public notConnected(): void { this.createStatusBar(); this._statusQuery.hide(); this._statusConnection.hide(); } - public connecting(connCreds: Interfaces.IConnectionCredentials) - { + public connecting(connCreds: Interfaces.IConnectionCredentials): void { this.createStatusBar(); - this._statusConnection.command = null; + this._statusConnection.command = undefined; this._statusConnection.tooltip = Constants.gConnectingTooltip + ConnInfo.getTooltip(connCreds); this._statusConnection.show(); this.showProgress(Constants.gConnectingLabel, this._statusConnection); } - public connectSuccess(connCreds: Interfaces.IConnectionCredentials) - { + public connectSuccess(connCreds: Interfaces.IConnectionCredentials): void { this.createStatusBar(); this._statusConnection.command = Constants.gCmdConnect; this._statusConnection.text = connCreds.server; @@ -75,44 +66,41 @@ export default class StatusView implements vscode.Disposable this._statusConnection.show(); } - public connectError(connCreds: Interfaces.IConnectionCredentials, error: any) - { + public connectError(connCreds: Interfaces.IConnectionCredentials, error: any): void { this.createStatusBar(); this._statusConnection.command = Constants.gCmdConnect; this._statusConnection.text = Constants.gConnectErrorLabel; - this._statusConnection.tooltip = Constants.gConnectErrorTooltip + connCreds.server + "\n" + - Constants.gConnectErrorCode + error.code + "\n" + + this._statusConnection.tooltip = Constants.gConnectErrorTooltip + connCreds.server + '\n' + + Constants.gConnectErrorCode + error.code + '\n' + Constants.gConnectErrorMessage + error.message; this._statusConnection.show(); } - public executingQuery(connCreds: Interfaces.IConnectionCredentials) - { + public executingQuery(connCreds: Interfaces.IConnectionCredentials): void { this.createStatusBar(); - this._statusQuery.command = null; + this._statusQuery.command = undefined; this._statusQuery.tooltip = Constants.gExecuteQueryLabel; this._statusQuery.show(); this.showProgress(Constants.gExecuteQueryLabel, this._statusQuery); } - public executedQuery() - { + public executedQuery(): void { this.createStatusBar(); this._statusQuery.hide(); } - private showProgress(statusText: string, statusBarItem: vscode.StatusBarItem) - { + private showProgress(statusText: string, statusBarItem: vscode.StatusBarItem): void { let index = 0; let progressTicks = [ '|', '/', '-', '\\']; this.tm = setInterval(() => { index++; - if (index > 3) + if (index > 3) { index = 0; + } let progressTick = progressTicks[index]; - statusBarItem.text = statusText + " " + progressTick; + statusBarItem.text = statusText + ' ' + progressTick; statusBarItem.show(); }, 200); } -} \ No newline at end of file +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000000..06a17fbd31 --- /dev/null +++ b/tslint.json @@ -0,0 +1,127 @@ +{ + "rules": { + "align": [ + true, + "parameters", + "statements" + ], + "ban": false, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "indent": [ + true, + "spaces" + ], + "interface-name": true, + "jsdoc-format": true, + "label-position": true, + "label-undefined": true, + "max-line-length": [ + true, + 160 + ], + "member-access": false, + "member-ordering": [ + false, + "static-before-instance", + "variables-before-functions" + ], + "no-any": false, + "no-arg": true, + "no-bitwise": true, + "no-conditional-assignment": true, + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-constructor-vars": false, + "no-debugger": true, + "no-duplicate-key": true, + "no-duplicate-variable": true, + "no-empty": true, + "no-eval": true, + "no-inferrable-types": false, + "no-internal-module": true, + "no-null-keyword": true, + "no-require-imports": false, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": false, + "no-trailing-whitespace": true, + "no-unreachable": true, + "no-unused-expression": false, + "no-unused-variable": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "no-var-requires": false, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-finally", + "check-whitespace" + ], + "quotemark": [ + true, + "single", + "avoid-escape" + ], + "radix": true, + "semicolon": true, + "switch-default": true, + "trailing-comma": [ + true, + { + "multiline": "never", + "singleline": "never" + } + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef": [ + true, + "call-signature", + "property-declaration" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "use-strict": false, + "variable-name": [ + true, + "allow-leading-underscore", + "ban-keywords" + ], + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} \ No newline at end of file