SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,270 @@
'use strict';
import * as crypto from 'crypto';
import * as os from 'os';
import vscode = require('vscode');
import Constants = require('./constants');
import {ExtensionContext} from 'vscode';
import fs = require('fs');
var path = require('path');
// CONSTANTS //////////////////////////////////////////////////////////////////////////////////////
const msInH = 3.6e6;
const msInM = 60000;
const msInS = 1000;
// INTERFACES /////////////////////////////////////////////////////////////////////////////////////
// Interface for package.json information
export interface IPackageInfo {
name: string;
version: string;
aiKey: string;
}
// FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////
// Get information from the extension's package.json file
export function getPackageInfo(context: ExtensionContext): IPackageInfo {
let extensionPackage = require(context.asAbsolutePath('./package.json'));
if (extensionPackage) {
return {
name: extensionPackage.name,
version: extensionPackage.version,
aiKey: extensionPackage.aiKey
};
}
}
// Generate a new GUID
export function generateGuid(): string {
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
let oct: string = '';
let tmp: number;
/* tslint:disable:no-bitwise */
for (let a: number = 0; a < 4; a++) {
tmp = (4294967296 * Math.random()) | 0;
oct += hexValues[tmp & 0xF] +
hexValues[tmp >> 4 & 0xF] +
hexValues[tmp >> 8 & 0xF] +
hexValues[tmp >> 12 & 0xF] +
hexValues[tmp >> 16 & 0xF] +
hexValues[tmp >> 20 & 0xF] +
hexValues[tmp >> 24 & 0xF] +
hexValues[tmp >> 28 & 0xF];
}
// 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
/* tslint:enable:no-bitwise */
}
// Generate a unique, deterministic ID for the current user of the extension
export function generateUserId(): Promise<string> {
return new Promise<string>(resolve => {
try {
let interfaces = os.networkInterfaces();
let mac;
for(let key of Object.keys(interfaces)) {
let item = interfaces[key][0];
if (!item.internal) {
mac = item.mac;
break;
}
}
if (mac) {
resolve(crypto.createHash('sha256').update(mac + os.homedir(), 'utf8').digest('hex'));
} else {
resolve(generateGuid());
}
} catch (err) {
resolve(generateGuid()); // fallback
}
});
}
// Return 'true' if the active editor window has a .sql file, false otherwise
export function isEditingSqlFile(languageId: string): boolean {
let sqlFile = false;
let editor = getActiveTextEditor();
if (editor) {
if (editor.document.languageId === languageId) {
sqlFile = true;
}
}
return sqlFile;
}
// Return the active text editor if there's one
export function getActiveTextEditor(): vscode.TextEditor {
let editor = undefined;
if (vscode.window && vscode.window.activeTextEditor) {
editor = vscode.window.activeTextEditor;
}
return editor;
}
// Retrieve the URI for the currently open file if there is one; otherwise return the empty string
export function getActiveTextEditorUri(): string {
if (typeof vscode.window.activeTextEditor !== 'undefined' &&
typeof vscode.window.activeTextEditor.document !== 'undefined') {
return vscode.window.activeTextEditor.document.uri.toString();
}
return '';
}
// Helper to log messages to output channel
export function logToOutputChannel(msg: any, outputChannelName: string): void {
let outputChannel = vscode.window.createOutputChannel(outputChannelName);
outputChannel.show();
if (msg instanceof Array) {
msg.forEach(element => {
outputChannel.appendLine(element.toString());
});
} else {
outputChannel.appendLine(msg.toString());
}
}
// Helper to log debug messages
export function logDebug(msg: any, extensionConfigSectionName: string): void {
let config = vscode.workspace.getConfiguration(extensionConfigSectionName);
let logDebugInfo = config[Constants.configLogDebugInfo];
if (logDebugInfo === true) {
let currentTime = new Date().toLocaleTimeString();
let outputMsg = '[' + currentTime + ']: ' + msg ? msg.toString() : '';
console.log(outputMsg);
}
}
// Helper to show an info message
export function showInfoMsg(msg: string, extensionName: string): void {
vscode.window.showInformationMessage(extensionName + ': ' + msg );
}
// Helper to show an warn message
export function showWarnMsg(msg: string, extensionName: string): void {
vscode.window.showWarningMessage(extensionName + ': ' + msg );
}
// Helper to show an error message
export function showErrorMsg(msg: string, extensionName: string): void {
vscode.window.showErrorMessage(extensionName + ': ' + msg );
}
export function isEmpty(str: any): boolean {
return (!str || '' === str);
}
export function isNotEmpty(str: any): boolean {
return <boolean>(str && '' !== str);
}
/**
* Format a string. Behaves like C#'s string.Format() function.
*/
export function formatString(str: string, ...args: any[]): string {
// This is based on code originally from https://github.com/Microsoft/vscode/blob/master/src/vs/nls.js
// License: https://github.com/Microsoft/vscode/blob/master/LICENSE.txt
let result: string;
if (args.length === 0) {
result = str;
} else {
result = str.replace(/\{(\d+)\}/g, (match, rest) => {
let index = rest[0];
return typeof args[index] !== 'undefined' ? args[index] : match;
});
}
return result;
}
/**
* Check if a file exists on disk
*/
export function isFileExisting(filePath: string): boolean {
try {
fs.statSync(filePath);
return true;
} catch (err) {
return false;
}
}
/**
* Takes a string in the format of HH:MM:SS.MS and returns a number representing the time in
* miliseconds
* @param value The string to convert to milliseconds
* @return False is returned if the string is an invalid format,
* the number of milliseconds in the time string is returned otherwise.
*/
export function parseTimeString(value: string): number | boolean {
if (!value) {
return false;
}
let tempVal = value.split('.');
if (tempVal.length !== 2) {
return false;
}
let ms = parseInt(tempVal[1].substring(0, 3), 10);
tempVal = tempVal[0].split(':');
if (tempVal.length !== 3) {
return false;
}
let h = parseInt(tempVal[0], 10);
let m = parseInt(tempVal[1], 10);
let s = parseInt(tempVal[2], 10);
return ms + (h * msInH) + (m * msInM) + (s * msInS);
}
/**
* Takes a number of milliseconds and converts it to a string like HH:MM:SS.fff
* @param value The number of milliseconds to convert to a timespan string
* @returns A properly formatted timespan string.
*/
export function parseNumAsTimeString(value: number): string {
let tempVal = value;
let h = Math.floor(tempVal / msInH);
tempVal %= msInH;
let m = Math.floor(tempVal / msInM);
tempVal %= msInM;
let s = Math.floor(tempVal / msInS);
tempVal %= msInS;
let hs = h < 10 ? '0' + h : '' + h;
let ms = m < 10 ? '0' + m : '' + m;
let ss = s < 10 ? '0' + s : '' + s;
let mss = tempVal < 10 ? '00' + tempVal : tempVal < 100 ? '0' + tempVal : '' + tempVal;
let rs = hs + ':' + ms + ':' + ss;
return tempVal > 0 ? rs + '.' + mss : rs;
}
// The function is a duplicate of carbon\src\paths.js. IT would be better to import path.js but it doesn't
// work for now because the extension is running in different process.
export function getAppDataPath() {
var platform = process.platform;
switch (platform) {
case 'win32': return process.env['APPDATA'] || path.join(process.env['USERPROFILE'], 'AppData', 'Roaming');
case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support');
case 'linux': return process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
default: throw new Error('Platform not supported');
}
}
export function getDefaultLogLocation() {
var platform = process.platform;
let rootFolderName: string = '.sqlops';
if (platform === 'win32') {
rootFolderName = 'sqlops';
}
return path.join(getAppDataPath(), rootFolderName);
}