Compare commits

...

51 Commits

Author SHA1 Message Date
Karl Burtram
8095643ed4 Merge branch 'master' into release/0.25 2018-01-12 15:43:19 -08:00
Matt Irvine
fcb6f7f9ee open-url changes 2018-01-12 15:00:21 -08:00
Karl Burtram
94bd1c4d7d Bump SQL Ops to 0.25.4 for next Jan release candidate build (#483) 2018-01-12 12:44:00 -08:00
Sebastian Pfliegel
e4a0e4e0c1 Add cursor snippet (#475)
* Add cursor snippet

* Workaround to avoid issue #480

Remove SELECT and tab to the place for custom code
2018-01-12 12:39:17 -08:00
Karl Burtram
96a3ded120 Merge branch 'master' into release/0.25 2018-01-11 17:33:31 -08:00
Karl Burtram
b73b09a1d3 Bump SQL Ops version to 0.23.3 for next release candidate build (#479) 2018-01-11 17:21:53 -08:00
Cory Rivera
a69a9778a6 Fix update package download paths (#476)
* Change update package download path to use sqlops naming.

* Add SqlEdit comments above download path changes.
2018-01-11 17:19:40 -08:00
Matt Irvine
6d3995aa29 Enable hot exit for saved files (#469) 2018-01-11 14:29:26 -08:00
Karl Burtram
bd3aa9c3cf Merge branch 'master' into release/0.25 2018-01-10 22:08:15 -08:00
Karl Burtram
7cf0847ef5 Bump Tools Service version to pick up latest changes (#471) 2018-01-10 21:58:27 -08:00
Matt Irvine
8e8e1f6913 Disable hot exit (#468) 2018-01-10 18:07:49 -08:00
Cory Rivera
b765e5aa90 Add updater service url to product.json. (#467) 2018-01-10 16:51:56 -08:00
Karl Burtram
7a421cc0bd Update changelog for Jan release (#466) 2018-01-10 16:48:08 -08:00
Karl Burtram
fb82440412 Bump product version to 0.25.2 (#461) 2018-01-10 13:10:35 -08:00
Benjamin Russell
2263ea48a1 Disabling the "learn more" link for now (#451)
* Disabling the "learn more" link for now

* Adding date/issue link
2018-01-10 10:29:06 -08:00
Matt Irvine
1868a6127a Fix bug where collapsed OE icon never appeared for selected element (#453) 2018-01-09 15:35:51 -05:00
Matt Irvine
5e4b8924ec Set tab color default off and add config for fill/border (#452) 2018-01-08 20:05:27 -05:00
Matt Irvine
62de97da54 Redraw tab background color when dragged (#442) 2018-01-08 12:40:04 -05:00
Anthony Dresser
9e051c6f63 update shrinkwrap (#445) 2018-01-04 16:32:30 -08:00
Karl Burtram
a43444e95f Bump SQL Ops to 0.25.1 for next release (#444) 2018-01-04 13:39:12 -08:00
Alex Tercete
a3948ac744 Fix "No extension gallery service configured" error (#427)
The error occurred when trying to install an extension from the new
_File > Install Extension from VSIX Package_ menu entry.

Because there's no gallery URL configured at the moment, querying the
gallery to retrieve package metadata is pointless, and skipping this
step fixes the problem for now.
2018-01-04 13:36:25 -08:00
Karl Burtram
1cd4b39e9d Revert "Remove unneeded npm package references from mssql" (#443)
* Revert "update libraries to clean node_modules (#394)"

This reverts commit e691b278ae.

* Revert "Update README.md to link to the insiders build release page (#440)"

This reverts commit 334c755118.

* Revert "Remove unneeded npm package references from mssql (#438)"

This reverts commit ee80bddd17.
2018-01-04 12:52:58 -08:00
Anthony Dresser
e691b278ae update libraries to clean node_modules (#394) 2018-01-04 11:48:21 -08:00
Karl Burtram
334c755118 Update README.md to link to the insiders build release page (#440) 2018-01-03 22:19:38 -08:00
Karl Burtram
ee80bddd17 Remove unneeded npm package references from mssql (#438) 2018-01-03 17:28:06 -08:00
Karl Burtram
c9067a0baf Install tools service relative to extension (#437) 2018-01-03 17:02:01 -08:00
Karl Burtram
ecc978a695 Update copyright date to 2018 (#431) 2018-01-03 14:47:28 -08:00
Aditya Bist
4a28e813c5 changed icon color when tree selected for light theme (#425) 2018-01-04 02:06:37 +05:30
Karl Burtram
b8db4a76b4 Fix broken Run Current Query command (#420) 2018-01-03 11:17:49 -08:00
Abbie Petchtes
e8b1b1a75f Add saved connections to connection dialog (#411)
* add saved connections to connection dialog

* fix saved connections layout

* add comments

* formatting
2018-01-02 13:41:13 -08:00
Abbie Petchtes
874b242944 fix theming issue for manage account status bar icon (#396) 2018-01-02 13:37:56 -08:00
Abbie Petchtes
da75681f83 Fix issue where loading unsave sql file open as untitiledEditorInput (#385)
* fix issue where loading unsave sql file open as untitiledEditorInput

* add SQL CARBON EDIT comment
2018-01-02 13:36:43 -08:00
Anthony Dresser
1dea81f82f Revert "idea"
This reverts commit 4826b6adc9.
2017-12-29 00:40:23 -08:00
Anthony Dresser
4826b6adc9 idea 2017-12-29 00:39:34 -08:00
Anthony Dresser
8afebd2e10 Extensions Cleanup (#359)
* clean up extensions

* updated copyrights

* formatting
2017-12-20 21:35:52 -08:00
Matt Irvine
b1b3a92717 Add tab coloring by server group (#383) 2017-12-20 18:21:48 -08:00
Karl Burtram
3ffafbe5bc Resize the start menu pinned icons to display correct (#382) 2017-12-20 13:56:27 -08:00
Karl Burtram
eb81a72b88 Update SQLOPS version to 0.25.0 for Jan release (#380) 2017-12-20 11:33:44 -08:00
Karl Burtram
2e70b55da8 Update pinned start menu icons (#379) 2017-12-20 11:27:52 -08:00
Karl Burtram
ad0c12ec95 Change 'Server name' to 'Server' (#372) 2017-12-20 10:25:10 -08:00
Aditya Bist
572aebd8c8 fixed bug where drag and drop would break scripting (#369) 2017-12-19 12:45:33 -08:00
Karl Burtram
dbb421f503 Disable custom title bar rendering on macOS (#362) 2017-12-19 00:33:42 -08:00
Karl Burtram
a75c799b34 Update download links on readme.md 2017-12-18 22:39:01 -08:00
Karl Burtram
579958409d Update readme and changelog files for Dec release (#360)
* Stage changes

* Update changelog with additional bug details
2017-12-18 21:27:21 -08:00
Karl Burtram
af2414efcb Update text in Getting Started prompt (#358) 2017-12-18 17:48:22 -08:00
Karl Burtram
18066a8c1c Turn off HotExit due to regression (#357) 2017-12-18 17:41:53 -08:00
Benjamin Russell
2e19ab4595 Adding row ID mapping to ensure correct IDs are used (#355) 2017-12-18 17:40:55 -08:00
Aditya Bist
f6497a9ac4 Context menu bug in macOS fixed (#350)
* context menu now doesnt show in origin on mac

* fixed context menu action being called twice in macOS
2017-12-18 14:45:54 -08:00
Matt Irvine
67aac4e624 Fix script as alter/execute capitalization (#349) 2017-12-18 13:55:08 -08:00
Matt Irvine
a602c7f570 Fix script executable permissions (#347) 2017-12-18 11:55:27 -08:00
Karl Burtram
4bf9955d43 Update License.txt line width to display correctly in Windows setup (#337) 2017-12-16 11:39:25 -08:00
133 changed files with 3007 additions and 5522 deletions

4
.vscode/launch.json vendored
View File

@@ -63,7 +63,7 @@
"outFiles": [ "outFiles": [
"${workspaceFolder}/out/**/*.js" "${workspaceFolder}/out/**/*.js"
] ]
}, },
{ {
"type": "chrome", "type": "chrome",
"request": "attach", "request": "attach",
@@ -95,7 +95,7 @@
"name": "Unit Tests", "name": "Unit Tests",
"protocol": "inspector", "protocol": "inspector",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops.app/Contents/MacOS/Electron", "runtimeExecutable": "${workspaceFolder}/.build/electron/SQL Operations Studio.app/Contents/MacOS/Electron",
"windows": { "windows": {
"runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops.exe" "runtimeExecutable": "${workspaceFolder}/.build/electron/sqlops.exe"
}, },

62
CHANGELOG.md Normal file
View File

@@ -0,0 +1,62 @@
# Change Log
## Version 0.25.2
* Release date: January 17, 2017
* Release status: Public Preview
## What's new in this version
The January release focuses on addressing a few of the top upvoted feature suggestions, as well as fixing high-priority bugs. This release period coincides with holiday vacations, so the churn in this release is
relatively scoped.
Here's some of the highlights in the January release.
* Tab-coloring based on Server Group
* Saved Server connections are available in Connection Dialog
* Enable HotExit feature
* Fix broken Run Current Query command
* Fix drag-and-drop breaking scripting bug
* Fix incorrect pinned Start Menu icon
* Fix missing Azure Account branding icon
* Change "Server name" to "Server" in Connection Dialog
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* alextercete for `Fix "No extension gallery service configured" error (#427)`
## Version 0.24.1
* Release date: December 19, 2017
* Release status: Public Preview
## What's new in this version
* Azure Integration with Create Firewall Rule
* Windows Setup, Linux DEB and Linux RPM installation packages
* Manage Dashboard visual layout editor
* Script As Alter and Script As Execute commands
* Integrate VS Code 1.18.1 editor platform
* Enable Sideloading of VSIX Extension files
* Support "GO N" batch iteration syntax
* "Run Current Query with Actual Plan" command
* Delete Recent Connection command in Connection Dialog
* Performance fixes for Object Explorer expansion and Scripting sprocs
* Fix IntelliSense settings namespace to be `mssql.*`
* Only show `Disconnect` menu item if server is connected
* Several snippet and default widget improvements
* Improve Kerberos connection failure error message
* Add command to hide query results window after running query
* Retain cursor line positon when switching document tabs
* Keep cursor focus in editor window after executing query
* Support shortcuts to execute common queries like sp_who or sp_help
* Fix tab order behavior when using keyboard to navigate dialog controls
* Improved chart axis and label behavior
* Allow expanding databases not in certain non-Online states
* Connection Dialog selects most common default authentication method based on platform
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with case-sensitive collation. (#152)`
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
* olljanat for `Implemented npm version check (#314)`

View File

@@ -2,21 +2,23 @@ MICROSOFT SOFTWARE LICENSE TERMS
MICROSOFT SQL OPERATIONS STUDIO MICROSOFT SQL OPERATIONS STUDIO
Microsoft Corporation (Microsoft) grants you a nonexclusive, perpetual, Microsoft Corporation ("Microsoft") grants you a nonexclusive, perpetual,
royalty-free right to use, copy, and modify the software code provided by us royalty-free right to use, copy, and modify the software code provided by us
("Software Code"). You may not sublicense the Software Code or any use of it ("Software Code"). You may not sublicense the Software Code or any use of it
(except to your affiliates and to vendors to perform work on your behalf) (except to your affiliates and to vendors to perform work on your behalf)
through distribution, network access, service agreement, lease, rental, or through distribution, network access, service agreement, lease, rental, or
otherwise. Unless applicable law gives you more rights, Microsoft reserves all otherwise. Unless applicable law gives you more rights, Microsoft reserves all
other rights not expressly granted herein, whether by implication, estoppel or other rights not expressly granted herein, whether by implication, estoppel or
otherwise.  otherwise.
 
THE SOFTWARE CODE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL MICROSOFT OR ITS WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR AND NONINFRINGEMENT. IN NO EVENT SHALL MICROSOFT OR ITS LICENSORS
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
THE USE OF THE SAMPLE CODE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
SAMPLE CODE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -2,20 +2,25 @@
SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux. SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
**Download SQL Operations Studio Public Preview 1** **Download SQL Operations Studio December Public Preview**
Platform | Link Platform | Link
-- | -- -- | --
Windows | https://go.microsoft.com/fwlink/?linkid=862648 Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=865305
macOS | https://go.microsoft.com/fwlink/?linkid=862647 Windows ZIP | https://go.microsoft.com/fwlink/?linkid=865304
Linux | https://go.microsoft.com/fwlink/?linkid=862646 macOS ZIP | https://go.microsoft.com/fwlink/?linkid=865306
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=865307
Linux DEB | https://go.microsoft.com/fwlink/?linkid=865308
Linux RPM | https://go.microsoft.com/fwlink/?linkid=865309
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions. Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
Try out the latest insiders build from `master` at https://github.com/Microsoft/sqlopsstudio/releases.
**Feature Highlights** **Feature Highlights**
- Cross-Platform DB management for Windows, macOS and Linux with simple XCopy deployment - Cross-Platform DB management for Windows, macOS and Linux with simple XCopy deployment
- SQL Server Connection Management with Connection Dialog, Server Groups, and Registered Servers - SQL Server Connection Management with Connection Dialog, Server Groups, Azure Integration and Registered Servers
- Object Explorer supporting schema browsing and contextual command execution - Object Explorer supporting schema browsing and contextual command execution
- T-SQL Query Editor with advanced coding features such as autosuggestions, error diagnostics, tooltips, formatting and peek definition - T-SQL Query Editor with advanced coding features such as autosuggestions, error diagnostics, tooltips, formatting and peek definition
- Query Results Viewer with advanced data grid supporting large result sets, export to JSON\CSV\Excel, query plan and charting - Query Results Viewer with advanced data grid supporting large result sets, export to JSON\CSV\Excel, query plan and charting
@@ -23,7 +28,7 @@ Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instruc
- Visual Data Editor that enables direct row insertion, update and deletion into tables - Visual Data Editor that enables direct row insertion, update and deletion into tables
- Backup and Restore dialogs that enables advanced customization and remote filesystem browsing, configured tasks can be executed or scripted - Backup and Restore dialogs that enables advanced customization and remote filesystem browsing, configured tasks can be executed or scripted
- Task History window to view current task execution status, completion results with error messages and task T-SQL scripting - Task History window to view current task execution status, completion results with error messages and task T-SQL scripting
- Scripting support to generate CREATE, SELECT and DROP statements for database objects - Scripting support to generate CREATE, SELECT, ALTER and DROP statements for database objects
- Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries - Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries
- Modern light-weight shell with theming, user settings, full screen support, integrated terminal and numerous other features - Modern light-weight shell with theming, user settings, full screen support, integrated terminal and numerous other features

View File

@@ -157,7 +157,7 @@ const config = {
version: packageJson.electronVersion, version: packageJson.electronVersion,
productAppName: product.nameLong, productAppName: product.nameLong,
companyName: 'Microsoft Corporation', companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2017 Microsoft. All rights reserved', copyright: 'Copyright (C) 2018 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns', darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier, darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools', darwinApplicationCategoryType: 'public.app-category.developer-tools',
@@ -167,7 +167,7 @@ const config = {
name: product.nameLong + ' document', name: product.nameLong + ' document',
role: 'Editor', role: 'Editor',
ostypes: ["TEXT", "utxt", "TUTX", "****"], ostypes: ["TEXT", "utxt", "TUTX", "****"],
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
extensions: ["csv", "json", "sqlplan", "sql", "xml"], extensions: ["csv", "json", "sqlplan", "sql", "xml"],
iconFile: 'resources/darwin/code_file.icns' iconFile: 'resources/darwin/code_file.icns'
}], }],
@@ -289,9 +289,9 @@ function packageTask(platform, arch, opts) {
const sources = es.merge(src, localExtensions, localExtensionDependencies) const sources = es.merge(src, localExtensions, localExtensionDependencies)
.pipe(util.setExecutableBit(['**/*.sh'])) .pipe(util.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', .pipe(filter(['**',
'!**/*.js.map', '!**/*.js.map',
'!extensions/**/node_modules/**/{test, tests}/**', '!extensions/**/node_modules/**/{test, tests}/**',
'!extensions/**/node_modules/**/test.js'])); '!extensions/**/node_modules/**/test.js']));
let version = packageJson.version; let version = packageJson.version;
const quality = product.quality; const quality = product.quality;
@@ -316,7 +316,7 @@ function packageTask(platform, arch, opts) {
// TODO the API should be copied to `out` during compile, not here // TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts')); const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts')); const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const depsSrc = _.flatten(dependencies const depsSrc = _.flatten(dependencies
.map(function (d) { return ['node_modules/' + d + '/**', '!node_modules/' + d + '/**/{test,tests}/**']; })); .map(function (d) { return ['node_modules/' + d + '/**', '!node_modules/' + d + '/**/{test,tests}/**']; }));
@@ -620,8 +620,8 @@ gulp.task('generate-vscode-configuration', () => {
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
// Install service locally before building carbon // Install service locally before building carbon
function installService(extObj) { function installService(extObj, path) {
var installer = new serviceInstaller.ServiceInstaller(extObj, true); var installer = new serviceInstaller.ServiceInstaller(extObj, path);
installer.getServiceInstallDirectoryRoot().then(serviceInstallFolder => { installer.getServiceInstallDirectoryRoot().then(serviceInstallFolder => {
console.log('Cleaning up the install folder: ' + serviceInstallFolder); console.log('Cleaning up the install folder: ' + serviceInstallFolder);
del(serviceInstallFolder + '/*').then(() => { del(serviceInstallFolder + '/*').then(() => {
@@ -639,7 +639,8 @@ function installService(extObj) {
gulp.task('install-sqltoolsservice', () => { gulp.task('install-sqltoolsservice', () => {
var mssqlExt = require('../extensions/mssql/client/out/models/constants'); var mssqlExt = require('../extensions/mssql/client/out/models/constants');
var extObj = new mssqlExt.Constants(); var extObj = new mssqlExt.Constants();
return installService(extObj); var path = '../extensions/mssql/client/out/config.json';
return installService(extObj, path);
}); });

View File

@@ -41,7 +41,8 @@ const extensions = [
'extension-editing', 'extension-editing',
'markdown', 'markdown',
'merge-conflict', 'merge-conflict',
'insights-default' 'insights-default',
'account-provider-azure'
]; ];
extensions.forEach(extension => npmInstall(`extensions/${extension}`)); extensions.forEach(extension => npmInstall(`extensions/${extension}`));

View File

@@ -0,0 +1,9 @@
.vscode/
lib/test/
lib/**/*.map
src/
test/
.eslintrc
.gitignore
gulpfile.js
tsd.json

View File

@@ -6,8 +6,8 @@
'use strict'; 'use strict';
const fs = require('fs'); const fs = require('fs');
import * as path from 'path'; import * as path from 'path';
import {IConfig} from '../languageservice/interfaces'; import { IConfig } from '../languageservice/interfaces';
import * as SharedConstants from '../models/constants'; import { Constants } from '../models/constants';
/* /*
* Config class handles getting values from config.json. * Config class handles getting values from config.json.
@@ -18,7 +18,7 @@ export default class Config implements IConfig {
private _extensionConfigSectionName: string = undefined; private _extensionConfigSectionName: string = undefined;
private _fromBuild: boolean = undefined; private _fromBuild: boolean = undefined;
constructor(extensionConfigSectionName: string, fromBuild?: boolean) { constructor(extensionConfigSectionName: string, private path: string, fromBuild?: boolean) {
this._extensionConfigSectionName = extensionConfigSectionName; this._extensionConfigSectionName = extensionConfigSectionName;
this._fromBuild = fromBuild; this._fromBuild = fromBuild;
} }
@@ -31,24 +31,24 @@ export default class Config implements IConfig {
} }
public getDownloadUrl(): string { public getDownloadUrl(): string {
return this.getConfigValue(SharedConstants.downloadUrlConfigKey); return this.getConfigValue(Constants.downloadUrlConfigKey);
} }
public getInstallDirectory(): string { public getInstallDirectory(): string {
return this.getConfigValue(SharedConstants.installDirConfigKey); return this.getConfigValue(Constants.installDirConfigKey);
} }
public getExecutableFiles(): string[] { public getExecutableFiles(): string[] {
return this.getConfigValue(SharedConstants.executableFilesConfigKey); return this.getConfigValue(Constants.executableFilesConfigKey);
} }
public getPackageVersion(): string { public getPackageVersion(): string {
return this.getConfigValue(SharedConstants.versionConfigKey); return this.getConfigValue(Constants.versionConfigKey);
} }
public getConfigValue(configKey: string): any { public getConfigValue(configKey: string): any {
let json = this.configJsonContent; let json = this.configJsonContent;
let toolsConfig = json[SharedConstants.serviceConfigKey]; let toolsConfig = json[Constants.serviceConfigKey];
let configValue: string = undefined; let configValue: string = undefined;
if (toolsConfig !== undefined) { if (toolsConfig !== undefined) {
configValue = toolsConfig[configKey]; configValue = toolsConfig[configKey];
@@ -82,7 +82,7 @@ export default class Config implements IConfig {
configContent = fs.readFileSync(path.join(__dirname, remainingPath)); configContent = fs.readFileSync(path.join(__dirname, remainingPath));
} }
else { else {
configContent = fs.readFileSync(path.join(__dirname, '../../../../client/out/config.json')); configContent = fs.readFileSync(this.path);
} }
return JSON.parse(configContent); return JSON.parse(configContent);
} }

View File

@@ -5,10 +5,10 @@
'use strict'; 'use strict';
import Config from './config'; import Config from './config';
import { workspace, WorkspaceConfiguration } from 'vscode'; import { workspace, WorkspaceConfiguration } from 'vscode';
import {IConfig} from '../languageservice/interfaces'; import { IConfig } from '../languageservice/interfaces';
import * as Constants from '../models/constants'; import { Constants } from '../models/constants';
/* /*
* ExtConfig class handles getting values from workspace config or config.json. * ExtConfig class handles getting values from workspace config or config.json.
@@ -16,10 +16,11 @@ import * as Constants from '../models/constants';
export default class ExtConfig implements IConfig { export default class ExtConfig implements IConfig {
constructor(private _extensionConfigSectionName: string, private _config?: IConfig, constructor(private _extensionConfigSectionName: string, private _config?: IConfig,
path?: string,
private _extensionConfig?: WorkspaceConfiguration, private _extensionConfig?: WorkspaceConfiguration,
private _workspaceConfig?: WorkspaceConfiguration) { private _workspaceConfig?: WorkspaceConfiguration) {
if (this._config === undefined) { if (this._config === undefined) {
this._config = new Config(_extensionConfigSectionName); this._config = new Config(_extensionConfigSectionName, path);
} }
if (this._extensionConfig === undefined) { if (this._extensionConfig === undefined) {
this._extensionConfig = workspace.getConfiguration(_extensionConfigSectionName); this._extensionConfig = workspace.getConfiguration(_extensionConfigSectionName);

View File

@@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import vscode = require('vscode'); import vscode = require('vscode');
import {IExtensionConstants} from '../models/contracts/contracts'; import { IExtensionConstants } from '../models/contracts/contracts';
export import TextEditor = vscode.TextEditor; export class VscodeWrapper {
export default class VscodeWrapper {
private _extensionConstants: IExtensionConstants; private _extensionConstants: IExtensionConstants;
/** /**
* Output channel for logging. Shared among all instances. * Output channel for logging. Shared among all instances.

View File

@@ -5,8 +5,8 @@
'use strict'; 'use strict';
import {IDecompressProvider, IPackage} from './interfaces'; import { IDecompressProvider, IPackage } from './interfaces';
import {ILogger} from '../models/interfaces'; import { ILogger } from '../models/interfaces';
const decompress = require('decompress'); const decompress = require('decompress');
export default class DecompressProvider implements IDecompressProvider { export default class DecompressProvider implements IDecompressProvider {

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {IPackage, IStatusView, PackageError, IHttpClient} from './interfaces'; import { IPackage, IStatusView, PackageError, IHttpClient } from './interfaces';
import {ILogger} from '../models/interfaces'; import { ILogger } from '../models/interfaces';
import {parse as parseUrl, Url} from 'url'; import { parse as parseUrl, Url } from 'url';
import * as https from 'https'; import * as https from 'https';
import * as http from 'http'; import * as http from 'http';
import {getProxyAgent} from './proxy'; import { getProxyAgent } from './proxy';
let fs = require('fs'); const fs = require('fs');
/* /*
* Http client class to handle downloading files using http or https urls * Http client class to handle downloading files using http or https urls

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as tmp from 'tmp'; import * as tmp from 'tmp';
import {ILogger} from '../models/interfaces'; import { ILogger } from '../models/interfaces';
export interface IStatusView { export interface IStatusView {
installingService(): void; installingService(): void;

View File

@@ -6,8 +6,8 @@
'use strict'; 'use strict';
import { Url, parse as parseUrl } from 'url'; import { Url, parse as parseUrl } from 'url';
let HttpProxyAgent = require('http-proxy-agent'); const HttpProxyAgent = require('http-proxy-agent');
let HttpsProxyAgent = require('https-proxy-agent'); const HttpsProxyAgent = require('https-proxy-agent');
function getSystemProxyURL(requestURL: Url): string { function getSystemProxyURL(requestURL: Url): string {
if (requestURL.protocol === 'http:') { if (requestURL.protocol === 'http:') {

View File

@@ -6,10 +6,10 @@
'use strict'; 'use strict';
import * as path from 'path'; import * as path from 'path';
import {Runtime} from '../models/platform'; import { Runtime } from '../models/platform';
import ServiceDownloadProvider from './serviceDownloadProvider'; import ServiceDownloadProvider from './serviceDownloadProvider';
import {IConfig, IStatusView} from './interfaces'; import { IConfig, IStatusView } from './interfaces';
let fs = require('fs-extra-promise'); const fs = require('fs-extra-promise');
/* /*

View File

@@ -5,10 +5,10 @@
'use strict'; 'use strict';
import {IStatusView} from './interfaces'; import { IStatusView } from './interfaces';
import vscode = require('vscode'); import vscode = require('vscode');
import {IExtensionConstants} from '../models/contracts/contracts'; import { IExtensionConstants } from '../models/contracts/contracts';
import * as Constants from '../models/constants'; import { Constants } from '../models/constants';
/* /*
* The status class which includes the service initialization result. * The status class which includes the service initialization result.

View File

@@ -1,44 +1,42 @@
/* -------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import { ExtensionContext, workspace, window, OutputChannel, languages } from 'vscode'; import { ExtensionContext, workspace, window, OutputChannel, languages } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, import {
TransportKind, RequestType, NotificationType, NotificationHandler, LanguageClient, LanguageClientOptions, ServerOptions,
ErrorAction, CloseAction } from 'dataprotocol-client'; TransportKind, RequestType, NotificationType, NotificationHandler,
ErrorAction, CloseAction
} from 'dataprotocol-client';
import VscodeWrapper from '../controllers/vscodeWrapper'; import { VscodeWrapper } from '../controllers/vscodeWrapper';
import Telemetry from '../models/telemetry'; import { Telemetry } from '../models/telemetry';
import * as Utils from '../models/utils'; import { Utils } from '../models/utils';
import {VersionRequest, IExtensionConstants} from '../models/contracts/contracts'; import { VersionRequest, IExtensionConstants } from '../models/contracts/contracts';
import {Logger} from '../models/logger'; import { Logger } from '../models/logger';
import Constants = require('../models/constants');
import {ILanguageClientHelper} from '../models/contracts/languageService';
import ServerProvider from './server'; import ServerProvider from './server';
import ServiceDownloadProvider from './serviceDownloadProvider'; import ServiceDownloadProvider from './serviceDownloadProvider';
import DecompressProvider from './decompressProvider'; import DecompressProvider from './decompressProvider';
import HttpClient from './httpClient'; import HttpClient from './httpClient';
import ExtConfig from '../configurations/extConfig'; import ExtConfig from '../configurations/extConfig';
import {PlatformInformation, Runtime} from '../models/platform'; import { PlatformInformation, Runtime } from '../models/platform';
import {ServerInitializationResult, ServerStatusView} from './serverStatus'; import { ServerInitializationResult, ServerStatusView } from './serverStatus';
import StatusView from '../views/statusView'; import StatusView from '../views/statusView';
import * as LanguageServiceContracts from '../models/contracts/languageService'; import * as LanguageServiceContracts from '../models/contracts/languageService';
import * as SharedConstants from '../models/constants'; import { Constants } from '../models/constants';
import * as utils from '../models/utils';
var path = require('path');
import ServiceStatus from './serviceStatus'; import ServiceStatus from './serviceStatus';
let opener = require('opener'); const opener = require('opener');
const path = require('path');
let _channel: OutputChannel = undefined; let _channel: OutputChannel = undefined;
const fs = require('fs-extra');
/** /**
* @interface IMessage * @interface IMessage
*/ */
interface IMessage { interface IMessage {
jsonrpc: string; jsonrpc: string;
} }
/** /**
@@ -47,446 +45,446 @@ interface IMessage {
*/ */
class LanguageClientErrorHandler { class LanguageClientErrorHandler {
private vscodeWrapper: VscodeWrapper; private vscodeWrapper: VscodeWrapper;
/** /**
* Creates an instance of LanguageClientErrorHandler. * Creates an instance of LanguageClientErrorHandler.
* @memberOf LanguageClientErrorHandler * @memberOf LanguageClientErrorHandler
*/ */
constructor(constants: IExtensionConstants) { constructor(constants: IExtensionConstants) {
if (!this.vscodeWrapper) { if (!this.vscodeWrapper) {
this.vscodeWrapper = new VscodeWrapper(constants); this.vscodeWrapper = new VscodeWrapper(constants);
} }
Telemetry.getRuntimeId = this.vscodeWrapper.constants.getRuntimeId; Telemetry.getRuntimeId = this.vscodeWrapper.constants.getRuntimeId;
} }
/** /**
* Show an error message prompt with a link to known issues wiki page * Show an error message prompt with a link to known issues wiki page
* @memberOf LanguageClientErrorHandler * @memberOf LanguageClientErrorHandler
*/ */
showOnErrorPrompt(): void { showOnErrorPrompt(): void {
let extensionConstants = this.vscodeWrapper.constants; let extensionConstants = this.vscodeWrapper.constants;
Telemetry.sendTelemetryEvent(extensionConstants.serviceName + 'Crash'); Telemetry.sendTelemetryEvent(extensionConstants.serviceName + 'Crash');
this.vscodeWrapper.showErrorMessage( this.vscodeWrapper.showErrorMessage(
extensionConstants.serviceCrashMessage, extensionConstants.serviceCrashMessage,
SharedConstants.serviceCrashButton).then(action => { Constants.serviceCrashButton).then(action => {
if (action && action === SharedConstants.serviceCrashButton) { if (action && action === Constants.serviceCrashButton) {
opener(extensionConstants.serviceCrashLink); opener(extensionConstants.serviceCrashLink);
} }
}); });
} }
/** /**
* Callback for language service client error * Callback for language service client error
* *
* @param {Error} error * @param {Error} error
* @param {Message} message * @param {Message} message
* @param {number} count * @param {number} count
* @returns {ErrorAction} * @returns {ErrorAction}
* *
* @memberOf LanguageClientErrorHandler * @memberOf LanguageClientErrorHandler
*/ */
error(error: Error, message: IMessage, count: number): ErrorAction { error(error: Error, message: IMessage, count: number): ErrorAction {
this.showOnErrorPrompt(); this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension // we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state // in a bad, unrecovered state
return ErrorAction.Shutdown; return ErrorAction.Shutdown;
} }
/** /**
* Callback for language service client closed * Callback for language service client closed
* *
* @returns {CloseAction} * @returns {CloseAction}
* *
* @memberOf LanguageClientErrorHandler * @memberOf LanguageClientErrorHandler
*/ */
closed(): CloseAction { closed(): CloseAction {
this.showOnErrorPrompt(); this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension // we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state // in a bad, unrecovered state
return CloseAction.DoNotRestart; return CloseAction.DoNotRestart;
} }
} }
// The Service Client class handles communication with the VS Code LanguageClient // The Service Client class handles communication with the VS Code LanguageClient
export default class SqlToolsServiceClient { export class SqlToolsServiceClient {
// singleton instance // singleton instance
private static _instance: SqlToolsServiceClient = undefined; private static _instance: SqlToolsServiceClient = undefined;
private static _constants: IExtensionConstants = undefined; private static _constants: IExtensionConstants = undefined;
public static get constants(): IExtensionConstants { public static get constants(): IExtensionConstants {
return this._constants; return this._constants;
} }
public static set constants(constantsObject: IExtensionConstants) { public static set constants(constantsObject: IExtensionConstants) {
this._constants = constantsObject; this._constants = constantsObject;
Telemetry.getRuntimeId = this._constants.getRuntimeId; Telemetry.getRuntimeId = this._constants.getRuntimeId;
} }
private static _helper: ILanguageClientHelper = undefined; private static _helper: LanguageServiceContracts.ILanguageClientHelper = undefined;
public static get helper(): ILanguageClientHelper { public static get helper(): LanguageServiceContracts.ILanguageClientHelper {
return this._helper; return this._helper;
} }
public static set helper(helperObject: ILanguageClientHelper) { public static set helper(helperObject: LanguageServiceContracts.ILanguageClientHelper) {
this._helper = helperObject; this._helper = helperObject;
} }
// VS Code Language Client // VS Code Language Client
private _client: LanguageClient = undefined; private _client: LanguageClient = undefined;
// getter method for the Language Client // getter method for the Language Client
private get client(): LanguageClient { private get client(): LanguageClient {
return this._client; return this._client;
} }
private set client(client: LanguageClient) { private set client(client: LanguageClient) {
this._client = client; this._client = client;
} }
public installDirectory: string; public installDirectory: string;
private _downloadProvider: ServiceDownloadProvider; private _downloadProvider: ServiceDownloadProvider;
private _vscodeWrapper: VscodeWrapper; private _vscodeWrapper: VscodeWrapper;
private _serviceStatus: ServiceStatus; private _serviceStatus: ServiceStatus;
private _languageClientStartTime: number = undefined; private _languageClientStartTime: number = undefined;
private _installationTime: number = undefined; private _installationTime: number = undefined;
constructor( constructor(
private _server: ServerProvider, private _server: ServerProvider,
private _logger: Logger, private _logger: Logger,
private _statusView: StatusView, private _statusView: StatusView,
private _config: ExtConfig) { private _config: ExtConfig) {
this._downloadProvider = _server.downloadProvider; this._downloadProvider = _server.downloadProvider;
if (!this._vscodeWrapper) { if (!this._vscodeWrapper) {
this._vscodeWrapper = new VscodeWrapper(SqlToolsServiceClient.constants); this._vscodeWrapper = new VscodeWrapper(SqlToolsServiceClient.constants);
} }
this._serviceStatus = new ServiceStatus(SqlToolsServiceClient._constants.serviceName); this._serviceStatus = new ServiceStatus(SqlToolsServiceClient._constants.serviceName);
} }
// gets or creates the singleton service client instance // gets or creates the singleton service client instance
public static get instance(): SqlToolsServiceClient { public static getInstance(path: string): SqlToolsServiceClient {
if (this._instance === undefined) { if (this._instance === undefined) {
let constants = this._constants; let constants = this._constants;
let config = new ExtConfig(constants.extensionConfigSectionName); let config = new ExtConfig(constants.extensionConfigSectionName, undefined, path);
_channel = window.createOutputChannel(constants.serviceInitializingOutputChannelName); _channel = window.createOutputChannel(constants.serviceInitializingOutputChannelName);
let logger = new Logger(text => _channel.append(text), constants); let logger = new Logger(text => _channel.append(text), constants);
let serverStatusView = new ServerStatusView(constants); let serverStatusView = new ServerStatusView(constants);
let httpClient = new HttpClient(); let httpClient = new HttpClient();
let decompressProvider = new DecompressProvider(); let decompressProvider = new DecompressProvider();
let downloadProvider = new ServiceDownloadProvider(config, logger, serverStatusView, httpClient, let downloadProvider = new ServiceDownloadProvider(config, logger, serverStatusView, httpClient,
decompressProvider, constants, false); decompressProvider, constants, false);
let serviceProvider = new ServerProvider(downloadProvider, config, serverStatusView, constants.extensionConfigSectionName); let serviceProvider = new ServerProvider(downloadProvider, config, serverStatusView, constants.extensionConfigSectionName);
let statusView = new StatusView(); let statusView = new StatusView();
this._instance = new SqlToolsServiceClient(serviceProvider, logger, statusView, config); this._instance = new SqlToolsServiceClient(serviceProvider, logger, statusView, config);
} }
return this._instance; return this._instance;
} }
// initialize the Service Client instance by launching // initialize the Service Client instance by launching
// out-of-proc server through the LanguageClient // out-of-proc server through the LanguageClient
public initialize(context: ExtensionContext): Promise<any> { public initialize(context: ExtensionContext): Promise<any> {
this._logger.appendLine(SqlToolsServiceClient._constants.serviceInitializing); this._logger.appendLine(SqlToolsServiceClient._constants.serviceInitializing);
this._languageClientStartTime = Date.now(); this._languageClientStartTime = Date.now();
return PlatformInformation.getCurrent(SqlToolsServiceClient._constants.getRuntimeId, SqlToolsServiceClient._constants.extensionName).then(platformInfo => { return PlatformInformation.getCurrent(SqlToolsServiceClient._constants.getRuntimeId, SqlToolsServiceClient._constants.extensionName).then(platformInfo => {
return this.initializeForPlatform(platformInfo, context); return this.initializeForPlatform(platformInfo, context);
}).catch(err => { }).catch(err => {
this._vscodeWrapper.showErrorMessage(err) this._vscodeWrapper.showErrorMessage(err);
}); });
} }
public initializeForPlatform(platformInfo: PlatformInformation, context: ExtensionContext): Promise<ServerInitializationResult> { public initializeForPlatform(platformInfo: PlatformInformation, context: ExtensionContext): Promise<ServerInitializationResult> {
return new Promise<ServerInitializationResult>( (resolve, reject) => { return new Promise<ServerInitializationResult>((resolve, reject) => {
this._logger.appendLine(SqlToolsServiceClient._constants.commandsNotAvailableWhileInstallingTheService); this._logger.appendLine(SqlToolsServiceClient._constants.commandsNotAvailableWhileInstallingTheService);
this._logger.appendLine(); this._logger.appendLine();
this._logger.append(`Platform: ${platformInfo.toString()}`); this._logger.append(`Platform: ${platformInfo.toString()}`);
if (!platformInfo.isValidRuntime()) { if (!platformInfo.isValidRuntime()) {
// if it's an unknown Linux distro then try generic Linux x64 and give a warning to the user // if it's an unknown Linux distro then try generic Linux x64 and give a warning to the user
if (platformInfo.isLinux()) { if (platformInfo.isLinux()) {
this._logger.appendLine(Constants.usingDefaultPlatformMessage); this._logger.appendLine(Constants.usingDefaultPlatformMessage);
platformInfo.runtimeId = Runtime.Linux_64; platformInfo.runtimeId = Runtime.Linux_64;
} }
let ignoreWarning: boolean = this._config.getWorkspaceConfig(Constants.ignorePlatformWarning, false); let ignoreWarning: boolean = this._config.getWorkspaceConfig(Constants.ignorePlatformWarning, false);
if (!ignoreWarning) { if (!ignoreWarning) {
this._vscodeWrapper.showErrorMessage( this._vscodeWrapper.showErrorMessage(
Constants.unsupportedPlatformErrorMessage, Constants.unsupportedPlatformErrorMessage,
Constants.neverShowAgain) Constants.neverShowAgain)
.then(action => { .then(action => {
if (action === Constants.neverShowAgain) { if (action === Constants.neverShowAgain) {
this._config.updateWorkspaceConfig(Constants.ignorePlatformWarning, true); this._config.updateWorkspaceConfig(Constants.ignorePlatformWarning, true);
} }
}); });
} }
Telemetry.sendTelemetryEvent('UnsupportedPlatform', {platform: platformInfo.toString()} ); Telemetry.sendTelemetryEvent('UnsupportedPlatform', { platform: platformInfo.toString() });
} }
if (platformInfo.runtimeId) { if (platformInfo.runtimeId) {
this._logger.appendLine(` (${platformInfo.getRuntimeDisplayName()})`); this._logger.appendLine(` (${platformInfo.getRuntimeDisplayName()})`);
} else { } else {
this._logger.appendLine(); this._logger.appendLine();
} }
this._logger.appendLine(); this._logger.appendLine();
this._server.getServerPath(platformInfo.runtimeId).then(serverPath => { this._server.getServerPath(platformInfo.runtimeId).then(serverPath => {
if (serverPath === undefined) { if (serverPath === undefined) {
// Check if the service already installed and if not open the output channel to show the logs // Check if the service already installed and if not open the output channel to show the logs
if (_channel !== undefined) { if (_channel !== undefined) {
_channel.show(); _channel.show();
} }
let installationStartTime = Date.now(); let installationStartTime = Date.now();
this._server.downloadServerFiles(platformInfo.runtimeId).then ( installedServerPath => { this._server.downloadServerFiles(platformInfo.runtimeId).then(installedServerPath => {
this._installationTime = Date.now() - installationStartTime; this._installationTime = Date.now() - installationStartTime;
this.initializeLanguageClient(installedServerPath, context, platformInfo.runtimeId); this.initializeLanguageClient(installedServerPath, context, platformInfo.runtimeId);
resolve(new ServerInitializationResult(true, true, installedServerPath)); resolve(new ServerInitializationResult(true, true, installedServerPath));
}).catch(downloadErr => { }).catch(downloadErr => {
reject(downloadErr); reject(downloadErr);
}); });
} else { } else {
this.initializeLanguageClient(serverPath, context, platformInfo.runtimeId); this.initializeLanguageClient(serverPath, context, platformInfo.runtimeId);
resolve(new ServerInitializationResult(false, true, serverPath)); resolve(new ServerInitializationResult(false, true, serverPath));
} }
}).catch(err => { }).catch(err => {
Utils.logDebug(SqlToolsServiceClient._constants.serviceLoadingFailed + ' ' + err, SqlToolsServiceClient._constants.extensionConfigSectionName); Utils.logDebug(SqlToolsServiceClient._constants.serviceLoadingFailed + ' ' + err, SqlToolsServiceClient._constants.extensionConfigSectionName);
Utils.showErrorMsg(SqlToolsServiceClient._constants.serviceLoadingFailed, SqlToolsServiceClient._constants.extensionName); Utils.showErrorMsg(SqlToolsServiceClient._constants.serviceLoadingFailed, SqlToolsServiceClient._constants.extensionName);
Telemetry.sendTelemetryEvent('ServiceInitializingFailed'); Telemetry.sendTelemetryEvent('ServiceInitializingFailed');
reject(err); reject(err);
}); });
}); });
} }
/** /**
* Initializes the SQL language configuration * Initializes the SQL language configuration
* *
* @memberOf SqlToolsServiceClient * @memberOf SqlToolsServiceClient
*/ */
private initializeLanguageConfiguration(): void { private initializeLanguageConfiguration(): void {
languages.setLanguageConfiguration('sql', { languages.setLanguageConfiguration('sql', {
comments: { comments: {
lineComment: '--', lineComment: '--',
blockComment: ['/*', '*/'] blockComment: ['/*', '*/']
}, },
brackets: [ brackets: [
['{', '}'], ['{', '}'],
['[', ']'], ['[', ']'],
['(', ')'] ['(', ')']
], ],
__characterPairSupport: { __characterPairSupport: {
autoClosingPairs: [ autoClosingPairs: [
{ open: '{', close: '}' }, { open: '{', close: '}' },
{ open: '[', close: ']' }, { open: '[', close: ']' },
{ open: '(', close: ')' }, { open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] }, { open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] } { open: '\'', close: '\'', notIn: ['string', 'comment'] }
] ]
} }
}); });
} }
private initializeLanguageClient(serverPath: string, context: ExtensionContext, runtimeId: Runtime): void { private initializeLanguageClient(serverPath: string, context: ExtensionContext, runtimeId: Runtime): void {
if (serverPath === undefined) { if (serverPath === undefined) {
Utils.logDebug(SqlToolsServiceClient._constants.invalidServiceFilePath, SqlToolsServiceClient._constants.extensionConfigSectionName); Utils.logDebug(SqlToolsServiceClient._constants.invalidServiceFilePath, SqlToolsServiceClient._constants.extensionConfigSectionName);
throw new Error(SqlToolsServiceClient._constants.invalidServiceFilePath); throw new Error(SqlToolsServiceClient._constants.invalidServiceFilePath);
} else { } else {
let self = this; let self = this;
if (SqlToolsServiceClient._constants.languageId === 'sql') { if (SqlToolsServiceClient._constants.languageId === 'sql') {
self.initializeLanguageConfiguration(); self.initializeLanguageConfiguration();
} }
// Use default createServerOptions if one isn't specified // Use default createServerOptions if one isn't specified
let serverOptions: ServerOptions = SqlToolsServiceClient._helper ? let serverOptions: ServerOptions = SqlToolsServiceClient._helper ?
SqlToolsServiceClient._helper.createServerOptions(serverPath, runtimeId) : self.createServerOptions(serverPath); SqlToolsServiceClient._helper.createServerOptions(serverPath, runtimeId) : self.createServerOptions(serverPath);
this.client = this.createLanguageClient(serverOptions); this.client = this.createLanguageClient(serverOptions);
this.installDirectory = this._downloadProvider.getInstallDirectory(runtimeId, SqlToolsServiceClient._constants.extensionConfigSectionName); this.installDirectory = this._downloadProvider.getInstallDirectory(runtimeId, SqlToolsServiceClient._constants.extensionConfigSectionName);
if (context !== undefined) { if (context !== undefined) {
// Create the language client and start the client. // Create the language client and start the client.
let disposable = this.client.start(); let disposable = this.client.start();
// Push the disposable to the context's subscriptions so that the // Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation // client can be deactivated on extension deactivation
context.subscriptions.push(disposable); context.subscriptions.push(disposable);
} }
} }
} }
public createClient(context: ExtensionContext, runtimeId: Runtime, languageClientHelper: ILanguageClientHelper, executableFiles: string[]): Promise<LanguageClient> { public createClient(context: ExtensionContext, runtimeId: Runtime, languageClientHelper: LanguageServiceContracts.ILanguageClientHelper, executableFiles: string[]): Promise<LanguageClient> {
return new Promise<LanguageClient>( (resolve, reject) => { return new Promise<LanguageClient>((resolve, reject) => {
let client: LanguageClient; let client: LanguageClient;
this._server.findServerPath(this.installDirectory, executableFiles).then(serverPath => { this._server.findServerPath(this.installDirectory, executableFiles).then(serverPath => {
if (serverPath === undefined) { if (serverPath === undefined) {
reject(new Error(SqlToolsServiceClient._constants.invalidServiceFilePath)); reject(new Error(SqlToolsServiceClient._constants.invalidServiceFilePath));
} else { } else {
let serverOptions: ServerOptions = languageClientHelper ? let serverOptions: ServerOptions = languageClientHelper ?
languageClientHelper.createServerOptions(serverPath, runtimeId) : this.createServerOptions(serverPath); languageClientHelper.createServerOptions(serverPath, runtimeId) : this.createServerOptions(serverPath);
// Options to control the language client // Options to control the language client
let clientOptions: LanguageClientOptions = { let clientOptions: LanguageClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId], documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: '', providerId: '',
synchronize: { synchronize: {
configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName
}, },
errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants), errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants),
serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata) serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata)
}; };
this._serviceStatus.showServiceLoading(); this._serviceStatus.showServiceLoading();
// cache the client instance for later use // cache the client instance for later use
client = new LanguageClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions); client = new LanguageClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
if (context !== undefined) { if (context !== undefined) {
// Create the language client and start the client. // Create the language client and start the client.
let disposable = client.start(); let disposable = client.start();
// Push the disposable to the context's subscriptions so that the // Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation // client can be deactivated on extension deactivation
context.subscriptions.push(disposable); context.subscriptions.push(disposable);
} }
client.onReady().then(this._serviceStatus.showServiceLoaded); client.onReady().then(this._serviceStatus.showServiceLoaded);
resolve(client); resolve(client);
} }
}, error => { }, error => {
reject(error); reject(error);
}); });
}); });
} }
private createServerOptions(servicePath): ServerOptions { private createServerOptions(servicePath): ServerOptions {
let serverArgs = []; let serverArgs = [];
let serverCommand: string = servicePath; let serverCommand: string = servicePath;
if (servicePath.endsWith('.dll')) { if (servicePath.endsWith('.dll')) {
serverArgs = [servicePath]; serverArgs = [servicePath];
serverCommand = 'dotnet'; serverCommand = 'dotnet';
} }
// Enable diagnostic logging in the service if it is configured // Enable diagnostic logging in the service if it is configured
let config = workspace.getConfiguration(SqlToolsServiceClient._constants.extensionConfigSectionName); let config = workspace.getConfiguration(SqlToolsServiceClient._constants.extensionConfigSectionName);
if (config) { if (config) {
let logDebugInfo = config[Constants.configLogDebugInfo]; let logDebugInfo = config[Constants.configLogDebugInfo];
if (logDebugInfo) { if (logDebugInfo) {
serverArgs.push('--enable-logging'); serverArgs.push('--enable-logging');
} }
} }
serverArgs.push('--log-dir'); serverArgs.push('--log-dir');
let logFileLocation = path.join(utils.getDefaultLogLocation(), SqlToolsServiceClient.constants.extensionName); let logFileLocation = path.join(Utils.getDefaultLogLocation(), SqlToolsServiceClient.constants.extensionName);
serverArgs.push(logFileLocation); serverArgs.push(logFileLocation);
// run the service host using dotnet.exe from the path // run the service host using dotnet.exe from the path
let serverOptions: ServerOptions = { command: serverCommand, args: serverArgs, transport: TransportKind.stdio }; let serverOptions: ServerOptions = { command: serverCommand, args: serverArgs, transport: TransportKind.stdio };
return serverOptions; return serverOptions;
} }
private createLanguageClient(serverOptions: ServerOptions): LanguageClient { private createLanguageClient(serverOptions: ServerOptions): LanguageClient {
// Options to control the language client // Options to control the language client
let clientOptions: LanguageClientOptions = { let clientOptions: LanguageClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId], documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: SqlToolsServiceClient._constants.providerId, providerId: SqlToolsServiceClient._constants.providerId,
synchronize: { synchronize: {
configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName
}, },
errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants), errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants),
serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata) serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata)
}; };
this._serviceStatus.showServiceLoading(); this._serviceStatus.showServiceLoading();
// cache the client instance for later use // cache the client instance for later use
let client = new LanguageClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions); let client = new LanguageClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
client.onReady().then( () => { client.onReady().then(() => {
this.checkServiceCompatibility(); this.checkServiceCompatibility();
this._serviceStatus.showServiceLoaded(); this._serviceStatus.showServiceLoaded();
client.onNotification(LanguageServiceContracts.TelemetryNotification.type, this.handleLanguageServiceTelemetryNotification()); client.onNotification(LanguageServiceContracts.TelemetryNotification.type, this.handleLanguageServiceTelemetryNotification());
client.onNotification(LanguageServiceContracts.StatusChangedNotification.type, this.handleLanguageServiceStatusNotification()); client.onNotification(LanguageServiceContracts.StatusChangedNotification.type, this.handleLanguageServiceStatusNotification());
// Report the language client startup time // Report the language client startup time
let endTime = Date.now(); let endTime = Date.now();
let installationTime = this._installationTime || 0; let installationTime = this._installationTime || 0;
let totalTime = endTime - this._languageClientStartTime; let totalTime = endTime - this._languageClientStartTime;
let processStartupTime = totalTime - installationTime; let processStartupTime = totalTime - installationTime;
Telemetry.sendTelemetryEvent('startup/LanguageClientStarted', { Telemetry.sendTelemetryEvent('startup/LanguageClientStarted', {
installationTime: String(installationTime), installationTime: String(installationTime),
processStartupTime: String(processStartupTime), processStartupTime: String(processStartupTime),
totalTime: String(totalTime), totalTime: String(totalTime),
beginningTimestamp: String(this._languageClientStartTime) beginningTimestamp: String(this._languageClientStartTime)
}); });
this._languageClientStartTime = undefined; this._languageClientStartTime = undefined;
this._installationTime = undefined; this._installationTime = undefined;
}); });
return client; return client;
} }
private handleLanguageServiceTelemetryNotification(): NotificationHandler<LanguageServiceContracts.TelemetryParams> { private handleLanguageServiceTelemetryNotification(): NotificationHandler<LanguageServiceContracts.TelemetryParams> {
return (event: LanguageServiceContracts.TelemetryParams): void => { return (event: LanguageServiceContracts.TelemetryParams): void => {
Telemetry.sendTelemetryEvent(event.params.eventName, event.params.properties, event.params.measures); Telemetry.sendTelemetryEvent(event.params.eventName, event.params.properties, event.params.measures);
}; };
} }
/** /**
* Public for testing purposes only. * Public for testing purposes only.
*/ */
public handleLanguageServiceStatusNotification(): NotificationHandler<LanguageServiceContracts.StatusChangeParams> { public handleLanguageServiceStatusNotification(): NotificationHandler<LanguageServiceContracts.StatusChangeParams> {
return (event: LanguageServiceContracts.StatusChangeParams): void => { return (event: LanguageServiceContracts.StatusChangeParams): void => {
this._statusView.languageServiceStatusChanged(event.ownerUri, event.status); this._statusView.languageServiceStatusChanged(event.ownerUri, event.status);
}; };
} }
/** /**
* Send a request to the service client * Send a request to the service client
* @param type The of the request to make * @param type The of the request to make
* @param params The params to pass with the request * @param params The params to pass with the request
* @returns A thenable object for when the request receives a response * @returns A thenable object for when the request receives a response
*/ */
public sendRequest<P, R, E>(type: RequestType<P, R, E>, params?: P, client: LanguageClient = undefined): Thenable<R> { public sendRequest<P, R, E>(type: RequestType<P, R, E>, params?: P, client: LanguageClient = undefined): Thenable<R> {
if (client === undefined) { if (client === undefined) {
client = this._client; client = this._client;
} }
if (client !== undefined) { if (client !== undefined) {
return client.sendRequest(type, params); return client.sendRequest(type, params);
} }
} }
/** /**
* Register a handler for a notification type * Register a handler for a notification type
* @param type The notification type to register the handler for * @param type The notification type to register the handler for
* @param handler The handler to register * @param handler The handler to register
*/ */
public onNotification<P>(type: NotificationType<P>, handler: NotificationHandler<P>, client: LanguageClient = undefined): void { public onNotification<P>(type: NotificationType<P>, handler: NotificationHandler<P>, client: LanguageClient = undefined): void {
if (client === undefined) { if (client === undefined) {
client = this._client; client = this._client;
} }
if (client !== undefined) { if (client !== undefined) {
return client.onNotification(type, handler); return client.onNotification(type, handler);
} }
} }
public checkServiceCompatibility(): Promise<boolean> { public checkServiceCompatibility(): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
this._client.sendRequest(VersionRequest.type, undefined).then((result) => { this._client.sendRequest(VersionRequest.type, undefined).then((result) => {
Utils.logDebug(SqlToolsServiceClient._constants.extensionName + ' service client version: ' + result, SqlToolsServiceClient._constants.extensionConfigSectionName); Utils.logDebug(SqlToolsServiceClient._constants.extensionName + ' service client version: ' + result, SqlToolsServiceClient._constants.extensionConfigSectionName);
if (result === undefined || !result.startsWith(SqlToolsServiceClient._constants.serviceCompatibleVersion)) { if (result === undefined || !result.startsWith(SqlToolsServiceClient._constants.serviceCompatibleVersion)) {
Utils.showErrorMsg(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionName); Utils.showErrorMsg(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionName);
Utils.logDebug(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionConfigSectionName); Utils.logDebug(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionConfigSectionName);
resolve(false); resolve(false);
} else { } else {
resolve(true); resolve(true);
} }
}); });
}); });
} }
} }

View File

@@ -9,11 +9,11 @@ import { Runtime, getRuntimeDisplayName } from '../models/platform';
import * as path from 'path'; import * as path from 'path';
import { IConfig, IStatusView, IPackage, PackageError, IHttpClient, IDecompressProvider } from './interfaces'; import { IConfig, IStatusView, IPackage, PackageError, IHttpClient, IDecompressProvider } from './interfaces';
import { ILogger } from '../models/interfaces'; import { ILogger } from '../models/interfaces';
import Constants = require('../models/constants'); import { Constants } from '../models/constants';
import * as tmp from 'tmp'; import * as tmp from 'tmp';
import {IExtensionConstants} from '../models/contracts/contracts'; import { IExtensionConstants } from '../models/contracts/contracts';
let fse = require('fs-extra'); const fse = require('fs-extra');
/* /*
* Service Download Provider class which handles downloading the SQL Tools service. * Service Download Provider class which handles downloading the SQL Tools service.
@@ -100,10 +100,9 @@ export default class ServiceDownloadProvider {
basePath = installDirFromConfig; basePath = installDirFromConfig;
} else if (this._fromBuild) { } else if (this._fromBuild) {
basePath = path.join(__dirname, '../../../../../extensions/' + extensionConfigSectionName + '/' + installDirFromConfig); basePath = path.join(__dirname, '../../../../../extensions/' + extensionConfigSectionName + '/' + installDirFromConfig);
} } else {
else {
// The path from config is relative to the out folder // The path from config is relative to the out folder
basePath = path.join(__dirname, '../../../../' + installDirFromConfig); basePath = path.join(__dirname, '../../../../' + extensionConfigSectionName + '/' + installDirFromConfig);
} }
return basePath; return basePath;
} }

View File

@@ -61,9 +61,9 @@ export class ServiceInstaller {
private _serverProvider = undefined; private _serverProvider = undefined;
private _extensionConstants = undefined; private _extensionConstants = undefined;
constructor(extensionConstants: IExtensionConstants) { constructor(extensionConstants: IExtensionConstants, path?: string) {
this._extensionConstants = extensionConstants; this._extensionConstants = extensionConstants;
this._config = new Config(extensionConstants.extensionConfigSectionName, true); this._config = new Config(extensionConstants.extensionConfigSectionName, path, true);
this._downloadProvider = new ServiceDownloadProvider(this._config, this._logger, this._statusView, this._httpClient, this._decompressProvider, extensionConstants, true); this._downloadProvider = new ServiceDownloadProvider(this._config, this._logger, this._statusView, this._httpClient, this._decompressProvider, extensionConstants, true);
this._serverProvider = new ServerProvider(this._downloadProvider, this._config, this._statusView, extensionConstants.extensionConfigSectionName); this._serverProvider = new ServerProvider(this._downloadProvider, this._config, this._statusView, extensionConstants.extensionConfigSectionName);
} }

View File

@@ -1,7 +1,7 @@
/* -------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import vscode = require('vscode'); import vscode = require('vscode');

View File

@@ -1,13 +1,15 @@
import SqlToolsServiceClient from './languageservice/serviceClient'; /*---------------------------------------------------------------------------------------------
import ServerProvider from './languageservice/server'; * Copyright (c) Microsoft Corporation. All rights reserved.
import VscodeWrapper from './controllers/vscodeWrapper'; * Licensed under the Source EULA. See License.txt in the project root for license information.
import * as SharedConstants from './models/constants'; *--------------------------------------------------------------------------------------------*/
import * as Utils from './models/utils'; export * from './controllers/vscodeWrapper';
export * from './models/constants';
export * from './models/utils';
export {SqlToolsServiceClient, VscodeWrapper, SharedConstants, Utils}; export { SqlToolsServiceClient } from './languageservice/serviceClient';
export {IExtensionConstants} from './models/contracts/contracts'; export { IExtensionConstants } from './models/contracts/contracts';
export {ILanguageClientHelper} from './models/contracts/languageService'; export { ILanguageClientHelper } from './models/contracts/languageService';
export {Runtime, PlatformInformation} from './models/platform'; export { Runtime, PlatformInformation } from './models/platform';
export {Telemetry} from './models/telemetry'; export { Telemetry } from './models/telemetry';
export {LinuxDistribution} from './models/platform'; export { LinuxDistribution } from './models/platform';
export {ServiceInstaller} from './languageservice/serviceInstallerUtil'; export { ServiceInstaller } from './languageservice/serviceInstallerUtil';

View File

@@ -3,24 +3,23 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
//constants export namespace Constants {
export const configLogDebugInfo: string = 'logDebugInfo'; //constants
export const serviceNotCompatibleError: string = "Client is not compatible with the service layer"; export const configLogDebugInfo: string = 'logDebugInfo';
export const serviceDownloading: string = "Downloading"; export const serviceNotCompatibleError: string = 'Client is not compatible with the service layer';
export const serviceInstalling: string = "Installing"; export const serviceDownloading: string = 'Downloading';
export const unsupportedPlatformErrorMessage: string = "This platform is unsupported and application services may not function correctly"; export const serviceInstalling: string = 'Installing';
export const extensionActivated: string = 'activated.'; export const unsupportedPlatformErrorMessage: string = 'This platform is unsupported and application services may not function correctly';
export const extensionDeactivated: string = 'de-activated.'; export const serviceConfigKey = 'service';
export const configEnabled: string = 'enabled'; export const executableFilesConfigKey = 'executableFiles';
export const configUseDebugSource = 'useDebugSource'; export const versionConfigKey = 'version';
export const serviceConfigKey = 'service'; export const downloadUrlConfigKey = 'downloadUrl';
export const executableFilesConfigKey = 'executableFiles'; export const installDirConfigKey = 'installDir';
export const versionConfigKey = 'version'; export const serviceCrashButton = 'View Known Issues';
export const downloadUrlConfigKey = 'downloadUrl'; export const neverShowAgain = 'Do not show again';
export const installDirConfigKey = 'installDir'; export const ignorePlatformWarning = 'ignorePlatformWarning';
export const serviceCrashButton = "View Known Issues"; export const usingDefaultPlatformMessage = 'Unknown platform detected, defaulting to Linux_x64 platform';
export const configDebugSourcePath = 'debugSourcePath'; export const serverConnectionMetadata = 'serverConnectionMetadata';
export const neverShowAgain = "Don't show again"; export const extensionDeactivated: string = 'de-activated.';
export const ignorePlatformWarning = 'ignorePlatformWarning'; export const extensionActivated: string = 'activated.';
export const usingDefaultPlatformMessage = "Unknown platform detected, defaulting to Linux_x64 platform"; }
export const serverConnectionMetadata = "serverConnectionMetadata";

View File

@@ -2,16 +2,16 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict' 'use strict';
import {RequestType} from 'dataprotocol-client'; import { RequestType } from 'dataprotocol-client';
import {Runtime, LinuxDistribution} from '../platform'; import { Runtime, LinuxDistribution } from '../platform';
// --------------------------------- < Version Request > ------------------------------------------------- // --------------------------------- < Version Request > -------------------------------------------------
// Version request message callback declaration // Version request message callback declaration
export namespace VersionRequest { export namespace VersionRequest {
export const type: RequestType<void, VersionResult, void> = { get method(): string { return 'version'; } }; export const type: RequestType<void, VersionResult, void> = { get method(): string { return 'version'; } };
} }
// Version response format // Version response format
@@ -21,30 +21,30 @@ export type VersionResult = string;
// Constants interface for each extension // Constants interface for each extension
export interface IExtensionConstants { export interface IExtensionConstants {
// TODO: Fill in interface // TODO: Fill in interface
// Definitely dependent on the extension // Definitely dependent on the extension
extensionName: string; extensionName: string;
invalidServiceFilePath: string; invalidServiceFilePath: string;
serviceName: string; serviceName: string;
extensionConfigSectionName: string; extensionConfigSectionName: string;
serviceCompatibleVersion: string; serviceCompatibleVersion: string;
outputChannelName: string; outputChannelName: string;
languageId: string; languageId: string;
serviceInstallingTo: string; serviceInstallingTo: string;
serviceInitializing: string; serviceInitializing: string;
serviceInstalled: string; serviceInstalled: string;
serviceLoadingFailed: string; serviceLoadingFailed: string;
serviceInstallationFailed: string; serviceInstallationFailed: string;
serviceInitializingOutputChannelName: string; serviceInitializingOutputChannelName: string;
commandsNotAvailableWhileInstallingTheService : string; commandsNotAvailableWhileInstallingTheService: string;
providerId: string; providerId: string;
serviceCrashMessage: string; serviceCrashMessage: string;
serviceCrashLink: string; serviceCrashLink: string;
installFolderName: string; installFolderName: string;
telemetryExtensionName: string; telemetryExtensionName: string;
getRuntimeId(platform: string, architecture: string, distribution: LinuxDistribution): Runtime; getRuntimeId(platform: string, architecture: string, distribution: LinuxDistribution): Runtime;
} }

View File

@@ -1,6 +1,10 @@
import {NotificationType, ServerOptions} from 'dataprotocol-client'; /*---------------------------------------------------------------------------------------------
import {ITelemetryEventProperties, ITelemetryEventMeasures} from '../telemetry'; * Copyright (c) Microsoft Corporation. All rights reserved.
import {Runtime} from '../platform'; * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NotificationType, ServerOptions } from 'dataprotocol-client';
import { ITelemetryEventProperties, ITelemetryEventMeasures } from '../telemetry';
import { Runtime } from '../platform';
// ------------------------------- < Telemetry Sent Event > ------------------------------------ // ------------------------------- < Telemetry Sent Event > ------------------------------------
@@ -8,18 +12,18 @@ import {Runtime} from '../platform';
* Event sent when the language service send a telemetry event * Event sent when the language service send a telemetry event
*/ */
export namespace TelemetryNotification { export namespace TelemetryNotification {
export const type: NotificationType<TelemetryParams> = { get method(): string { return 'telemetry/sqlevent'; } }; export const type: NotificationType<TelemetryParams> = { get method(): string { return 'telemetry/sqlevent'; } };
} }
/** /**
* Update event parameters * Update event parameters
*/ */
export class TelemetryParams { export class TelemetryParams {
public params: { public params: {
eventName: string; eventName: string;
properties: ITelemetryEventProperties; properties: ITelemetryEventProperties;
measures: ITelemetryEventMeasures; measures: ITelemetryEventMeasures;
}; };
} }
// ------------------------------- </ Telemetry Sent Event > ---------------------------------- // ------------------------------- </ Telemetry Sent Event > ----------------------------------
@@ -30,26 +34,26 @@ export class TelemetryParams {
* Event sent when the language service send a status change event * Event sent when the language service send a status change event
*/ */
export namespace StatusChangedNotification { export namespace StatusChangedNotification {
export const type: NotificationType<StatusChangeParams> = { get method(): string { return 'textDocument/statusChanged'; } }; export const type: NotificationType<StatusChangeParams> = { get method(): string { return 'textDocument/statusChanged'; } };
} }
/** /**
* Update event parameters * Update event parameters
*/ */
export class StatusChangeParams { export class StatusChangeParams {
/** /**
* URI identifying the text document * URI identifying the text document
*/ */
public ownerUri: string; public ownerUri: string;
/** /**
* The new status of the document * The new status of the document
*/ */
public status: string; public status: string;
} }
// ------------------------------- </ Status Sent Event > ---------------------------------- // ------------------------------- </ Status Sent Event > ----------------------------------
export interface ILanguageClientHelper { export interface ILanguageClientHelper {
createServerOptions(servicePath: string, runtimeId?: Runtime): ServerOptions; createServerOptions(servicePath: string, runtimeId?: Runtime): ServerOptions;
} }

View File

@@ -1,13 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
export interface ILogger { export interface ILogger {
logDebug(message: string): void; logDebug(message: string): void;
increaseIndent(): void; increaseIndent(): void;
decreaseIndent(): void; decreaseIndent(): void;
append(message?: string): void; append(message?: string): void;
appendLine(message?: string): void; appendLine(message?: string): void;
}
export interface IRuntime {
getRuntimeDisplayName();
} }

View File

@@ -3,66 +3,67 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as os from 'os'; import * as os from 'os';
import {ILogger} from './interfaces'; import { ILogger } from './interfaces';
import * as Utils from './utils'; import { Utils } from './utils';
import {IExtensionConstants} from './contracts/contracts'; import { IExtensionConstants } from './contracts/contracts';
/* /*
* Logger class handles logging messages using the Util functions. * Logger class handles logging messages using the Util functions.
*/ */
export class Logger implements ILogger { export class Logger implements ILogger {
private _writer: (message: string) => void; private _writer: (message: string) => void;
private _prefix: string; private _prefix: string;
private _extensionConstants: IExtensionConstants; private _extensionConstants: IExtensionConstants;
private _indentLevel: number = 0; private _indentLevel: number = 0;
private _indentSize: number = 4; private _indentSize: number = 4;
private _atLineStart: boolean = false; private _atLineStart: boolean = false;
constructor(writer: (message: string) => void, extensionConstants: IExtensionConstants, prefix?: string) { constructor(writer: (message: string) => void, extensionConstants: IExtensionConstants, prefix?: string) {
this._writer = writer; this._writer = writer;
this._prefix = prefix; this._prefix = prefix;
this._extensionConstants = extensionConstants; this._extensionConstants = extensionConstants;
} }
public logDebug(message: string): void { public logDebug(message: string): void {
Utils.logDebug(message, this._extensionConstants.extensionConfigSectionName); Utils.logDebug(message, this._extensionConstants.extensionConfigSectionName);
} }
private _appendCore(message: string): void { private _appendCore(message: string): void {
if (this._atLineStart) { if (this._atLineStart) {
if (this._indentLevel > 0) { if (this._indentLevel > 0) {
const indent = ' '.repeat(this._indentLevel * this._indentSize); const indent = ' '.repeat(this._indentLevel * this._indentSize);
this._writer(indent); this._writer(indent);
} }
if (this._prefix) { if (this._prefix) {
this._writer(`[${this._prefix}] `); this._writer(`[${this._prefix}] `);
} }
this._atLineStart = false; this._atLineStart = false;
} }
this._writer(message); this._writer(message);
} }
public increaseIndent(): void { public increaseIndent(): void {
this._indentLevel += 1; this._indentLevel += 1;
} }
public decreaseIndent(): void { public decreaseIndent(): void {
if (this._indentLevel > 0) { if (this._indentLevel > 0) {
this._indentLevel -= 1; this._indentLevel -= 1;
} }
} }
public append(message?: string): void { public append(message?: string): void {
message = message || ''; message = message || '';
this._appendCore(message); this._appendCore(message);
} }
public appendLine(message?: string): void { public appendLine(message?: string): void {
message = message || ''; message = message || '';
this._appendCore(message + os.EOL); this._appendCore(message + os.EOL);
this._atLineStart = true; this._atLineStart = true;
} }
} }

View File

@@ -12,284 +12,229 @@ import * as os from 'os';
const unknown = 'unknown'; const unknown = 'unknown';
export enum Runtime { export enum Runtime {
UnknownRuntime = <any>'Unknown', UnknownRuntime = <any>'Unknown',
UnknownVersion = <any>'Unknown', UnknownVersion = <any>'Unknown',
Windows_86 = <any>'Windows_86', Windows_86 = <any>'Windows_86',
Windows_64 = <any>'Windows_64', Windows_64 = <any>'Windows_64',
OSX = <any> 'OSX', OSX = <any>'OSX',
CentOS_7 = <any>'CentOS_7', CentOS_7 = <any>'CentOS_7',
Debian_8 = <any>'Debian_8', Debian_8 = <any>'Debian_8',
Fedora_23 = <any>'Fedora_23', Fedora_23 = <any>'Fedora_23',
OpenSUSE_13_2 = <any>'OpenSUSE_13_2', OpenSUSE_13_2 = <any>'OpenSUSE_13_2',
SLES_12_2 = <any>'SLES_12_2', SLES_12_2 = <any>'SLES_12_2',
RHEL_7 = <any>'RHEL_7', RHEL_7 = <any>'RHEL_7',
Ubuntu_14 = <any>'Ubuntu_14', Ubuntu_14 = <any>'Ubuntu_14',
Ubuntu_16 = <any>'Ubuntu_16', Ubuntu_16 = <any>'Ubuntu_16',
Linux_64 = <any>'Linux_64', Linux_64 = <any>'Linux_64',
Linux_86 = <any>'Linux-86' Linux_86 = <any>'Linux-86'
} }
export function getRuntimeDisplayName(runtime: Runtime): string { export function getRuntimeDisplayName(runtime: Runtime): string {
switch (runtime) { switch (runtime) {
case Runtime.Windows_64: case Runtime.Windows_64:
return 'Windows'; return 'Windows';
case Runtime.Windows_86: case Runtime.Windows_86:
return 'Windows'; return 'Windows';
case Runtime.OSX: case Runtime.OSX:
return 'OSX'; return 'OSX';
case Runtime.CentOS_7: case Runtime.CentOS_7:
return 'Linux'; return 'Linux';
case Runtime.Debian_8: case Runtime.Debian_8:
return 'Linux'; return 'Linux';
case Runtime.Fedora_23: case Runtime.Fedora_23:
return 'Linux'; return 'Linux';
case Runtime.OpenSUSE_13_2: case Runtime.OpenSUSE_13_2:
return 'Linux'; return 'Linux';
case Runtime.SLES_12_2: case Runtime.SLES_12_2:
return 'Linux'; return 'Linux';
case Runtime.RHEL_7: case Runtime.RHEL_7:
return 'Linux'; return 'Linux';
case Runtime.Ubuntu_14: case Runtime.Ubuntu_14:
return 'Linux'; return 'Linux';
case Runtime.Ubuntu_16: case Runtime.Ubuntu_16:
return 'Linux'; return 'Linux';
case Runtime.Linux_64: case Runtime.Linux_64:
return 'Linux'; return 'Linux';
case Runtime.Linux_86: case Runtime.Linux_86:
return 'Linux'; return 'Linux';
default: default:
return 'Unknown'; return 'Unknown';
} }
} }
export class PlatformInformation { export class PlatformInformation {
public runtimeId: Runtime; public runtimeId: Runtime;
public constructor( public constructor(
public platform: string, public platform: string,
public architecture: string, public architecture: string,
public distribution: LinuxDistribution = undefined, public distribution: LinuxDistribution = undefined,
public getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime) { public getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime) {
try { try {
this.runtimeId = this.getRuntimeId(platform, architecture, distribution); this.runtimeId = this.getRuntimeId(platform, architecture, distribution);
} catch (err) { } catch (err) {
this.runtimeId = undefined; this.runtimeId = undefined;
} }
} }
public isWindows(): boolean { public isWindows(): boolean {
return this.platform === 'win32'; return this.platform === 'win32';
} }
public isMacOS(): boolean { public isMacOS(): boolean {
return this.platform === 'darwin'; return this.platform === 'darwin';
} }
public isLinux(): boolean { public isLinux(): boolean {
return this.platform === 'linux'; return this.platform === 'linux';
} }
public isValidRuntime(): boolean { public isValidRuntime(): boolean {
return this.runtimeId !== undefined && this.runtimeId !== Runtime.UnknownRuntime && this.runtimeId !== Runtime.UnknownVersion; return this.runtimeId !== undefined && this.runtimeId !== Runtime.UnknownRuntime && this.runtimeId !== Runtime.UnknownVersion;
} }
public getRuntimeDisplayName(): string { public getRuntimeDisplayName(): string {
return getRuntimeDisplayName(this.runtimeId); return getRuntimeDisplayName(this.runtimeId);
} }
public toString(): string { public toString(): string {
let result = this.platform; let result = this.platform;
if (this.architecture) { if (this.architecture) {
if (result) { if (result) {
result += ', '; result += ', ';
} }
result += this.architecture; result += this.architecture;
} }
if (this.distribution) { if (this.distribution) {
if (result) { if (result) {
result += ', '; result += ', ';
} }
result += this.distribution.toString(); result += this.distribution.toString();
} }
return result; return result;
} }
public static getCurrent(getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime, public static getCurrent(getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime,
extensionName: string): Promise<any> { extensionName: string): Promise<any> {
let platform = os.platform(); let platform = os.platform();
let architecturePromise: Promise<string>; let architecturePromise: Promise<string>;
let distributionPromise: Promise<LinuxDistribution>; let distributionPromise: Promise<LinuxDistribution>;
switch (platform) { switch (platform) {
case 'win32': case 'win32':
architecturePromise = PlatformInformation.getWindowsArchitecture(); architecturePromise = PlatformInformation.getWindowsArchitecture();
distributionPromise = Promise.resolve(undefined); distributionPromise = Promise.resolve(undefined);
break; break;
case 'darwin': case 'darwin':
let osVersion = os.release(); let osVersion = os.release();
if (parseFloat(osVersion) < 16.0 && extensionName === 'mssql') { if (parseFloat(osVersion) < 16.0 && extensionName === 'mssql') {
return Promise.reject('The current version of macOS is not supported. Only macOS Sierra and above (>= 10.12) are supported.') return Promise.reject('The current version of macOS is not supported. Only macOS Sierra and above (>= 10.12) are supported.');
} }
architecturePromise = PlatformInformation.getUnixArchitecture(); architecturePromise = PlatformInformation.getUnixArchitecture();
distributionPromise = Promise.resolve(undefined); distributionPromise = Promise.resolve(undefined);
break; break;
case 'linux': case 'linux':
architecturePromise = PlatformInformation.getUnixArchitecture(); architecturePromise = PlatformInformation.getUnixArchitecture();
distributionPromise = LinuxDistribution.getCurrent(); distributionPromise = LinuxDistribution.getCurrent();
break; break;
default: default:
return Promise.reject(`Unsupported platform: ${platform}`); return Promise.reject(`Unsupported platform: ${platform}`);
} }
return architecturePromise.then( arch => { return architecturePromise.then(arch => {
return distributionPromise.then(distro => { return distributionPromise.then(distro => {
return new PlatformInformation(platform, arch, distro, getRuntimeId); return new PlatformInformation(platform, arch, distro, getRuntimeId);
}); });
}); });
} }
private static getWindowsArchitecture(): Promise<string> { private static getWindowsArchitecture(): Promise<string> {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
// try to get the architecture from WMIC // try to get the architecture from WMIC
PlatformInformation.getWindowsArchitectureWmic().then(architecture => { PlatformInformation.getWindowsArchitectureWmic().then(architecture => {
if (architecture && architecture !== unknown) { if (architecture && architecture !== unknown) {
resolve(architecture); resolve(architecture);
} else { } else {
// sometimes WMIC isn't available on the path so then try to parse the envvar // sometimes WMIC isn't available on the path so then try to parse the envvar
PlatformInformation.getWindowsArchitectureEnv().then(architecture => { PlatformInformation.getWindowsArchitectureEnv().then(architecture => {
resolve(architecture); resolve(architecture);
}); });
} }
}); });
}); });
} }
private static getWindowsArchitectureWmic(): Promise<string> { private static getWindowsArchitectureWmic(): Promise<string> {
return this.execChildProcess('wmic os get osarchitecture') return this.execChildProcess('wmic os get osarchitecture')
.then(architecture => { .then(architecture => {
if (architecture) { if (architecture) {
let archArray: string[] = architecture.split(os.EOL); let archArray: string[] = architecture.split(os.EOL);
if (archArray.length >= 2) { if (archArray.length >= 2) {
let arch = archArray[1].trim(); let arch = archArray[1].trim();
// Note: This string can be localized. So, we'll just check to see if it contains 32 or 64. // Note: This string can be localized. So, we'll just check to see if it contains 32 or 64.
if (arch.indexOf('64') >= 0) { if (arch.indexOf('64') >= 0) {
return 'x86_64'; return 'x86_64';
} else if (arch.indexOf('32') >= 0) { } else if (arch.indexOf('32') >= 0) {
return 'x86'; return 'x86';
} }
} }
} }
return unknown; return unknown;
}).catch((error) => { }).catch((error) => {
return unknown; return unknown;
}); });
} }
private static getWindowsArchitectureEnv(): Promise<string> { private static getWindowsArchitectureEnv(): Promise<string> {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
if (process.env.PROCESSOR_ARCHITECTURE === 'x86' && process.env.PROCESSOR_ARCHITEW6432 === undefined) { if (process.env.PROCESSOR_ARCHITECTURE === 'x86' && process.env.PROCESSOR_ARCHITEW6432 === undefined) {
resolve('x86'); resolve('x86');
} }
else { else {
resolve('x86_64'); resolve('x86_64');
} }
}); });
} }
private static getUnixArchitecture(): Promise<string> { private static getUnixArchitecture(): Promise<string> {
return this.execChildProcess('uname -m') return this.execChildProcess('uname -m')
.then(architecture => { .then(architecture => {
if (architecture) { if (architecture) {
return architecture.trim(); return architecture.trim();
} }
return undefined; return undefined;
}); });
} }
private static execChildProcess(process: string): Promise<string> { private static execChildProcess(process: string): Promise<string> {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
child_process.exec(process, { maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => { child_process.exec(process, { maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => {
if (error) { if (error) {
reject(error); reject(error);
return; return;
} }
if (stderr && stderr.length > 0) { if (stderr && stderr.length > 0) {
reject(new Error(stderr)); reject(new Error(stderr));
return; return;
} }
resolve(stdout); resolve(stdout);
}); });
}); });
} }
private static getRuntimeIdHelper(distributionName: string, distributionVersion: string): Runtime {
switch (distributionName) {
case 'ubuntu':
if (distributionVersion.startsWith('14')) {
// This also works for Linux Mint
return Runtime.Ubuntu_14;
} else if (distributionVersion.startsWith('16')) {
return Runtime.Ubuntu_16;
}
break;
case 'elementary':
case 'elementary OS':
if (distributionVersion.startsWith('0.3')) {
// Elementary OS 0.3 Freya is binary compatible with Ubuntu 14.04
return Runtime.Ubuntu_14;
} else if (distributionVersion.startsWith('0.4')) {
// Elementary OS 0.4 Loki is binary compatible with Ubuntu 16.04
return Runtime.Ubuntu_16;
}
break;
case 'linuxmint':
if (distributionVersion.startsWith('18')) {
// Linux Mint 18 is binary compatible with Ubuntu 16.04
return Runtime.Ubuntu_16;
}
break;
case 'centos':
case 'ol':
// Oracle Linux is binary compatible with CentOS
return Runtime.CentOS_7;
case 'fedora':
return Runtime.Fedora_23;
case 'opensuse':
return Runtime.OpenSUSE_13_2;
case 'sles':
return Runtime.SLES_12_2;
case 'rhel':
return Runtime.RHEL_7;
case 'debian':
return Runtime.Debian_8;
case 'galliumos':
if (distributionVersion.startsWith('2.0')) {
return Runtime.Ubuntu_16;
}
break;
default:
return Runtime.Linux_64;
}
return Runtime.Linux_64;
}
} }
/** /**
@@ -299,71 +244,71 @@ export class PlatformInformation {
* https://www.freedesktop.org/software/systemd/man/os-release.html * https://www.freedesktop.org/software/systemd/man/os-release.html
*/ */
export class LinuxDistribution { export class LinuxDistribution {
public constructor( public constructor(
public name: string, public name: string,
public version: string, public version: string,
public idLike?: string[]) { } public idLike?: string[]) { }
public static getCurrent(): Promise<LinuxDistribution> { public static getCurrent(): Promise<LinuxDistribution> {
// Try /etc/os-release and fallback to /usr/lib/os-release per the synopsis // Try /etc/os-release and fallback to /usr/lib/os-release per the synopsis
// at https://www.freedesktop.org/software/systemd/man/os-release.html. // at https://www.freedesktop.org/software/systemd/man/os-release.html.
return LinuxDistribution.fromFilePath('/etc/os-release') return LinuxDistribution.fromFilePath('/etc/os-release')
.catch(() => LinuxDistribution.fromFilePath('/usr/lib/os-release')) .catch(() => LinuxDistribution.fromFilePath('/usr/lib/os-release'))
.catch(() => Promise.resolve(new LinuxDistribution(unknown, unknown))); .catch(() => Promise.resolve(new LinuxDistribution(unknown, unknown)));
} }
public toString(): string { public toString(): string {
return `name=${this.name}, version=${this.version}`; return `name=${this.name}, version=${this.version}`;
} }
private static fromFilePath(filePath: string): Promise<LinuxDistribution> { private static fromFilePath(filePath: string): Promise<LinuxDistribution> {
return new Promise<LinuxDistribution>((resolve, reject) => { return new Promise<LinuxDistribution>((resolve, reject) => {
fs.readFile(filePath, 'utf8', (error, data) => { fs.readFile(filePath, 'utf8', (error, data) => {
if (error) { if (error) {
reject(error); reject(error);
} else { } else {
resolve(LinuxDistribution.fromReleaseInfo(data)); resolve(LinuxDistribution.fromReleaseInfo(data));
} }
}); });
}); });
} }
public static fromReleaseInfo(releaseInfo: string, eol: string = os.EOL): LinuxDistribution { public static fromReleaseInfo(releaseInfo: string, eol: string = os.EOL): LinuxDistribution {
let name = unknown; let name = unknown;
let version = unknown; let version = unknown;
let idLike: string[] = undefined; let idLike: string[] = undefined;
const lines = releaseInfo.split(eol); const lines = releaseInfo.split(eol);
for (let line of lines) { for (let line of lines) {
line = line.trim(); line = line.trim();
let equalsIndex = line.indexOf('='); let equalsIndex = line.indexOf('=');
if (equalsIndex >= 0) { if (equalsIndex >= 0) {
let key = line.substring(0, equalsIndex); let key = line.substring(0, equalsIndex);
let value = line.substring(equalsIndex + 1); let value = line.substring(equalsIndex + 1);
// Strip quotes if necessary // Strip quotes if necessary
if (value.length > 1 && value.startsWith('"') && value.endsWith('"')) { if (value.length > 1 && value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1); value = value.substring(1, value.length - 1);
} else if (value.length > 1 && value.startsWith('\'') && value.endsWith('\'')) { } else if (value.length > 1 && value.startsWith('\'') && value.endsWith('\'')) {
value = value.substring(1, value.length - 1); value = value.substring(1, value.length - 1);
} }
if (key === 'ID') { if (key === 'ID') {
name = value; name = value;
} else if (key === 'VERSION_ID') { } else if (key === 'VERSION_ID') {
version = value; version = value;
} else if (key === 'ID_LIKE') { } else if (key === 'ID_LIKE') {
idLike = value.split(' '); idLike = value.split(' ');
} }
if (name !== unknown && version !== unknown && idLike !== undefined) { if (name !== unknown && version !== unknown && idLike !== undefined) {
break; break;
} }
} }
} }
return new LinuxDistribution(name, version, idLike); return new LinuxDistribution(name, version, idLike);
} }
} }

View File

@@ -6,13 +6,13 @@
'use strict'; 'use strict';
import vscode = require('vscode'); import vscode = require('vscode');
import TelemetryReporter from 'vscode-extension-telemetry'; import TelemetryReporter from 'vscode-extension-telemetry';
import Utils = require('./utils'); import { Utils } from './utils';
import { PlatformInformation, Runtime, LinuxDistribution } from './platform'; import { PlatformInformation, Runtime, LinuxDistribution } from './platform';
import { IExtensionConstants } from './contracts/contracts'; import { IExtensionConstants } from './contracts/contracts';
export interface ITelemetryEventProperties { export interface ITelemetryEventProperties {
[key: string]: string; [key: string]: string;
} }
export interface ITelemetryEventMeasures { export interface ITelemetryEventMeasures {
[key: string]: number; [key: string]: number;
@@ -79,16 +79,16 @@ export class Telemetry {
/** /**
* Disable telemetry reporting * Disable telemetry reporting
*/ */
public static disable(): void { public static disable(): void {
this.disabled = true; this.disabled = true;
} }
/** /**
* Initialize the telemetry reporter for use. * Initialize the telemetry reporter for use.
*/ */
public static initialize(context: vscode.ExtensionContext, extensionConstants: IExtensionConstants): void { public static initialize(context: vscode.ExtensionContext, extensionConstants: IExtensionConstants): void {
if (typeof this.reporter === 'undefined') { if (typeof this.reporter === 'undefined') {
// Check if the user has opted out of telemetry // Check if the user has opted out of telemetry
@@ -102,9 +102,9 @@ export class Telemetry {
} }
} }
/** /**
* Send a telemetry event for an exception * Send a telemetry event for an exception
*/ */
public static sendTelemetryEventForException( public static sendTelemetryEventForException(
err: any, methodName: string, extensionConfigName: string): void { err: any, methodName: string, extensionConfigName: string): void {
try { try {
@@ -127,9 +127,9 @@ export class Telemetry {
} }
} }
/** /**
* Send a telemetry event using application insights * Send a telemetry event using application insights
*/ */
public static sendTelemetryEvent( public static sendTelemetryEvent(
eventName: string, eventName: string,
properties?: ITelemetryEventProperties, properties?: ITelemetryEventProperties,
@@ -157,5 +157,3 @@ export class Telemetry {
}); });
} }
} }
export default Telemetry;

View File

@@ -1,264 +1,130 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import * as os from 'os'; import * as os from 'os';
import vscode = require('vscode'); import vscode = require('vscode');
import Constants = require('./constants'); import { Constants } from './constants';
import {ExtensionContext} from 'vscode'; import { ExtensionContext } from 'vscode';
import fs = require('fs');
var path = require('path'); var path = require('path');
// CONSTANTS ////////////////////////////////////////////////////////////////////////////////////// export namespace Utils {
const msInH = 3.6e6; // INTERFACES /////////////////////////////////////////////////////////////////////////////////////
const msInM = 60000;
const msInS = 1000;
// INTERFACES ///////////////////////////////////////////////////////////////////////////////////// // Interface for package.json information
export interface IPackageInfo {
name: string;
version: string;
aiKey: string;
}
// Interface for package.json information // FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////
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
};
}
}
// Get information from the extension's package.json file // Generate a new GUID
export function getPackageInfo(context: ExtensionContext): IPackageInfo { export function generateGuid(): string {
let extensionPackage = require(context.asAbsolutePath('./package.json')); let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
if (extensionPackage) { // c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
return { let oct: string = '';
name: extensionPackage.name, let tmp: number;
version: extensionPackage.version, /* tslint:disable:no-bitwise */
aiKey: extensionPackage.aiKey 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];
}
// Generate a new GUID // 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
export function generateGuid(): string { let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']; return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx) /* tslint:enable:no-bitwise */
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' // Generate a unique, deterministic ID for the current user of the extension
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0]; export function generateUserId(): Promise<string> {
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12); return new Promise<string>(resolve => {
/* tslint:enable:no-bitwise */ 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
}
});
}
// Generate a unique, deterministic ID for the current user of the extension // Retrieve the URI for the currently open file if there is one; otherwise return the empty string
export function generateUserId(): Promise<string> { export function getActiveTextEditorUri(): string {
return new Promise<string>(resolve => { if (typeof vscode.window.activeTextEditor !== 'undefined' &&
try { typeof vscode.window.activeTextEditor.document !== 'undefined') {
let interfaces = os.networkInterfaces(); return vscode.window.activeTextEditor.document.uri.toString();
let mac; }
for(let key of Object.keys(interfaces)) { return '';
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 // Helper to log debug messages
export function isEditingSqlFile(languageId: string): boolean { export function logDebug(msg: any, extensionConfigSectionName: string): void {
let sqlFile = false; let config = vscode.workspace.getConfiguration(extensionConfigSectionName);
let editor = getActiveTextEditor(); let logDebugInfo = config[Constants.configLogDebugInfo];
if (editor) { if (logDebugInfo === true) {
if (editor.document.languageId === languageId) { let currentTime = new Date().toLocaleTimeString();
sqlFile = true; let outputMsg = '[' + currentTime + ']: ' + msg ? msg.toString() : '';
} console.log(outputMsg);
} }
return sqlFile; }
}
// Return the active text editor if there's one // Helper to show an error message
export function getActiveTextEditor(): vscode.TextEditor { export function showErrorMsg(msg: string, extensionName: string): void {
let editor = undefined; vscode.window.showErrorMessage(extensionName + ': ' + msg);
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 isEmpty(str: any): boolean {
export function getActiveTextEditorUri(): string { return (!str || '' === str);
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 // The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
export function logToOutputChannel(msg: any, outputChannelName: string): void { // work for now because the extension is running in different process.
let outputChannel = vscode.window.createOutputChannel(outputChannelName); export function getAppDataPath() {
outputChannel.show(); var platform = process.platform;
if (msg instanceof Array) { switch (platform) {
msg.forEach(element => { case 'win32': return process.env['APPDATA'] || path.join(process.env['USERPROFILE'], 'AppData', 'Roaming');
outputChannel.appendLine(element.toString()); case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support');
}); case 'linux': return process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
} else { default: throw new Error('Platform not supported');
outputChannel.appendLine(msg.toString()); }
} }
}
// Helper to log debug messages export function getDefaultLogLocation() {
export function logDebug(msg: any, extensionConfigSectionName: string): void { return path.join(getAppDataPath(), 'sqlops');
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 \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() {
return path.join(getAppDataPath(), 'sqlops');
}

View File

@@ -1,3 +0,0 @@
'use strict';
export default require('error-ex')('EscapeException');

View File

@@ -1,3 +0,0 @@
'use strict';
export default require('error-ex')('ValidationException');

View File

@@ -1,142 +1,146 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import vscode = require('vscode'); import vscode = require('vscode');
import * as Utils from '../models/utils'; import { Utils } from '../models/utils';
// Status bar element for each file in the editor // Status bar element for each file in the editor
class FileStatusBar { class FileStatusBar {
// Item for the connection status // Item for the connection status
public statusConnection: vscode.StatusBarItem; public statusConnection: vscode.StatusBarItem;
// Item for the query status // Item for the query status
public statusQuery: vscode.StatusBarItem; public statusQuery: vscode.StatusBarItem;
// Item for language service status // Item for language service status
public statusLanguageService: vscode.StatusBarItem; public statusLanguageService: vscode.StatusBarItem;
// Timer used for displaying a progress indicator on queries // Timer used for displaying a progress indicator on queries
public progressTimerId: NodeJS.Timer; public progressTimerId: NodeJS.Timer;
public currentLanguageServiceStatus: string; public currentLanguageServiceStatus: string;
} }
export default class StatusView implements vscode.Disposable { export default class StatusView implements vscode.Disposable {
private _statusBars: { [fileUri: string]: FileStatusBar }; private _statusBars: { [fileUri: string]: FileStatusBar };
private _lastShownStatusBar: FileStatusBar; private _lastShownStatusBar: FileStatusBar;
constructor() { constructor() {
this._statusBars = {}; this._statusBars = {};
vscode.window.onDidChangeActiveTextEditor((params) => this.onDidChangeActiveTextEditor(params)); vscode.window.onDidChangeActiveTextEditor((params) => this.onDidChangeActiveTextEditor(params));
vscode.workspace.onDidCloseTextDocument((params) => this.onDidCloseTextDocument(params)); vscode.workspace.onDidCloseTextDocument((params) => this.onDidCloseTextDocument(params));
} }
dispose(): void { dispose(): void {
for (let bar in this._statusBars) { for (let bar in this._statusBars) {
if (this._statusBars.hasOwnProperty(bar)) { if (this._statusBars.hasOwnProperty(bar)) {
this._statusBars[bar].statusConnection.dispose(); this._statusBars[bar].statusConnection.dispose();
this._statusBars[bar].statusQuery.dispose(); this._statusBars[bar].statusQuery.dispose();
this._statusBars[bar].statusLanguageService.dispose(); this._statusBars[bar].statusLanguageService.dispose();
clearInterval(this._statusBars[bar].progressTimerId); clearInterval(this._statusBars[bar].progressTimerId);
delete this._statusBars[bar]; delete this._statusBars[bar];
} }
} }
} }
// Create status bar item if needed // Create status bar item if needed
private createStatusBar(fileUri: string): void { private createStatusBar(fileUri: string): void {
let bar = new FileStatusBar(); let bar = new FileStatusBar();
bar.statusConnection = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); bar.statusConnection = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
bar.statusQuery = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); bar.statusQuery = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
bar.statusLanguageService = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); bar.statusLanguageService = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
this._statusBars[fileUri] = bar; this._statusBars[fileUri] = bar;
} }
private destroyStatusBar(fileUri: string): void { private destroyStatusBar(fileUri: string): void {
let bar = this._statusBars[fileUri]; let bar = this._statusBars[fileUri];
if (bar) { if (bar) {
if (bar.statusConnection) { if (bar.statusConnection) {
bar.statusConnection.dispose(); bar.statusConnection.dispose();
} }
if (bar.statusQuery) { if (bar.statusQuery) {
bar.statusQuery.dispose(); bar.statusQuery.dispose();
} }
if (bar.statusLanguageService) { if (bar.statusLanguageService) {
bar.statusLanguageService.dispose(); bar.statusLanguageService.dispose();
} }
if (bar.progressTimerId) { if (bar.progressTimerId) {
clearInterval(bar.progressTimerId); clearInterval(bar.progressTimerId);
} }
delete this._statusBars[fileUri]; delete this._statusBars[fileUri];
} }
} }
private getStatusBar(fileUri: string): FileStatusBar { private getStatusBar(fileUri: string): FileStatusBar {
if (!(fileUri in this._statusBars)) { if (!(fileUri in this._statusBars)) {
// Create it if it does not exist // Create it if it does not exist
this.createStatusBar(fileUri); this.createStatusBar(fileUri);
} }
let bar = this._statusBars[fileUri]; let bar = this._statusBars[fileUri];
if (bar.progressTimerId) { if (bar.progressTimerId) {
clearInterval(bar.progressTimerId); clearInterval(bar.progressTimerId);
} }
return bar; return bar;
} }
public languageServiceStatusChanged(fileUri: string, status: string): void { public languageServiceStatusChanged(fileUri: string, status: string): void {
let bar = this.getStatusBar(fileUri); let bar = this.getStatusBar(fileUri);
bar.currentLanguageServiceStatus = status; bar.currentLanguageServiceStatus = status;
this.updateStatusMessage(status, this.updateStatusMessage(status,
() => { return bar.currentLanguageServiceStatus; }, (message) => { () => { return bar.currentLanguageServiceStatus; }, (message) => {
bar.statusLanguageService.text = message; bar.statusLanguageService.text = message;
this.showStatusBarItem(fileUri, bar.statusLanguageService); this.showStatusBarItem(fileUri, bar.statusLanguageService);
}); });
} }
public updateStatusMessage( public updateStatusMessage(
newStatus: string, newStatus: string,
getCurrentStatus: () => string, getCurrentStatus: () => string,
updateMessage: (message: string) => void): void { updateMessage: (message: string) => void): void {
} }
private hideLastShownStatusBar(): void { private hideLastShownStatusBar(): void {
if (typeof this._lastShownStatusBar !== 'undefined') { if (typeof this._lastShownStatusBar !== 'undefined') {
this._lastShownStatusBar.statusConnection.hide(); this._lastShownStatusBar.statusConnection.hide();
this._lastShownStatusBar.statusQuery.hide(); this._lastShownStatusBar.statusQuery.hide();
this._lastShownStatusBar.statusLanguageService.hide(); this._lastShownStatusBar.statusLanguageService.hide();
} }
} }
private onDidChangeActiveTextEditor(editor: vscode.TextEditor): void { private onDidChangeActiveTextEditor(editor: vscode.TextEditor): void {
// Hide the most recently shown status bar // Hide the most recently shown status bar
this.hideLastShownStatusBar(); this.hideLastShownStatusBar();
// Change the status bar to match the open file // Change the status bar to match the open file
if (typeof editor !== 'undefined') { if (typeof editor !== 'undefined') {
const fileUri = editor.document.uri.toString(); const fileUri = editor.document.uri.toString();
const bar = this._statusBars[fileUri]; const bar = this._statusBars[fileUri];
if (bar) { if (bar) {
this.showStatusBarItem(fileUri, bar.statusConnection); this.showStatusBarItem(fileUri, bar.statusConnection);
this.showStatusBarItem(fileUri, bar.statusLanguageService); this.showStatusBarItem(fileUri, bar.statusLanguageService);
} }
} }
} }
private onDidCloseTextDocument(doc: vscode.TextDocument): void { private onDidCloseTextDocument(doc: vscode.TextDocument): void {
// Remove the status bar associated with the document // Remove the status bar associated with the document
this.destroyStatusBar(doc.uri.toString()); this.destroyStatusBar(doc.uri.toString());
} }
private showStatusBarItem(fileUri: string, statusBarItem: vscode.StatusBarItem): void { private showStatusBarItem(fileUri: string, statusBarItem: vscode.StatusBarItem): void {
let currentOpenFile = Utils.getActiveTextEditorUri(); let currentOpenFile = Utils.getActiveTextEditorUri();
// Only show the status bar if it matches the currently open file and is not empty // Only show the status bar if it matches the currently open file and is not empty
if (fileUri === currentOpenFile && !Utils.isEmpty(statusBarItem.text) ) { if (fileUri === currentOpenFile && !Utils.isEmpty(statusBarItem.text)) {
statusBarItem.show(); statusBarItem.show();
if (fileUri in this._statusBars) { if (fileUri in this._statusBars) {
this._lastShownStatusBar = this._statusBars[fileUri]; this._lastShownStatusBar = this._statusBars[fileUri];
} }
} else { } else {
statusBarItem.hide(); statusBarItem.hide();
} }
} }
} }

View File

View File

@@ -0,0 +1,3 @@
src/**
tsconfig.json
npm-shrinkwrap.json

View File

@@ -0,0 +1,348 @@
{
"name": "account-provider-azure",
"version": "0.0.1",
"dependencies": {
"@types/node": {
"version": "8.5.1",
"from": "@types/node@>=8.0.47 <9.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.1.tgz"
},
"adal-node": {
"version": "0.1.25",
"from": "adal-node@0.1.25",
"resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.1.25.tgz"
},
"ansi-regex": {
"version": "2.1.1",
"from": "ansi-regex@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz"
},
"ansi-styles": {
"version": "2.2.1",
"from": "ansi-styles@>=2.2.1 <3.0.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz"
},
"asn1": {
"version": "0.1.11",
"from": "asn1@0.1.11",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz"
},
"assert-plus": {
"version": "0.1.5",
"from": "assert-plus@>=0.1.5 <0.2.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz"
},
"async": {
"version": "2.6.0",
"from": "async@>=0.6.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz"
},
"aws-sign2": {
"version": "0.5.0",
"from": "aws-sign2@>=0.5.0 <0.6.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz"
},
"base64url": {
"version": "2.0.0",
"from": "base64url@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz"
},
"bl": {
"version": "1.0.3",
"from": "bl@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz"
},
"bluebird": {
"version": "2.11.0",
"from": "bluebird@>=2.9.30 <3.0.0",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz"
},
"boom": {
"version": "2.10.1",
"from": "boom@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz"
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"from": "buffer-equal-constant-time@1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz"
},
"caseless": {
"version": "0.11.0",
"from": "caseless@>=0.11.0 <0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz"
},
"chalk": {
"version": "1.1.3",
"from": "chalk@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
},
"combined-stream": {
"version": "1.0.5",
"from": "combined-stream@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz"
},
"commander": {
"version": "2.12.2",
"from": "commander@>=2.8.1 <3.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz"
},
"core-util-is": {
"version": "1.0.2",
"from": "core-util-is@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
},
"cryptiles": {
"version": "2.0.5",
"from": "cryptiles@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz"
},
"ctype": {
"version": "0.5.3",
"from": "ctype@0.5.3",
"resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz"
},
"date-utils": {
"version": "1.2.21",
"from": "date-utils@*",
"resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz"
},
"delayed-stream": {
"version": "1.0.0",
"from": "delayed-stream@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
},
"ecdsa-sig-formatter": {
"version": "1.0.9",
"from": "ecdsa-sig-formatter@1.0.9",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz"
},
"escape-string-regexp": {
"version": "1.0.5",
"from": "escape-string-regexp@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
},
"extend": {
"version": "3.0.1",
"from": "extend@>=3.0.0 <3.1.0",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz"
},
"forever-agent": {
"version": "0.6.1",
"from": "forever-agent@>=0.6.0 <0.7.0",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz"
},
"form-data": {
"version": "1.0.1",
"from": "form-data@>=1.0.0-rc1 <1.1.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz"
},
"generate-function": {
"version": "2.0.0",
"from": "generate-function@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz"
},
"generate-object-property": {
"version": "1.2.0",
"from": "generate-object-property@>=1.1.0 <2.0.0",
"resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz"
},
"har-validator": {
"version": "1.8.0",
"from": "har-validator@>=1.6.1 <2.0.0",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz"
},
"has-ansi": {
"version": "2.0.0",
"from": "has-ansi@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
},
"hawk": {
"version": "3.1.3",
"from": "hawk@>=3.1.0 <3.2.0",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz"
},
"hoek": {
"version": "2.16.3",
"from": "hoek@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz"
},
"http-signature": {
"version": "0.11.0",
"from": "http-signature@>=0.11.0 <0.12.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz"
},
"inherits": {
"version": "2.0.3",
"from": "inherits@>=2.0.1 <2.1.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
},
"is-my-json-valid": {
"version": "2.17.1",
"from": "is-my-json-valid@>=2.12.0 <3.0.0",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz"
},
"is-property": {
"version": "1.0.2",
"from": "is-property@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz"
},
"isarray": {
"version": "1.0.0",
"from": "isarray@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
},
"isstream": {
"version": "0.1.2",
"from": "isstream@>=0.1.1 <0.2.0",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz"
},
"json-stringify-safe": {
"version": "5.0.1",
"from": "json-stringify-safe@>=5.0.0 <5.1.0",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz"
},
"jsonpointer": {
"version": "4.0.1",
"from": "jsonpointer@>=4.0.0 <5.0.0",
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz"
},
"jwa": {
"version": "1.1.5",
"from": "jwa@>=1.1.4 <2.0.0",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz"
},
"jws": {
"version": "3.1.4",
"from": "jws@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz"
},
"lodash": {
"version": "4.17.4",
"from": "lodash@>=4.14.0 <5.0.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz"
},
"mime-db": {
"version": "1.30.0",
"from": "mime-db@>=1.30.0 <1.31.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz"
},
"mime-types": {
"version": "2.1.17",
"from": "mime-types@>=2.1.2 <2.2.0",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz"
},
"oauth-sign": {
"version": "0.8.2",
"from": "oauth-sign@>=0.8.0 <0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
"from": "process-nextick-args@>=1.0.6 <1.1.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"punycode": {
"version": "1.4.1",
"from": "punycode@>=1.4.1 <2.0.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz"
},
"qs": {
"version": "5.1.0",
"from": "qs@>=5.1.0 <5.2.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-5.1.0.tgz"
},
"readable-stream": {
"version": "2.0.6",
"from": "readable-stream@>=2.0.5 <2.1.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz"
},
"request": {
"version": "2.63.0",
"from": "request@2.63.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.63.0.tgz",
"dependencies": {
"node-uuid": {
"version": "1.4.8",
"from": "node-uuid@>=1.4.0 <1.5.0",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz"
}
}
},
"safe-buffer": {
"version": "5.1.1",
"from": "safe-buffer@>=5.0.1 <6.0.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz"
},
"sntp": {
"version": "1.0.9",
"from": "sntp@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz"
},
"string_decoder": {
"version": "0.10.31",
"from": "string_decoder@>=0.10.0 <0.11.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
},
"stringstream": {
"version": "0.0.5",
"from": "stringstream@>=0.0.4 <0.1.0",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz"
},
"strip-ansi": {
"version": "3.0.1",
"from": "strip-ansi@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz"
},
"supports-color": {
"version": "2.0.0",
"from": "supports-color@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz"
},
"tough-cookie": {
"version": "2.3.3",
"from": "tough-cookie@>=0.12.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz"
},
"tunnel-agent": {
"version": "0.4.3",
"from": "tunnel-agent@>=0.4.0 <0.5.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
},
"underscore": {
"version": "1.8.3",
"from": "underscore@>=1.3.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
},
"util-deprecate": {
"version": "1.0.2",
"from": "util-deprecate@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
},
"uuid": {
"version": "3.1.0",
"from": "uuid@>=3.1.0 <4.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz"
},
"vscode-nls": {
"version": "2.0.2",
"from": "vscode-nls@2.0.2",
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
},
"xmldom": {
"version": "0.1.27",
"from": "xmldom@>=0.1.0",
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz"
},
"xpath.js": {
"version": "1.0.7",
"from": "xpath.js@>=1.0.5 <1.1.0",
"resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.0.7.tgz"
},
"xtend": {
"version": "4.0.1",
"from": "xtend@>=4.0.0 <5.0.0",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz"
}
}
}

View File

@@ -0,0 +1,55 @@
{
"name": "account-provider-azure",
"version": "0.0.1",
"publisher": "Microsoft",
"engines": { "vscode": "*" },
"main": "./out/main",
"activationEvents": [ "*" ],
"scripts": {
"compile": "gulp compile-extension:account-provider-azure"
},
"dependencies": {
"adal-node": "0.1.25",
"request": "2.63.0",
"vscode-nls": "2.0.2"
},
"devDependencies": {
"@types/node": "^8.0.24"
},
"contributes": {
"commands": [
{
"command": "extension.clearTokenCache",
"title": "%extension.clearTokenCache%",
"category": "Azure Accounts"
}
],
"configuration": {
"type": "object",
"title": "Azure Account Configuration",
"properties": {
"accounts.azure.enablePublicCloud": {
"type": "boolean",
"default": true,
"description": "%config.enablePublicCloudDescription%"
}
}
},
"account-type": [
{
"id": "microsoft",
"icon": {
"light": "./out/account-provider/media/microsoft_account_light.svg",
"dark": "./out/account-provider/media/microsoft_account_dark.svg"
}
},
{
"id": "work_school",
"icon": {
"light": "./out/account-provider/media/work_school_account_light.svg",
"dark": "./out/account-provider/media/work_school_account_dark.svg"
}
}
]
}
}

View File

@@ -0,0 +1,7 @@
{
"extension.clearTokenCache": "Clear Azure Account Token Cache",
"config.enablePublicCloudDescription": "Should Azure public cloud integration be enabled",
"config.enableUsGovCloudDescription": "Should US Government Azure cloud (Fairfax) integration be enabled",
"config.enableChinaCloudDescription": "Should Azure China integration be enabled",
"config.enableGermanyCloudDescription": "Should Azure Germany integration be enabled"
}

View File

@@ -5,16 +5,18 @@
'use strict'; 'use strict';
import * as constants from '../constants';
import * as data from 'data'; import * as data from 'data';
import * as events from 'events'; import * as events from 'events';
import * as nls from 'vscode-nls';
import * as path from 'path'; import * as path from 'path';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import CredentialServiceTokenCache from './tokenCache'; import CredentialServiceTokenCache from './tokenCache';
import providerSettings from './providerSettings'; import providerSettings from './providerSettings';
import { AzureAccountProvider } from './azureAccountProvider'; import { AzureAccountProvider } from './azureAccountProvider';
import { AzureAccountProviderMetadata, ProviderSettings } from './interfaces'; import { AzureAccountProviderMetadata, ProviderSettings } from './interfaces';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle(); let localize = nls.loadMessageBundle();
export class AzureAccountProviderService implements vscode.Disposable { export class AzureAccountProviderService implements vscode.Disposable {
// CONSTANTS /////////////////////////////////////////////////////////////// // CONSTANTS ///////////////////////////////////////////////////////////////
@@ -75,14 +77,14 @@ export class AzureAccountProviderService implements vscode.Disposable {
return Promise.all(promises) return Promise.all(promises)
.then( .then(
() => { () => {
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared'); let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
vscode.window.showInformationMessage(`mssql: ${message}`); vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
}, },
err => { err => {
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache'); let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
vscode.window.showErrorMessage(`mssql: ${message}: ${err}`); vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
}); });
} }
private onDidChangeConfiguration(): void { private onDidChangeConfiguration(): void {
@@ -97,7 +99,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
// Determine what providers need to be changed // Determine what providers need to be changed
let providerChanges: Thenable<void>[] = []; let providerChanges: Thenable<void>[] = [];
for(let provider of providerSettings) { for (let provider of providerSettings) {
// If the old config doesn't exist, then assume everything was disabled // If the old config doesn't exist, then assume everything was disabled
// There will always be a new config value // There will always be a new config value
let oldConfigValue = oldConfig let oldConfigValue = oldConfig
@@ -138,7 +140,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
self._accountProviders[provider.metadata.id] = accountProvider; self._accountProviders[provider.metadata.id] = accountProvider;
self._accountDisposals[provider.metadata.id] = data.accounts.registerAccountProvider(provider.metadata, accountProvider); self._accountDisposals[provider.metadata.id] = data.accounts.registerAccountProvider(provider.metadata, accountProvider);
resolve(); resolve();
} catch(e) { } catch (e) {
console.error(`Failed to register account provider: ${e}`); console.error(`Failed to register account provider: ${e}`);
reject(e); reject(e);
} }
@@ -154,7 +156,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
delete self._accountProviders[provider.metadata.id]; delete self._accountProviders[provider.metadata.id];
delete self._accountDisposals[provider.metadata.id]; delete self._accountDisposals[provider.metadata.id];
resolve(); resolve();
} catch(e) { } catch (e) {
console.error(`Failed to unregister account provider: ${e}`); console.error(`Failed to unregister account provider: ${e}`);
reject(e); reject(e);
} }

View File

@@ -32,6 +32,7 @@ const publicAzureSettings: ProviderSettings = {
} }
}; };
/* Leaving for reference
const usGovAzureSettings: ProviderSettings = { const usGovAzureSettings: ProviderSettings = {
configKey: 'enableUsGovCloud', configKey: 'enableUsGovCloud',
metadata: { metadata: {
@@ -97,6 +98,7 @@ const germanyAzureSettings: ProviderSettings = {
} }
} }
}; };
*/
// TODO: Enable China, Germany, and US Gov clouds: (#3031) // TODO: Enable China, Germany, and US Gov clouds: (#3031)
export default <ProviderSettings[]>[publicAzureSettings, /*chinaAzureSettings, germanyAzureSettings, usGovAzureSettings*/]; export default <ProviderSettings[]>[publicAzureSettings, /*chinaAzureSettings, germanyAzureSettings, usGovAzureSettings*/];

View File

@@ -34,8 +34,8 @@ export default class TokenCache implements adal.TokenCache {
.then(cache => self.addToCache(cache, entries)) .then(cache => self.addToCache(cache, entries))
.then(updatedCache => self.writeCache(updatedCache)) .then(updatedCache => self.writeCache(updatedCache))
.then( .then(
() => callback(null, false), () => callback(null, false),
(err) => callback(err, true) (err) => callback(err, true)
); );
}); });
} }
@@ -55,8 +55,8 @@ export default class TokenCache implements adal.TokenCache {
} }
}); });
}) })
.then(() => { return self._credentialProvider.deleteCredential(self._credentialServiceKey); }) .then(() => { return self._credentialProvider.deleteCredential(self._credentialServiceKey); })
.then(() => {}); .then(() => { });
} }
public find(query: any, callback: (error: Error, results: any[]) => void): void { public find(query: any, callback: (error: Error, results: any[]) => void): void {
@@ -70,8 +70,8 @@ export default class TokenCache implements adal.TokenCache {
); );
}) })
.then( .then(
results => callback(null, results), results => callback(null, results),
(err) => callback(err, null) (err) => callback(err, null)
); );
}); });
} }
@@ -104,8 +104,8 @@ export default class TokenCache implements adal.TokenCache {
.then(cache => self.removeFromCache(cache, entries)) .then(cache => self.removeFromCache(cache, entries))
.then(updatedCache => self.writeCache(updatedCache)) .then(updatedCache => self.writeCache(updatedCache))
.then( .then(
() => callback(null, null), () => callback(null, null),
(err) => callback(err, null) (err) => callback(err, null)
); );
}); });
} }
@@ -189,7 +189,7 @@ export default class TokenCache implements adal.TokenCache {
key: new Buffer(splitValues[0], 'hex'), key: new Buffer(splitValues[0], 'hex'),
initializationVector: new Buffer(splitValues[1], 'hex') initializationVector: new Buffer(splitValues[1], 'hex')
}; };
} catch(e) { } catch (e) {
// Swallow the error and fall through to generate new params // Swallow the error and fall through to generate new params
console.warn('Failed to deserialize encryption params, new ones will be generated.'); console.warn('Failed to deserialize encryption params, new ones will be generated.');
} }
@@ -204,7 +204,7 @@ export default class TokenCache implements adal.TokenCache {
let serializedValues = `${encryptKey.toString('hex')}|${initializationVector.toString('hex')}`; let serializedValues = `${encryptKey.toString('hex')}|${initializationVector.toString('hex')}`;
return self._credentialProvider.saveCredential(self._credentialServiceKey, serializedValues) return self._credentialProvider.saveCredential(self._credentialServiceKey, serializedValues)
.then(() => { .then(() => {
return <EncryptionParams> { return <EncryptionParams>{
key: encryptKey, key: encryptKey,
initializationVector: initializationVector initializationVector: initializationVector
}; };
@@ -237,7 +237,7 @@ export default class TokenCache implements adal.TokenCache {
} }
return cacheObj; return cacheObj;
} catch(e) { } catch (e) {
throw e; throw e;
} }
}) })

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export const extensionName = localize('extensionName', 'Azure Accounts');

