fix jslint problems and added config

This commit is contained in:
Anthony Dresser 2016-07-22 14:47:21 -07:00
Родитель 23c4f7647a
Коммит bd509ff7a7
15 изменённых файлов: 553 добавлений и 603 удалений

Просмотреть файл

@ -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"
}
}

Просмотреть файл

@ -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<any>((resolve, reject) =>
{
if(this.isConnected) {
public onDisconnect(): Promise<any> {
return new Promise<any>((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<boolean> {
const self = this;
return new Promise<boolean>((resolve, reject) =>
{
return new Promise<boolean>((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<any> {
const self = this;
return new Promise<any>((resolve, reject) =>
{
return new Promise<any>((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);
});
});
}
}
}

Просмотреть файл

@ -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<any> {
return this._connectionMgr.onDisconnect();
}
// Let users pick from a list of connections
public onNewConnection()
{
public onNewConnection(): Promise<boolean> {
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();
}
}
}
}

Просмотреть файл

@ -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();
}
}
}

Просмотреть файл

@ -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<any>((resolve, reject) =>
{
private executeBatch(sqlText, connection): Promise<any> {
return new Promise<any>((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 = <Interfaces.IBackgridColumnMetadata> {
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';
}
}
}
}
}

Просмотреть файл

@ -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();
}
}
}

Просмотреть файл

@ -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 : "<connection default>") +
", username: " + (connCreds.user ? connCreds.user : "<prompt>") +
"]";
export function getPicklistDescription(connCreds: Interfaces.IConnectionCredentials): string {
return '[' +
'database: ' + (connCreds.database ? connCreds.database : '<connection default>') +
', username: ' + (connCreds.user ? connCreds.user : '<prompt>') +
']';
}
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 : "<connection default>") + "\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;
}
export function getTooltip(connCreds: Interfaces.IConnectionCredentials): string {
return 'server: ' + connCreds.server + '\r\n' +
'database: ' + (connCreds.database ? connCreds.database : '<connection default>') + '\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;
}

Просмотреть файл

@ -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 <server>.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 <server>.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.";
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.';

Просмотреть файл

@ -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
};
export interface ISqlResultset {
columns: any[];
rows: any[];
executionPlanXml: string;
};

Просмотреть файл

@ -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<Interfaces.IConnectionCredentialsQuickPickItem[]> {
const self = this;
return new Promise<Interfaces.IConnectionCredentialsQuickPickItem[]>((resolve, reject) =>
{
return new Promise<Interfaces.IConnectionCredentialsQuickPickItem[]>((resolve, reject) => {
self.loadConnections()
.then(function(connections)
.then(function(connections): void
{
const pickListItems = connections.map( (item: Interfaces.IConnectionCredentials) => {
return <Interfaces.IConnectionCredentialsQuickPickItem> {
@ -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<Interfaces.IConnectionCredentials[]>((resolve, reject) =>
{
private loadConnections(): Promise<Interfaces.IConnectionCredentials[]> {
return new Promise<Interfaces.IConnectionCredentials[]>((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);
});
}
}
}

Просмотреть файл

@ -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<string, QueryResultSet> = new Map<string, QueryResultSet>();
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( <Interfaces.ISqlResultsetMeta> {
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:<port>' after the page loads
@ -149,4 +139,4 @@ export class SqlOutputContentProvider implements vscode.TextDocumentContentProvi
<body></body>
</html>`;
}
}
}

Просмотреть файл

@ -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 );
}
export function showErrorMsg(msg: string): void {
vscode.window.showErrorMessage(Constants.gExtensionName + ': ' + msg );
}

Просмотреть файл

@ -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<Interfaces.IConnectionCredentials> {
const self = this;
return new Promise<Interfaces.IConnectionCredentials>((resolve, reject) =>
{
return new Promise<Interfaces.IConnectionCredentials>((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<Interfaces.IConnectionCredentials> {
const self = this;
return new Promise<Interfaces.IConnectionCredentials>((resolve, reject) =>
{
return new Promise<Interfaces.IConnectionCredentials>((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<Interfaces.IConnectionCredentials> {
const self = this;
return new Promise<Interfaces.IConnectionCredentials>((resolve, reject) =>
{
return new Promise<Interfaces.IConnectionCredentials>((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<string>((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();
});
}
}
// private promptUser(options: vscode.InputBoxOptions, mandatoryInput = true): Promise<string> {
// return new Promise<string>((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();
// });
// }
}

Просмотреть файл

@ -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);
}
}
}

127
tslint.json Normal file
Просмотреть файл

@ -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"
]
}
}