View File

@@ -0,0 +1,35 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';
import { Utils } from 'extensions-modules';
import * as constants from './constants';
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
// EXTENSION ACTIVATION ////////////////////////////////////////////////////
export function activate(context: vscode.ExtensionContext): void {
// Create the folder for storing the token caches
let storagePath = path.join(Utils.getDefaultLogLocation(), constants.extensionName);
try {
if (!fs.existsSync(storagePath)) {
fs.mkdirSync(storagePath);
console.log('Initialized Azure account extension storage.');
}
} catch (e) {
console.error(`Initialization of Azure account extension storage failed: ${e}`);
console.error('Azure accounts will not be available');
return;
}
// Create the provider service and activate
const accountProviderService = new AzureAccountProviderService(context, storagePath);
context.subscriptions.push(accountProviderService);
accountProviderService.activate();
}

View File

@@ -0,0 +1,7 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../src/sql/data.d.ts'/>

View File

@@ -0,0 +1,20 @@
{
"compileOnSave": true,
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "./out",
"lib": [
"es6", "es2015.promise"
],
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"declaration": true,
"types": ["node"]
},
"exclude": [
"./node_modules"
]
}

View File

@@ -1 +1 @@
sqltoolsservice sqltoolsservice

View File

@@ -0,0 +1,4 @@
client/src/**
client/tsconfig.json
npm-shrinkwrap.json
test/**

View File

@@ -1,7 +1,7 @@
{ {
"service": { "service": {
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "1.2.0-alpha.49", "version": "1.4.0-alpha.3",
"downloadFileNames": { "downloadFileNames": {
"Windows_86": "win-x86-netcoreapp2.0.zip", "Windows_86": "win-x86-netcoreapp2.0.zip",
"Windows_64": "win-x64-netcoreapp2.0.zip", "Windows_64": "win-x64-netcoreapp2.0.zip",
@@ -28,7 +28,7 @@
"specialValueType": "serverName", "specialValueType": "serverName",
"isIdentity": true, "isIdentity": true,
"name": "server", "name": "server",
"displayName": "Server name", "displayName": "Server",
"description": "Name of the SQL Server instance", "description": "Name of the SQL Server instance",
"groupName": "Source", "groupName": "Source",
"valueType": "string", "valueType": "string",
@@ -42,7 +42,7 @@
"specialValueType": "databaseName", "specialValueType": "databaseName",
"isIdentity": true, "isIdentity": true,
"name": "database", "name": "database",
"displayName": "Database name", "displayName": "Database",
"description": "The name of the initial catalog or database int the data source", "description": "The name of the initial catalog or database int the data source",
"groupName": "Source", "groupName": "Source",
"valueType": "string", "valueType": "string",

View File

@@ -8,183 +8,158 @@ import vscode = require('vscode');
import data = require('data'); import data = require('data');
import { Constants } from '../models/constants'; import { Constants } from '../models/constants';
import { Serialization } from '../serialize/serialization'; import { Serialization } from '../serialize/serialization';
import { AzureResourceProvider } from '../resourceprovider/resourceprovider'; import { AzureResourceProvider } from '../resourceProvider/resourceProvider';
import { CredentialStore } from '../credentialstore/credentialstore'; import { CredentialStore } from '../credentialstore/credentialstore';
import {IExtensionConstants, Telemetry, SharedConstants, SqlToolsServiceClient, VscodeWrapper, Utils, PlatformInformation} from 'extensions-modules'; import { IExtensionConstants, Telemetry, Constants as SharedConstants, SqlToolsServiceClient, VscodeWrapper, Utils, PlatformInformation } from 'extensions-modules';
import { LanguageClient } from 'dataprotocol-client'; import { LanguageClient } from 'dataprotocol-client';
import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import { AzureAccountProviderService } from '../account-provider/azureAccountProviderService';
/** /**
* The main controller class that initializes the extension * The main controller class that initializes the extension
*/ */
export default class MainController implements vscode.Disposable { export default class MainController implements vscode.Disposable {
private _context: vscode.ExtensionContext; private _context: vscode.ExtensionContext;
private _vscodeWrapper: VscodeWrapper; private _vscodeWrapper: VscodeWrapper;
private _initialized: boolean = false; private _initialized: boolean = false;
private _serialization: Serialization; private _serialization: Serialization;
private _credentialStore: CredentialStore; private _credentialStore: CredentialStore;
private static _extensionConstants: IExtensionConstants = new Constants(); private static _extensionConstants: IExtensionConstants = new Constants();
private _client: SqlToolsServiceClient; private _client: SqlToolsServiceClient;
/** /**
* The main controller constructor * The main controller constructor
* @constructor * @constructor
*/ */
constructor(context: vscode.ExtensionContext, constructor(context: vscode.ExtensionContext,
vscodeWrapper?: VscodeWrapper) { vscodeWrapper?: VscodeWrapper) {
this._context = context; this._context = context;
this._vscodeWrapper = vscodeWrapper || new VscodeWrapper(MainController._extensionConstants); this._vscodeWrapper = vscodeWrapper || new VscodeWrapper(MainController._extensionConstants);
SqlToolsServiceClient.constants = MainController._extensionConstants; SqlToolsServiceClient.constants = MainController._extensionConstants;
this._client = SqlToolsServiceClient.instance; this._client = SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json'));
this._credentialStore = new CredentialStore(this._client); this._credentialStore = new CredentialStore(this._client);
this._serialization = new Serialization(this._client); this._serialization = new Serialization(this._client);
} }
/** /**
* Disposes the controller * Disposes the controller
*/ */
dispose(): void { dispose(): void {
this.deactivate(); this.deactivate();
} }
/** /**
* Deactivates the extension * Deactivates the extension
*/ */
public deactivate(): void { public deactivate(): void {
Utils.logDebug(SharedConstants.extensionDeactivated, MainController._extensionConstants.extensionConfigSectionName); Utils.logDebug(SharedConstants.extensionDeactivated, MainController._extensionConstants.extensionConfigSectionName);
} }
/** /**
* Initializes the extension * Initializes the extension
*/ */
public activate(): Promise<boolean> { public activate(): Promise<boolean> {
return this.initialize(); return this.initialize();
} }
/** /**
* Returns a flag indicating if the extension is initialized * Returns a flag indicating if the extension is initialized
*/ */
public isInitialized(): boolean { public isInitialized(): boolean {
return this._initialized; return this._initialized;
} }
private createClient( executableFiles: string[]): Promise<LanguageClient> { private createClient(executableFiles: string[]): Promise<LanguageClient> {
return PlatformInformation.getCurrent(SqlToolsServiceClient.constants.getRuntimeId, SqlToolsServiceClient.constants.extensionName).then( platformInfo => { return PlatformInformation.getCurrent(SqlToolsServiceClient.constants.getRuntimeId, SqlToolsServiceClient.constants.extensionName).then(platformInfo => {
return SqlToolsServiceClient.instance.createClient(this._context, platformInfo.runtimeId, undefined, executableFiles); return SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json')).createClient(this._context, platformInfo.runtimeId, undefined, executableFiles);
}); });
} }
private createCredentialClient(): Promise<LanguageClient> { private createCredentialClient(): Promise<LanguageClient> {
return this.createClient(['MicrosoftSqlToolsCredentials.exe', 'MicrosoftSqlToolsCredentials']); return this.createClient(['MicrosoftSqlToolsCredentials.exe', 'MicrosoftSqlToolsCredentials']);
} }
private createSerializationClient(): Promise<LanguageClient> { private createSerializationClient(): Promise<LanguageClient> {
return this.createClient(['MicrosoftSqlToolsSerialization.exe', 'MicrosoftSqlToolsSerialization']); return this.createClient(['MicrosoftSqlToolsSerialization.exe', 'MicrosoftSqlToolsSerialization']);
} }
private createResourceProviderClient(): Promise<LanguageClient> { private createResourceProviderClient(): Promise<LanguageClient> {
return this.createClient(['SqlToolsResourceProviderService.exe', 'SqlToolsResourceProviderService']); return this.createClient(['SqlToolsResourceProviderService.exe', 'SqlToolsResourceProviderService']);
} }
/** /**
* Initializes the extension * Initializes the extension
*/ */
public initialize(): Promise<boolean> { public initialize(): Promise<boolean> {
const self = this;
// initialize language service client // initialize language service client
return new Promise<boolean>( (resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
const self = this;
SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json')).initialize(self._context).then(serverResult => {
let constants = new Constants(); // Initialize telemetry
Telemetry.initialize(self._context, new Constants());
// Create the folder for storing the token caches // telemetry for activation
let storagePath = path.join(Utils.getDefaultLogLocation(), constants.extensionName); Telemetry.sendTelemetryEvent('ExtensionActivated', {},
try { { serviceInstalled: serverResult.installedBeforeInitializing ? 1 : 0 }
if (!fs.existsSync(storagePath)) { );
fs.mkdirSync(storagePath);
console.log('Initialized Azure account extension storage.');
}
} catch(e) {
console.error(`Initialization of Azure account extension storage failed: ${e}`);
console.error('Azure accounts will not be available');
return;
}
// Create the provider service and activate self.createSerializationClient().then(serializationClient => {
const accountProviderService = new AzureAccountProviderService(this._context, storagePath); // Serialization
this._context.subscriptions.push(accountProviderService); let serializationProvider: data.SerializationProvider = {
accountProviderService.activate(); handle: 0,
saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> {
return self._serialization.saveAs(saveFormat, savePath, results, appendToFile);
}
};
data.serialization.registerProvider(serializationProvider);
}, error => {
Utils.logDebug('Cannot find Serialization executables. error: ' + error, MainController._extensionConstants.extensionConfigSectionName);
});
const self = this; self.createResourceProviderClient().then(rpClient => {
SqlToolsServiceClient.instance.initialize(self._context).then(serverResult => { let resourceProvider = new AzureResourceProvider(self._client, rpClient);
data.resources.registerResourceProvider({
displayName: 'Azure SQL Resource Provider', // TODO Localize
id: 'Microsoft.Azure.SQL.ResourceProvider',
settings: {
// Initialize telemetry }
Telemetry.initialize(self._context, new Constants()); }, resourceProvider);
Utils.logDebug('resourceProvider registered', MainController._extensionConstants.extensionConfigSectionName);
}, error => {
Utils.logDebug('Cannot find ResourceProvider executables. error: ' + error, MainController._extensionConstants.extensionConfigSectionName);
});
// telemetry for activation self.createCredentialClient().then(credentialClient => {
Telemetry.sendTelemetryEvent('ExtensionActivated', {},
{ serviceInstalled: serverResult.installedBeforeInitializing ? 1 : 0 }
);
self.createSerializationClient().then(serializationClient => { self._credentialStore.languageClient = credentialClient;
let serialization = new Serialization(self._client, serializationClient); let credentialProvider: data.CredentialProvider = {
// Serialization handle: 0,
let serializationProvider: data.SerializationProvider = { saveCredential(credentialId: string, password: string): Thenable<boolean> {
handle: 0, return self._credentialStore.saveCredential(credentialId, password);
saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> { },
return self._serialization.saveAs(saveFormat, savePath, results, appendToFile); readCredential(credentialId: string): Thenable<data.Credential> {
} return self._credentialStore.readCredential(credentialId);
}; },
data.serialization.registerProvider(serializationProvider); deleteCredential(credentialId: string): Thenable<boolean> {
}, error => { return self._credentialStore.deleteCredential(credentialId);
Utils.logDebug('Cannot find Serialization executables. error: ' + error , MainController._extensionConstants.extensionConfigSectionName); }
}); };
data.credentials.registerProvider(credentialProvider);
Utils.logDebug('credentialProvider registered', MainController._extensionConstants.extensionConfigSectionName);
}, error => {
Utils.logDebug('Cannot find credentials executables. error: ' + error, MainController._extensionConstants.extensionConfigSectionName);
});
self.createResourceProviderClient().then(rpClient => {
let resourceProvider = new AzureResourceProvider(self._client, rpClient);
data.resources.registerResourceProvider({
displayName: 'Azure SQL Resource Provider', // TODO Localize
id: 'Microsoft.Azure.SQL.ResourceProvider',
settings: {
}
}, resourceProvider);
Utils.logDebug('resourceProvider registered', MainController._extensionConstants.extensionConfigSectionName);
}, error => {
Utils.logDebug('Cannot find ResourceProvider executables. error: ' + error , MainController._extensionConstants.extensionConfigSectionName);
});
self.createCredentialClient().then(credentialClient => { Utils.logDebug(SharedConstants.extensionActivated, MainController._extensionConstants.extensionConfigSectionName);
self._initialized = true;
self._credentialStore.languageClient = credentialClient; resolve(true);
let credentialProvider: data.CredentialProvider = { }).catch(err => {
handle: 0, Telemetry.sendTelemetryEventForException(err, 'initialize', MainController._extensionConstants.extensionConfigSectionName);
saveCredential(credentialId: string, password: string): Thenable<boolean> { reject(err);
return self._credentialStore.saveCredential(credentialId, password); });
}, });
readCredential(credentialId: string): Thenable<data.Credential> { }
return self._credentialStore.readCredential(credentialId);
},
deleteCredential(credentialId: string): Thenable<boolean> {
return self._credentialStore.deleteCredential(credentialId);
}
};
data.credentials.registerProvider(credentialProvider);
Utils.logDebug('credentialProvider registered', MainController._extensionConstants.extensionConfigSectionName);
}, error => {
Utils.logDebug('Cannot find credentials executables. error: ' + error , MainController._extensionConstants.extensionConfigSectionName);
});
Utils.logDebug(SharedConstants.extensionActivated, MainController._extensionConstants.extensionConfigSectionName);
self._initialized = true;
resolve(true);
}).catch(err => {
Telemetry.sendTelemetryEventForException(err, 'initialize', MainController._extensionConstants.extensionConfigSectionName);
reject(err);
});
});
}
} }

View File

@@ -1,13 +1,14 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as Contracts from '../models/contracts'; import * as Contracts from '../models/contracts';
import { ICredentialStore } from './icredentialstore'; import { ICredentialStore } from './icredentialstore';
import { SqlToolsServiceClient, Utils } from 'extensions-modules'; import { SqlToolsServiceClient, Utils } from 'extensions-modules';
import { LanguageClient } from 'dataprotocol-client'; import { LanguageClient } from 'dataprotocol-client';
import * as path from 'path';
/** /**
* Implements a credential storage for Windows, Mac (darwin), or Linux. * Implements a credential storage for Windows, Mac (darwin), or Linux.
@@ -16,58 +17,58 @@ import { LanguageClient } from 'dataprotocol-client';
*/ */
export class CredentialStore implements ICredentialStore { export class CredentialStore implements ICredentialStore {
public languageClient: LanguageClient; public languageClient: LanguageClient;
constructor(private _client?: SqlToolsServiceClient) { constructor(private _client?: SqlToolsServiceClient) {
if (!this._client) { if (!this._client) {
this._client = SqlToolsServiceClient.instance; this._client = SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json'));
} }
} }
/** /**
* Gets a credential saved in the credential store * Gets a credential saved in the credential store
* *
* @param {string} credentialId the ID uniquely identifying this credential * @param {string} credentialId the ID uniquely identifying this credential
* @returns {Promise<Credential>} Promise that resolved to the credential, or undefined if not found * @returns {Promise<Credential>} Promise that resolved to the credential, or undefined if not found
*/ */
public readCredential(credentialId: string): Promise<Contracts.Credential> { public readCredential(credentialId: string): Promise<Contracts.Credential> {
Utils.logDebug(this.languageClient, 'MainController._extensionConstants'); Utils.logDebug(this.languageClient, 'MainController._extensionConstants');
let self = this; let self = this;
let cred: Contracts.Credential = new Contracts.Credential(); let cred: Contracts.Credential = new Contracts.Credential();
cred.credentialId = credentialId; cred.credentialId = credentialId;
return new Promise<Contracts.Credential>( (resolve, reject) => { return new Promise<Contracts.Credential>((resolve, reject) => {
self._client self._client
.sendRequest(Contracts.ReadCredentialRequest.type, cred, this.languageClient) .sendRequest(Contracts.ReadCredentialRequest.type, cred, this.languageClient)
.then(returnedCred => { .then(returnedCred => {
resolve(<Contracts.Credential>returnedCred); resolve(<Contracts.Credential>returnedCred);
}, err => reject(err)); }, err => reject(err));
}); });
} }
public saveCredential(credentialId: string, password: any): Promise<boolean> { public saveCredential(credentialId: string, password: any): Promise<boolean> {
let self = this; let self = this;
let cred: Contracts.Credential = new Contracts.Credential(); let cred: Contracts.Credential = new Contracts.Credential();
cred.credentialId = credentialId; cred.credentialId = credentialId;
cred.password = password; cred.password = password;
return new Promise<boolean>( (resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
self._client self._client
.sendRequest(Contracts.SaveCredentialRequest.type, cred, this.languageClient) .sendRequest(Contracts.SaveCredentialRequest.type, cred, this.languageClient)
.then(status => { .then(status => {
resolve(<boolean>status); resolve(<boolean>status);
}, err => reject(err)); }, err => reject(err));
}); });
} }
public deleteCredential(credentialId: string): Promise<boolean> { public deleteCredential(credentialId: string): Promise<boolean> {
let self = this; let self = this;
let cred: Contracts.Credential = new Contracts.Credential(); let cred: Contracts.Credential = new Contracts.Credential();
cred.credentialId = credentialId; cred.credentialId = credentialId;
return new Promise<boolean>( (resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
self._client self._client
.sendRequest(Contracts.DeleteCredentialRequest.type, cred, this.languageClient) .sendRequest(Contracts.DeleteCredentialRequest.type, cred, this.languageClient)
.then(status => { .then(status => {
resolve(<boolean>status); resolve(<boolean>status);
}, err => reject(err)); }, err => reject(err));
}); });
} }
} }

View File

@@ -1,7 +1,7 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
@@ -17,7 +17,7 @@ import { Credential } from '../models/contracts';
* @interface ICredentialStore * @interface ICredentialStore
*/ */
export interface ICredentialStore { export interface ICredentialStore {
readCredential(credentialId: string): Promise<Credential>; readCredential(credentialId: string): Promise<Credential>;
saveCredential(credentialId: string, password: any): Promise<boolean>; saveCredential(credentialId: string, password: any): Promise<boolean>;
deleteCredential(credentialId: string): Promise<boolean>; deleteCredential(credentialId: string): Promise<boolean>;
} }

View File

@@ -7,7 +7,7 @@
import vscode = require('vscode'); import vscode = require('vscode');
import MainController from './controllers/mainController'; import MainController from './controllers/mainController';
let controller: MainController = undefined; export let controller: MainController;
export function activate(context: vscode.ExtensionContext) { export function activate(context: vscode.ExtensionContext) {
controller = new MainController(context); controller = new MainController(context);
@@ -17,14 +17,7 @@ export function activate(context: vscode.ExtensionContext) {
// this method is called when your extension is deactivated // this method is called when your extension is deactivated
export function deactivate(): void { export function deactivate(): void {
if (controller) { if (controller) {
controller.deactivate(); controller.deactivate();
} }
}
/**
* Exposed for testing purposes
*/
export function getController(): MainController {
return controller;
} }

View File

@@ -3,315 +3,141 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import {IExtensionConstants} from 'extensions-modules/lib/models/contracts/contracts'; import { IExtensionConstants } from 'extensions-modules/lib/models/contracts/contracts';
import {Runtime, LinuxDistribution} from 'extensions-modules/lib/models/platform'; import { Runtime, LinuxDistribution } from 'extensions-modules/lib/models/platform';
// constants // constants
export class Constants implements IExtensionConstants { export class Constants implements IExtensionConstants {
public readonly languageId = 'sql'; public readonly languageId = 'sql';
public readonly extensionName = 'mssql'; public readonly extensionName = 'mssql';
public readonly extensionConfigSectionName = 'mssql'; public readonly extensionConfigSectionName = 'mssql';
public readonly connectionApplicationName = 'vscode-mssql'; public readonly outputChannelName = 'MSSQL';
public readonly outputChannelName = 'MSSQL'; public readonly providerId = 'MSSQL';
public readonly connectionConfigFilename = 'settings.json'; public readonly installFolderName = 'sqltoolsservice';
public readonly connectionsArrayName = 'mssql.connections'; public readonly telemetryExtensionName = 'carbon-mssql';
public readonly cmdRunQuery = 'extension.runQuery';
public readonly cmdCancelQuery = 'extension.cancelQuery';
public readonly cmdConnect = 'extension.connect';
public readonly cmdDisconnect = 'extension.disconnect';
public readonly cmdChooseDatabase = 'extension.chooseDatabase';
public readonly cmdShowReleaseNotes = 'extension.showReleaseNotes';
public readonly cmdShowGettingStarted = 'extension.showGettingStarted';
public readonly cmdNewQuery = 'extension.newQuery';
public readonly cmdManageConnectionProfiles = 'extension.manageProfiles';
public readonly sqlDbPrefix = '.database.windows.net';
public readonly defaultConnectionTimeout = 15;
public readonly azureSqlDbConnectionTimeout = 30;
public readonly azureDatabase = 'Azure';
public readonly defaultPortNumber = 1433;
public readonly sqlAuthentication = 'SqlLogin';
public readonly defaultDatabase = 'master';
public readonly errorPasswordExpired = 18487;
public readonly errorPasswordNeedsReset = 18488;
public readonly maxDisplayedStatusTextLength = 50;
public readonly outputContentTypeRoot = 'root';
public readonly outputContentTypeMessages = 'messages';
public readonly outputContentTypeResultsetMeta = 'resultsetsMeta';
public readonly outputContentTypeColumns = 'columns';
public readonly outputContentTypeRows = 'rows';
public readonly outputContentTypeConfig = 'config';
public readonly outputContentTypeSaveResults = 'saveResults';
public readonly outputContentTypeOpenLink = 'openLink';
public readonly outputContentTypeCopy = 'copyResults';
public readonly outputContentTypeEditorSelection = 'setEditorSelection';
public readonly outputContentTypeShowError = 'showError';
public readonly outputContentTypeShowWarning = 'showWarning';
public readonly outputServiceLocalhost = 'http://localhost:';
public readonly msgContentProviderSqlOutputHtml = 'dist/html/sqlOutput.ejs';
public readonly contentProviderMinFile = 'dist/js/app.min.js';
public readonly configLogDebugInfo = 'logDebugInfo';
public readonly providerId = 'MSSQL';
public readonly installFolderName = 'sqltoolsservice';
public readonly telemetryExtensionName = 'carbon-mssql';
// localizable strings // localizable strings
public readonly configMyConnectionsNoServerName = 'Missing server name in user preferences connection: '; public readonly serviceCompatibleVersion = '1.0.0';
public readonly msgLocalWebserviceStaticContent = 'LocalWebService: added static html content path: '; public readonly serviceInstallingTo = 'Installing SQL tools service to';
public readonly msgLocalWebserviceStarted = 'LocalWebService listening on port '; public readonly serviceInitializing = 'Initializing SQL tools service for the mssql extension.';
public readonly msgRunQueryAllBatchesExecuted = 'runQuery: all batches executed'; public readonly commandsNotAvailableWhileInstallingTheService = 'Note: mssql commands will be available after installing the service.';
public readonly msgStartedExecute = 'Started query execution for document "{0}"'; public readonly serviceInstalled = 'Sql Tools Service installed';
public readonly msgFinishedExecute = 'Finished query execution for document "{0}"'; public readonly serviceInstallationFailed = 'Failed to install Sql Tools Service';
public readonly msgRunQueryError = 'runQuery: error: '; public readonly serviceLoadingFailed = 'Failed to load Sql Tools Service';
public readonly msgRunQueryExecutingBatch = 'runQuery: executeBatch called with SQL: '; public readonly invalidServiceFilePath = 'Invalid file path for Sql Tools Service';
public readonly msgRunQueryAddBatchResultsets = 'runQuery: adding resultsets for batch: '; public readonly serviceName = 'SQLToolsService';
public readonly msgRunQueryAddBatchError = 'runQuery: adding error message for batch: '; public readonly serviceInitializingOutputChannelName = 'SqlToolsService Initialization';
public readonly msgRunQueryConnectionActive = 'runQuery: active connection is connected, using it to run query'; public readonly serviceCrashMessage = 'SQL Tools Service component exited unexpectedly. Please restart SQL Operations Studio.';
public readonly msgRunQueryConnectionDisconnected = 'runQuery: active connection is disconnected, reconnecting'; public readonly serviceCrashLink = 'https://github.com/Microsoft/vscode-mssql/wiki/SqlToolsService-Known-Issues';
public readonly msgRunQueryNoConnection = 'runQuery: no active connection - prompting for user';
public readonly msgRunQueryInProgress = 'A query is already running for this editor session. Please cancel this query or wait for its completion.';
public readonly runQueryBatchStartMessage = 'Started executing query at ';
public readonly runQueryBatchStartLine = 'Line {0}';
public readonly msgCancelQueryFailed = 'Canceling the query failed: {0}';
public readonly msgCancelQueryNotRunning = 'Cannot cancel query as no query is running.';
public readonly msgCancelQuerySuccess = 'Successfully canceled the query.';
public readonly msgContentProviderOnContentUpdated = 'Content provider: onContentUpdated called';
public readonly msgContentProviderAssociationFailure = 'Content provider: Unable to associate status view for current file';
public readonly msgContentProviderOnRootEndpoint = 'LocalWebService: Root end-point called';
public readonly msgContentProviderOnResultsEndpoint = 'LocalWebService: ResultsetsMeta endpoint called';
public readonly msgContentProviderOnMessagesEndpoint = 'LocalWebService: Messages end-point called';
public readonly msgContentProviderOnColumnsEndpoint = 'LocalWebService: Columns end-point called for index = ';
public readonly msgContentProviderOnRowsEndpoint = 'LocalWebService: Rows end-point called for index = ';
public readonly msgContentProviderOnClear = 'Content provider: clear called';
public readonly msgContentProviderOnUpdateContent = 'Content provider: updateContent called';
public readonly msgContentProviderProvideContent = 'Content provider: provideTextDocumentContent called: ';
public readonly msgChooseDatabaseNotConnected = 'No connection was found. Please connect to a server first.';
public readonly msgChooseDatabasePlaceholder = 'Choose a database from the list below';
public readonly msgConnectionError = 'Error {0}: {1}';
public readonly msgConnectionError2 = 'Failed to connect: {0}';
public readonly msgConnectionErrorPasswordExpired = 'Error {0}: {1} Please login as a different user and change the password using ALTER LOGIN.';
public readonly connectionErrorChannelName = 'Connection Errors';
public readonly msgPromptCancelConnect = 'Server connection in progress. Do you want to cancel?';
public readonly msgPromptClearRecentConnections = 'Confirm to clear recent connections list';
public readonly msgOpenSqlFile = 'To use this command, Open a .sql file -or- ' +
'Change editor language to "SQL" -or- ' +
'Select T-SQL text in the active SQL editor.';
public readonly recentConnectionsPlaceholder = 'Choose a connection profile from the list below';
public readonly msgNoConnectionsInSettings = 'To use this command, add connection profile to User Settings.';
public readonly labelOpenGlobalSettings = 'Open Global Settings';
public readonly labelOpenWorkspaceSettings = 'Open Workspace Settings';
public readonly CreateProfileFromConnectionsListLabel = 'Create Connection Profile';
public readonly CreateProfileLabel = 'Create';
public readonly ClearRecentlyUsedLabel = 'Clear Recent Connections List';
public readonly EditProfilesLabel = 'Edit';
public readonly RemoveProfileLabel = 'Remove';
public readonly ManageProfilesPrompt = 'Manage Connection Profiles';
public readonly SampleServerName = '{{put-server-name-here}}';
public readonly serverPrompt = 'Server name';
public readonly serverPlaceholder = 'hostname\\instance or <server>.database.windows.net';
public readonly databasePrompt = 'Database name';
public readonly databasePlaceholder = '[Optional] Database to connect (press Enter to connect to <default> database)';
public readonly databaseDefaultValue = 'master';
public readonly authTypePrompt = 'Authentication Type';
public readonly authTypeIntegrated = 'Integrated';
public readonly authTypeSql = 'SQL Login';
public readonly authTypeAdUniversal = 'Active Directory Universal';
public readonly usernamePrompt = 'User name';
public readonly usernamePlaceholder = 'User name (SQL Login)';
public readonly passwordPrompt = 'Password';
public readonly passwordPlaceholder = 'Password (SQL Login)';
public readonly msgSavePassword = 'Save Password? If \'No\', password will be required each time you connect';
public readonly profileNamePrompt = 'Profile Name';
public readonly profileNamePlaceholder = '[Optional] Enter a name for this profile';
public readonly filepathPrompt = 'File path';
public readonly filepathPlaceholder = 'File name';
public readonly filepathMessage = 'File name';
public readonly overwritePrompt = 'A file with this name already exists. Do you want to replace the existing file?';
public readonly overwritePlaceholder = 'A file with this name already exists';
public readonly msgSaveResultInProgress = 'A save request is already executing. Please wait for its completion.';
public readonly msgCannotOpenContent = 'Error occurred opening content in editor.';
public readonly msgSaveStarted = 'Started saving results to ';
public readonly msgSaveFailed = 'Failed to save results. ';
public readonly msgSaveSucceeded = 'Successfully saved results to ';
public readonly msgSelectProfile = 'Select connection profile';
public readonly msgSelectProfileToRemove = 'Select profile to remove';
public readonly confirmRemoveProfilePrompt = 'Confirm to remove this profile.';
public readonly msgNoProfilesSaved = 'No connection profile to remove.';
public readonly msgProfileRemoved = 'Profile removed successfully';
public readonly msgProfileCreated = 'Profile created successfully';
public readonly msgProfileCreatedAndConnected = 'Profile created and connected';
public readonly msgClearedRecentConnections = 'Recent connections list cleared';
public readonly msgSelectionIsRequired = 'Selection is required.';
public readonly msgIsRequired = ' is required.';
public readonly msgRetry = 'Retry';
public readonly msgError = 'Error: ';
public readonly msgYes = 'Yes';
public readonly msgNo = 'No';
public readonly defaultDatabaseLabel = '<default>';
public readonly notConnectedLabel = 'Disconnected';
public readonly notConnectedTooltip = 'Click to connect to a database';
public readonly connectingLabel = 'Connecting';
public readonly connectingTooltip = 'Connecting to: ';
public readonly connectedLabel = 'Connected.';
public readonly connectErrorLabel = 'Connection error';
public readonly connectErrorTooltip = 'Error connecting to: ';
public readonly connectErrorCode = 'Errorcode: ';
public readonly connectErrorMessage = 'ErrorMessage: ';
public readonly executeQueryLabel = 'Executing query ';
public readonly cancelingQueryLabel = 'Canceling query ';
public readonly updatingIntelliSenseLabel = 'Updating IntelliSense...';
public readonly unfoundResult = 'Data was disposed when text editor was closed; to view data please reexecute query.';
public readonly serviceCompatibleVersion = '1.0.0';
public readonly serviceNotCompatibleError = 'Client is not compatible with the service layer';
public readonly serviceInstallingTo = 'Installing SQL tools service to';
public readonly serviceInitializing = 'Initializing SQL tools service for the mssql extension.';
public readonly commandsNotAvailableWhileInstallingTheService = 'Note: mssql commands will be available after installing the service.';
public readonly serviceInstalled = 'Sql Tools Service installed';
public readonly serviceInstallationFailed = 'Failed to install Sql Tools Service';
public readonly serviceLoadingFailed = 'Failed to load Sql Tools Service';
public readonly invalidServiceFilePath = 'Invalid file path for Sql Tools Service';
public readonly extensionNotInitializedError = 'Unable to execute the command while the extension is initializing. Please try again later.';
public readonly untitledScheme = 'untitled';
public readonly untitledSaveTimeThreshold = 10.0;
public readonly renamedOpenTimeThreshold = 10.0;
public readonly msgChangeLanguageMode = 'To use this command, you must set the language to \"SQL\". Confirm to change language mode.';
public readonly timeToWaitForLanguageModeChange = 10000.0;
public readonly msgChangedDatabaseContext = 'Changed database context to \"{0}\" for document \"{1}\"';
public readonly msgPromptRetryCreateProfile = 'Error: Unable to connect using the connection information provided. Retry profile creation?';
public readonly retryLabel = 'Retry';
public readonly msgConnecting = 'Connecting to server \"{0}\" on document \"{1}\".';
public readonly msgConnectedServerInfo = 'Connected to server \"{0}\" on document \"{1}\". Server information: {2}';
public readonly msgConnectionFailed = 'Error connecting to server \"{0}\". Details: {1}';
public readonly msgChangingDatabase = 'Changing database context to \"{0}\" on server \"{1}\" on document \"{2}\".';
public readonly msgChangedDatabase = 'Changed database context to \"{0}\" on server \"{1}\" on document \"{2}\".';
public readonly msgDisconnected = 'Disconnected on document \"{0}\"';
public readonly msgErrorReadingConfigFile = 'Error: Unable to load connection profiles from [{0}]. Check if the file is formatted correctly.';
public readonly msgErrorOpeningConfigFile = 'Error: Unable to open connection profile settings file.';
public readonly extConfigResultKeys = ['shortcuts', 'messagesDefaultOpen'];
public readonly extConfigResultFontFamily = 'resultsFontFamily';
public readonly extConfigResultFontSize = 'resultsFontSize';
public readonly titleResultsPane = 'Results: {0}';
public readonly macOpenSslErrorMessage = `OpenSSL version >=1.0.1 is required to connect.`;
public readonly macOpenSslHelpButton = 'Help';
public readonly macOpenSslHelpLink = 'https://github.com/Microsoft/vscode-mssql/wiki/OpenSSL-Configuration';
public readonly serviceName = 'SQLToolsService';
public readonly serviceInitializingOutputChannelName = 'SqlToolsService Initialization';
public readonly gettingStartedGuideLink = 'https://aka.ms/mssql-getting-started';
public readonly serviceCrashMessage = 'SQL Tools Service component exited unexpectedly. Please restart SQL Operations Studio.';
public readonly serviceCrashLink = 'https://github.com/Microsoft/vscode-mssql/wiki/SqlToolsService-Known-Issues';
public readonly gettingDefinitionMessage = 'Getting definition ...';
public readonly definitionRequestedStatus = 'DefinitionRequested';
public readonly definitionRequestCompletedStatus = 'DefinitionRequestCompleted';
public readonly updatingIntelliSenseStatus = 'updatingIntelliSense';
public readonly intelliSenseUpdatedStatus = 'intelliSenseUpdated';
/** /**
* Returns a supported .NET Core Runtime ID (RID) for the current platform. The list of Runtime IDs * Returns a supported .NET Core Runtime ID (RID) for the current platform. The list of Runtime IDs
* is available at https://github.com/dotnet/corefx/tree/master/pkg/Microsoft.NETCore.Platforms. * is available at https://github.com/dotnet/corefx/tree/master/pkg/Microsoft.NETCore.Platforms.
*/ */
public getRuntimeId(platform: string, architecture: string, distribution: LinuxDistribution): Runtime { public getRuntimeId(platform: string, architecture: string, distribution: LinuxDistribution): Runtime {
switch (platform) { switch (platform) {
case 'win32': case 'win32':
switch (architecture) { switch (architecture) {
case 'x86': return Runtime.Windows_86; case 'x86': return Runtime.Windows_86;
case 'x86_64': return Runtime.Windows_64; case 'x86_64': return Runtime.Windows_64;
default: default:
} }
throw new Error(`Unsupported Windows architecture: ${architecture}`); throw new Error(`Unsupported Windows architecture: ${architecture}`);
case 'darwin': case 'darwin':
if (architecture === 'x86_64') { if (architecture === 'x86_64') {
// Note: We return the El Capitan RID for Sierra // Note: We return the El Capitan RID for Sierra
return Runtime.OSX; return Runtime.OSX;
} }
throw new Error(`Unsupported macOS architecture: ${architecture}`); throw new Error(`Unsupported macOS architecture: ${architecture}`);
case 'linux': case 'linux':
if (architecture === 'x86_64') { if (architecture === 'x86_64') {
// First try the distribution name // First try the distribution name
let runtimeId = Constants.getRuntimeIdHelper(distribution.name, distribution.version); let runtimeId = Constants.getRuntimeIdHelper(distribution.name, distribution.version);
// If the distribution isn't one that we understand, but the 'ID_LIKE' field has something that we understand, use that // If the distribution isn't one that we understand, but the 'ID_LIKE' field has something that we understand, use that
// //
// NOTE: 'ID_LIKE' doesn't specify the version of the 'like' OS. So we will use the 'VERSION_ID' value. This will restrict // NOTE: 'ID_LIKE' doesn't specify the version of the 'like' OS. So we will use the 'VERSION_ID' value. This will restrict
// how useful ID_LIKE will be since it requires the version numbers to match up, but it is the best we can do. // how useful ID_LIKE will be since it requires the version numbers to match up, but it is the best we can do.
if (runtimeId === Runtime.UnknownRuntime && distribution.idLike && distribution.idLike.length > 0) { if (runtimeId === Runtime.UnknownRuntime && distribution.idLike && distribution.idLike.length > 0) {
for (let id of distribution.idLike) { for (let id of distribution.idLike) {
runtimeId = Constants.getRuntimeIdHelper(id, distribution.version); runtimeId = Constants.getRuntimeIdHelper(id, distribution.version);
if (runtimeId !== Runtime.UnknownRuntime) { if (runtimeId !== Runtime.UnknownRuntime) {
break; break;
} }
} }
} }
if (runtimeId !== Runtime.UnknownRuntime && runtimeId !== Runtime.UnknownVersion) { if (runtimeId !== Runtime.UnknownRuntime && runtimeId !== Runtime.UnknownVersion) {
return runtimeId; return runtimeId;
} }
} }
// If we got here, this is not a Linux distro or architecture that we currently support. // If we got here, this is not a Linux distro or architecture that we currently support.
throw new Error(`Unsupported Linux distro: ${distribution.name}, ${distribution.version}, ${architecture}`); throw new Error(`Unsupported Linux distro: ${distribution.name}, ${distribution.version}, ${architecture}`);
default : default:
// If we got here, we've ended up with a platform we don't support like 'freebsd' or 'sunos'. // If we got here, we've ended up with a platform we don't support like 'freebsd' or 'sunos'.
// Chances are, VS Code doesn't support these platforms either. // Chances are, VS Code doesn't support these platforms either.
throw Error('Unsupported platform ' + platform); throw Error('Unsupported platform ' + platform);
} }
} }
private static getRuntimeIdHelper(distributionName: string, distributionVersion: string): Runtime { private static getRuntimeIdHelper(distributionName: string, distributionVersion: string): Runtime {
switch (distributionName) { switch (distributionName) {
case 'ubuntu': case 'ubuntu':
if (distributionVersion.startsWith('14')) { if (distributionVersion.startsWith('14')) {
// This also works for Linux Mint // This also works for Linux Mint
return Runtime.Ubuntu_14; return Runtime.Ubuntu_14;
} else if (distributionVersion.startsWith('16')) { } else if (distributionVersion.startsWith('16')) {
return Runtime.Ubuntu_16; return Runtime.Ubuntu_16;
} }
break; break;
case 'elementary': case 'elementary':
case 'elementary OS': case 'elementary OS':
if (distributionVersion.startsWith('0.3')) { if (distributionVersion.startsWith('0.3')) {
// Elementary OS 0.3 Freya is binary compatible with Ubuntu 14.04 // Elementary OS 0.3 Freya is binary compatible with Ubuntu 14.04
return Runtime.Ubuntu_14; return Runtime.Ubuntu_14;
} else if (distributionVersion.startsWith('0.4')) { } else if (distributionVersion.startsWith('0.4')) {
// Elementary OS 0.4 Loki is binary compatible with Ubuntu 16.04 // Elementary OS 0.4 Loki is binary compatible with Ubuntu 16.04
return Runtime.Ubuntu_16; return Runtime.Ubuntu_16;
} }
break; break;
case 'linuxmint': case 'linuxmint':
if (distributionVersion.startsWith('18')) { if (distributionVersion.startsWith('18')) {
// Linux Mint 18 is binary compatible with Ubuntu 16.04 // Linux Mint 18 is binary compatible with Ubuntu 16.04
return Runtime.Ubuntu_16; return Runtime.Ubuntu_16;
} }
break; break;
case 'centos': case 'centos':
case 'ol': case 'ol':
// Oracle Linux is binary compatible with CentOS // Oracle Linux is binary compatible with CentOS
return Runtime.CentOS_7; return Runtime.CentOS_7;
case 'fedora': case 'fedora':
return Runtime.Fedora_23; return Runtime.Fedora_23;
case 'opensuse': case 'opensuse':
return Runtime.OpenSUSE_13_2; return Runtime.OpenSUSE_13_2;
case 'sles': case 'sles':
return Runtime.SLES_12_2; return Runtime.SLES_12_2;
case 'rhel': case 'rhel':
return Runtime.RHEL_7; return Runtime.RHEL_7;
case 'debian': case 'debian':
return Runtime.Debian_8; return Runtime.Debian_8;
case 'galliumos': case 'galliumos':
if (distributionVersion.startsWith('2.0')) { if (distributionVersion.startsWith('2.0')) {
return Runtime.Ubuntu_16; return Runtime.Ubuntu_16;
} }
break; break;
default: default:
return Runtime.UnknownRuntime; return Runtime.UnknownRuntime;
} }
return Runtime.UnknownVersion; return Runtime.UnknownVersion;
} }
} }

View File

@@ -1,10 +1,10 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import {RequestType} from 'dataprotocol-client'; import { RequestType } from 'dataprotocol-client';
import * as data from 'data'; import * as data from 'data';
// DEV-NOTE: Still finalizing what we'll need as part of this interface // DEV-NOTE: Still finalizing what we'll need as part of this interface
@@ -16,37 +16,35 @@ import * as data from 'data';
* @param {boolean} appendToFile Whether we should append or overwrite the file in savePath * @param {boolean} appendToFile Whether we should append or overwrite the file in savePath
*/ */
export class SaveResultsInfo { export class SaveResultsInfo {
constructor(public saveFormat: string, public savePath: string, public results: string,
public appendToFile: boolean) {
constructor(public saveFormat: string, public savePath: string, public results: string, }
public appendToFile: boolean) {
}
} }
export namespace SaveAsRequest { export namespace SaveAsRequest {
export const type: RequestType<SaveResultsInfo, data.SaveResultRequestResult, void> = { get method(): string { return 'query/saveAs'; } }; export const type: RequestType<SaveResultsInfo, data.SaveResultRequestResult, void> = { get method(): string { return 'query/saveAs'; } };
} }
// --------------------------------- < Read Credential Request > ------------------------------------------------- // --------------------------------- < Read Credential Request > -------------------------------------------------
// Read Credential request message callback declaration // Read Credential request message callback declaration
export namespace ReadCredentialRequest { export namespace ReadCredentialRequest {
export const type: RequestType<Credential, Credential, void> = { get method(): string { return 'credential/read'; } }; export const type: RequestType<Credential, Credential, void> = { get method(): string { return 'credential/read'; } };
} }
/** /**
* Parameters to initialize a connection to a database * Parameters to initialize a connection to a database
*/ */
export class Credential { export class Credential {
/** /**
* Unique ID identifying the credential * Unique ID identifying the credential
*/ */
public credentialId: string; public credentialId: string;
/** /**
* password * password
*/ */
public password: string; public password: string;
} }
// --------------------------------- </ Read Credential Request > ------------------------------------------------- // --------------------------------- </ Read Credential Request > -------------------------------------------------
@@ -55,7 +53,7 @@ export class Credential {
// Save Credential request message callback declaration // Save Credential request message callback declaration
export namespace SaveCredentialRequest { export namespace SaveCredentialRequest {
export const type: RequestType<Credential, boolean, void> = { get method(): string { return 'credential/save'; } }; export const type: RequestType<Credential, boolean, void> = { get method(): string { return 'credential/save'; } };
} }
// --------------------------------- </ Save Credential Request > ------------------------------------------------- // --------------------------------- </ Save Credential Request > -------------------------------------------------
@@ -64,7 +62,7 @@ export namespace SaveCredentialRequest {
// Delete Credential request message callback declaration // Delete Credential request message callback declaration
export namespace DeleteCredentialRequest { export namespace DeleteCredentialRequest {
export const type: RequestType<Credential, boolean, void> = { get method(): string { return 'credential/delete'; } }; export const type: RequestType<Credential, boolean, void> = { get method(): string { return 'credential/delete'; } };
} }
// --------------------------------- </ Delete Credential Request > ------------------------------------------------- // --------------------------------- </ Delete Credential Request > -------------------------------------------------
@@ -101,4 +99,3 @@ export interface HandleFirewallRuleResponse {
result: boolean; result: boolean;
ipAddress: string; ipAddress: string;
} }

View File

@@ -1,13 +1,14 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as Contracts from '../models/contracts'; import * as Contracts from '../models/contracts';
import { SqlToolsServiceClient } from 'extensions-modules'; import { SqlToolsServiceClient } from 'extensions-modules';
import { LanguageClient } from 'dataprotocol-client'; import { LanguageClient } from 'dataprotocol-client';
import * as data from 'data'; import * as data from 'data';
import * as path from 'path';
/** /**
@@ -17,47 +18,47 @@ import * as data from 'data';
*/ */
export class AzureResourceProvider implements data.ResourceProvider { export class AzureResourceProvider implements data.ResourceProvider {
public languageClient: LanguageClient; public languageClient: LanguageClient;
constructor(private _client?: SqlToolsServiceClient, langClient?: LanguageClient) { constructor(private _client?: SqlToolsServiceClient, langClient?: LanguageClient) {
if (!this._client) { if (!this._client) {
this._client = SqlToolsServiceClient.instance; this._client = SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json'));
} }
this.languageClient = langClient; this.languageClient = langClient;
} }
public createFirewallRule(account: data.Account, firewallruleInfo: data.FirewallRuleInfo): Thenable<data.CreateFirewallRuleResponse> { public createFirewallRule(account: data.Account, firewallruleInfo: data.FirewallRuleInfo): Thenable<data.CreateFirewallRuleResponse> {
let self = this; let self = this;
return new Promise<data.CreateFirewallRuleResponse>((resolve, reject) => { return new Promise<data.CreateFirewallRuleResponse>((resolve, reject) => {
self._client. self._client.
sendRequest(Contracts.CreateFirewallRuleRequest.type, self.asCreateFirewallRuleParams(account, firewallruleInfo), self.languageClient) sendRequest(Contracts.CreateFirewallRuleRequest.type, self.asCreateFirewallRuleParams(account, firewallruleInfo), self.languageClient)
.then(response => { .then(response => {
resolve(response); resolve(response);
}, err => reject(err)); }, err => reject(err));
}); });
} }
public handleFirewallRule(errorCode: number, errorMessage: string, connectionTypeId: string): Thenable<data.HandleFirewallRuleResponse> { public handleFirewallRule(errorCode: number, errorMessage: string, connectionTypeId: string): Thenable<data.HandleFirewallRuleResponse> {
let self = this; let self = this;
return new Promise<data.HandleFirewallRuleResponse>((resolve, reject) => { return new Promise<data.HandleFirewallRuleResponse>((resolve, reject) => {
let params: Contracts.HandleFirewallRuleParams = { errorCode: errorCode, errorMessage: errorMessage, connectionTypeId: connectionTypeId }; let params: Contracts.HandleFirewallRuleParams = { errorCode: errorCode, errorMessage: errorMessage, connectionTypeId: connectionTypeId };
self._client. self._client.
sendRequest(Contracts.HandleFirewallRuleRequest.type, params, self.languageClient) sendRequest(Contracts.HandleFirewallRuleRequest.type, params, self.languageClient)
.then(response => { .then(response => {
resolve(response); resolve(response);
}, err => reject(err)); }, err => reject(err));
}); });
} }
private asCreateFirewallRuleParams(account: data.Account, params: data.FirewallRuleInfo): Contracts.CreateFirewallRuleParams { private asCreateFirewallRuleParams(account: data.Account, params: data.FirewallRuleInfo): Contracts.CreateFirewallRuleParams {
return { return {
account: account, account: account,
serverName: params.serverName, serverName: params.serverName,
startIpAddress: params.startIpAddress, startIpAddress: params.startIpAddress,
endIpAddress: params.endIpAddress, endIpAddress: params.endIpAddress,
securityTokenMappings: params.securityTokenMappings securityTokenMappings: params.securityTokenMappings
}; };
} }
} }

View File

@@ -1,10 +1,9 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import { SaveResultsInfo } from '../models/contracts';
import * as data from 'data'; import * as data from 'data';
/** /**
@@ -14,5 +13,5 @@ import * as data from 'data';
* @interface ISerialization * @interface ISerialization
*/ */
export interface ISerialization { export interface ISerialization {
saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Promise<data.SaveResultRequestResult>; saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Promise<data.SaveResultRequestResult>;
} }

View File

@@ -1,7 +1,7 @@
/*--------------------------------------------------------------------------------------------- /*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as Contracts from '../models/contracts'; import * as Contracts from '../models/contracts';
@@ -9,33 +9,34 @@ import { ISerialization } from './iserialization';
import { SqlToolsServiceClient } from 'extensions-modules'; import { SqlToolsServiceClient } from 'extensions-modules';
import * as data from 'data'; import * as data from 'data';
import { LanguageClient } from 'dataprotocol-client'; import { LanguageClient } from 'dataprotocol-client';
import * as path from 'path';
/** /**
* Implements serializer for query results * Implements serializer for query results
*/ */
export class Serialization implements ISerialization { export class Serialization implements ISerialization {
constructor(private _client?: SqlToolsServiceClient, private _languageClient?: LanguageClient) { constructor(private _client?: SqlToolsServiceClient, private _languageClient?: LanguageClient) {
if (!this._client) { if (!this._client) {
this._client = SqlToolsServiceClient.instance; this._client = SqlToolsServiceClient.getInstance(path.join(__dirname, '../config.json'));
} }
} }
/** /**
* Saves results as a specified path * Saves results as a specified path
* *
* @param {string} credentialId the ID uniquely identifying this credential * @param {string} credentialId the ID uniquely identifying this credential
* @returns {Promise<ISaveResultsInfo>} Promise that resolved to the credential, or undefined if not found * @returns {Promise<ISaveResultsInfo>} Promise that resolved to the credential, or undefined if not found
*/ */
public saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Promise<data.SaveResultRequestResult> { public saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Promise<data.SaveResultRequestResult> {
let self = this; let self = this;
let resultsInfo: Contracts.SaveResultsInfo = new Contracts.SaveResultsInfo(saveFormat, savePath, results, appendToFile); let resultsInfo: Contracts.SaveResultsInfo = new Contracts.SaveResultsInfo(saveFormat, savePath, results, appendToFile);
return new Promise<data.SaveResultRequestResult>( (resolve, reject) => { return new Promise<data.SaveResultRequestResult>((resolve, reject) => {
self._client self._client
.sendRequest(Contracts.SaveAsRequest.type, resultsInfo, this._languageClient) .sendRequest(Contracts.SaveAsRequest.type, resultsInfo, this._languageClient)
.then(result => { .then(result => {
resolve(<data.SaveResultRequestResult>result); resolve(<data.SaveResultRequestResult>result);
}, err => reject(err)); }, err => reject(err));
}); });
} }
} }

View File

@@ -4,4 +4,5 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
/// <reference path='../../../../../src/vs/vscode.d.ts'/> /// <reference path='../../../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../../../src/sql/data.d.ts'/> /// <reference path='../../../../../src/sql/data.d.ts'/>
/// <reference types='@types/node'/>

File diff suppressed because it is too large Load Diff

View File

@@ -9,13 +9,14 @@
"activationEvents": [ "activationEvents": [
"*" "*"
], ],
"main": "./client/out/mssqlMain", "main": "./client/out/main",
"extensionDependencies": [ "extensionDependencies": [
"vscode.sql" "vscode.sql"
], ],
"scripts": { "scripts": {
"compile": "gulp compile-extension:mssql-client", "compile": "gulp compile-extension:mssql-client",
"postinstall": "node ./node_modules/vscode/bin/install" "postinstall": "node ./node_modules/vscode/bin/install",
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json"
}, },
"contributes": { "contributes": {
"languages": [ "languages": [
@@ -26,15 +27,7 @@
], ],
"aliases": [ "aliases": [
"SQL" "SQL"
], ]
"configuration": "./syntaxes/sql.configuration.json"
}
],
"grammars": [
{
"language": "sql",
"scopeName": "source.sql",
"path": "./syntaxes/SQL.plist"
} }
], ],
"outputChannels": [ "outputChannels": [
@@ -46,38 +39,10 @@
"path": "./snippets/mssql.json" "path": "./snippets/mssql.json"
} }
], ],
"commands": [
{
"command": "extension.clearTokenCache",
"title": "%extension.clearTokenCache%",
"category": "Azure Accounts"
}
],
"account-type": [
{
"id": "microsoft",
"icon": {
"light": "./out/account-provider/media/microsoft_account_light.svg",
"dark": "./out/account-provider/media/microsoft_account_dark.svg"
}
},
{
"id": "work_school",
"icon": {
"light": "./out/account-provider/media/work_school_account_light.svg",
"dark": "./out/account-provider/media/work_school_account_dark.svg"
}
}
],
"configuration": { "configuration": {
"type": "object", "type": "object",
"title": "MSSQL configuration", "title": "MSSQL configuration",
"properties": { "properties": {
"accounts.azure.enablePublicCloud": {
"type": "boolean",
"default": true,
"description": "%config.enablePublicCloudDescription%"
},
"mssql.query.displayBitAsNumber": { "mssql.query.displayBitAsNumber": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,
@@ -227,18 +192,9 @@
} }
}, },
"dependencies": { "dependencies": {
"dataprotocol-client": "file:../../dataprotocol-node/client", "dataprotocol-client": "file:../../dataprotocol-node/client"
"extensions-modules": "file:../../extensions-modules",
"adal-node": "0.1.25",
"decompress": "^4.0.0",
"fs-extra-promise": "^1.0.1",
"opener": "1.4.3",
"request": "2.63.0",
"vscode-extension-telemetry": "^0.0.8",
"vscode-nls": "2.0.2"
}, },
"devDependencies": { "devDependencies": {
"vscode": "1.0.1", "vscode": "1.0.1"
"@types/node": "^8.0.24"
} }
} }

View File

@@ -1,7 +1,8 @@
{ {
"extension.clearTokenCache": "Clear Azure Account Token Cache", "json.schemas.desc": "Associate schemas to JSON files in the current project",
"config.enablePublicCloudDescription": "Should Azure public cloud integration be enabled", "json.schemas.url.desc": "A URL to a schema or a relative path to a schema in the current directory",
"config.enableUsGovCloudDescription": "Should US Government Azure cloud (Fairfax) integration be enabled", "json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas.",
"config.enableChinaCloudDescription": "Should Azure China integration be enabled", "json.schemas.fileMatch.item.desc": "A file pattern that can contain '*' to match against when resolving JSON files to schemas.",
"config.enableGermanyCloudDescription": "Should Azure Germany integration be enabled" "json.schemas.schema.desc": "The schema definition for the given URL. The schema only needs to be provided to avoid accesses to the schema URL.",
"json.format.enable.desc": "Enable/disable default JSON formatter (requires restart)"
} }

View File

@@ -208,10 +208,10 @@
"body": [ "body": [
"-- Get a list of tables and views in the current database", "-- Get a list of tables and views in the current database",
"SELECT table_catalog [database], table_schema [schema], table_name name, table_type type", "SELECT table_catalog [database], table_schema [schema], table_name name, table_type type",
"FROM INFORMATION_SCHEMA.TABLES", "FROM information_schema.tables",
"GO" "GO"
], ],
"description": "List tables and views in the current database" "description": "List tables and vies in the current database"
}, },
"List databases": { "List databases": {
@@ -229,20 +229,47 @@
"body": [ "body": [
"-- List columns in all tables whose name is like '${1:TableName}'", "-- List columns in all tables whose name is like '${1:TableName}'",
"SELECT ", "SELECT ",
"\tTableName = tbl.TABLE_SCHEMA + '.' + tbl.TABLE_NAME, ", "\tTableName = tbl.table_schema + '.' + tbl.table_name, ",
"\tColumnName = col.COLUMN_NAME, ", "\tColumnName = col.column_name, ",
"\tColumnDataType = col.DATA_TYPE", "\tColumnDataType = col.data_type",
"FROM INFORMATION_SCHEMA.TABLES tbl", "FROM information_schema.tables tbl",
"INNER JOIN INFORMATION_SCHEMA.COLUMNS col ", "INNER JOIN information_schema.columns col ",
"\tON col.TABLE_NAME = tbl.TABLE_NAME", "\tON col.table_name = tbl.table_name",
"\tAND col.TABLE_SCHEMA = tbl.TABLE_SCHEMA", "\tAND col.table_schema = tbl.table_schema",
"", "",
"WHERE tbl.TABLE_TYPE = 'BASE TABLE' and tbl.TABLE_NAME like '%${1:TableName}%'", "WHERE tbl.table_type = 'base table' and tbl.table_name like '%${1:TableName}%'",
"GO" "GO"
], ],
"description": "Lists all the columns and their types for tables matching a LIKE statement" "description": "Lists all the columns and their types for tables matching a LIKE statement"
}, },
"Declare a cursor": {
"prefix": "sqlCursor",
"body": [
"-- Declare a cursor for a Table or a View '${1:TableOrViewName}' in schema '${2:SchemaName}'",
"DECLARE @Column1 NVARCHAR(50), @Column2 NVARCHAR(50)",
"",
"DECLARE db_cursor CURSOR FOR",
"SELECT Column1, Column2",
"FROM $2.$1",
"",
"OPEN db_cursor",
"FETCH NEXT FROM db_cursor INTO @Column1, @Column2",
"",
"WHILE @@FETCH_STATUS = 0",
"BEGIN",
"\t-- add instructions to be executed for every row",
"\t$3",
"\tFETCH NEXT FROM db_cursor INTO @Column1, @Column2",
"END",
"",
"CLOSE db_cursor",
"DEALLOCATE db_cursor",
"GO"
],
"description": "Declare a cursor"
},
"Show space used by tables": { "Show space used by tables": {
"prefix": "sqlGetSpaceUsed", "prefix": "sqlGetSpaceUsed",
"body": [ "body": [

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
}

View File

@@ -1,11 +0,0 @@
{
"name": "vscode-extensions",
"version": "0.0.1",
"dependencies": {
"typescript": {
"version": "2.6.1",
"from": "typescript@2.6.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz"
}
}
}

View File

@@ -3,7 +3,8 @@
"version": "0.0.1", "version": "0.0.1",
"description": "Dependencies shared by all extensions", "description": "Dependencies shared by all extensions",
"dependencies": { "dependencies": {
"typescript": "2.6.1" "typescript": "2.6.1",
"extensions-modules": "file:../extensions-modules"
}, },
"scripts": { "scripts": {
"postinstall": "node ./postinstall" "postinstall": "node ./postinstall"

File diff suppressed because one or more lines are too long

694
npm-shrinkwrap.json generated
View File

@@ -1,12 +1,7 @@
{ {
"name": "sqlops", "name": "sqlops",
"version": "0.24.0", "version": "0.25.4",
"dependencies": { "dependencies": {
"zone.js": {
"version": "0.8.11",
"from": "zone.js@>=0.8.4 <0.9.0",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.11.tgz"
},
"@angular/animations": { "@angular/animations": {
"version": "4.1.3", "version": "4.1.3",
"from": "@angular/animations@>=4.1.3 <4.2.0", "from": "@angular/animations@>=4.1.3 <4.2.0",
@@ -62,20 +57,20 @@
"from": "agent-base@>=1.0.1 <1.1.0", "from": "agent-base@>=1.0.1 <1.1.0",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz" "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz"
}, },
"angular2-slickgrid": {
"version": "1.3.4",
"from": "git://github.com/Microsoft/angular2-slickgrid.git#1.3.5",
"resolved": "git://github.com/Microsoft/angular2-slickgrid.git#d122015f2f3e4023394a7e485079da62f20b8356"
},
"angular2-grid": { "angular2-grid": {
"version": "2.0.6", "version": "2.0.6",
"from": "angular2-grid@2.0.6", "from": "angular2-grid@2.0.6",
"resolved": "https://registry.npmjs.org/angular2-grid/-/angular2-grid-2.0.6.tgz" "resolved": "https://registry.npmjs.org/angular2-grid/-/angular2-grid-2.0.6.tgz"
}, },
"angular2-slickgrid": {
"version": "1.3.6",
"from": "git://github.com/Microsoft/angular2-slickgrid.git#1.3.6",
"resolved": "git://github.com/Microsoft/angular2-slickgrid.git#0393bae34ba65464e6b6fc248b950ccea44382d9"
},
"anymatch": { "anymatch": {
"version": "1.3.0", "version": "1.3.2",
"from": "anymatch@>=1.3.0 <2.0.0", "from": "anymatch@>=1.3.0 <2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz" "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz"
}, },
"applicationinsights": { "applicationinsights": {
"version": "0.17.1", "version": "0.17.1",
@@ -88,19 +83,19 @@
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz" "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz"
}, },
"arr-flatten": { "arr-flatten": {
"version": "1.0.3", "version": "1.1.0",
"from": "arr-flatten@>=1.0.1 <2.0.0", "from": "arr-flatten@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz" "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz"
}, },
"array-unique": { "array-unique": {
"version": "0.2.1", "version": "0.2.1",
"from": "array-unique@>=0.2.1 <0.3.0", "from": "array-unique@>=0.2.1 <0.3.0",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz" "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz"
}, },
"arrify": { "asap": {
"version": "1.0.1", "version": "2.0.6",
"from": "arrify@>=1.0.0 <2.0.0", "from": "asap@>=2.0.3 <2.1.0",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz" "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz"
}, },
"async-each": { "async-each": {
"version": "1.0.1", "version": "1.0.1",
@@ -108,25 +103,25 @@
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz" "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz"
}, },
"balanced-match": { "balanced-match": {
"version": "0.4.2", "version": "1.0.0",
"from": "balanced-match@>=0.4.1 <0.5.0", "from": "balanced-match@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
}, },
"binary-extensions": { "binary-extensions": {
"version": "1.8.0", "version": "1.11.0",
"from": "binary-extensions@>=1.0.0 <2.0.0", "from": "binary-extensions@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz" "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz"
}, },
"bindings": { "bindings": {
"version": "1.2.1", "version": "1.3.0",
"from": "bindings@>=1.2.1 <2.0.0", "from": "bindings@>=1.2.1 <2.0.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
"optional": true "optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.7", "version": "1.1.8",
"from": "brace-expansion@>=1.1.7 <2.0.0", "from": "brace-expansion@>=1.1.7 <2.0.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz" "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz"
}, },
"braces": { "braces": {
"version": "1.8.5", "version": "1.8.5",
@@ -138,35 +133,32 @@
"from": "buffer-crc32@>=0.2.3 <0.3.0", "from": "buffer-crc32@>=0.2.3 <0.3.0",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz"
}, },
"buffer-shims": {
"version": "1.0.0",
"from": "buffer-shims@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz"
},
"caniuse-db": { "caniuse-db": {
"version": "1.0.30000676", "version": "1.0.30000787",
"from": "caniuse-db@>=1.0.30000161 <2.0.0", "from": "caniuse-db@>=1.0.30000161 <2.0.0",
"resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000676.tgz" "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000787.tgz"
}, },
"chart.js": { "chart.js": {
"version": "2.6.0", "version": "2.7.1",
"from": "chart.js@>=2.6.0 <3.0.0", "from": "chart.js@>=2.6.0 <3.0.0",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.6.0.tgz" "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.7.1.tgz",
"dependencies": {
"moment": {
"version": "2.18.1",
"from": "moment@>=2.18.0 <2.19.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz"
}
}
}, },
"chartjs-color": { "chartjs-color": {
"version": "2.1.0", "version": "2.2.0",
"from": "chartjs-color@>=2.1.0 <3.0.0", "from": "chartjs-color@>=2.2.0 <2.3.0",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.1.0.tgz" "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.2.0.tgz"
}, },
"chartjs-color-string": { "chartjs-color-string": {
"version": "0.4.0", "version": "0.5.0",
"from": "chartjs-color-string@>=0.4.0 <0.5.0", "from": "chartjs-color-string@>=0.5.0 <0.6.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.4.0.tgz" "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz"
},
"chokidar": {
"version": "1.6.1",
"from": "bpasero/chokidar#vscode",
"resolved": "git://github.com/bpasero/chokidar.git#4c167ce0c29dae1727518998ecad63a049433e35"
}, },
"color-convert": { "color-convert": {
"version": "0.5.3", "version": "0.5.3",
@@ -174,14 +166,9 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz" "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz"
}, },
"color-name": { "color-name": {
"version": "1.1.2",
"from": "color-name@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.2.tgz"
},
"comment-json": {
"version": "1.1.3", "version": "1.1.3",
"from": "comment-json@>=1.1.3 <2.0.0", "from": "color-name@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/comment-json/-/comment-json-1.1.3.tgz" "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
@@ -189,9 +176,9 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
}, },
"core-js": { "core-js": {
"version": "2.4.1", "version": "2.5.3",
"from": "core-js@>=2.4.1 <3.0.0", "from": "core-js@>=2.4.1 <3.0.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz" "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz"
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@@ -199,9 +186,9 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
}, },
"debug": { "debug": {
"version": "2.6.8", "version": "2.6.9",
"from": "debug@>=2.0.0 <3.0.0", "from": "debug@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
}, },
"emmet": { "emmet": {
"version": "1.3.2", "version": "1.3.2",
@@ -218,11 +205,6 @@
"from": "escape-string-regexp@>=1.0.2 <2.0.0", "from": "escape-string-regexp@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
}, },
"esprima": {
"version": "2.7.3",
"from": "esprima@>=2.7.0 <3.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz"
},
"expand-brackets": { "expand-brackets": {
"version": "0.1.5", "version": "0.1.5",
"from": "expand-brackets@>=0.1.4 <0.2.0", "from": "expand-brackets@>=0.1.4 <0.2.0",
@@ -269,9 +251,9 @@
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz"
}, },
"for-in": { "for-in": {
"version": "0.1.5", "version": "1.0.2",
"from": "for-in@>=0.1.5 <0.2.0", "from": "for-in@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.5.tgz" "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz"
}, },
"for-own": { "for-own": {
"version": "0.1.5", "version": "0.1.5",
@@ -283,15 +265,14 @@
"from": "fs-extra@>=3.0.1 <4.0.0", "from": "fs-extra@>=3.0.1 <4.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz" "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz"
}, },
"fsevents": { "fs.realpath": {
"version": "0.3.8", "version": "1.0.0",
"from": "bpasero/fsevents#vscode", "from": "fs.realpath@>=1.0.0 <2.0.0",
"resolved": "git+https://github.com/bpasero/fsevents.git#fe2aaccaaffbd69a23374cf46a8c6bafe8e51b01", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
"optional": true
}, },
"gc-signals": { "gc-signals": {
"version": "0.0.1", "version": "0.0.1",
"from": "gc-signals@0.0.1", "from": "gc-signals@>=0.0.1 <0.0.2",
"resolved": "https://registry.npmjs.org/gc-signals/-/gc-signals-0.0.1.tgz" "resolved": "https://registry.npmjs.org/gc-signals/-/gc-signals-0.0.1.tgz"
}, },
"getmac": { "getmac": {
@@ -315,9 +296,9 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz"
}, },
"html-query-plan": { "html-query-plan": {
"version": "1.0.0", "version": "2.2.6",
"from": "git://github.com/anthonydresser/html-query-plan.git#v2.2.5", "from": "git://github.com/anthonydresser/html-query-plan.git#2.2.6",
"resolved": "git://github.com/anthonydresser/html-query-plan.git#fbf8beac00b3870c0d3f4e95de979f7f1ec7af5d" "resolved": "git://github.com/anthonydresser/html-query-plan.git#e09ffda978113c73366b663066372f884cf75e05"
}, },
"http-proxy-agent": { "http-proxy-agent": {
"version": "0.2.7", "version": "0.2.7",
@@ -334,9 +315,14 @@
"from": "iconv-lite@0.4.15", "from": "iconv-lite@0.4.15",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz"
}, },
"inflight": {
"version": "1.0.6",
"from": "inflight@>=1.0.4 <2.0.0",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
},
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"from": "inherits@>=2.0.1 <3.0.0", "from": "inherits@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
}, },
"is-arrayish": { "is-arrayish": {
@@ -350,9 +336,9 @@
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz"
}, },
"is-buffer": { "is-buffer": {
"version": "1.1.5", "version": "1.1.6",
"from": "is-buffer@>=1.1.5 <2.0.0", "from": "is-buffer@>=1.1.5 <2.0.0",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz" "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz"
}, },
"is-dotfile": { "is-dotfile": {
"version": "1.0.3", "version": "1.0.3",
@@ -411,70 +397,63 @@
}, },
"jquery-ui": { "jquery-ui": {
"version": "1.12.1", "version": "1.12.1",
"from": "jquery-ui@>=1.12.1 <2.0.0", "from": "jquery-ui@>=1.8.0",
"resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz" "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz"
}, },
"jquery.event.drag": {
"version": "2.2.2",
"from": "jquery.event.drag@2.2.2",
"resolved": "https://registry.npmjs.org/jquery.event.drag/-/jquery.event.drag-2.2.2.tgz"
},
"jschardet": { "jschardet": {
"version": "1.5.1", "version": "1.6.0",
"from": "jschardet@>=1.5.1 <2.0.0", "from": "jschardet@>=1.5.1 <2.0.0",
"resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz" "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz"
},
"json-parser": {
"version": "1.1.5",
"from": "json-parser@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/json-parser/-/json-parser-1.1.5.tgz"
}, },
"jsonfile": { "jsonfile": {
"version": "3.0.0", "version": "3.0.1",
"from": "jsonfile@>=3.0.0 <4.0.0", "from": "jsonfile@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.0.tgz" "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz"
}, },
"keytar": { "keytar": {
"version": "4.0.5", "version": "4.1.0",
"from": "keytar@latest", "from": "keytar@>=4.0.5 <5.0.0",
"resolved": "https://registry.npmjs.org/keytar/-/keytar-4.0.5.tgz", "resolved": "https://registry.npmjs.org/keytar/-/keytar-4.1.0.tgz"
"dependencies": {
"nan": {
"version": "2.5.1",
"from": "nan@2.5.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz"
}
}
}, },
"kind-of": { "kind-of": {
"version": "3.0.4", "version": "3.2.2",
"from": "kind-of@>=3.0.2 <4.0.0", "from": "kind-of@>=3.0.2 <4.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.0.4.tgz" "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
},
"klaw": {
"version": "1.3.1",
"from": "klaw@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz"
},
"lodash.isinteger": {
"version": "4.0.4",
"from": "lodash.isinteger@>=4.0.4 <5.0.0",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz"
},
"lodash.isundefined": {
"version": "3.0.1",
"from": "lodash.isundefined@>=3.0.1 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz"
}, },
"make-error": { "make-error": {
"version": "1.3.0", "version": "1.3.2",
"from": "make-error@>=1.1.1 <2.0.0", "from": "make-error@>=1.1.1 <2.0.0",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz" "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.2.tgz"
}, },
"micromatch": { "micromatch": {
"version": "2.3.11", "version": "2.3.11",
"from": "micromatch@>=2.1.5 <3.0.0", "from": "micromatch@>=2.1.5 <3.0.0",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz" "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz"
}, },
"minimatch": {
"version": "3.0.3",
"from": "minimatch@>=3.0.2 <4.0.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz"
},
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"from": "minimist@1.2.0", "from": "minimist@1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz" "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz"
}, },
"moment": { "moment": {
"version": "2.18.1", "version": "2.20.1",
"from": "moment@>=2.15.1 <3.0.0", "from": "moment@>=2.15.1 <3.0.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz" "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz"
}, },
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
@@ -482,9 +461,9 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
}, },
"nan": { "nan": {
"version": "2.5.0", "version": "2.5.1",
"from": "nan@2.5.0", "from": "nan@2.5.1",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.5.0.tgz" "resolved": "https://registry.npmjs.org/nan/-/nan-2.5.1.tgz"
}, },
"native-keymap": { "native-keymap": {
"version": "1.2.5", "version": "1.2.5",
@@ -502,27 +481,94 @@
"resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz" "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz"
}, },
"node-pty": { "node-pty": {
"version": "0.7.3", "version": "0.7.0",
"from": "node-pty@0.7.3", "from": "node-pty@0.7.0",
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.7.3.tgz", "resolved": "https://registry.npmjs.org/node-pty/-/node-pty-0.7.0.tgz",
"dependencies": { "dependencies": {
"nan": { "nan": {
"version": "2.5.0", "version": "2.8.0",
"from": "nan@2.5.0", "from": "nan@>=2.6.2 <3.0.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.5.0.tgz" "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz"
} }
} }
}, },
"nodegit-promise": {
"version": "4.0.0",
"from": "nodegit-promise@>=4.0.0 <4.1.0",
"resolved": "https://registry.npmjs.org/nodegit-promise/-/nodegit-promise-4.0.0.tgz"
},
"normalize-path": { "normalize-path": {
"version": "2.1.1", "version": "2.1.1",
"from": "normalize-path@>=2.0.1 <3.0.0", "from": "normalize-path@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz"
}, },
"nsfw": {
"version": "1.0.16",
"from": "nsfw@1.0.16",
"resolved": "https://registry.npmjs.org/nsfw/-/nsfw-1.0.16.tgz",
"dependencies": {
"fs-extra": {
"version": "0.26.7",
"from": "fs-extra@>=0.26.5 <0.27.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz"
},
"jsonfile": {
"version": "2.4.0",
"from": "jsonfile@>=2.1.0 <3.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz"
}
}
},
"object.omit": {
"version": "2.0.1",
"from": "object.omit@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz"
},
"once": {
"version": "1.4.0",
"from": "once@>=1.3.0 <2.0.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
},
"oniguruma": {
"version": "6.2.1",
"from": "oniguruma@>=6.0.1 <7.0.0",
"resolved": "https://registry.npmjs.org/oniguruma/-/oniguruma-6.2.1.tgz"
},
"parse-glob": {
"version": "3.0.4",
"from": "parse-glob@>=3.0.4 <4.0.0",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz"
},
"path-is-absolute": {
"version": "1.0.1",
"from": "path-is-absolute@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
},
"pend": {
"version": "1.2.0",
"from": "pend@>=1.2.0 <1.3.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz"
},
"preserve": {
"version": "0.2.0",
"from": "preserve@>=0.2.0 <0.3.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz"
},
"pretty-data": { "pretty-data": {
"version": "0.40.0", "version": "0.40.0",
"from": "pretty-data@>=0.40.0 <0.41.0", "from": "pretty-data@>=0.40.0 <0.41.0",
"resolved": "https://registry.npmjs.org/pretty-data/-/pretty-data-0.40.0.tgz" "resolved": "https://registry.npmjs.org/pretty-data/-/pretty-data-0.40.0.tgz"
}, },
"process-nextick-args": {
"version": "1.0.7",
"from": "process-nextick-args@>=1.0.6 <1.1.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
},
"promisify-node": {
"version": "0.3.0",
"from": "promisify-node@>=0.3.0 <0.4.0",
"resolved": "https://registry.npmjs.org/promisify-node/-/promisify-node-0.3.0.tgz"
},
"pty.js": { "pty.js": {
"version": "0.3.0", "version": "0.3.0",
"from": "https://github.com/Tyriar/pty.js/tarball/c75c2dcb6dcad83b0cb3ef2ae42d0448fb912642", "from": "https://github.com/Tyriar/pty.js/tarball/c75c2dcb6dcad83b0cb3ef2ae42d0448fb912642",
@@ -540,195 +586,99 @@
} }
} }
}, },
"nsfw": { "randomatic": {
"version": "1.0.16", "version": "1.1.7",
"from": "nsfw@1.0.16", "from": "randomatic@>=1.1.3 <2.0.0",
"resolved": "https://registry.npmjs.org/nsfw/-/nsfw-1.0.16.tgz", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
"dependencies": { "dependencies": {
"asap": { "is-number": {
"version": "2.0.5", "version": "3.0.0",
"from": "asap@>=2.0.3 <2.1.0", "from": "is-number@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz" "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"dependencies": {
"kind-of": {
"version": "3.2.2",
"from": "kind-of@^3.0.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
}
}
}, },
"balanced-match": { "kind-of": {
"version": "1.0.0",
"from": "balanced-match@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
},
"brace-expansion": {
"version": "1.1.8",
"from": "brace-expansion@>=1.1.7 <2.0.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz"
},
"concat-map": {
"version": "0.0.1",
"from": "concat-map@0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
},
"fs-extra": {
"version": "0.26.7",
"from": "fs-extra@>=0.26.5 <0.27.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz"
},
"fs.realpath": {
"version": "1.0.0",
"from": "fs.realpath@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
},
"glob": {
"version": "7.1.2",
"from": "glob@>=7.0.5 <8.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz"
},
"graceful-fs": {
"version": "4.1.11",
"from": "graceful-fs@>=4.1.2 <5.0.0",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz"
},
"inflight": {
"version": "1.0.6",
"from": "inflight@>=1.0.4 <2.0.0",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
},
"inherits": {
"version": "2.0.3",
"from": "inherits@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
},
"jsonfile": {
"version": "2.4.0",
"from": "jsonfile@>=2.1.0 <3.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz"
},
"klaw": {
"version": "1.3.1",
"from": "klaw@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz"
},
"lodash": {
"version": "4.17.4",
"from": "lodash@>=4.6.1 <5.0.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz"
},
"lodash.isinteger": {
"version": "4.0.4",
"from": "lodash.isinteger@>=4.0.4 <5.0.0",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz"
},
"lodash.isundefined": {
"version": "3.0.1",
"from": "lodash.isundefined@>=3.0.1 <4.0.0",
"resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz"
},
"minimatch": {
"version": "3.0.4",
"from": "minimatch@>=3.0.4 <4.0.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
},
"nan": {
"version": "2.6.2",
"from": "nan@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz"
},
"nodegit-promise": {
"version": "4.0.0", "version": "4.0.0",
"from": "nodegit-promise@>=4.0.0 <4.1.0", "from": "kind-of@>=4.0.0 <5.0.0",
"resolved": "https://registry.npmjs.org/nodegit-promise/-/nodegit-promise-4.0.0.tgz" "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz"
},
"once": {
"version": "1.4.0",
"from": "once@>=1.3.0 <2.0.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
},
"path-is-absolute": {
"version": "1.0.1",
"from": "path-is-absolute@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
},
"promisify-node": {
"version": "0.3.0",
"from": "promisify-node@>=0.3.0 <0.4.0",
"resolved": "https://registry.npmjs.org/promisify-node/-/promisify-node-0.3.0.tgz"
},
"rimraf": {
"version": "2.6.1",
"from": "rimraf@>=2.2.8 <3.0.0",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz"
},
"wrappy": {
"version": "1.0.2",
"from": "wrappy@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
} }
} }
}, },
"object.omit": { "readable-stream": {
"version": "2.0.0", "version": "2.3.3",
"from": "object.omit@>=2.0.0 <3.0.0", "from": "readable-stream@>=2.0.2 <3.0.0",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.0.tgz" "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz"
},
"oniguruma": {
"version": "6.1.1",
"from": "oniguruma@>=6.0.1 <7.0.0",
"resolved": "https://registry.npmjs.org/oniguruma/-/oniguruma-6.1.1.tgz"
},
"parse-glob": {
"version": "3.0.4",
"from": "parse-glob@>=3.0.4 <4.0.0",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz"
},
"path-is-absolute": {
"version": "1.0.0",
"from": "path-is-absolute@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz"
},
"pend": {
"version": "1.2.0",
"from": "pend@>=1.2.0 <1.3.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz"
},
"preserve": {
"version": "0.2.0",
"from": "preserve@>=0.2.0 <0.3.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz"
},
"process-nextick-args": {
"version": "1.0.7",
"from": "process-nextick-args@>=1.0.6 <1.1.0",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz"
}, },
"readdirp": { "readdirp": {
"version": "2.1.0", "version": "2.1.0",
"from": "readdirp@>=2.0.0 <3.0.0", "from": "readdirp@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
"dependencies": { "dependencies": {
"balanced-match": {
"version": "1.0.0",
"from": "balanced-match@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz"
},
"brace-expansion": {
"version": "1.1.8",
"from": "brace-expansion@>=1.1.7 <2.0.0",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz"
},
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"from": "minimatch@>=3.0.2 <4.0.0", "from": "minimatch@^3.0.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
} }
} }
}, },
"reflect-metadata": {
"version": "0.1.10",
"from": "reflect-metadata@>=0.1.8 <0.2.0",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz"
},
"regex-cache": { "regex-cache": {
"version": "0.4.3", "version": "0.4.4",
"from": "regex-cache@>=0.4.2 <0.5.0", "from": "regex-cache@>=0.4.2 <0.5.0",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz" "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz"
},
"remove-trailing-separator": {
"version": "1.1.0",
"from": "remove-trailing-separator@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz"
}, },
"repeat-element": { "repeat-element": {
"version": "1.1.2", "version": "1.1.2",
"from": "repeat-element@>=1.1.2 <2.0.0", "from": "repeat-element@>=1.1.2 <2.0.0",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz"
}, },
"repeat-string": {
"version": "1.6.1",
"from": "repeat-string@>=1.5.2 <2.0.0",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz"
},
"rimraf": {
"version": "2.6.2",
"from": "rimraf@>=2.2.8 <3.0.0",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
"dependencies": {
"glob": {
"version": "7.1.2",
"from": "glob@>=7.0.5 <8.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz"
},
"minimatch": {
"version": "3.0.4",
"from": "minimatch@>=3.0.4 <4.0.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
}
}
},
"rxjs": {
"version": "5.4.0",
"from": "rxjs@5.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.0.tgz"
},
"safe-buffer": {
"version": "5.1.1",
"from": "safe-buffer@>=5.1.1 <5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz"
},
"semver": { "semver": {
"version": "4.3.6", "version": "4.3.6",
"from": "semver@4.3.6", "from": "semver@4.3.6",
@@ -739,11 +689,46 @@
"from": "set-immediate-shim@>=1.0.1 <2.0.0", "from": "set-immediate-shim@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz" "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz"
}, },
"slickgrid": {
"version": "2.3.4",
"from": "anthonydresser/SlickGrid#2.3.7",
"resolved": "git://github.com/anthonydresser/SlickGrid.git#fa7911c34b5449f9ce1e7148480fbc24fd20743a"
},
"string_decoder": {
"version": "1.0.3",
"from": "string_decoder@>=1.0.3 <1.1.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz"
},
"svg.js": {
"version": "2.6.3",
"from": "svg.js@>=2.2.5 <3.0.0",
"resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.6.3.tgz"
},
"symbol-observable": {
"version": "1.1.0",
"from": "symbol-observable@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.1.0.tgz"
},
"systemjs": {
"version": "0.19.40",
"from": "systemjs@0.19.40",
"resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.19.40.tgz"
},
"typechecker": { "typechecker": {
"version": "2.0.8", "version": "2.0.8",
"from": "typechecker@>=2.0.1 <2.1.0", "from": "typechecker@>=2.0.1 <2.1.0",
"resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz" "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz"
}, },
"underscore": {
"version": "1.8.3",
"from": "underscore@>=1.8.3 <2.0.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
},
"universalify": {
"version": "0.1.1",
"from": "universalify@>=0.1.0 <0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz"
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"from": "util-deprecate@>=1.0.1 <1.1.0", "from": "util-deprecate@>=1.0.1 <1.1.0",
@@ -754,6 +739,11 @@
"from": "jrieken/v8-profiler#vscode", "from": "jrieken/v8-profiler#vscode",
"resolved": "git://github.com/jrieken/v8-profiler.git#5e4a336693e1d5b079c7aecd286a1abcfbc10421" "resolved": "git://github.com/jrieken/v8-profiler.git#5e4a336693e1d5b079c7aecd286a1abcfbc10421"
}, },
"vscode-chokidar": {
"version": "1.6.2",
"from": "vscode-chokidar@1.6.2",
"resolved": "https://registry.npmjs.org/vscode-chokidar/-/vscode-chokidar-1.6.2.tgz"
},
"vscode-debugprotocol": { "vscode-debugprotocol": {
"version": "1.24.0", "version": "1.24.0",
"from": "vscode-debugprotocol@1.24.0", "from": "vscode-debugprotocol@1.24.0",
@@ -766,94 +756,9 @@
}, },
"vscode-textmate": { "vscode-textmate": {
"version": "3.2.0", "version": "3.2.0",
"from": "vscode-textmate@3.2.0", "from": "vscode-textmate@>=3.2.0 <4.0.0",
"resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-3.2.0.tgz" "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-3.2.0.tgz"
}, },
"winreg": {
"version": "1.2.0",
"from": "winreg@1.2.0",
"resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.0.tgz"
},
"windows-process-tree": {
"version": "0.1.6",
"from": "windows-process-tree@0.1.6",
"resolved": "https://registry.npmjs.org/windows-process-tree/-/windows-process-tree-0.1.6.tgz"
},
"xterm": {
"version": "2.9.1",
"from": "Tyriar/xterm.js#vscode-release/1.18",
"resolved": "git+https://github.com/Tyriar/xterm.js.git#074dbb562062423e322300a513869eed1836a9ba"
},
"yauzl": {
"version": "2.8.0",
"from": "yauzl@2.8.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz"
},
"randomatic": {
"version": "1.1.6",
"from": "randomatic@>=1.1.3 <2.0.0",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz"
},
"readable-stream": {
"version": "2.2.10",
"from": "readable-stream@>=2.0.2 <3.0.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.10.tgz"
},
"reflect-metadata": {
"version": "0.1.10",
"from": "reflect-metadata@>=0.1.8 <0.2.0",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.10.tgz"
},
"remove-trailing-separator": {
"version": "1.0.1",
"from": "remove-trailing-separator@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz"
},
"repeat-string": {
"version": "1.6.1",
"from": "repeat-string@>=1.5.2 <2.0.0",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.4.tgz"
},
"rxjs": {
"version": "5.4.0",
"from": "rxjs@5.4.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.4.0.tgz"
},
"safe-buffer": {
"version": "5.1.0",
"from": "safe-buffer@>=5.0.1 <6.0.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz"
},
"slickgrid": {
"version": "2.3.6",
"from": "anthonydresser/SlickGrid#2.3.7",
"resolved": "git://github.com/anthonydresser/SlickGrid.git#fa7911c34b5449f9ce1e7148480fbc24fd20743a"
},
"string_decoder": {
"version": "1.0.1",
"from": "string_decoder@>=1.0.0 <1.1.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.1.tgz"
},
"symbol-observable": {
"version": "1.0.4",
"from": "symbol-observable@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz"
},
"systemjs": {
"version": "0.19.40",
"from": "systemjs@0.19.40",
"resolved": "https://registry.npmjs.org/systemjs/-/systemjs-0.19.40.tgz"
},
"underscore": {
"version": "1.8.3",
"from": "underscore@>=1.8.3 <2.0.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz"
},
"universalify": {
"version": "0.1.0",
"from": "universalify@>=0.1.0 <0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.0.tgz"
},
"when": { "when": {
"version": "3.7.8", "version": "3.7.8",
"from": "when@>=3.7.5 <4.0.0", "from": "when@>=3.7.5 <4.0.0",
@@ -870,6 +775,45 @@
"from": "windows-mutex@>=0.2.0 <0.3.0", "from": "windows-mutex@>=0.2.0 <0.3.0",
"resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz", "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz",
"optional": true "optional": true
},
"windows-process-tree": {
"version": "0.1.6",
"from": "windows-process-tree@0.1.6",
"resolved": "https://registry.npmjs.org/windows-process-tree/-/windows-process-tree-0.1.6.tgz",
"optional": true,
"dependencies": {
"nan": {
"version": "2.8.0",
"from": "nan@>=2.6.2 <3.0.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz",
"optional": true
}
}
},
"winreg": {
"version": "1.2.0",
"from": "winreg@1.2.0",
"resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.0.tgz"
},
"wrappy": {
"version": "1.0.2",
"from": "wrappy@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
},
"xterm": {
"version": "2.9.1",
"from": "Tyriar/xterm.js#vscode-release/1.18",
"resolved": "git://github.com/Tyriar/xterm.js.git#074dbb562062423e322300a513869eed1836a9ba"
},
"yauzl": {
"version": "2.8.0",
"from": "yauzl@2.8.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz"
},
"zone.js": {
"version": "0.8.19",
"from": "zone.js@>=0.8.4 <0.9.0",
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.19.tgz"
} }
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "sqlops", "name": "sqlops",
"version": "0.24.1", "version": "0.25.4",
"electronVersion": "1.7.9", "electronVersion": "1.7.9",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee", "distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": { "author": {
@@ -33,11 +33,9 @@
"@angular/router": "~4.1.3", "@angular/router": "~4.1.3",
"@angular/upgrade": "~4.1.3", "@angular/upgrade": "~4.1.3",
"angular2-grid": "2.0.6", "angular2-grid": "2.0.6",
"angular2-slickgrid": "git://github.com/Microsoft/angular2-slickgrid.git#1.3.5", "angular2-slickgrid": "git://github.com/Microsoft/angular2-slickgrid.git#1.3.6",
"applicationinsights": "0.17.1", "applicationinsights": "0.17.1",
"chart.js": "^2.6.0", "chart.js": "^2.6.0",
"chokidar": "bpasero/chokidar#vscode",
"comment-json": "^1.1.3",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"emmet": "ramya-rao-a/emmet#vscode", "emmet": "ramya-rao-a/emmet#vscode",
"error-ex": "^1.3.0", "error-ex": "^1.3.0",
@@ -47,13 +45,11 @@
"gc-signals": "^0.0.1", "gc-signals": "^0.0.1",
"getmac": "1.0.7", "getmac": "1.0.7",
"graceful-fs": "4.1.11", "graceful-fs": "4.1.11",
"html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#v2.2.5", "html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.2.6",
"http-proxy-agent": "0.2.7", "http-proxy-agent": "0.2.7",
"https-proxy-agent": "0.3.6", "https-proxy-agent": "0.3.6",
"iconv-lite": "0.4.15", "iconv-lite": "0.4.15",
"jquery": "^2.2.0", "jquery": "^2.2.0",
"jquery-ui": "^1.12.1",
"jquery.event.drag": "2.2.2",
"make-error": "^1.1.1", "make-error": "^1.1.1",
"jschardet": "^1.5.1", "jschardet": "^1.5.1",
"keytar": "^4.0.5", "keytar": "^4.0.5",
@@ -74,6 +70,7 @@
"systemjs": "0.19.40", "systemjs": "0.19.40",
"underscore": "^1.8.3", "underscore": "^1.8.3",
"v8-profiler": "jrieken/v8-profiler#vscode", "v8-profiler": "jrieken/v8-profiler#vscode",
"vscode-chokidar": "1.6.2",
"vscode-debugprotocol": "1.24.0", "vscode-debugprotocol": "1.24.0",
"vscode-ripgrep": "0.6.0-patch.0.2", "vscode-ripgrep": "0.6.0-patch.0.2",
"vscode-textmate": "^3.2.0", "vscode-textmate": "^3.2.0",
@@ -150,7 +147,6 @@
"typescript-formatter": "4.0.1", "typescript-formatter": "4.0.1",
"uglify-js": "mishoo/UglifyJS2#harmony-v2.8.22", "uglify-js": "mishoo/UglifyJS2#harmony-v2.8.22",
"uglify-es": "^3.0.18", "uglify-es": "^3.0.18",
"underscore": "^1.8.2",
"vinyl": "^0.4.5", "vinyl": "^0.4.5",
"vinyl-fs": "^2.4.3", "vinyl-fs": "^2.4.3",
"vsce": "^1.25.1", "vsce": "^1.25.1",

View File

@@ -28,5 +28,7 @@
"releaseNotesUrl": "https://go.microsoft.com/fwlink/?linkid=862039", "releaseNotesUrl": "https://go.microsoft.com/fwlink/?linkid=862039",
"documentationUrl": "https://go.microsoft.com/fwlink/?linkid=862277", "documentationUrl": "https://go.microsoft.com/fwlink/?linkid=862277",
"commit": "9ca6200018fc206d67a47229f991901a8a453781", "commit": "9ca6200018fc206d67a47229f991901a8a453781",
"date": "2017-12-15T12:00:00.000Z" "date": "2017-12-15T12:00:00.000Z",
"updateUrl": "https://sqlops-update.azurewebsites.net",
"quality": "stable"
} }

0
resources/darwin/bin/code.sh Normal file → Executable file
View File

0
resources/linux/bin/code.sh Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 1.6 KiB

0
scripts/build.sh Normal file → Executable file
View File

0
scripts/code-cli.sh Normal file → Executable file
View File

0
scripts/env.sh Normal file → Executable file
View File

0
scripts/sql-cli.sh Normal file → Executable file
View File

0
scripts/test-electron.sh Normal file → Executable file
View File

0
scripts/test-int-mocha.sh Normal file → Executable file
View File

0
scripts/test-integration.sh Normal file → Executable file
View File

0
scripts/test-mocha.sh Normal file → Executable file
View File

View File

@@ -7,25 +7,35 @@
import 'vs/css!./media/accountListStatusbarItem'; import 'vs/css!./media/accountListStatusbarItem';
import { Action, IAction } from 'vs/base/common/actions'; import { Action, IAction } from 'vs/base/common/actions';
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';
import { $, append } from 'vs/base/browser/dom'; import { $, append } from 'vs/base/browser/dom';
import { onUnexpectedError } from 'vs/base/common/errors'; import { onUnexpectedError } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { Themable, STATUS_BAR_FOREGROUND } from 'vs/workbench/common/theme';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IAccountManagementService } from 'sql/services/accountManagement/interfaces'; import { IAccountManagementService } from 'sql/services/accountManagement/interfaces';
export class AccountListStatusbarItem implements IStatusbarItem { export class AccountListStatusbarItem extends Themable implements IStatusbarItem {
private _toDispose: IDisposable[];
private _manageLinkedAccountAction: IAction; private _manageLinkedAccountAction: IAction;
private _icon: HTMLElement;
constructor( constructor(
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IAccountManagementService private _accountManagementService: IAccountManagementService @IAccountManagementService private _accountManagementService: IAccountManagementService,
@IThemeService themeService: IThemeService
) { ) {
this._toDispose = []; super(themeService);
}
protected updateStyles(): void {
super.updateStyles();
if (this._icon) {
this._icon.style.backgroundColor = this.getColor(STATUS_BAR_FOREGROUND);
}
} }
public render(container: HTMLElement): IDisposable { public render(container: HTMLElement): IDisposable {
@@ -34,9 +44,11 @@ export class AccountListStatusbarItem implements IStatusbarItem {
const accountElement = append(rootElement, $('a.linked-account-status-selection')); const accountElement = append(rootElement, $('a.linked-account-status-selection'));
accountElement.title = ManageLinkedAccountAction.LABEL; accountElement.title = ManageLinkedAccountAction.LABEL;
accountElement.onclick = () => this._onClick(); accountElement.onclick = () => this._onClick();
append(accountElement, $('.linked-account-icon')); this._icon = append(accountElement, $('.linked-account-icon'));
return combinedDisposable(this._toDispose); this.updateStyles();
return this;
} }
private _onClick() { private _onClick() {

View File

@@ -6,7 +6,6 @@
.statusbar-item .linked-account-staus a.linked-account-status-selection .linked-account-icon { .statusbar-item .linked-account-staus a.linked-account-status-selection .linked-account-icon {
-webkit-mask: url('accounts_statusbar_inverse.svg') no-repeat 50% 50%; -webkit-mask: url('accounts_statusbar_inverse.svg') no-repeat 50% 50%;
-webkit-mask-size: 12px; -webkit-mask-size: 12px;
background-color: rgb(255, 255, 255);
width: 12px; width: 12px;
height: 22px; height: 22px;
} }

View File

@@ -93,7 +93,7 @@ export class FirewallRuleDialog extends Modal {
protected renderBody(container: HTMLElement) { protected renderBody(container: HTMLElement) {
let descriptionSection; let descriptionSection;
$().div({ class: 'firewall-rule-description-section new-section' }, (descriptionContainer) => { $().div({ 'class': 'firewall-rule-description-section new-section' }, (descriptionContainer) => {
descriptionSection = descriptionContainer.getHTMLElement(); descriptionSection = descriptionContainer.getHTMLElement();
DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-icon')); DOM.append(descriptionContainer.getHTMLElement(), DOM.$('div.firewall-rule-icon'));
@@ -101,9 +101,11 @@ export class FirewallRuleDialog extends Modal {
let dialogDescription = localize('firewallRuleDialogDescription', let dialogDescription = localize('firewallRuleDialogDescription',
'Your client IP address does not have access to the server. Sign in to an Azure account and create a new firewall rule to enable access.'); 'Your client IP address does not have access to the server. Sign in to an Azure account and create a new firewall rule to enable access.');
this.createLabelElement(new Builder(textDescriptionContainer), dialogDescription, false); this.createLabelElement(new Builder(textDescriptionContainer), dialogDescription, false);
this._helpLink = DOM.append(textDescriptionContainer, DOM.$('a.help-link'));
this._helpLink.setAttribute('href', 'https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure'); // TODO: Make this 1) extensible and 2) open the info via an action (01/08/2018, https://github.com/Microsoft/sqlopsstudio/issues/450)
this._helpLink.innerHTML += localize('firewallRuleHelpDescription', 'Learn more about firewall settings'); // this._helpLink = DOM.append(textDescriptionContainer, DOM.$('a.help-link'));
// this._helpLink.setAttribute('href', 'https://docs.microsoft.com/en-us/azure/sql-database/sql-database-firewall-configure');
// this._helpLink.innerHTML += localize('firewallRuleHelpDescription', 'Learn more about firewall settings');
}); });
// Create account picker with event handling // Create account picker with event handling
@@ -116,43 +118,43 @@ export class FirewallRuleDialog extends Modal {
this._accountPickerService.onAccountSelectionChangeEvent((account) => this.onAccountSelectionChange(account)); this._accountPickerService.onAccountSelectionChangeEvent((account) => this.onAccountSelectionChange(account));
let azureAccountSection; let azureAccountSection;
$().div({ class: 'azure-account-section new-section' }, (azureAccountContainer) => { $().div({ 'class': 'azure-account-section new-section' }, (azureAccountContainer) => {
azureAccountSection = azureAccountContainer.getHTMLElement(); azureAccountSection = azureAccountContainer.getHTMLElement();
let azureAccountLabel = localize('azureAccount', 'Azure account'); let azureAccountLabel = localize('azureAccount', 'Azure account');
this.createLabelElement(azureAccountContainer, azureAccountLabel, true); this.createLabelElement(azureAccountContainer, azureAccountLabel, true);
azureAccountContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { azureAccountContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._accountPickerService.renderAccountPicker(inputCellContainer.getHTMLElement()); this._accountPickerService.renderAccountPicker(inputCellContainer.getHTMLElement());
}); });
}); });
let subnetIPRangeSection; let subnetIPRangeSection;
$().div({ class: 'subnet-ip-range-input' }, (subnetIPRangeContainer) => { $().div({ 'class': 'subnet-ip-range-input' }, (subnetIPRangeContainer) => {
subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement(); subnetIPRangeSection = subnetIPRangeContainer.getHTMLElement();
subnetIPRangeContainer.div({ class: 'dialog-input-section' }, (inputContainer) => { subnetIPRangeContainer.div({ 'class': 'dialog-input-section' }, (inputContainer) => {
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
labelContainer.innerHtml(localize('from', 'From')); labelContainer.innerHtml(localize('from', 'From'));
}); });
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._fromRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService); this._fromRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService);
}); });
inputContainer.div({ class: 'dialog-label' }, (labelContainer) => { inputContainer.div({ 'class': 'dialog-label' }, (labelContainer) => {
labelContainer.innerHtml(localize('to', 'To')); labelContainer.innerHtml(localize('to', 'To'));
}); });
inputContainer.div({ class: 'dialog-input' }, (inputCellContainer) => { inputContainer.div({ 'class': 'dialog-input' }, (inputCellContainer) => {
this._toRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService); this._toRangeinputBox = new InputBox(inputCellContainer.getHTMLElement(), this._contextViewService);
}); });
}); });
}); });
let firewallRuleSection; let firewallRuleSection;
$().div({ class: 'firewall-rule-section new-section' }, (firewallRuleContainer) => { $().div({ 'class': 'firewall-rule-section new-section' }, (firewallRuleContainer) => {
firewallRuleSection = firewallRuleContainer.getHTMLElement(); firewallRuleSection = firewallRuleContainer.getHTMLElement();
let firewallRuleLabel = localize('filewallRule', 'Firewall rule'); let firewallRuleLabel = localize('filewallRule', 'Firewall rule');
this.createLabelElement(firewallRuleContainer, firewallRuleLabel, true); this.createLabelElement(firewallRuleContainer, firewallRuleLabel, true);
firewallRuleContainer.div({ class: 'radio-section' }, (radioContainer) => { firewallRuleContainer.div({ 'class': 'radio-section' }, (radioContainer) => {
const form = DOM.append(radioContainer.getHTMLElement(), DOM.$('form.firewall-rule')); const form = DOM.append(radioContainer.getHTMLElement(), DOM.$('form.firewall-rule'));
const IPAddressDiv = DOM.append(form, DOM.$('div.firewall-ip-address dialog-input')); const IPAddressDiv = DOM.append(form, DOM.$('div.firewall-ip-address dialog-input'));
const subnetIPRangeDiv = DOM.append(form, DOM.$('div.firewall-subnet-ip-range dialog-input')); const subnetIPRangeDiv = DOM.append(form, DOM.$('div.firewall-subnet-ip-range dialog-input'));
@@ -177,7 +179,7 @@ export class FirewallRuleDialog extends Modal {
}); });
}); });
new Builder(container).div({ class: 'firewall-rule-dialog' }, (builder) => { new Builder(container).div({ 'class': 'firewall-rule-dialog' }, (builder) => {
builder.append(descriptionSection); builder.append(descriptionSection);
builder.append(azureAccountSection); builder.append(azureAccountSection);
builder.append(firewallRuleSection); builder.append(firewallRuleSection);
@@ -214,7 +216,7 @@ export class FirewallRuleDialog extends Modal {
if (isHeader) { if (isHeader) {
className += ' header'; className += ' header';
} }
container.div({ class: className }, (labelContainer) => { container.div({ 'class': className }, (labelContainer) => {
labelContainer.innerHtml(content); labelContainer.innerHtml(content);
}); });
} }
@@ -305,4 +307,4 @@ export class FirewallRuleDialog extends Modal {
this.show(); this.show();
} }
} }

View File

@@ -220,6 +220,8 @@ export interface IConnectionManagementService {
canChangeConnectionConfig(profile: ConnectionProfile, newGroupID: string): boolean; canChangeConnectionConfig(profile: ConnectionProfile, newGroupID: string): boolean;
getTabColorForUri(uri: string): string;
/** /**
* Sends a notification that the language flavor for a given URI has changed. * Sends a notification that the language flavor for a given URI has changed.
* For SQL, this would be the specific SQL implementation being used. * For SQL, this would be the specific SQL implementation being used.

View File

@@ -29,6 +29,7 @@ import * as TelemetryUtils from 'sql/common/telemetryUtilities';
import { warn } from 'sql/base/common/log'; import { warn } from 'sql/base/common/log';
import { IResourceProviderService } from 'sql/parts/accountManagement/common/interfaces'; import { IResourceProviderService } from 'sql/parts/accountManagement/common/interfaces';
import { IAngularEventingService, AngularEventType } from 'sql/services/angularEventing/angularEventingService'; import { IAngularEventingService, AngularEventType } from 'sql/services/angularEventing/angularEventingService';
import * as QueryConstants from 'sql/parts/query/common/constants';
import * as data from 'data'; import * as data from 'data';
@@ -148,6 +149,11 @@ export class ConnectionManagementService implements IConnectionManagementService
this.disposables.push(this._onAddConnectionProfile); this.disposables.push(this._onAddConnectionProfile);
this.disposables.push(this._onDeleteConnectionProfile); this.disposables.push(this._onDeleteConnectionProfile);
// Refresh editor titles when connections start/end/change to ensure tabs are colored correctly
this.onConnectionChanged(() => this.refreshEditorTitles());
this.onConnect(() => this.refreshEditorTitles());
this.onDisconnect(() => this.refreshEditorTitles());
} }
// Event Emitters // Event Emitters
@@ -953,7 +959,6 @@ export class ConnectionManagementService implements IConnectionManagementService
return this._connectionStore.changeGroupIdForConnection(source, targetGroupId).then(result => { return this._connectionStore.changeGroupIdForConnection(source, targetGroupId).then(result => {
if (id && targetGroupId) { if (id && targetGroupId) {
source.groupId = targetGroupId; source.groupId = targetGroupId;
this._connectionStatusManager.updateConnectionProfile(source, id);
} }
}); });
} }
@@ -1220,6 +1225,7 @@ export class ConnectionManagementService implements IConnectionManagementService
public editGroup(group: ConnectionProfileGroup): Promise<any> { public editGroup(group: ConnectionProfileGroup): Promise<any> {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
this._connectionStore.editGroup(group).then(groupId => { this._connectionStore.editGroup(group).then(groupId => {
this.refreshEditorTitles();
this._onAddConnectionProfile.fire(); this._onAddConnectionProfile.fire();
resolve(null); resolve(null);
}).catch(err => { }).catch(err => {
@@ -1324,4 +1330,25 @@ export class ConnectionManagementService implements IConnectionManagementService
} }
return Promise.reject('The given URI is not currently connected'); return Promise.reject('The given URI is not currently connected');
} }
public getTabColorForUri(uri: string): string {
if (WorkbenchUtils.getSqlConfigValue<string>(this._workspaceConfigurationService, 'tabColorMode') === QueryConstants.tabColorModeOff) {
return undefined;
}
let connectionProfile = this.getConnectionProfile(uri);
if (!connectionProfile) {
return undefined;
}
let matchingGroup = this._connectionStore.getGroupFromId(connectionProfile.groupId);
if (!matchingGroup) {
return undefined;
}
return matchingGroup.color;
}
private refreshEditorTitles(): void {
if (this._editorGroupService instanceof EditorPart) {
this._editorGroupService.refreshEditorTitles();
}
}
} }

View File

@@ -147,11 +147,11 @@ export class ConnectionStatusbarItem implements IStatusbarItem {
} }
let tooltip: string = let tooltip: string =
'Server name: ' + connectionProfile.serverName + '\r\n' + 'Server: ' + connectionProfile.serverName + '\r\n' +
'Database name: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '<default>') + '\r\n'; 'Database: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '<default>') + '\r\n';
if (connectionProfile.userName && connectionProfile.userName !== '') { if (connectionProfile.userName && connectionProfile.userName !== '') {
tooltip = tooltip + 'Login name: ' + connectionProfile.userName + '\r\n'; tooltip = tooltip + 'Login: ' + connectionProfile.userName + '\r\n';
} }
this._connectionElement.textContent = text; this._connectionElement.textContent = text;

View File

@@ -19,7 +19,6 @@ import { ConfigurationEditingService } from 'vs/workbench/services/configuration
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import * as data from 'data'; import * as data from 'data';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
const MAX_CONNECTIONS_DEFAULT = 25; const MAX_CONNECTIONS_DEFAULT = 25;
@@ -490,6 +489,11 @@ export class ConnectionStore {
return result; return result;
} }
public getGroupFromId(groupId: string): IConnectionProfileGroup {
let groups = this._connectionConfig.getAllGroups();
return groups.find(group => group.id === groupId);
}
private getMaxRecentConnectionsCount(): number { private getMaxRecentConnectionsCount(): number {
let config = this._workspaceConfigurationService.getConfiguration(Constants.sqlConfigSectionName); let config = this._workspaceConfigurationService.getConfiguration(Constants.sqlConfigSectionName);

View File

@@ -4,10 +4,8 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/connectionDialog'; import 'vs/css!./media/connectionDialog';
import nls = require('vs/nls');
import { Button } from 'sql/base/browser/ui/button/button'; import { Button } from 'sql/base/browser/ui/button/button';
import { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler'; import { attachModalDialogStyler, attachButtonStyler } from 'sql/common/theme/styler';
import { TPromise } from 'vs/base/common/winjs.base';
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox'; import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { Modal } from 'sql/base/browser/ui/modal/modal'; import { Modal } from 'sql/base/browser/ui/modal/modal';
@@ -16,24 +14,28 @@ import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper';
import { TreeCreationUtils } from 'sql/parts/registeredServer/viewlet/treeCreationUtils'; import { TreeCreationUtils } from 'sql/parts/registeredServer/viewlet/treeCreationUtils';
import { TreeUpdateUtils } from 'sql/parts/registeredServer/viewlet/treeUpdateUtils'; import { TreeUpdateUtils } from 'sql/parts/registeredServer/viewlet/treeUpdateUtils';
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile'; import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
import { TabbedPanel, PanelTabIdentifier } from 'sql/base/browser/ui/panel/panel';
import { RecentConnectionTreeController, RecentConnectionActionsProvider } from 'sql/parts/connection/connectionDialog/recentConnectionTreeController';
import { SavedConnectionTreeController } from 'sql/parts/connection/connectionDialog/savedConnectionTreeController';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { IWorkbenchThemeService, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import * as styler from 'vs/platform/theme/common/styler';
import { IPartService } from 'vs/workbench/services/part/common/partService'; import { IPartService } from 'vs/workbench/services/part/common/partService';
import Event, { Emitter } from 'vs/base/common/event'; import Event, { Emitter } from 'vs/base/common/event';
import { Builder, $ } from 'vs/base/browser/builder'; import { Builder, $ } from 'vs/base/browser/builder';
import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults'; import { ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { ITree } from 'vs/base/parts/tree/browser/tree'; import { ITree } from 'vs/base/parts/tree/browser/tree';
import { RecentConnectionTreeController, RecentConnectionActionsProvider } from 'sql/parts/connection/connectionDialog/recentConnectionTreeController';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IMessageService, IConfirmation } from 'vs/platform/message/common/message'; import { IMessageService, IConfirmation } from 'vs/platform/message/common/message';
import * as styler from 'vs/platform/theme/common/styler';
import { TPromise } from 'vs/base/common/winjs.base';
import * as DOM from 'vs/base/browser/dom';
export interface OnShowUIResponse { export interface OnShowUIResponse {
selectedProviderType: string; selectedProviderType: string;
@@ -44,14 +46,20 @@ export class ConnectionDialogWidget extends Modal {
private _bodyBuilder: Builder; private _bodyBuilder: Builder;
private _recentConnectionBuilder: Builder; private _recentConnectionBuilder: Builder;
private _noRecentConnectionBuilder: Builder; private _noRecentConnectionBuilder: Builder;
private _savedConnectionBuilder: Builder;
private _noSavedConnectionBuilder: Builder;
private _dividerBuilder: Builder; private _dividerBuilder: Builder;
private _connectButton: Button; private _connectButton: Button;
private _closeButton: Button; private _closeButton: Button;
private _providerTypeSelectBox: SelectBox; private _providerTypeSelectBox: SelectBox;
private _newConnectionParams: INewConnectionParams; private _newConnectionParams: INewConnectionParams;
private _recentConnectionTree: ITree; private _recentConnectionTree: ITree;
private _savedConnectionTree: ITree;
private $connectionUIContainer: Builder; private $connectionUIContainer: Builder;
private _panel: TabbedPanel;
private _recentConnectionTabId: PanelTabIdentifier;
private _onInitDialog = new Emitter<void>(); private _onInitDialog = new Emitter<void>();
public onInitDialog: Event<void> = this._onInitDialog.event; public onInitDialog: Event<void> = this._onInitDialog.event;
@@ -86,16 +94,69 @@ export class ConnectionDialogWidget extends Modal {
} }
protected renderBody(container: HTMLElement): void { protected renderBody(container: HTMLElement): void {
this._bodyBuilder = new Builder(container); let connectionContainer = $('.connection-dialog');
container.appendChild(connectionContainer.getHTMLElement());
this._bodyBuilder = new Builder(connectionContainer.getHTMLElement());
this._providerTypeSelectBox = new SelectBox(this.providerTypeOptions, this.selectedProviderType); this._providerTypeSelectBox = new SelectBox(this.providerTypeOptions, this.selectedProviderType);
this._bodyBuilder.div({ class: 'connection-recent', id: 'recentConnection' }, (builder) => { // Recent connection tab
let recentConnectionTab = $('.connection-recent-tab');
recentConnectionTab.div({ class: 'connection-recent', id: 'recentConnection' }, (builder) => {
this._recentConnectionBuilder = new Builder(builder.getHTMLElement()); this._recentConnectionBuilder = new Builder(builder.getHTMLElement());
this._noRecentConnectionBuilder = new Builder(builder.getHTMLElement()); this._noRecentConnectionBuilder = new Builder(builder.getHTMLElement());
this.createRecentConnections(); this.createRecentConnections();
this._recentConnectionBuilder.hide(); this._recentConnectionBuilder.hide();
}); });
// Saved connection tab
let savedConnectionTab = $('.connection-saved-tab');
savedConnectionTab.div({ class: 'connection-saved' }, (builder) => {
this._savedConnectionBuilder = new Builder(builder.getHTMLElement());
this._noSavedConnectionBuilder = new Builder(builder.getHTMLElement());
this.createSavedConnections();
this._savedConnectionBuilder.hide();
});
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
this._recentConnectionTabId = this._panel.pushTab({
identifier: 'recent_connection',
title: localize('recentConnectionTitle', 'Recent connections'),
view: {
render: c => {
recentConnectionTab.appendTo(c);
},
layout: () => { }
}
});
let savedConnectionTabId = this._panel.pushTab({
identifier: 'saved_connection',
title: localize('savedConnectionTitle', 'Saved connections'),
view: {
layout: () => { },
render: c => {
savedConnectionTab.appendTo(c);
}
}
});
this._panel.onTabChange(c => {
if (c === savedConnectionTabId && this._savedConnectionTree.getContentHeight() === 0) {
// Update saved connection tree
TreeUpdateUtils.structuralTreeUpdate(this._savedConnectionTree, 'saved', this._connectionManagementService);
if (this._savedConnectionTree.getContentHeight() > 0) {
this._noSavedConnectionBuilder.hide();
this._savedConnectionBuilder.show();
} else {
this._noSavedConnectionBuilder.show();
this._savedConnectionBuilder.hide();
}
this._savedConnectionTree.layout(DOM.getTotalHeight(this._savedConnectionTree.getHTMLElement()));
}
});
this._bodyBuilder.div({ class: 'Connection-divider' }, (dividerContainer) => { this._bodyBuilder.div({ class: 'Connection-divider' }, (dividerContainer) => {
this._dividerBuilder = dividerContainer; this._dividerBuilder = dividerContainer;
}); });
@@ -194,7 +255,7 @@ export class ConnectionDialogWidget extends Modal {
private clearRecentConnectionList(): TPromise<boolean> { private clearRecentConnectionList(): TPromise<boolean> {
let confirm: IConfirmation = { let confirm: IConfirmation = {
message: nls.localize('clearRecentConnectionMessage', 'Are you sure you want to delete all the connections from the list?'), message: localize('clearRecentConnectionMessage', 'Are you sure you want to delete all the connections from the list?'),
primaryButton: localize('yes', 'Yes'), primaryButton: localize('yes', 'Yes'),
secondaryButton: localize('no', 'No'), secondaryButton: localize('no', 'No'),
type: 'question' type: 'question'
@@ -214,11 +275,11 @@ export class ConnectionDialogWidget extends Modal {
private createRecentConnectionList(): void { private createRecentConnectionList(): void {
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => { this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
let recentHistoryLabel = localize('recentHistory', 'Recent history'); let recentHistoryLabel = localize('recentHistory', 'Recent history');
recentConnectionContainer.div({ class: 'recent-titles-container'}, (container) => { recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
container.div({ class: 'connection-history-label' }, (recentTitle) => { container.div({ class: 'connection-history-label' }, (recentTitle) => {
recentTitle.innerHtml(recentHistoryLabel); recentTitle.innerHtml(recentHistoryLabel);
}); });
container.div({ class: 'search-action clear-search-results'}, (clearSearchIcon) => { container.div({ class: 'search-action clear-search-results' }, (clearSearchIcon) => {
clearSearchIcon.on('click', () => this.clearRecentConnectionList()); clearSearchIcon.on('click', () => this.clearRecentConnectionList());
}); });
}); });
@@ -227,7 +288,7 @@ export class ConnectionDialogWidget extends Modal {
let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => { let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item // element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) { if (element instanceof ConnectionProfile) {
this.onRecentConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element); this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
} }
}; };
let actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider, this._instantiationService, this._connectionManagementService, let actionProvider = this._instantiationService.createInstance(RecentConnectionActionsProvider, this._instantiationService, this._connectionManagementService,
@@ -238,7 +299,7 @@ export class ConnectionDialogWidget extends Modal {
}); });
controller.onRecentConnectionRemoved(() => { controller.onRecentConnectionRemoved(() => {
this.open(this._connectionManagementService.getRecentConnections().length > 0); this.open(this._connectionManagementService.getRecentConnections().length > 0);
}) });
this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller); this._recentConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller);
// Theme styler // Theme styler
@@ -252,18 +313,46 @@ export class ConnectionDialogWidget extends Modal {
private createRecentConnections() { private createRecentConnections() {
this.createRecentConnectionList(); this.createRecentConnectionList();
this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => { this._noRecentConnectionBuilder.div({ class: 'connection-recent-content' }, (noRecentConnectionContainer) => {
let recentHistoryLabel = localize('recentHistory', 'Recent history'); let noRecentHistoryLabel = localize('noRecentConnections', 'No recent connection');
noRecentConnectionContainer.div({ class: 'connection-history-label' }, (recentTitle) => {
recentTitle.innerHtml(recentHistoryLabel);
});
let noRecentHistoryLabel = localize('noRecentConnections', 'No Recent Connections');
noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => { noRecentConnectionContainer.div({ class: 'no-recent-connections' }, (noRecentTitle) => {
noRecentTitle.innerHtml(noRecentHistoryLabel); noRecentTitle.innerHtml(noRecentHistoryLabel);
}); });
}); });
} }
private onRecentConnectionClick(event: any, element: IConnectionProfile) { private createSavedConnectionList(): void {
this._savedConnectionBuilder.div({ class: 'connection-saved-content' }, (savedConnectioncontainer) => {
savedConnectioncontainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
divContainer.div({ class: 'explorer-servers' }, (treeContainer: Builder) => {
let leftClick = (element: any, eventish: ICancelableEvent, origin: string) => {
// element will be a server group if the tree is clicked rather than a item
if (element instanceof ConnectionProfile) {
this.onConnectionClick({ payload: { origin: origin, originalEvent: eventish } }, element);
}
};
let controller = new SavedConnectionTreeController(leftClick);
this._savedConnectionTree = TreeCreationUtils.createConnectionTree(treeContainer.getHTMLElement(), this._instantiationService, controller);
// Theme styler
this._register(styler.attachListStyler(this._savedConnectionTree, this._themeService));
divContainer.append(this._savedConnectionTree.getHTMLElement());
});
});
});
}
private createSavedConnections() {
this.createSavedConnectionList();
this._noSavedConnectionBuilder.div({ class: 'connection-saved-content' }, (noSavedConnectionContainer) => {
let noSavedConnectionLabel = localize('noSavedConnections', 'No saved connection');
noSavedConnectionContainer.div({ class: 'no-saved-connections' }, (titleContainer) => {
titleContainer.innerHtml(noSavedConnectionLabel);
});
});
}
private onConnectionClick(event: any, element: IConnectionProfile) {
let isMouseOrigin = event.payload && (event.payload.origin === 'mouse'); let isMouseOrigin = event.payload && (event.payload.origin === 'mouse');
let isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2; let isDoubleClick = isMouseOrigin && event.payload.originalEvent && event.payload.originalEvent.detail === 2;
if (isDoubleClick) { if (isDoubleClick) {
@@ -280,6 +369,7 @@ export class ConnectionDialogWidget extends Modal {
* @param recentConnections Are there recent connections that should be shown * @param recentConnections Are there recent connections that should be shown
*/ */
public open(recentConnections: boolean) { public open(recentConnections: boolean) {
this._panel.showTab(this._recentConnectionTabId);
this.show(); this.show();
if (recentConnections) { if (recentConnections) {
this._noRecentConnectionBuilder.hide(); this._noRecentConnectionBuilder.hide();
@@ -289,6 +379,10 @@ export class ConnectionDialogWidget extends Modal {
this._noRecentConnectionBuilder.show(); this._noRecentConnectionBuilder.show();
} }
TreeUpdateUtils.structuralTreeUpdate(this._recentConnectionTree, 'recent', this._connectionManagementService); TreeUpdateUtils.structuralTreeUpdate(this._recentConnectionTree, 'recent', this._connectionManagementService);
// reset saved connection tree
this._savedConnectionTree.setInput([]);
// call layout with view height // call layout with view height
this.layout(); this.layout();
this.initDialog(); this.initDialog();

View File

@@ -14,16 +14,23 @@
padding-bottom: 5px; padding-bottom: 5px;
} }
.connection-recent { .connection-dialog {
height: calc(100% - 20px);
}
.connection-dialog .tabbedPanel {
border-top-color: transparent;
height: calc(100% - 350px);
}
.connection-recent, .connection-saved {
margin: 15px; margin: 15px;
height: calc(100% - 400px); height: calc(100% - 60px);
overflow-y: auto; overflow-y: auto;
} }
.no-recent-connections { .no-recent-connections, .no-saved-connections {
font-size: 12px; font-size: 12px;
text-align: left;
display: block;
padding-top: 5px; padding-top: 5px;
} }
@@ -52,6 +59,10 @@
table-layout: fixed; table-layout: fixed;
} }
.connection-saved-content {
height: 100%;
}
.connection-type { .connection-type {
margin: 15px; margin: 15px;
overflow-y: hidden; overflow-y: hidden;

View File

@@ -89,7 +89,7 @@ export class RecentConnectionTreeController extends DefaultController {
protected onRightClick(tree: ITree, element: any, eventish: ICancelableEvent, origin: string = 'mouse'): boolean { protected onRightClick(tree: ITree, element: any, eventish: ICancelableEvent, origin: string = 'mouse'): boolean {
this.clickcb(element, eventish, origin); this.clickcb(element, eventish, origin);
this.onContextMenu(tree, element, event); this.showContextMenu(tree, element, event);
return true; return true;
} }
@@ -113,7 +113,7 @@ export class RecentConnectionTreeController extends DefaultController {
return super.onKeyDown(tree, event); return super.onKeyDown(tree, event);
} }
public onContextMenu(tree: ITree, element: any, event: any): boolean { public showContextMenu(tree: ITree, element: any, event: any): boolean {
var actionContext: any; var actionContext: any;
if (element instanceof ConnectionProfile) { if (element instanceof ConnectionProfile) {
@@ -136,7 +136,6 @@ export class RecentConnectionTreeController extends DefaultController {
}, },
getActionsContext: () => (actionContext) getActionsContext: () => (actionContext)
}); });
return true; return true;
} }
} }

View File

@@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { DefaultController, ICancelableEvent } from 'vs/base/parts/tree/browser/treeDefaults';
import { ITree } from 'vs/base/parts/tree/browser/tree';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
export class SavedConnectionTreeController extends DefaultController {
constructor(private clickcb: (element: any, eventish: ICancelableEvent, origin: string) => void) {
super();
}
protected onLeftClick(tree: ITree, element: any, eventish: ICancelableEvent, origin: string = 'mouse'): boolean {
this.clickcb(element, eventish, origin);
return super.onLeftClick(tree, element, eventish, origin);
}
protected onEnter(tree: ITree, event: IKeyboardEvent): boolean {
super.onEnter(tree, event);
// grab the current selection for use later
let selection = tree.getSelection();
this.clickcb(selection[0], event, 'keyboard');
tree.toggleExpansion(selection[0]);
return true;
}
}

View File

@@ -5,7 +5,6 @@
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import { EditorInput, EditorModel } from 'vs/workbench/common/editor'; import { EditorInput, EditorModel } from 'vs/workbench/common/editor';
import { UntitledEditorInput } from 'vs/workbench/common/editor/untitledEditorInput';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri'; import URI from 'vs/base/common/uri';
import { IModelService } from 'vs/editor/common/services/modelService'; import { IModelService } from 'vs/editor/common/services/modelService';
@@ -70,7 +69,7 @@ export class DashboardInput extends EditorInput {
} }
public getTypeId(): string { public getTypeId(): string {
return UntitledEditorInput.ID; return DashboardInput.ID;
} }
public getResource(): URI { public getResource(): URI {
@@ -167,4 +166,8 @@ export class DashboardInput extends EditorInput {
&& profile1.authenticationType === profile2.authenticationType && profile1.authenticationType === profile2.authenticationType
&& profile1.groupFullName === profile2.groupFullName; && profile1.groupFullName === profile2.groupFullName;
} }
public get tabColor(): string {
return this._connectionService.getTabColorForUri(this.uri);
}
} }

Some files were not shown because too many files have changed in this diff Show More