Compare commits

..

17 Commits
1.9.0 ... 1.7.0

Author SHA1 Message Date
Alan Yu
295004c42e Adding CMS readme (#5417) 2019-05-07 17:59:15 -07:00
Alan Ren
45333e8852 bump the version of schema compare extension (#5411) 2019-05-07 17:59:06 -07:00
Aditya Bist
e1280022d6 Fix agent css in packaged builds (#5409)
* fix agent css in packaged

* fix agent css
2019-05-07 14:24:22 -07:00
Karl Burtram
c90d630703 Bump agent, import, profiler extension versions (#5405) 2019-05-07 13:03:28 -07:00
Karl Burtram
bfcdf28cbc Merge branch 'release/1.7' of https://github.com/Microsoft/azuredatastudio into release/1.7 2019-05-07 12:35:58 -07:00
Anthony Dresser
1c694cbd3b Fix css to fix new dashboard tab dialog (#5385)
* fix css to fix new dashboard tab dialog

* add readonly
2019-05-07 09:08:13 -07:00
kisantia
2b0aba119d bump dacpac extension version (#5387) 2019-05-07 09:08:04 -07:00
Karl Burtram
59cc8e5d7f Bump the VS Code version metadata (#5392) 2019-05-07 09:07:53 -07:00
Chris LaFreniere
f8da5bd1c7 Don't scroll when running code cell if in view (#5365) 2019-05-07 09:03:19 -07:00
Anthony Dresser
26667eb1dc Fix css to fix new dashboard tab dialog (#5385)
* fix css to fix new dashboard tab dialog

* add readonly
2019-05-06 17:33:26 -07:00
kisantia
5e6a9ca9fa bump dacpac extension version (#5387) 2019-05-06 17:33:19 -07:00
Karl Burtram
4ecf5fae84 Bump the VS Code version metadata (#5392) 2019-05-06 17:33:13 -07:00
Alan Ren
f76500d5f0 fix profiler formatter issue (#5372) 2019-05-06 15:58:55 -07:00
Maddy
2a212edf1e Maddy/newline overrides edit data (#5364)
* formatting it before displaying

* replace with space

* added comments and method to handle the line break space conversion
2019-05-06 15:58:47 -07:00
Anthony Dresser
7bcd19987b add a applystyle function with saftey checks in header filter (#5380) 2019-05-06 15:58:39 -07:00
Anthony Dresser
0ce5f02dd2 fix error icon (#5373) 2019-05-06 15:58:31 -07:00
udeeshagautam
0831e9e161 Changing the start for Schema compare and adding some text (#5356)
* Dialog Ok will not start Schema compare explit compare will. Adding wait text.

* Fixing variable name and spelling
2019-05-06 15:58:20 -07:00
4324 changed files with 72921 additions and 218006 deletions

6
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.DS_Store .DS_Store
.cache
npm-debug.log npm-debug.log
Thumbs.db Thumbs.db
node_modules/ node_modules/
@@ -15,10 +14,7 @@ out-editor-min/
out-monaco-editor-core/ out-monaco-editor-core/
out-vscode/ out-vscode/
out-vscode-min/ out-vscode-min/
out-vscode-reh/ build/node_modules
out-vscode-reh-min/
out-vscode-reh-pkg/
**/node_modules
coverage/ coverage/
test_data/ test_data/
test-results/ test-results/

View File

@@ -1,39 +1,5 @@
# Change Log # Change Log
## Version 1.8.0
* Release date: June 6, 2019
* Release status: General Availability
## What's new in this version
* Initial release of the Database Admin Tool Extensions for Windows *Preview* extension
* Initial release of the Central Management Servers extension
* **Schema Compare**
* Added Exclude/Include Options
* Generate Script opens script after being generated
* Removed double scroll bars
* Formatting and layout improvements
* Complete changes can be found [here](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue+milestone%3A%22June+2019+Release%22+label%3A%22Area%3A+Schema+Compare%22+is%3Aclosed)
* Messages panel moved into results panel - when users ran SQL queries, results and messages were in stacked panels. Now they are in separate tabs in a single panel similar to SSMS.
* **Notebook**
* Users can now choose to use their own Python 3 or Anaconda installs in notebooks
* Multiple Stability + fit/finish fixes
* View the full list of improvements and fixes [here](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue+milestone%3A%22June+2019+Release%22+is%3Aclosed+label%3A%22Area%3A+Notebooks%22)
* Visual Studio Code May Release Merge 1.34 - the latest improvements can be found [here](https://code.visualstudio.com/updates/v1_34)
* Resolved [bugs and issues](https://github.com/microsoft/azuredatastudio/milestone/32?closed=1).
## Version 1.7.0
* Release date: May 8, 2019
* Release status: General Availability
## What's new in this version
* Announcing Schema Compare *Preview* extension
* Tasks Panel UX improvement
* Announcing new Welcome page
* Resolved [bugs and issues](https://github.com/microsoft/azuredatastudio/milestone/31?closed=1).
## Contributions and "thank you"
We would like to thank all our users who raised issues.
## Version 1.6.0 ## Version 1.6.0
* Release date: April 18, 2019 * Release date: April 18, 2019
* Release status: General Availability * Release status: General Availability

View File

@@ -5,21 +5,21 @@
Azure Data 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. Azure Data 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 the latest Azure Data Studio release** **Download the latest Azure Data Studio release**
Platform | Link Platform | Link
-- | -- -- | --
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2094100 Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2087316
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2094200 Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2087317
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2094201 Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2087318
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2094202 macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2087170
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2094101 Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2087414
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2094102 Linux RPM | https://go.microsoft.com/fwlink/?linkid=2087171
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2094203 Linux DEB | https://go.microsoft.com/fwlink/?linkid=2087415
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions. Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
## Try out the latest insiders build from `master`: Try out the latest insiders build from `master`:
- [Windows User Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-user/insider) - [Windows User Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-user/insider)
- [Windows System Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64/insider) - [Windows System Installer - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64/insider)
- [Windows ZIP - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-archive/insider) - [Windows ZIP - **Insiders build**](https://azuredatastudio-update.azurewebsites.net/latest/win32-x64-archive/insider)
@@ -28,7 +28,7 @@ Go to our [download page](https://aka.ms/azuredatastudio) for more specific inst
See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CHANGELOG.md) for additional details of what's in this release. See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CHANGELOG.md) for additional details of what's in this release.
## **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, Azure Integration and Registered Servers - SQL Server Connection Management with Connection Dialog, Server Groups, Azure Integration and Registered Servers
@@ -68,8 +68,7 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
## Contributions and "Thank You" ## 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: We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* Stevoni for `Corrected Keyboard Shortcut Execution Issue #5480` * yamatoya for `fix the format (#4899)`
* yamatoya for `fix the format #4899`
* GeoffYoung for `Fix sqlDropColumn description #4422` * GeoffYoung for `Fix sqlDropColumn description #4422`
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277` * AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
* sadedil for `Missing feature request: Save as XML #3729` * sadedil for `Missing feature request: Save as XML #3729`

View File

@@ -46,6 +46,7 @@ expressly granted herein, whether by implication, estoppel or otherwise.
node-fetch: https://github.com/bitinn/node-fetch node-fetch: https://github.com/bitinn/node-fetch
node-pty: https://github.com/Tyriar/node-pty node-pty: https://github.com/Tyriar/node-pty
nsfw: https://github.com/Axosoft/nsfw nsfw: https://github.com/Axosoft/nsfw
pretty-data: https://github.com/vkiryukhin/pretty-data
primeng: https://github.com/primefaces/primeng primeng: https://github.com/primefaces/primeng
process-nextick-args: https://github.com/calvinmetcalf/process-nextick-args process-nextick-args: https://github.com/calvinmetcalf/process-nextick-args
pty.js: https://github.com/chjj/pty.js pty.js: https://github.com/chjj/pty.js
@@ -1419,6 +1420,16 @@ SOFTWARE.
========================================= =========================================
END OF nsfw NOTICES AND INFORMATION END OF nsfw NOTICES AND INFORMATION
%% pretty-data NOTICES AND INFORMATION BEGIN HERE
=========================================
License: Dual licensed under the MIT and GPL licenses:
http://www.opensource.org/licenses/mit-license.php
http://www.gnu.org/licenses/gpl.html
=========================================
END OF pretty-data NOTICES AND INFORMATION
%% primeng NOTICES AND INFORMATION BEGIN HERE %% primeng NOTICES AND INFORMATION BEGIN HERE
========================================= =========================================
The MIT License (MIT) The MIT License (MIT)

View File

@@ -1,10 +1,13 @@
steps: steps:
- task: NodeTool@0 - task: NodeTool@0
inputs: inputs:
versionSpec: '10.15.1' versionSpec: '8.x'
displayName: 'Install Node.js' displayName: 'Install Node.js'
- script: | - script: |
git submodule update --init --recursive
nvm install 10.15.1
nvm use 10.15.1
npm i -g yarn npm i -g yarn
displayName: 'preinstall' displayName: 'preinstall'
@@ -46,12 +49,12 @@ steps:
- script: | - script: |
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
displayName: 'Tests' displayName: 'Tests'
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) condition: eq(variables['Agent.OS'], 'Linux')
- script: | - script: |
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter --coverage DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter --coverage
displayName: 'Tests' displayName: 'Tests'
condition: and(succeeded(), ne(variables['Agent.OS'], 'Linux')) condition: ne(variables['Agent.OS'], 'Linux')
- task: PublishTestResults@2 - task: PublishTestResults@2
inputs: inputs:

View File

@@ -1,126 +0,0 @@
# cleanup rules for native node modules, .gitignore style
fsevents/binding.gyp
fsevents/fsevents.cc
fsevents/build/**
fsevents/src/**
fsevents/test/**
!fsevents/**/*.node
vscode-sqlite3/binding.gyp
vscode-sqlite3/benchmark/**
vscode-sqlite3/cloudformation/**
vscode-sqlite3/deps/**
vscode-sqlite3/test/**
vscode-sqlite3/build/**
vscode-sqlite3/src/**
!vscode-sqlite3/build/Release/*.node
oniguruma/binding.gyp
oniguruma/build/**
oniguruma/src/**
oniguruma/deps/**
!oniguruma/build/Release/*.node
!oniguruma/src/*.js
windows-mutex/binding.gyp
windows-mutex/build/**
windows-mutex/src/**
!windows-mutex/**/*.node
native-keymap/binding.gyp
native-keymap/build/**
native-keymap/src/**
native-keymap/deps/**
!native-keymap/build/Release/*.node
native-is-elevated/binding.gyp
native-is-elevated/build/**
native-is-elevated/src/**
native-is-elevated/deps/**
!native-is-elevated/build/Release/*.node
native-watchdog/binding.gyp
native-watchdog/build/**
native-watchdog/src/**
!native-watchdog/build/Release/*.node
spdlog/binding.gyp
spdlog/build/**
spdlog/deps/**
spdlog/src/**
spdlog/test/**
!spdlog/build/Release/*.node
jschardet/dist/**
windows-foreground-love/binding.gyp
windows-foreground-love/build/**
windows-foreground-love/src/**
!windows-foreground-love/**/*.node
windows-process-tree/binding.gyp
windows-process-tree/build/**
windows-process-tree/src/**
!windows-process-tree/**/*.node
gc-signals/binding.gyp
gc-signals/build/**
gc-signals/src/**
gc-signals/deps/**
!gc-signals/build/Release/*.node
!gc-signals/src/index.js
keytar/binding.gyp
keytar/build/**
keytar/src/**
keytar/script/**
keytar/node_modules/**
!keytar/**/*.node
node-pty/binding.gyp
node-pty/build/**
node-pty/src/**
node-pty/tools/**
!node-pty/build/Release/*.exe
!node-pty/build/Release/*.dll
!node-pty/build/Release/*.node
chart.js/node_modules/**
emmet/node_modules/**
pty.js/build/**
!pty.js/build/Release/**
jquery-ui/external/**
jquery-ui/demos/**
core-js/**/**
slickgrid/node_modules/**
slickgrid/examples/**
vscode-nsfw/binding.gyp
vscode-nsfw/build/**
vscode-nsfw/src/**
vscode-nsfw/openpa/**
vscode-nsfw/includes/**
!vscode-nsfw/build/Release/*.node
!vscode-nsfw/**/*.a
vsda/binding.gyp
vsda/README.md
vsda/build/**
vsda/*.bat
vsda/*.sh
vsda/*.cpp
vsda/*.h
!vsda/build/Release/vsda.node
vscode-windows-ca-certs/**/*
!vscode-windows-ca-certs/package.json
!vscode-windows-ca-certs/**/*.node
node-addon-api/**/*

View File

@@ -3,12 +3,10 @@
* 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 cp from 'child_process'; import * as cp from 'child_process';
import * as path from 'path';
function yarnInstall(packageName: string): void { function yarnInstall(packageName: string): void {
cp.execSync(`yarn add --no-lockfile ${packageName}`); cp.execSync(`yarn add --no-lockfile ${packageName}`);
cp.execSync(`yarn add --no-lockfile ${packageName}`, { cwd: path.join( process.cwd(), 'remote') });
} }
const product = require('../../../product.json'); const product = require('../../../product.json');

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
yarn gulp vscode-darwin-min yarn gulp vscode-darwin-min
yarn gulp vscode-reh-darwin-min
yarn gulp upload-vscode-sourcemaps yarn gulp upload-vscode-sourcemaps

View File

@@ -7,21 +7,15 @@ steps:
inputs: inputs:
versionSpec: "1.10.1" versionSpec: "1.10.1"
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- script: | - script: |
set -e set -e
cat << EOF > ~/.netrc cat << EOF > ~/.netrc
machine monacotools.visualstudio.com machine monacotools.visualstudio.com
password $(devops-pat) password $(VSO_PAT)
machine github.com machine github.com
login vscode login vscode
password $(github-distro-mixin-password) password $(VSCODE_MIXIN_PASSWORD)
EOF EOF
git config user.email "vscode@microsoft.com" git config user.email "vscode@microsoft.com"
@@ -40,8 +34,8 @@ steps:
- script: | - script: |
set -e set -e
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
./build/azure-pipelines/darwin/build.sh ./build/azure-pipelines/darwin/build.sh
displayName: Build displayName: Build
@@ -83,11 +77,11 @@ steps:
- script: | - script: |
set -e set -e
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \ AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
VSCODE_HOCKEYAPP_TOKEN="$(vscode-hockeyapp-token)" \ VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
./build/azure-pipelines/darwin/publish.sh ./build/azure-pipelines/darwin/publish.sh
displayName: Publish displayName: Publish

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
# remove pkg from archive # remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg" zip -d ../VSCode-darwin.zip "*.pkg"
@@ -16,19 +15,6 @@ node build/azure-pipelines/common/publish.js \
true \ true \
../VSCode-darwin.zip ../VSCode-darwin.zip
# package Remote Extension Host
pushd .. && mv vscode-reh-darwin vscode-server-darwin && zip -Xry vscode-server-darwin.zip vscode-server-darwin && popd
# publish Remote Extension Host
node build/azure-pipelines/common/publish.js \
"$VSCODE_QUALITY" \
server-darwin \
archive-unsigned \
"vscode-server-darwin.zip" \
$VERSION \
true \
../vscode-server-darwin.zip
# publish hockeyapp symbols # publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS" node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS"

View File

@@ -10,19 +10,13 @@ steps:
inputs: inputs:
versionSpec: "10.15.1" versionSpec: "10.15.1"
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- script: | - script: |
set -e set -e
cat << EOF > ~/.netrc cat << EOF > ~/.netrc
machine github.com machine github.com
login vscode login vscode
password $(github-distro-mixin-password) password $(VSCODE_MIXIN_PASSWORD)
EOF EOF
git config user.email "vscode@microsoft.com" git config user.email "vscode@microsoft.com"

View File

@@ -1,7 +1,3 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
yarn gulp "vscode-linux-$VSCODE_ARCH-min" yarn gulp "vscode-linux-$VSCODE_ARCH-min"
if [[ "$VSCODE_ARCH" != "ia32" ]]; then
yarn gulp vscode-reh-linux-$VSCODE_ARCH-min
fi

View File

@@ -7,12 +7,6 @@ steps:
inputs: inputs:
versionSpec: "1.10.1" versionSpec: "1.10.1"
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- script: | - script: |
set -e set -e
export npm_config_arch="$(VSCODE_ARCH)" export npm_config_arch="$(VSCODE_ARCH)"
@@ -22,10 +16,10 @@ steps:
cat << EOF > ~/.netrc cat << EOF > ~/.netrc
machine monacotools.visualstudio.com machine monacotools.visualstudio.com
password $(devops-pat) password $(VSO_PAT)
machine github.com machine github.com
login vscode login vscode
password $(github-distro-mixin-password) password $(VSCODE_MIXIN_PASSWORD)
EOF EOF
git config user.email "vscode@microsoft.com" git config user.email "vscode@microsoft.com"
@@ -44,7 +38,7 @@ steps:
- script: | - script: |
set -e set -e
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
./build/azure-pipelines/linux/build.sh ./build/azure-pipelines/linux/build.sh
displayName: Build displayName: Build
@@ -61,10 +55,10 @@ steps:
- script: | - script: |
set -e set -e
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" \ VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
VSCODE_HOCKEYAPP_TOKEN="$(vscode-hockeyapp-token)" \ VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
./build/azure-pipelines/linux/publish.sh ./build/azure-pipelines/linux/publish.sh
displayName: Publish displayName: Publish

View File

@@ -20,19 +20,6 @@ rm -rf $ROOT/code-*.tar.*
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH" node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
# Publish Remote Extension Host
if [[ "$VSCODE_ARCH" != "ia32" ]]; then
LEGACY_SERVER_BUILD_NAME="vscode-reh-$PLATFORM_LINUX"
SERVER_BUILD_NAME="vscode-server-$PLATFORM_LINUX"
SERVER_TARBALL_FILENAME="vscode-server-$PLATFORM_LINUX.tar.gz"
SERVER_TARBALL_PATH="$ROOT/$SERVER_TARBALL_FILENAME"
rm -rf $ROOT/vscode-server-*.tar.*
(cd $ROOT && mv $LEGACY_SERVER_BUILD_NAME $SERVER_BUILD_NAME && tar -czf $SERVER_TARBALL_PATH $SERVER_BUILD_NAME)
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "server-$PLATFORM_LINUX" archive-unsigned "$SERVER_TARBALL_FILENAME" "$VERSION" true "$SERVER_TARBALL_PATH"
fi
# Publish hockeyapp symbols # Publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64" node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64"

View File

@@ -7,12 +7,6 @@ steps:
inputs: inputs:
versionSpec: "1.10.1" versionSpec: "1.10.1"
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- task: DownloadPipelineArtifact@0 - task: DownloadPipelineArtifact@0
displayName: 'Download Pipeline Artifact' displayName: 'Download Pipeline Artifact'
inputs: inputs:
@@ -50,6 +44,6 @@ steps:
(cd $SNAP_ROOT/code-* && sudo snapcraft snap --output "$SNAP_PATH") (cd $SNAP_ROOT/code-* && sudo snapcraft snap --output "$SNAP_PATH")
# Publish snap package # Publish snap package
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH" node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"

View File

@@ -1,11 +1,9 @@
resources: resources:
containers: containers:
- container: vscode-x64 - container: vscode-x64
endpoint: VSCodeHub image: joaomoreno/vscode-linux-build-agent:x64
image: vscodehub.azurecr.io/vscode-linux-build-agent:x64
- container: vscode-ia32 - container: vscode-ia32
endpoint: VSCodeHub image: joaomoreno/vscode-linux-build-agent:ia32
image: vscodehub.azurecr.io/vscode-linux-build-agent:ia32
- container: snapcraft - container: snapcraft
image: snapcore/snapcraft image: snapcore/snapcraft

View File

@@ -1,2 +0,0 @@
node_modules/
*.js

View File

@@ -1,36 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const cp = require("child_process");
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
if (!isValidTag(tag)) {
throw Error(`Invalid tag ${tag}`);
}
}
catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function isValidTag(t) {
if (t.split('.').length !== 3) {
return false;
}
const [major, minor, bug] = t.split('.');
// Only release for tags like 1.34.0
if (bug !== '0') {
return false;
}
if (parseInt(major, 10) === NaN || parseInt(minor, 10) === NaN) {
return false;
}
return true;
}

View File

@@ -1,43 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 cp from 'child_process';
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
if (!isValidTag(tag)) {
throw Error(`Invalid tag ${tag}`);
}
} catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function isValidTag(t: string) {
if (t.split('.').length !== 3) {
return false;
}
const [major, minor, bug] = t.split('.');
// Only release for tags like 1.34.0
if (bug !== '0') {
return false;
}
if (parseInt(major, 10) === NaN || parseInt(minor, 10) === NaN) {
return false;
}
return true;
}

View File

@@ -1,67 +0,0 @@
# Publish @types/vscode for each release
trigger:
branches:
include: ['refs/tags/*']
pr: none
steps:
- task: NodeTool@0
inputs:
versionSpec: "10.15.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- bash: |
# Install build dependencies
(cd build && yarn)
node build/azure-pipelines/publish-types/check-version.js
displayName: Check version
- bash: |
git config --global user.email "vscode@microsoft.com"
git config --global user.name "VSCode"
git clone https://$(GITHUB_TOKEN)@github.com/DefinitelyTyped/DefinitelyTyped.git --depth=1
node build/azure-pipelines/publish-types/update-types.js
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
cd DefinitelyTyped
git diff --color | cat
git add -A
git status
git checkout -b "vscode-types-$TAG_VERSION"
git commit -m "VS Code $TAG_VERSION Extension API"
git push origin "vscode-types-$TAG_VERSION"
displayName: Push update to DefinitelyTyped
- bash: |
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
CHANNEL="G1C14HJ2F"
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:"
LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details."
MESSAGE2="[@octref, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE"'"}' \
https://slack.com/api/chat.postMessage
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$LINK"'"}' \
https://slack.com/api/chat.postMessage
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \
--data '{"channel":"'"$CHANNEL"'", "link_names": true, "text":"'"$MESSAGE2"'"}' \
https://slack.com/api/chat.postMessage
displayName: Send message on Slack

View File

@@ -1,62 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const cp = require("child_process");
const path = require("path");
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vs/vscode.d.ts`;
const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts');
cp.execSync(`curl ${dtsUri} --output ${outPath}`);
updateDTSFile(outPath, tag);
console.log(`Done updating vscode.d.ts at ${outPath}`);
}
catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function updateDTSFile(outPath, tag) {
const oldContent = fs.readFileSync(outPath, 'utf-8');
const newContent = getNewFileContent(oldContent, tag);
fs.writeFileSync(outPath, newContent);
}
function getNewFileContent(content, tag) {
const oldheader = [
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the Source EULA. See License.txt in the project root for license information.`,
` *--------------------------------------------------------------------------------------------*/`
].join('\n');
return getNewFileHeader(tag) + content.slice(oldheader.length);
}
function getNewFileHeader(tag) {
const [major, minor] = tag.split('.');
const shorttag = `${major}.${minor}`;
const header = [
`// Type definitions for Visual Studio Code ${shorttag}`,
`// Project: https://github.com/microsoft/vscode`,
`// Definitions by: Visual Studio Code Team, Microsoft <https://github.com/Microsoft>`,
`// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`,
``,
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the Source EULA.`,
` * See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information.`,
` *--------------------------------------------------------------------------------------------*/`,
``,
`/**`,
` * Type Definition for Visual Studio Code ${shorttag} Extension API`,
` * See https://code.visualstudio.com/api for more information`,
` */`
].join('\n');
return header;
}

View File

@@ -1,73 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 cp from 'child_process';
import * as path from 'path';
let tag = '';
try {
tag = cp
.execSync('git describe --tags `git rev-list --tags --max-count=1`')
.toString()
.trim();
const dtsUri = `https://raw.githubusercontent.com/microsoft/vscode/${tag}/src/vs/vscode.d.ts`;
const outPath = path.resolve(process.cwd(), 'DefinitelyTyped/types/vscode/index.d.ts');
cp.execSync(`curl ${dtsUri} --output ${outPath}`);
updateDTSFile(outPath, tag);
console.log(`Done updating vscode.d.ts at ${outPath}`);
} catch (err) {
console.error(err);
console.error('Failed to update types');
process.exit(1);
}
function updateDTSFile(outPath: string, tag: string) {
const oldContent = fs.readFileSync(outPath, 'utf-8');
const newContent = getNewFileContent(oldContent, tag);
fs.writeFileSync(outPath, newContent);
}
function getNewFileContent(content: string, tag: string) {
const oldheader = [
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the Source EULA. See License.txt in the project root for license information.`,
` *--------------------------------------------------------------------------------------------*/`
].join('\n');
return getNewFileHeader(tag) + content.slice(oldheader.length);
}
function getNewFileHeader(tag: string) {
const [major, minor] = tag.split('.');
const shorttag = `${major}.${minor}`;
const header = [
`// Type definitions for Visual Studio Code ${shorttag}`,
`// Project: https://github.com/microsoft/vscode`,
`// Definitions by: Visual Studio Code Team, Microsoft <https://github.com/Microsoft>`,
`// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped`,
``,
`/*---------------------------------------------------------------------------------------------`,
` * Copyright (c) Microsoft Corporation. All rights reserved.`,
` * Licensed under the Source EULA.`,
` * See https://github.com/Microsoft/vscode/blob/master/LICENSE.txt for license information.`,
` *--------------------------------------------------------------------------------------------*/`,
``,
`/**`,
` * Type Definition for Visual Studio Code ${shorttag} Extension API`,
` * See https://code.visualstudio.com/api for more information`,
` */`
].join('\n');
return header;
}

View File

@@ -7,18 +7,12 @@ steps:
inputs: inputs:
versionSpec: "1.10.1" versionSpec: "1.10.1"
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- script: | - script: |
set -e set -e
(cd build ; yarn) (cd build ; yarn)
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(vscode-storage-key)" \ AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(vscode-mooncake-storage-key)" \ MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY" node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY"

View File

@@ -1,5 +1,4 @@
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min" }
exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min" }
exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" }

View File

@@ -12,16 +12,10 @@ steps:
versionSpec: '2.x' versionSpec: '2.x'
addToPath: true addToPath: true
- task: AzureKeyVault@1
displayName: 'Azure Key Vault: Get Secrets'
inputs:
azureSubscription: 'vscode-builds-subscription'
KeyVaultName: vscode
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
"machine monacotools.visualstudio.com`npassword $(devops-pat)`nmachine github.com`nlogin vscode`npassword $(github-distro-mixin-password)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII "machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)" $env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1" $env:CHILD_CONCURRENCY="1"
@@ -42,7 +36,7 @@ steps:
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$env:VSCODE_MIXIN_PASSWORD="$(github-distro-mixin-password)" $env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
.\build\azure-pipelines\win32\build.ps1 .\build\azure-pipelines\win32\build.ps1
displayName: Build displayName: Build
@@ -132,15 +126,15 @@ steps:
- powershell: | - powershell: |
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
.\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 -AuthCertificateBase64 $(esrp-auth-certificate) -AuthCertificateKey $(esrp-auth-certificate-key) .\build\azure-pipelines\win32\import-esrp-auth-cert.ps1 -AuthCertificateBase64 $(ESRP_AUTH_CERTIFICATE) -AuthCertificateKey $(ESRP_AUTH_CERTIFICATE_KEY)
displayName: Import ESRP Auth Certificate displayName: Import ESRP Auth Certificate
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(vscode-storage-key)" $env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(builds-docdb-key-readwrite)" $env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$env:VSCODE_HOCKEYAPP_TOKEN = "$(vscode-hockeyapp-token)" $env:VSCODE_HOCKEYAPP_TOKEN = "$(VSCODE_HOCKEYAPP_TOKEN)"
.\build\azure-pipelines\win32\publish.ps1 .\build\azure-pipelines\win32\publish.ps1
displayName: Publish displayName: Publish

View File

@@ -10,16 +10,8 @@ $Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe" $SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe" $UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip" $Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip"
$LegacyServer = "$Root\vscode-reh-win32-$Arch"
$ServerName = "vscode-server-win32-$Arch"
$Server = "$Root\$ServerName"
$ServerZip = "$Repo\.build\vscode-server-win32-$Arch.zip"
$Build = "$Root\VSCode-win32-$Arch" $Build = "$Root\VSCode-win32-$Arch"
# Create server archive
exec { Rename-Item -Path $LegacyServer -NewName $ServerName }
exec { .\node_modules\7zip\7zip-lite\7z.exe a -tzip $ServerZip $Server -r }
# get version # get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json $PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version $Version = $PackageJson.version
@@ -30,7 +22,6 @@ $AssetPlatform = if ("$Arch" -eq "ia32") { "win32" } else { "win32-x64" }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip } exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe } exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe } exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe }
exec { node build/azure-pipelines/common/publish.js $Quality "server-$AssetPlatform" archive "vscode-server-win32-$Arch.zip" $Version true $ServerZip }
# publish hockeyapp symbols # publish hockeyapp symbols
$hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" } $hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" }

View File

@@ -92,12 +92,11 @@ const indentationFilter = [
'!**/*.dockerfile', '!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js', '!extensions/markdown-language-features/media/*.js',
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
'!**/*.{xlf,docx,sql,vsix,bacpac}', '!**/*.xlf',
'!**/*.docx',
'!**/*.sql',
'!extensions/mssql/sqltoolsservice/**', '!extensions/mssql/sqltoolsservice/**',
'!extensions/import/flatfileimportservice/**', '!extensions/import/flatfileimportservice/**',
'!extensions/admin-tool-ext-win/ssmsmin/**',
'!extensions/resource-deployment/notebooks/**',
'!extensions/mssql/notebooks/**'
]; ];
const copyrightFilter = [ const copyrightFilter = [
@@ -156,9 +155,7 @@ const copyrightFilter = [
'!extensions/mssql/src/prompts/**', '!extensions/mssql/src/prompts/**',
'!extensions/notebook/resources/jupyter_config/**', '!extensions/notebook/resources/jupyter_config/**',
'!**/*.gif', '!**/*.gif',
'!**/*.xlf', '!**/*.xlf'
'!**/*.dacpac',
'!**/*.bacpac'
]; ];
const eslintFilter = [ const eslintFilter = [
@@ -187,11 +184,6 @@ const tslintFilter = [
'!extensions/html-language-features/server/lib/jquery.d.ts' '!extensions/html-language-features/server/lib/jquery.d.ts'
]; ];
// {{SQL CARBON EDIT}}
const useStrictFilter = [
'src/**'
];
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const copyrightHeaderLines = [ const copyrightHeaderLines = [
'/*---------------------------------------------------------------------------------------------', '/*---------------------------------------------------------------------------------------------',
@@ -242,8 +234,8 @@ function hygiene(some) {
}); });
const copyrights = es.through(function (file) { const copyrights = es.through(function (file) {
const lines = file.__lines; const lines = file.__lines;
for (let i = 0; i < copyrightHeaderLines.length; i++) { for (let i = 0; i < copyrightHeaderLines.length; i++) {
if (lines[i] !== copyrightHeaderLines[i]) { if (lines[i] !== copyrightHeaderLines[i]) {
console.error(file.relative + ': Missing or bad copyright statement'); console.error(file.relative + ': Missing or bad copyright statement');
@@ -255,23 +247,6 @@ function hygiene(some) {
this.emit('data', file); this.emit('data', file);
}); });
// {{SQL CARBON EDIT}}
// Check for unnecessary 'use strict' lines. These are automatically added by the alwaysStrict compiler option so don't need to be added manually
const useStrict = es.through(function (file) {
const lines = file.__lines;
// Only take the first 10 lines to reduce false positives- the compiler will throw an error if it's not the first non-comment line in a file
// (10 is used to account for copyright and extraneous newlines)
lines.slice(0, 10).forEach((line, i) => {
if (/\s*'use\s*strict\s*'/.test(line)) {
console.error(file.relative + '(' + (i + 1) + ',1): Unnecessary \'use strict\' - this is already added by the compiler');
errorCount++;
}
});
this.emit('data', file);
});
// {{SQL CARBON EDIT}} END
const formatting = es.map(function (file, cb) { const formatting = es.map(function (file, cb) {
tsfmt.processString(file.path, file.contents.toString('utf8'), { tsfmt.processString(file.path, file.contents.toString('utf8'), {
verify: false, verify: false,
@@ -330,10 +305,7 @@ function hygiene(some) {
const typescript = result const typescript = result
.pipe(filter(tslintFilter)) .pipe(filter(tslintFilter))
.pipe(formatting) .pipe(formatting)
.pipe(tsl) .pipe(tsl);
// {{SQL CARBON EDIT}}
.pipe(filter(useStrictFilter))
.pipe(useStrict);
const javascript = result const javascript = result
.pipe(filter(eslintFilter)) .pipe(filter(eslintFilter))
@@ -387,7 +359,7 @@ function createGitIndexVinyls(paths) {
return e(err); return e(err);
} }
cp.exec(`git show ":${relativePath}"`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => { cp.exec(`git show :${relativePath}`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => {
if (err) { if (err) {
return e(err); return e(err);
} }

View File

@@ -9,7 +9,6 @@ const gulp = require('gulp');
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
const jeditor = require('gulp-json-editor'); const jeditor = require('gulp-json-editor');
const product = require('../product.json');
gulp.task('mixin', function () { gulp.task('mixin', function () {
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
@@ -26,53 +25,19 @@ gulp.task('mixin', function () {
return; return;
} }
// {{SQL CARBON EDIT}} - apply ADS insiders values if needed // {{SQL CARBON EDIT}}
let serviceUrl = 'https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json';
if (quality === 'insider') {
serviceUrl = `https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery-${quality}.json`;
}
let newValues = { let newValues = {
"nameShort": product.nameShort,
"nameLong": product.nameLong,
"applicationName": product.applicationName,
"dataFolderName": product.dataFolderName,
"win32MutexName": product.win32MutexName,
"win32DirName": product.win32DirName,
"win32NameVersion": product.win32NameVersion,
"win32RegValueName": product.win32RegValueName,
"win32AppId": product.win32AppId,
"win32x64AppId": product.win32x64AppId,
"win32UserAppId": product.win32UserAppId,
"win32x64UserAppId": product.win32x64UserAppId,
"win32AppUserModelId": product.win32AppUserModelId,
"win32ShellNameShort": product.win32ShellNameShort,
"darwinBundleIdentifier": product.darwinBundleIdentifier,
"updateUrl": updateUrl, "updateUrl": updateUrl,
"quality": quality, "quality": quality,
"extensionsGallery": { "extensionsGallery": {
"serviceUrl": 'https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json' "serviceUrl": serviceUrl
} }
}; };
if (quality === 'insider') {
let dashSuffix = '-insiders';
let dotSuffix = '.insiders';
let displaySuffix = ' - Insiders';
newValues.extensionsGallery.serviceUrl = `https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery-${quality}.json`;
newValues.nameShort += dashSuffix;
newValues.nameLong += displaySuffix;
newValues.applicationName += dashSuffix;
newValues.dataFolderName += dashSuffix;
newValues.win32MutexName += dashSuffix;
newValues.win32DirName += displaySuffix;
newValues.win32NameVersion += displaySuffix;
newValues.win32RegValueName += dashSuffix;
newValues.win32AppId = "{{9F0801B2-DEE3-4272-A2C6-FBDF25BAAF0F}";
newValues.win32x64AppId = "{{6748A5FD-29EB-4BA6-B3C6-E7B981B8D6B0}";
newValues.win32UserAppId = "{{0F8CD1ED-483C-40EB-8AD2-8ED784651AA1}";
newValues.win32x64UserAppId += dashSuffix;
newValues.win32AppUserModelId += dotSuffix;
newValues.win32ShellNameShort += displaySuffix;
newValues.darwinBundleIdentifier += dotSuffix;
}
return gulp.src('./product.json') return gulp.src('./product.json')
.pipe(jeditor(newValues)) .pipe(jeditor(newValues))
.pipe(gulp.dest('.')); .pipe(gulp.dest('.'));

View File

@@ -1,16 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const gulp = require('gulp');
const noop = () => { return Promise.resolve(); };
gulp.task('vscode-reh-win32-ia32-min', noop);
gulp.task('vscode-reh-win32-x64-min', noop);
gulp.task('vscode-reh-darwin-min', noop);
gulp.task('vscode-reh-linux-x64-min', noop);
gulp.task('vscode-reh-linux-arm-min', noop);

View File

@@ -335,7 +335,33 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const deps = gulp.src(depsSrc, { base: '.', dot: true }) const deps = gulp.src(depsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json'])) .pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModules(path.join(__dirname, '.nativeignore'))) .pipe(util.cleanNodeModule('fsevents', ['binding.gyp', 'fsevents.cc', 'build/**', 'src/**', 'test/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('vscode-sqlite3', ['binding.gyp', 'benchmark/**', 'cloudformation/**', 'deps/**', 'test/**', 'build/**', 'src/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/*.js']))
.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['build/Release/*.node']))
.pipe(util.cleanNodeModule('jschardet', ['dist/**']))
.pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
// {{SQL CARBON EDIT}}
.pipe(util.cleanNodeModule('chart.js', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('emmet', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('pty.js', ['build/**'], ['build/Release/**']))
.pipe(util.cleanNodeModule('jquery-ui', ['external/**', 'demos/**'], undefined))
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['build/Release/*.node', '**/*.a']))
// {{SQL CARBON EDIT}} - End
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
.pipe(util.cleanNodeModule('vscode-windows-ca-certs', ['**/*'], ['package.json', '**/*.node']))
.pipe(util.cleanNodeModule('node-addon-api', ['**/*']))
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar')); .pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
@@ -354,7 +380,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
], { base: '.', dot: true }); ], { base: '.', dot: true });
let all = es.merge( let all = es.merge(
packageJsonStream, packageJsonStream,
productJsonStream, productJsonStream,
license, license,
api, api,
@@ -526,14 +552,10 @@ gulp.task('vscode-translations-pull', function () {
gulp.task('vscode-translations-import', function () { gulp.task('vscode-translations-import', function () {
// {{SQL CARBON EDIT}} - Replace function body with our own // {{SQL CARBON EDIT}} - Replace function body with our own
return new Promise(function(resolve) { [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
[...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => { gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`)
let languageId = language.translationId ? language.translationId : language.id; .pipe(i18n.prepareI18nFiles())
gulp.src(`resources/xlf/${languageId}/**/*.xlf`) .pipe(vfs.dest(`./i18n/${language.folderName}`));
.pipe(i18n.prepareI18nFiles())
.pipe(vfs.dest(`./i18n/${language.folderName}`));
resolve();
});
}); });
// {{SQL CARBON EDIT}} - End // {{SQL CARBON EDIT}} - End
}); });
@@ -681,26 +703,3 @@ function installService() {
gulp.task('install-sqltoolsservice', () => { gulp.task('install-sqltoolsservice', () => {
return installService(); return installService();
}); });
function installSsmsMin() {
const config = require('../extensions/admin-tool-ext-win/src/config.json');
return platformInfo.getCurrent().then(p => {
const runtime = p.runtimeId;
// fix path since it won't be correct
config.installDirectory = path.join(__dirname, '..', 'extensions', 'admin-tool-ext-win', config.installDirectory);
var installer = new serviceDownloader(config);
const serviceInstallFolder = installer.getInstallDirectory(runtime);
const serviceCleanupFolder = path.join(serviceInstallFolder, '..');
console.log('Cleaning up the install folder: ' + serviceCleanupFolder);
return del(serviceCleanupFolder + '/*').then(() => {
console.log('Installing the service. Install folder: ' + serviceInstallFolder);
return installer.installService(runtime);
}, delError => {
console.log('failed to delete the install folder error: ' + delError);
});
});
}
gulp.task('install-ssmsmin', () => {
return installSsmsMin();
});

View File

@@ -40,19 +40,8 @@ function packageBuiltInExtensions() {
.filter(({ name }) => excludedExtensions.indexOf(name) === -1) .filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name)) .filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0); .filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
const visxDirectory = path.join(path.dirname(root), 'vsix');
try {
if (!fs.existsSync(visxDirectory)) {
fs.mkdirSync(visxDirectory);
}
}
catch (err) {
// don't fail the build if the output directory already exists
console.warn(err);
}
sqlBuiltInLocalExtensionDescriptions.forEach(element => { sqlBuiltInLocalExtensionDescriptions.forEach(element => {
let pkgJson = JSON.parse(fs.readFileSync(path.join(element.path, 'package.json'), { encoding: 'utf8' })); const packagePath = path.join(path.dirname(root), element.name + '.vsix');
const packagePath = path.join(visxDirectory, `${pkgJson.name}-${pkgJson.version}.vsix`);
console.info('Creating vsix for ' + element.path + ' result:' + packagePath); console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({ vsce.createVSIX({
cwd: element.path, cwd: element.path,
@@ -266,7 +255,6 @@ const sqlBuiltInExtensions = [
'big-data-cluster', 'big-data-cluster',
'dacpac', 'dacpac',
'schema-compare', 'schema-compare',
'resource-deployment',
'cms' 'cms'
]; ];
const builtInExtensions = require('../builtInExtensions.json'); const builtInExtensions = require('../builtInExtensions.json');
@@ -314,7 +302,9 @@ function packageExtensionsStream(optsIn) {
..._.flatten(extensionsProductionDependencies.map((d) => path.relative(root, d.path)).map((d) => [`${d}/**`, `!${d}/**/{test,tests}/**`])), ..._.flatten(extensionsProductionDependencies.map((d) => path.relative(root, d.path)).map((d) => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
]; ];
const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true }) const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json'])); .pipe(filter(['**', '!**/package-lock.json']))
.pipe(util2.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util2.cleanNodeModule('typescript', ['**/**'], undefined));
// Original code commented out here // Original code commented out here
// const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' }); // const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });
// const marketplaceExtensions = () => es.merge( // const marketplaceExtensions = () => es.merge(

View File

@@ -43,18 +43,8 @@ export function packageBuiltInExtensions() {
.filter(({ name }) => excludedExtensions.indexOf(name) === -1) .filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name)) .filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0); .filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
const visxDirectory = path.join(path.dirname(root), 'vsix');
try {
if (!fs.existsSync(visxDirectory)) {
fs.mkdirSync(visxDirectory);
}
} catch (err) {
// don't fail the build if the output directory already exists
console.warn(err);
}
sqlBuiltInLocalExtensionDescriptions.forEach(element => { sqlBuiltInLocalExtensionDescriptions.forEach(element => {
let pkgJson = JSON.parse(fs.readFileSync(path.join(element.path, 'package.json'), { encoding: 'utf8' })); const packagePath = path.join(path.dirname(root), element.name + '.vsix');
const packagePath = path.join(visxDirectory, `${pkgJson.name}-${pkgJson.version}.vsix`);
console.info('Creating vsix for ' + element.path + ' result:' + packagePath); console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({ vsce.createVSIX({
cwd: element.path, cwd: element.path,
@@ -312,7 +302,6 @@ const sqlBuiltInExtensions = [
'big-data-cluster', 'big-data-cluster',
'dacpac', 'dacpac',
'schema-compare', 'schema-compare',
'resource-deployment',
'cms' 'cms'
]; ];
// {{SQL CARBON EDIT}} - End // {{SQL CARBON EDIT}} - End
@@ -376,7 +365,9 @@ export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): Nod
]; ];
const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true }) const localExtensionDependencies = () => gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json'])); .pipe(filter(['**', '!**/package-lock.json']))
.pipe(util2.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util2.cleanNodeModule('typescript', ['**/**'], undefined));
// Original code commented out here // Original code commented out here
// const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' }); // const localExtensionDependencies = () => gulp.src('extensions/node_modules/**', { base: '.' });

View File

@@ -110,10 +110,6 @@
"name": "vs/workbench/contrib/quickopen", "name": "vs/workbench/contrib/quickopen",
"project": "vscode-workbench" "project": "vscode-workbench"
}, },
{
"name": "vs/workbench/contrib/remote",
"project": "vscode-workbench"
},
{ {
"name": "vs/workbench/contrib/relauncher", "name": "vs/workbench/contrib/relauncher",
"project": "vscode-workbench" "project": "vscode-workbench"

View File

@@ -40,7 +40,6 @@ function extractEditor(options) {
compilerOptions.noUnusedLocals = false; compilerOptions.noUnusedLocals = false;
compilerOptions.preserveConstEnums = false; compilerOptions.preserveConstEnums = false;
compilerOptions.declaration = false; compilerOptions.declaration = false;
compilerOptions.noImplicitAny = false;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic; compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
options.compilerOptions = compilerOptions; options.compilerOptions = compilerOptions;
let result = tss.shake(options); let result = tss.shake(options);
@@ -91,8 +90,6 @@ function extractEditor(options) {
} }
delete tsConfig.compilerOptions.moduleResolution; delete tsConfig.compilerOptions.moduleResolution;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
const tsConfigBase = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.base.json')).toString());
writeOutputFile('tsconfig.base.json', JSON.stringify(tsConfigBase, null, '\t'));
[ [
'vs/css.build.js', 'vs/css.build.js',
'vs/css.d.ts', 'vs/css.d.ts',

View File

@@ -44,7 +44,6 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
compilerOptions.noUnusedLocals = false; compilerOptions.noUnusedLocals = false;
compilerOptions.preserveConstEnums = false; compilerOptions.preserveConstEnums = false;
compilerOptions.declaration = false; compilerOptions.declaration = false;
compilerOptions.noImplicitAny = false;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic; compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
@@ -100,8 +99,6 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
delete tsConfig.compilerOptions.moduleResolution; delete tsConfig.compilerOptions.moduleResolution;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t')); writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
const tsConfigBase = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.base.json')).toString());
writeOutputFile('tsconfig.base.json', JSON.stringify(tsConfigBase, null, '\t'));
[ [
'vs/css.build.js', 'vs/css.build.js',

View File

@@ -8,6 +8,7 @@ const es = require("event-stream");
const debounce = require("debounce"); const debounce = require("debounce");
const _filter = require("gulp-filter"); const _filter = require("gulp-filter");
const rename = require("gulp-rename"); const rename = require("gulp-rename");
const _ = require("underscore");
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const _rimraf = require("rimraf"); const _rimraf = require("rimraf");
@@ -99,18 +100,22 @@ function skipDirectories() {
}); });
} }
exports.skipDirectories = skipDirectories; exports.skipDirectories = skipDirectories;
function cleanNodeModules(rulePath) { function cleanNodeModule(name, excludes, includes) {
const rules = fs.readFileSync(rulePath, 'utf8') const toGlob = (path) => '**/node_modules/' + name + (path ? '/' + path : '');
.split(/\r?\n/g) const negate = (str) => '!' + str;
.map(line => line.trim()) const allFilter = _filter(toGlob('**'), { restore: true });
.filter(line => line && !/^#/.test(line)); const globs = [toGlob('**')].concat(excludes.map(_.compose(negate, toGlob)));
const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`);
const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`);
const input = es.through(); const input = es.through();
const output = es.merge(input.pipe(_filter(['**', ...excludes])), input.pipe(_filter(includes))); const nodeModuleInput = input.pipe(allFilter);
let output = nodeModuleInput.pipe(_filter(globs));
if (includes) {
const includeGlobs = includes.map(toGlob);
output = es.merge(output, nodeModuleInput.pipe(_filter(includeGlobs)));
}
output = output.pipe(allFilter.restore);
return es.duplex(input, output); return es.duplex(input, output);
} }
exports.cleanNodeModules = cleanNodeModules; exports.cleanNodeModule = cleanNodeModule;
function loadSourcemaps() { function loadSourcemaps() {
const input = es.through(); const input = es.through();
const output = input const output = input

View File

@@ -132,21 +132,23 @@ export function skipDirectories(): NodeJS.ReadWriteStream {
}); });
} }
export function cleanNodeModules(rulePath: string): NodeJS.ReadWriteStream { export function cleanNodeModule(name: string, excludes: string[], includes?: string[]): NodeJS.ReadWriteStream {
const rules = fs.readFileSync(rulePath, 'utf8') const toGlob = (path: string) => '**/node_modules/' + name + (path ? '/' + path : '');
.split(/\r?\n/g) const negate = (str: string) => '!' + str;
.map(line => line.trim())
.filter(line => line && !/^#/.test(line));
const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`); const allFilter = _filter(toGlob('**'), { restore: true });
const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`); const globs = [toGlob('**')].concat(excludes.map(_.compose(negate, toGlob) as (x: string) => string));
const input = es.through(); const input = es.through();
const output = es.merge( const nodeModuleInput = input.pipe(allFilter);
input.pipe(_filter(['**', ...excludes])), let output: NodeJS.ReadWriteStream = nodeModuleInput.pipe(_filter(globs));
input.pipe(_filter(includes))
);
if (includes) {
const includeGlobs = includes.map(toGlob);
output = es.merge(output, nodeModuleInput.pipe(_filter(includeGlobs)));
}
output = output.pipe(allFilter.restore);
return es.duplex(input, output); return es.duplex(input, output);
} }

View File

@@ -36,8 +36,6 @@ function yarnInstall(location, opts) {
yarnInstall('extensions'); // node modules shared by all extensions yarnInstall('extensions'); // node modules shared by all extensions
yarnInstall('remote'); // node modules used by vscode server
const allExtensionFolders = fs.readdirSync('extensions'); const allExtensionFolders = fs.readdirSync('extensions');
const extensions = allExtensionFolders.filter(e => { const extensions = allExtensionFolders.filter(e => {
try { try {

View File

@@ -133,7 +133,7 @@ begin
#if "user" == InstallTarget #if "user" == InstallTarget
if not WizardSilent() and IsAdminLoggedOn() then begin if not WizardSilent() and IsAdminLoggedOn() then begin
if MsgBox('This User Installer is not meant to be run as an Administrator. If you would like to install Azure Data Studio for all users in this system, download the System Installer instead from https://docs.microsoft.com/sql/azure-data-studio/download. Are you sure you want to continue?', mbError, MB_OKCANCEL) = IDCANCEL then begin if MsgBox('This User Installer is not meant to be run as an Administrator. If you would like to install VS Code for all users in this system, download the System Installer instead from https://code.visualstudio.com. Are you sure you want to continue?', mbError, MB_OKCANCEL) = IDCANCEL then begin
Result := False; Result := False;
end; end;
end; end;

View File

@@ -1,5 +1,5 @@
out/test/** out/test/**
src/** src/**
ssmsmin/**
.gitignore .gitignore
tsconfig.json tsconfig.json
InstallSsmsMin.bat

View File

@@ -1,4 +0,0 @@
@echo off
REM Run this command to install SsmsMin for local development testing
gulp install-ssmsmin

View File

@@ -1,26 +1,9 @@
# Database Admin Tool Extensions for Windows *(preview)* # Database Admin Tool Extensions for Windows
The Database Admin Tool Extensions for Windows adds Windows-specific functionality into Azure Data Studio. Currently this This adds Windows-specific functionality into Azure Data Studio.
functionality includes the ability to launch a set of SQL Server Management Studio experiences directly from Azure Data Studio.
These experiences include:
* SSMS Property dialogs for select object types, such as Databases, Views, Stored Procedures and more
* The [Generate Scripts Wizard](https://docs.microsoft.com/en-us/sql/ssms/scripting/generate-and-publish-scripts-wizard)
### How do I launch these experiences?
Both of these are available as menu items on the context menu for nodes in the Object Explorer tree. Right click on a node that supports one of the experiences and select the appropriate item.
**Properties** for the property dialogs of supported object types
![Properties](https://user-images.githubusercontent.com/28519865/58999549-13a93080-87bb-11e9-82e4-6dd3f5de5c13.png)
**Generate Scripts...** for the Generate Scripts Wizard (only available on Database nodes)
![Generate Scripts Wizard](https://user-images.githubusercontent.com/28519865/58999482-e2306500-87ba-11e9-9f21-6c5a4996e529.png)
## Code of Conduct ## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Privacy Statement ## Privacy Statement

View File

@@ -1,95 +0,0 @@
MICROSOFT SOFTWARE LICENSE TERMS
MICROSOFT AZURE DATA STUDIO EXTENSION
________________________________________
These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsofts rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS.
1. INSTALLATION AND USE RIGHTS.
a) General. You may install and use one copy of the software on your device.
b) Third Party Software. The software may include third party applications that are licensed to you under this agreement or under their own terms. License terms, notices, and acknowledgements, if any, for the third party applications may be accessible online at http://aka.ms/thirdpartynotices or in an accompanying notices file. Even if such applications are governed by other agreements, the disclaimer, limitations on, and exclusions of damages below also apply to the extent allowed by applicable law.
2. DISTRIBUTABLE CODE. The software may contain code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section.
a) Distribution Rights. The code and files described below are distributable if included with the software.
i. Sample Code, Templates, and Styles. You may copy, modify, and distribute the source and object code form of code marked as “sample”, “template”, “simple styles”, and “sketch styles”.
ii. Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications.
b) Distribution Requirements. For any code you distribute, you must:
i. add significant primary functionality to it in your applications;
ii. require distributors and external end users to agree to terms that protect it and Microsoft at least as much as this agreement; and
iii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code.
c) Distribution Restrictions. You may not:
i. use Microsofts trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or
ii. modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsofts other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it.
3. DATA COLLECTION. The software may collect information about you and your use of the software and send that to Microsoft. Microsoft may use this information to provide services and improve Microsofts products and services. Your opt-out rights, if any, are described in the product documentation. Some features in the software may enable collection of data from users of your applications that access or use the software. If you use these features to enable data collection in your applications, you must comply with applicable law, including getting any required user consent, and maintain a prominent privacy policy that accurately informs users about how you use, collect, and share their data. You can learn more about Microsofts data collection and use in the product documentation and the Microsoft Privacy Statement at https://go.microsoft.com/fwlink/?LinkId=512132. You agree to comply with all applicable provisions of the Microsoft Privacy Statement.
4. SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to):
a) work around any technical limitations in the software that only allow you to use it in certain ways;
b) reverse engineer, decompile or disassemble the software;
c) remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software;
d) use the software in any way that is against the law or to create or propagate malware; or
e) share, publish, distribute, or lend the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone hosted solution for others to use, or transfer the software or this agreement to any third party.
5. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit http://aka.ms/exporting.
6. SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind.
7. ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software.
8. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles. If you acquired the software in any other country, its laws apply. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court. If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court.
9. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you:
a) Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights.
b) Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software.
c) Germany and Austria.
i. Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software.
ii. Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law.
Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence.
10. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
11. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES.
This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law.
It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages.
Please note: As this software is distributed in Canada, some of the clauses in this agreement are provided below in French.
Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en français.
EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft naccorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de qualité marchande, dadéquation à un usage particulier et dabsence de contrefaçon sont exclues.
LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices.
Cette limitation concerne:
• tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou dans des programmes tiers; et
• les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou dune autre faute dans la limite autorisée par la loi en vigueur.
Elle sapplique également, même si Microsoft connaissait ou devrait connaître léventualité dun tel dommage. Si votre pays nautorise pas lexclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou lexclusion ci-dessus ne sappliquera pas à votre égard.
EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir dautres droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le permettent pas.

View File

@@ -5,12 +5,12 @@
"version": "0.0.1", "version": "0.0.1",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/extensions/admin-tool-ext-win/license/Azure%20Data%20Studio%20Extension%20-%20Standalone%20(free)%20Use%20Terms.txt", "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
"icon": "images/sqlserver.png", "icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412", "aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": { "engines": {
"vscode": "^1.30.1", "vscode": "^1.30.1",
"azdata": ">=1.8.0" "sqlops": "*"
}, },
"activationEvents": [ "activationEvents": [
"*" "*"
@@ -55,12 +55,7 @@
}, },
{ {
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog", "command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
"when": "isWindows && connectionProvider == MSSQL && serverInfo && !isCloud && nodeType && nodeType == Server", "when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType =~ /^(Server|Database|Table|Column|Index|Statistic|View|ServerLevelLogin|ServerLevelServerRole|ServerLevelCredential|ServerLevelServerAudit|ServerLevelServerAuditSpecification|StoredProcedure|ScalarValuedFunction|TableValuedFunction|AggregateFunction|Synonym|Assembly|UserDefinedDataType|UserDefinedType|UserDefinedTableType|Sequence|User|DatabaseRole|ApplicationRole|Schema|SecurityPolicy|ServerLevelLinkedServer)$/",
"group": "z-AdminToolExt@2"
},
{
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
"when": "isWindows && connectionProvider == MSSQL && serverInfo && nodeType && nodeType =~ /^(Database|Table|Column|Index|Statistic|View|ServerLevelLogin|ServerLevelServerRole|ServerLevelCredential|ServerLevelServerAudit|ServerLevelServerAuditSpecification|StoredProcedure|ScalarValuedFunction|TableValuedFunction|AggregateFunction|Synonym|Assembly|UserDefinedDataType|UserDefinedType|UserDefinedTableType|Sequence|User|DatabaseRole|ApplicationRole|Schema|SecurityPolicy|ServerLevelLinkedServer)$/",
"group": "z-AdminToolExt@2" "group": "z-AdminToolExt@2"
} }
] ]
@@ -70,15 +65,11 @@
] ]
}, },
"dependencies": { "dependencies": {
"ads-extension-telemetry": "github:Charles-Gagnon/ads-extension-telemetry#0.1.0", "service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "^0.0.15",
"vscode-nls": "^3.2.1" "vscode-nls": "^3.2.1"
}, },
"devDependencies": { "devDependencies": {
"vscode": "1.0.1" "vscode": "1.0.1"
},
"__metadata": {
"id": "41",
"publisherDisplayName": "Microsoft",
"publisherId": "Microsoft"
} }
} }

View File

@@ -1,12 +1,12 @@
{ {
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}", "downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
"version": "15.0.18124.0", "version": "15.0.18120.0",
"downloadFileNames": { "downloadFileNames": {
"Windows_64": "SsmsMin-15.0.18124.0-win-x64.zip", "Windows_64": "SsmsMin-15.0.18120.0-win-x64.zip",
"Windows_86": "SsmsMin-15.0.18124.0-win-x86.zip" "Windows_86": "SsmsMin-15.0.18120.0-win-x86.zip"
}, },
"installDirectory": "ssmsmin/{#platform#}/{#version#}", "installDirectory": "ssmsmin/{#platform#}/{#version#}",
"executableFiles": [ "executableFiles": [
"SsmsMin.exe" "SsmsMin.exe"
] ]
} }

View File

@@ -7,14 +7,16 @@ import * as nls from 'vscode-nls';
import * as path from 'path'; import * as path from 'path';
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { TelemetryReporter, TelemetryViews } from './telemetry'; import { IConfig, ServerProvider } from 'service-downloader';
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getTelemetryErrorType } from './utils'; import { Telemetry } from './telemetry';
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getConfiguration } from './utils';
import { ChildProcess, exec } from 'child_process'; import { ChildProcess, exec } from 'child_process';
const localize = nls.loadMessageBundle();
const ssmsMinVer = JSON.parse(JSON.stringify(require('./config.json'))).version;
const baseConfig = require('./config.json');
const localize = nls.loadMessageBundle();
let exePath: string; let exePath: string;
const runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>(); let runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
interface SmoMapping { interface SmoMapping {
action: string; action: string;
@@ -66,8 +68,39 @@ export interface LaunchSsmsDialogParams {
export async function activate(context: vscode.ExtensionContext): Promise<void> { export async function activate(context: vscode.ExtensionContext): Promise<void> {
// This is for Windows-specific support so do nothing on other platforms // This is for Windows-specific support so do nothing on other platforms
if (process.platform === 'win32') { if (process.platform === 'win32') {
exePath = path.join(context.extensionPath, 'ssmsmin', 'Windows', ssmsMinVer, 'ssmsmin.exe'); Telemetry.sendTelemetryEvent('startup/ExtensionActivated');
registerCommands(context);
let config: IConfig = JSON.parse(JSON.stringify(baseConfig));
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
config.proxy = getConfiguration('http').get('proxy');
config.strictSSL = getConfiguration('http').get('proxyStrictSSL') || true;
const serverdownloader = new ServerProvider(config);
const installationStart = Date.now();
try {
let downloadedExePath = await serverdownloader.getOrDownloadServer();
const installationComplete = Date.now();
// Don't register the command if we couldn't find the EXE since it won't be able to do anything
if (downloadedExePath) {
exePath = downloadedExePath;
} else {
throw new Error('Could not find SsmsMin.exe after downloading');
}
// Register the commands now that we have the exePath to run the tool with
registerCommands(context);
Telemetry.sendTelemetryEvent('startup/ExtensionStarted', {
installationTime: String(installationComplete - installationStart),
beginningTimestamp: String(installationStart)
});
}
catch (err) {
Telemetry.sendTelemetryEvent('startup/ExtensionInitializationFailed');
console.error(`Error Initializing Admin Tool Extension for Windows - ${err}`);
}
} }
} }
@@ -75,7 +108,7 @@ export async function deactivate(): Promise<void> {
// If the extension is being deactivated we want to kill all processes that are still currently // If the extension is being deactivated we want to kill all processes that are still currently
// running otherwise they will continue to run as orphan processes. We use taskkill here in case // running otherwise they will continue to run as orphan processes. We use taskkill here in case
// they started off child processes of their own // they started off child processes of their own
runningProcesses.forEach(p => exec(`taskkill /pid ${p.pid} /T /F`)); runningProcesses.forEach(p => exec('taskkill /pid ' + p.pid + ' /T /F'));
} }
/** /**
@@ -95,7 +128,6 @@ function registerCommands(context: vscode.ExtensionContext): void {
*/ */
async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> { async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
if (!connectionContext) { if (!connectionContext) {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoConnectionContext');
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand')); vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
return; return;
} }
@@ -106,9 +138,9 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
} }
else if (connectionContext.nodeInfo) { else if (connectionContext.nodeInfo) {
nodeType = connectionContext.nodeInfo.nodeType; nodeType = connectionContext.nodeInfo.nodeType;
} else { }
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinProperties, 'NoOENode'); else {
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext))); vscode.window.showErrorMessage(localize('adminToolExtWin.noOeNode', 'Could not determine NodeType for handleLaunchSsmsMinPropertiesDialogCommand with context {0}', JSON.stringify(connectionContext)));
return; return;
} }
@@ -122,14 +154,12 @@ async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: az
* @param connectionId The connection context from the command * @param connectionId The connection context from the command
*/ */
async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> { async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
const action = 'GenerateScripts';
if (!connectionContext) { if (!connectionContext) {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand')); vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
} }
launchSsmsDialog( launchSsmsDialog(
action, 'GenerateScripts',
connectionContext); connectionContext);
} }
@@ -140,12 +170,33 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
* @param urn The URN to pass to SsmsMin * @param urn The URN to pass to SsmsMin
*/ */
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> { async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
if (!exePath) {
vscode.window.showErrorMessage(localize('adminToolExtWin.noExeError', 'Unable to find SsmsMin.exe.'));
return;
}
if (!connectionContext.connectionProfile) { if (!connectionContext.connectionProfile) {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoConnectionProfile');
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext))); vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext)));
return; return;
} }
// Currently Azure isn't supported by the SSMS server properties dialog
const serverInfo = await azdata.connection.getServerInfo(connectionContext.connectionProfile.id);
if (serverInfo && serverInfo.isCloud) {
vscode.window.showErrorMessage(localize('adminToolExtWin.invalidEngineType', 'This option is not currently available for this engine type.'));
return;
}
// Note - this is a temporary fix for the issue that currently the connection API doesn't allow retrieving credentials for a disconnected
// node. So until that's fixed we'll prevent users from attempting to launch SsmsMin on a disconnected node.
// We also aren't able to hide the menu item on disconnected nodes because we currently don't have a contextKey for the connected status
// of a node.
const activeConnections = await azdata.connection.getActiveConnections();
if (!activeConnections.some(conn => conn.connectionId === connectionContext.connectionProfile.id)) {
vscode.window.showErrorMessage(localize('adminToolExtWin.notConnected', 'This option requires a connected node - please connect and try again.'));
return;
}
let oeNode: azdata.objectexplorer.ObjectExplorerNode; let oeNode: azdata.objectexplorer.ObjectExplorerNode;
// Server node is a Connection node and so doesn't have the NodeInfo // Server node is a Connection node and so doesn't have the NodeInfo
if (connectionContext.isConnectionNode) { if (connectionContext.isConnectionNode) {
@@ -155,20 +206,19 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath); oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath);
} }
else { else {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinDialog, 'NoOENode');
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext))); vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext)));
return; return;
} }
const urn: string = await buildUrn(oeNode); let urn: string = await buildUrn(connectionContext.connectionProfile.serverName, oeNode);
let password: string = connectionContext.connectionProfile.password; let password: string = connectionContext.connectionProfile.password;
if (!password || password === '') { if (!password || password === '') {
const creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id); let creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id);
password = creds[azdata.ConnectionOptionSpecialType.password]; password = creds[azdata.ConnectionOptionSpecialType.password];
} }
const params: LaunchSsmsDialogParams = { let params: LaunchSsmsDialogParams = {
action: action, action: action,
server: connectionContext.connectionProfile.serverName, server: connectionContext.connectionProfile.serverName,
database: connectionContext.connectionProfile.databaseName, database: connectionContext.connectionProfile.databaseName,
@@ -177,35 +227,22 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
urn: urn urn: urn
}; };
const args = buildSsmsMinCommandArgs(params); let args = buildSsmsMinCommandArgs(params);
TelemetryReporter.createActionEvent(
TelemetryViews.SsmsMinDialog,
'LaunchSsmsDialog',
'',
action).withAdditionalProperties(
{
nodeType: oeNode ? oeNode.nodeType : 'Server'
}).withConnectionInfo(connectionContext.connectionProfile)
.send();
vscode.window.setStatusBarMessage(localize('adminToolExtWin.launchingDialogStatus', 'Launching dialog...'), 3000); Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
// This will be an async call since we pass in the callback // This will be an async call since we pass in the callback
const proc: ChildProcess = exec( let proc: ChildProcess = exec(
/*command*/ `"${exePath}" ${args}`, /*command*/ `"${exePath}" ${args}`,
/*options*/ undefined, /*options*/ undefined,
(execException, stdout, stderr) => { (execException, stdout, stderr) => {
// Process has exited so remove from map of running processes // Process has exited so remove from map of running processes
runningProcesses.delete(proc.pid); runningProcesses.delete(proc.pid);
const err = stderr.toString(); Telemetry.sendTelemetryEvent('LaunchSsmsDialogResult', {
if ((execException && execException.code !== 0) || err !== '') { 'action': params.action,
TelemetryReporter.sendErrorEvent( 'returnCode': execException && execException.code ? execException.code.toString() : '0'
TelemetryViews.SsmsMinDialog, });
'LaunchSsmsDialogError', let err = stderr.toString();
execException ? execException.code.toString() : '',
getTelemetryErrorType(err));
}
if (err !== '') { if (err !== '') {
vscode.window.showErrorMessage(localize( vscode.window.showErrorMessage(localize(
'adminToolExtWin.ssmsMinError', 'adminToolExtWin.ssmsMinError',
@@ -232,16 +269,17 @@ export function buildSsmsMinCommandArgs(params: LaunchSsmsDialogParams): string
return `${params.action ? '-a "' + backEscapeDoubleQuotes(params.action) + '"' : ''}\ return `${params.action ? '-a "' + backEscapeDoubleQuotes(params.action) + '"' : ''}\
${params.server ? ' -S "' + backEscapeDoubleQuotes(params.server) + '"' : ''}\ ${params.server ? ' -S "' + backEscapeDoubleQuotes(params.server) + '"' : ''}\
${params.database ? ' -D "' + backEscapeDoubleQuotes(params.database) + '"' : ''}\ ${params.database ? ' -D "' + backEscapeDoubleQuotes(params.database) + '"' : ''}\
${params.user ? ' -U "' + backEscapeDoubleQuotes(params.user) + '"' : ''}\ ${params.useAad !== true && params.user ? ' -U "' + backEscapeDoubleQuotes(params.user) + '"' : ''}\
${params.useAad === true ? ' -G' : ''}\ ${params.useAad === true ? ' -G' : ''}\
${params.urn ? ' -u "' + backEscapeDoubleQuotes(params.urn) + '"' : ''}`; ${params.urn ? ' -u "' + backEscapeDoubleQuotes(params.urn) + '"' : ''}`;
} }
/** /**
* Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin * Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin
* @param serverName The name of the Server to use for the Server segment
* @param node The node to get the URN of * @param node The node to get the URN of
*/ */
export async function buildUrn(node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> { export async function buildUrn(serverName: string, node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
let urnNodes: string[] = []; let urnNodes: string[] = [];
while (node) { while (node) {
// Server is special since it's a connection node - always add it as the root // Server is special since it's a connection node - always add it as the root
@@ -250,13 +288,12 @@ export async function buildUrn(node: azdata.objectexplorer.ObjectExplorerNode):
} }
else if (node.metadata && node.nodeType !== 'Folder') { else if (node.metadata && node.nodeType !== 'Folder') {
// SFC URN expects Name and Schema to be separate properties // SFC URN expects Name and Schema to be separate properties
const urnSegment = node.metadata.schema && node.metadata.schema !== '' ? let urnSegment = node.metadata.schema && node.metadata.schema !== '' ?
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}' and @Schema='${doubleEscapeSingleQuotes(node.metadata.schema)}']` : `${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}' and @Schema='${doubleEscapeSingleQuotes(node.metadata.schema)}']` :
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}']`; `${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}']`;
urnNodes = [urnSegment].concat(urnNodes); urnNodes = [urnSegment].concat(urnNodes);
} }
node = await node.getParent(); node = await node.getParent();
} }
return [`Server[@Name='${doubleEscapeSingleQuotes(serverName)}']`].concat(urnNodes).join('/');
return ['Server'].concat(urnNodes).join('/');
} }

View File

@@ -4,23 +4,132 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import AdsTelemetryReporter from 'ads-extension-telemetry'; import * as vscode from 'vscode';
import TelemetryReporter from 'vscode-extension-telemetry';
import { PlatformInformation } from 'service-downloader/out/platform';
import * as Utils from './utils'; import * as Utils from './utils';
const packageJson = require('../package.json'); const packageJson = require('../package.json');
let packageInfo = Utils.getPackageInfo(packageJson); export interface ITelemetryEventProperties {
[key: string]: string;
export const TelemetryReporter = new AdsTelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
export enum TelemetryViews {
SsmsMinProperties = 'SsmsMinProperties',
SsmsMinGsw = 'SsmsMinGsw',
SsmsMinDialog = 'SsmsMinDialog'
} }
export interface ITelemetryEventMeasures {
[key: string]: number;
}
/**
* Filters error paths to only include source files. Exported to support testing
*/
export function filterErrorPath(line: string): string {
if (line) {
let values: string[] = line.split('/out/');
if (values.length <= 1) {
// Didn't match expected format
return line;
} else {
return values[1];
}
}
}
export class Telemetry {
private static reporter: TelemetryReporter;
private static userId: string;
private static platformInformation: PlatformInformation;
private static disabled: boolean;
public static getPlatformInformation(): Promise<PlatformInformation> {
if (this.platformInformation) {
return Promise.resolve(this.platformInformation);
} else {
return new Promise<PlatformInformation>(resolve => {
PlatformInformation.getCurrent().then(info => {
this.platformInformation = info;
resolve(this.platformInformation);
});
});
}
}
/**
* Disable telemetry reporting
*/
public static disable(): void {
this.disabled = true;
}
/**
* Initialize the telemetry reporter for use.
*/
public static initialize(): void {
if (typeof this.reporter === 'undefined') {
// Check if the user has opted out of telemetry
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
this.disable();
return;
}
let packageInfo = Utils.getPackageInfo(packageJson);
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
}
}
/**
* Send a telemetry event for an exception
*/
public static sendTelemetryEventForException(
err: any, methodName: string, extensionConfigName: string): void {
try {
let stackArray: string[];
let firstLine: string = '';
if (err !== undefined && err.stack !== undefined) {
stackArray = err.stack.split('\n');
if (stackArray !== undefined && stackArray.length >= 2) {
firstLine = stackArray[1]; // The first line is the error message and we don't want to send that telemetry event
firstLine = filterErrorPath(firstLine);
}
}
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
} catch (telemetryErr) {
// If sending telemetry event fails ignore it so it won't break the extension
console.error('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
}
}
/**
* Send a telemetry event using application insights
*/
public static sendTelemetryEvent(
eventName: string,
properties?: ITelemetryEventProperties,
measures?: ITelemetryEventMeasures): void {
if (typeof this.disabled === 'undefined') {
this.disabled = false;
}
if (this.disabled || typeof (this.reporter) === 'undefined') {
// Don't do anything if telemetry is disabled
return;
}
if (!properties || typeof properties === 'undefined') {
properties = {};
}
// Augment the properties structure with additional common properties before sending
Promise.all([this.getPlatformInformation()]).then(() => {
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
this.reporter.sendTelemetryEvent(eventName, properties, measures);
});
}
}
Telemetry.initialize();

View File

@@ -36,8 +36,8 @@ describe('buildSsmsMinCommandArgs Method Tests', () => {
urn: 'Server\\Database\\Table' urn: 'Server\\Database\\Table'
}; };
const args = buildSsmsMinCommandArgs(params); const args = buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -G -u "Server\\Database\\Table"'); should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
}); });
it('Should be built correctly and names escaped correctly', function (): void { it('Should be built correctly and names escaped correctly', function (): void {
@@ -50,8 +50,8 @@ describe('buildSsmsMinCommandArgs Method Tests', () => {
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]' urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
}; };
const args = buildSsmsMinCommandArgs(params); const args = buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -U "user\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"'); should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
}); });
it('Should be built correctly with only action and server', function (): void { it('Should be built correctly with only action and server', function (): void {
@@ -65,6 +65,8 @@ describe('buildSsmsMinCommandArgs Method Tests', () => {
}); });
}); });
const serverName = 'My\'Server';
const escapedServerName = doubleEscapeSingleQuotes(serverName);
const dbName = 'My\'Db'; const dbName = 'My\'Db';
const escapedDbName = doubleEscapeSingleQuotes(dbName); const escapedDbName = doubleEscapeSingleQuotes(dbName);
const dbSchema = 'db\'sch'; const dbSchema = 'db\'sch';
@@ -76,21 +78,21 @@ const escapedTableSchema = doubleEscapeSingleQuotes(tableSchema);
describe('buildUrn Method Tests', () => { describe('buildUrn Method Tests', () => {
it('Urn should be correct with just server', async function (): Promise<void> { it('Urn should be correct with just server', async function (): Promise<void> {
should(await buildUrn(undefined)).equal('Server'); should(await buildUrn(serverName, undefined)).equal(`Server[@Name=\'${escapedServerName}\']`);
}); });
it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> { it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub = const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined); new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined);
should(await buildUrn(leafNode)).equal('Server'); should(await buildUrn(serverName, leafNode)).equal(`Server[@Name='${escapedServerName}']`);
}); });
it('Urn should be correct with Server and Database node', async function (): Promise<void> { it('Urn should be correct with Server and Database node', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub = const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined) new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database'); .createChild(dbName, dbSchema, 'Database');
should(await buildUrn(leafNode)).equal( should(await buildUrn(serverName, leafNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`); `Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`);
}); });
it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> { it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> {
@@ -99,8 +101,8 @@ describe('buildUrn Method Tests', () => {
.createChild(dbName, dbSchema, 'Database') .createChild(dbName, dbSchema, 'Database')
.createChild('Tables', undefined, 'Folder') .createChild('Tables', undefined, 'Folder')
.createChild(tableName, tableSchema, 'Table'); .createChild(tableName, tableSchema, 'Table');
should(await buildUrn(rootNode)).equal( should(await buildUrn(serverName, rootNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`); `Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`);
}); });
}); });

View File

@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
'use strict'; 'use strict';
import * as vscode from 'vscode';
export interface IPackageInfo { export interface IPackageInfo {
name: string; name: string;
version: string; version: string;
@@ -20,6 +22,25 @@ export function getPackageInfo(packageJson: any): IPackageInfo {
} }
} }
/**
* Get the configuration for a extensionName
* @param extensionName The string name of the extension to get the configuration for
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
} else if (!resource) {
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
resource = null;
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/** /**
* Escapes all single-quotes (') by prefixing them with another single quote ('') * Escapes all single-quotes (') by prefixing them with another single quote ('')
* ' => '' * ' => ''
@@ -36,26 +57,4 @@ export function doubleEscapeSingleQuotes(value: string): string {
*/ */
export function backEscapeDoubleQuotes(value: string): string { export function backEscapeDoubleQuotes(value: string): string {
return value.replace(/"/g, '\\"'); return value.replace(/"/g, '\\"');
}
/**
* Map an error message into a friendly short name for the type of error.
* @param msg The error message to map
*/
export function getTelemetryErrorType(msg: string): string {
if (msg.indexOf('is not recognized as an internal or external command') !== -1) {
return 'ExeNotFound';
}
else if (msg.indexOf('Unknown Action') !== -1) {
return 'UnknownAction';
}
else if (msg.indexOf('No Action Provided') !== -1) {
return 'NoActionProvided';
}
else if (msg.indexOf('Run exception') !== -1) {
return 'RunException';
}
else {
return 'Other';
}
} }

View File

@@ -2,11 +2,12 @@
# yarn lockfile v1 # yarn lockfile v1
"ads-extension-telemetry@github:Charles-Gagnon/ads-extension-telemetry#0.1.0": agent-base@4, agent-base@^4.1.0:
version "0.1.0" version "4.2.1"
resolved "https://codeload.github.com/Charles-Gagnon/ads-extension-telemetry/tar.gz/70c2fea10e9ff6e329c4c5ec0b77017ada514b6d" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies: dependencies:
vscode-extension-telemetry "0.1.1" es6-promisify "^5.0.0"
ajv@^6.5.5: ajv@^6.5.5:
version "6.9.2" version "6.9.2"
@@ -55,10 +56,10 @@ ansi-wrap@0.1.0:
resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768=
applicationinsights@1.0.8: applicationinsights@1.0.1:
version "1.0.8" version "1.0.1"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg== integrity sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=
dependencies: dependencies:
diagnostic-channel "0.2.0" diagnostic-channel "0.2.0"
diagnostic-channel-publishers "0.2.1" diagnostic-channel-publishers "0.2.1"
@@ -140,6 +141,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-js@^1.0.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==
bcrypt-pbkdf@^1.0.0: bcrypt-pbkdf@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
@@ -152,6 +158,14 @@ beeper@^1.0.0:
resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809"
integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=
bl@^1.0.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
dependencies:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
block-stream@*: block-stream@*:
version "0.0.9" version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
@@ -176,11 +190,37 @@ braces@^1.8.2:
preserve "^0.2.0" preserve "^0.2.0"
repeat-element "^1.1.2" repeat-element "^1.1.2"
buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
buffer-alloc@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies:
buffer-alloc-unsafe "^1.1.0"
buffer-fill "^1.0.0"
buffer-crc32@~0.2.3: buffer-crc32@~0.2.3:
version "0.2.13" version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
buffer-fill@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
buffer@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6"
integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
camelcase-keys@^2.0.0: camelcase-keys@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
@@ -277,6 +317,13 @@ commander@2.3.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873"
integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM= integrity sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=
commander@~2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4"
integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=
dependencies:
graceful-readlink ">= 1.0.0"
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -328,11 +375,78 @@ debug@2.2.0:
dependencies: dependencies:
ms "0.7.1" ms "0.7.1"
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies:
ms "^2.1.1"
decamelize@^1.1.2: decamelize@^1.1.2:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
dependencies:
file-type "^5.2.0"
is-stream "^1.1.0"
tar-stream "^1.5.2"
decompress-tarbz2@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
dependencies:
decompress-tar "^4.1.0"
file-type "^6.1.0"
is-stream "^1.1.0"
seek-bzip "^1.0.5"
unbzip2-stream "^1.0.9"
decompress-targz@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
dependencies:
decompress-tar "^4.1.1"
file-type "^5.2.0"
is-stream "^1.1.0"
decompress-unzip@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
dependencies:
file-type "^3.8.0"
get-stream "^2.2.0"
pify "^2.3.0"
yauzl "^2.4.2"
decompress@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d"
integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=
dependencies:
decompress-tar "^4.0.0"
decompress-tarbz2 "^4.0.0"
decompress-targz "^4.0.0"
decompress-unzip "^4.0.1"
graceful-fs "^4.1.10"
make-dir "^1.0.0"
pify "^2.3.0"
strip-dirs "^2.0.0"
deep-assign@^1.0.0: deep-assign@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b"
@@ -406,6 +520,18 @@ error-ex@^1.2.0:
dependencies: dependencies:
is-arrayish "^0.2.1" is-arrayish "^0.2.1"
es6-promise@^4.0.3:
version "4.2.6"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f"
integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"
escape-string-regexp@1.0.2: escape-string-regexp@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1"
@@ -455,6 +581,11 @@ event-stream@~3.1.5:
stream-combiner "~0.0.4" stream-combiner "~0.0.4"
through "~2.3.1" through "~2.3.1"
eventemitter2@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452"
integrity sha1-YZegldX7a1folC9v1+qtY6CclFI=
expand-brackets@^0.1.4: expand-brackets@^0.1.4:
version "0.1.5" version "0.1.5"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
@@ -525,6 +656,21 @@ fd-slicer@~1.1.0:
dependencies: dependencies:
pend "~1.2.0" pend "~1.2.0"
file-type@^3.8.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
file-type@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
file-type@^6.1.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
filename-regex@^2.0.0: filename-regex@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@@ -585,6 +731,11 @@ from@^0.1.7, from@~0:
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs.realpath@^1.0.0: fs.realpath@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -610,6 +761,14 @@ get-stdin@^4.0.1:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
get-stream@^2.2.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
dependencies:
object-assign "^4.0.1"
pinkie-promise "^2.0.0"
getpass@^0.1.1: getpass@^0.1.1:
version "0.1.7" version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -692,7 +851,7 @@ glogg@^1.0.0:
dependencies: dependencies:
sparkles "^1.0.0" sparkles "^1.0.0"
graceful-fs@^4.0.0, graceful-fs@^4.1.2: graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.2:
version "4.1.15" version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
@@ -704,6 +863,11 @@ graceful-fs@~3.0.2:
dependencies: dependencies:
natives "^1.1.0" natives "^1.1.0"
"graceful-readlink@>= 1.0.0":
version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
growl@1.9.2: growl@1.9.2:
version "1.9.2" version "1.9.2"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
@@ -882,6 +1046,14 @@ hosted-git-info@^2.1.4:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==
http-proxy-agent@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
dependencies:
agent-base "4"
debug "3.1.0"
http-signature@~1.2.0: http-signature@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@@ -891,6 +1063,19 @@ http-signature@~1.2.0:
jsprim "^1.2.2" jsprim "^1.2.2"
sshpk "^1.7.0" sshpk "^1.7.0"
https-proxy-agent@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
dependencies:
agent-base "^4.1.0"
debug "^3.1.0"
ieee754@^1.1.4:
version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==
indent-string@^2.1.0: indent-string@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
@@ -969,6 +1154,11 @@ is-glob@^3.1.0:
dependencies: dependencies:
is-extglob "^2.1.0" is-extglob "^2.1.0"
is-natural-number@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
is-number@^2.1.0: is-number@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
@@ -1341,6 +1531,13 @@ lru-cache@2:
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI= integrity sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=
make-dir@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
dependencies:
pify "^3.0.0"
map-obj@^1.0.0, map-obj@^1.0.1: map-obj@^1.0.0, map-obj@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
@@ -1478,6 +1675,16 @@ ms@0.7.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg= integrity sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
multimatch@^2.0.0: multimatch@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
@@ -1573,6 +1780,11 @@ ordered-read-streams@^0.3.0:
is-stream "^1.0.1" is-stream "^1.0.1"
readable-stream "^2.0.1" readable-stream "^2.0.1"
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
parse-glob@^3.0.4: parse-glob@^3.0.4:
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
@@ -1643,11 +1855,16 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
pify@^2.0.0: pify@^2.0.0, pify@^2.3.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pinkie-promise@^2.0.0: pinkie-promise@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
@@ -1733,7 +1950,7 @@ read-pkg@^1.0.0:
isarray "0.0.1" isarray "0.0.1"
string_decoder "~0.10.x" string_decoder "~0.10.x"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.3.5, readable-stream@~2.3.6: readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6:
version "2.3.6" version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@@ -1843,7 +2060,7 @@ rimraf@2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
@@ -1853,11 +2070,29 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
seek-bzip@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=
dependencies:
commander "~2.8.1"
"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0: "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0:
version "5.6.0" version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
"service-downloader@github:anthonydresser/service-downloader#0.1.5":
version "0.1.5"
resolved "https://codeload.github.com/anthonydresser/service-downloader/tar.gz/6ebb0465573cc140e461a22f334260f55ef45546"
dependencies:
decompress "^4.2.0"
eventemitter2 "^5.0.1"
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.1"
mkdirp "^0.5.1"
tmp "^0.0.33"
sigmund@~1.0.0: sigmund@~1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
@@ -2027,6 +2262,13 @@ strip-bom@^2.0.0:
dependencies: dependencies:
is-utf8 "^0.2.0" is-utf8 "^0.2.0"
strip-dirs@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
dependencies:
is-natural-number "^4.0.1"
strip-indent@^1.0.1: strip-indent@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
@@ -2049,6 +2291,19 @@ supports-color@^2.0.0:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
tar-stream@^1.5.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
bl "^1.0.0"
buffer-alloc "^1.2.0"
end-of-stream "^1.0.0"
fs-constants "^1.0.0"
readable-stream "^2.3.0"
to-buffer "^1.1.1"
xtend "^4.0.0"
tar@~0.1.19: tar@~0.1.19:
version "0.1.20" version "0.1.20"
resolved "https://registry.yarnpkg.com/tar/-/tar-0.1.20.tgz#42940bae5b5f22c74483699126f9f3f27449cb13" resolved "https://registry.yarnpkg.com/tar/-/tar-0.1.20.tgz#42940bae5b5f22c74483699126f9f3f27449cb13"
@@ -2116,6 +2371,13 @@ time-stamp@^1.0.0:
resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3"
integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies:
os-tmpdir "~1.0.2"
to-absolute-glob@^0.1.1: to-absolute-glob@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f"
@@ -2123,6 +2385,11 @@ to-absolute-glob@^0.1.1:
dependencies: dependencies:
extend-shallow "^2.0.1" extend-shallow "^2.0.1"
to-buffer@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
to-iso-string@0.0.2: to-iso-string@0.0.2:
version "0.0.2" version "0.0.2"
resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1"
@@ -2153,6 +2420,14 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
unbzip2-stream@^1.0.9:
version "1.3.3"
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a"
integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==
dependencies:
buffer "^5.2.1"
through "^2.3.8"
unique-stream@^2.0.2: unique-stream@^2.0.2:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac"
@@ -2277,12 +2552,12 @@ vinyl@~2.0.1:
remove-trailing-separator "^1.0.1" remove-trailing-separator "^1.0.1"
replace-ext "^1.0.0" replace-ext "^1.0.0"
vscode-extension-telemetry@0.1.1: vscode-extension-telemetry@^0.0.15:
version "0.1.1" version "0.0.15"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b" resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856"
integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA== integrity sha512-Yf6dL9r2x2GISI1xh22XsAaydSTQG/4aBitu8sGBwGr42n2TyOsIXGtXSDgqQBNZgYD6+P1EHqrrzetn9ekWTQ==
dependencies: dependencies:
applicationinsights "1.0.8" applicationinsights "1.0.1"
vscode-nls@^3.2.1: vscode-nls@^3.2.1:
version "3.2.5" version "3.2.5"
@@ -2313,7 +2588,7 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
@@ -2330,7 +2605,7 @@ xtend@~3.0.0:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a" resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a"
integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo= integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=
yauzl@^2.2.1: yauzl@^2.2.1, yauzl@^2.4.2:
version "2.10.0" version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=

View File

@@ -1 +0,0 @@
*.vsix

View File

@@ -1,3 +1,2 @@
src/** client/src/**
out/test/** client/tsconfig.json
tsconfig.json

2710
extensions/agent/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "agent", "name": "agent",
"displayName": "SQL Server Agent", "displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Server Agent jobs", "description": "Manage and troubleshoot SQL Server Agent jobs",
"version": "0.41.0", "version": "0.39.0",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt", "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",

View File

@@ -10,7 +10,6 @@ import * as vscode from 'vscode';
import { AgentUtils } from '../agentUtils'; import { AgentUtils } from '../agentUtils';
import { IAgentDialogData, AgentDialogMode } from '../interfaces'; import { IAgentDialogData, AgentDialogMode } from '../interfaces';
import { JobData } from './jobData'; import { JobData } from './jobData';
import { JobStepDialog } from '../dialogs/jobStepDialog';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -27,10 +26,10 @@ export class JobStepData implements IAgentDialogData {
public script: string; public script: string;
public scriptName: string; public scriptName: string;
public stepName: string; public stepName: string;
public subSystem: azdata.AgentSubSystem; public subSystem: string;
public id: number; public id: number;
public failureAction: azdata.StepCompletionAction; public failureAction: string;
public successAction: azdata.StepCompletionAction; public successAction: string;
public successStepId: number; public successStepId: number;
public failStepId: number; public failStepId: number;
public command: string; public command: string;
@@ -102,27 +101,27 @@ export class JobStepData implements IAgentDialogData {
stepData.jobId = jobStepInfo.jobId; stepData.jobId = jobStepInfo.jobId;
stepData.jobName = jobStepInfo.jobName; stepData.jobName = jobStepInfo.jobName;
stepData.script = jobStepInfo.script; stepData.script = jobStepInfo.script;
stepData.scriptName = jobStepInfo.scriptName; stepData.scriptName = jobStepInfo.scriptName,
stepData.stepName = jobStepInfo.stepName; stepData.stepName = jobStepInfo.stepName,
stepData.subSystem = jobStepInfo.subSystem; stepData.subSystem = jobStepInfo.subSystem,
stepData.id = jobStepInfo.id; stepData.id = jobStepInfo.id,
stepData.failureAction = jobStepInfo.failureAction; stepData.failureAction = jobStepInfo.failureAction,
stepData.successAction = jobStepInfo.successAction; stepData.successAction = jobStepInfo.successAction,
stepData.failStepId = jobStepInfo.failStepId; stepData.failStepId = jobStepInfo.failStepId,
stepData.successStepId = jobStepInfo.successStepId; stepData.successStepId = jobStepInfo.successStepId,
stepData.command = jobStepInfo.command; stepData.command = jobStepInfo.command,
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode; stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
stepData.databaseName = jobStepInfo.databaseName; stepData.databaseName = jobStepInfo.databaseName,
stepData.databaseUserName = jobStepInfo.databaseUserName; stepData.databaseUserName = jobStepInfo.databaseUserName,
stepData.server = jobStepInfo.server; stepData.server = jobStepInfo.server,
stepData.outputFileName = jobStepInfo.outputFileName; stepData.outputFileName = jobStepInfo.outputFileName,
stepData.appendToLogFile = jobStepInfo.appendToLogFile; stepData.appendToLogFile = jobStepInfo.appendToLogFile,
stepData.appendToStepHist = jobStepInfo.appendToStepHist; stepData.appendToStepHist = jobStepInfo.appendToStepHist,
stepData.writeLogToTable = jobStepInfo.writeLogToTable; stepData.writeLogToTable = jobStepInfo.writeLogToTable,
stepData.appendLogToTable = jobStepInfo.appendLogToTable; stepData.appendLogToTable = jobStepInfo.appendLogToTable,
stepData.retryAttempts = jobStepInfo.retryAttempts; stepData.retryAttempts = jobStepInfo.retryAttempts,
stepData.retryInterval = jobStepInfo.retryInterval; stepData.retryInterval = jobStepInfo.retryInterval,
stepData.proxyName = jobStepInfo.proxyName; stepData.proxyName = jobStepInfo.proxyName;
stepData.dialogMode = AgentDialogMode.EDIT; stepData.dialogMode = AgentDialogMode.EDIT;
stepData.viaJobDialog = true; stepData.viaJobDialog = true;
return stepData; return stepData;
@@ -158,115 +157,4 @@ export class JobStepData implements IAgentDialogData {
return result; return result;
} }
public static convertToAgentSubSystem(subSystemDisplayName: string): azdata.AgentSubSystem {
switch (subSystemDisplayName) {
case (JobStepDialog.TSQLScript): {
return azdata.AgentSubSystem.TransactSql;
}
case (JobStepDialog.Powershell): {
return azdata.AgentSubSystem.PowerShell;
}
case (JobStepDialog.CmdExec): {
return azdata.AgentSubSystem.CmdExec;
}
case (JobStepDialog.ReplicationDistributor): {
return azdata.AgentSubSystem.Distribution;
}
case (JobStepDialog.ReplicationMerge): {
return azdata.AgentSubSystem.Merge;
}
case (JobStepDialog.ReplicationQueueReader): {
return azdata.AgentSubSystem.QueueReader;
}
case (JobStepDialog.ReplicationSnapshot): {
return azdata.AgentSubSystem.Snapshot;
}
case (JobStepDialog.ReplicationTransactionLogReader): {
return azdata.AgentSubSystem.LogReader;
}
case (JobStepDialog.AnalysisServicesCommand): {
return azdata.AgentSubSystem.AnalysisCommands;
}
case (JobStepDialog.AnalysisServicesQuery): {
return azdata.AgentSubSystem.AnalysisQuery;
}
case (JobStepDialog.ServicesPackage): {
return azdata.AgentSubSystem.Ssis;
}
default:
return azdata.AgentSubSystem.TransactSql;
}
}
public static convertToSubSystemDisplayName(subSystem: azdata.AgentSubSystem): string {
switch (subSystem) {
case (azdata.AgentSubSystem.TransactSql): {
return JobStepDialog.TSQLScript;
}
case (azdata.AgentSubSystem.PowerShell): {
return JobStepDialog.Powershell;
}
case (azdata.AgentSubSystem.CmdExec): {
return JobStepDialog.CmdExec;
}
case (azdata.AgentSubSystem.Distribution): {
return JobStepDialog.ReplicationDistributor;
}
case (azdata.AgentSubSystem.Merge): {
return JobStepDialog.ReplicationMerge;
}
case (azdata.AgentSubSystem.QueueReader): {
return JobStepDialog.ReplicationQueueReader;
}
case (azdata.AgentSubSystem.Snapshot): {
return JobStepDialog.ReplicationSnapshot;
}
case (azdata.AgentSubSystem.LogReader): {
return JobStepDialog.ReplicationTransactionLogReader;
}
case (azdata.AgentSubSystem.AnalysisCommands): {
return JobStepDialog.AnalysisServicesCommand;
}
case (azdata.AgentSubSystem.AnalysisQuery): {
return JobStepDialog.AnalysisServicesQuery;
}
case (azdata.AgentSubSystem.Ssis): {
return JobStepDialog.ServicesPackage;
}
default:
return JobStepDialog.TSQLScript;
}
}
public static convertToStepCompletionAction(actionDisplayName: string): azdata.StepCompletionAction {
switch (actionDisplayName) {
case (JobStepDialog.NextStep): {
return azdata.StepCompletionAction.GoToNextStep;
}
case (JobStepDialog.QuitJobReportingSuccess): {
return azdata.StepCompletionAction.QuitWithSuccess;
}
case (JobStepDialog.QuitJobReportingFailure): {
return azdata.StepCompletionAction.QuitWithFailure;
}
default:
return azdata.StepCompletionAction.GoToNextStep;
}
}
public static convertToCompletionActionDisplayName(stepCompletionAction: azdata.StepCompletionAction): string {
switch (stepCompletionAction) {
case (azdata.StepCompletionAction.GoToNextStep): {
return JobStepDialog.NextStep;
}
case (azdata.StepCompletionAction.QuitWithFailure): {
return JobStepDialog.QuitJobReportingFailure;
}
case (azdata.StepCompletionAction.QuitWithSuccess): {
return JobStepDialog.QuitJobReportingSuccess;
}
default:
return JobStepDialog.NextStep;
}
}
} }

View File

@@ -20,16 +20,11 @@ export class PickScheduleData implements IAgentDialogData {
this.jobName = jobName; this.jobName = jobName;
} }
public async initialize(): Promise<azdata.AgentJobScheduleInfo[]> { public async initialize() {
let agentService = await AgentUtils.getAgentService(); let agentService = await AgentUtils.getAgentService();
try { let result = await agentService.getJobSchedules(this.ownerUri);
let result = await agentService.getJobSchedules(this.ownerUri); if (result && result.success) {
if (result && result.success) { this.schedules = result.schedules;
this.schedules = result.schedules;
return this.schedules;
}
} catch (error) {
throw error;
} }
} }

View File

@@ -17,7 +17,6 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
private static readonly CancelButtonText: string = localize('agentDialog.Cancel', 'Cancel'); private static readonly CancelButtonText: string = localize('agentDialog.Cancel', 'Cancel');
protected _onSuccess: vscode.EventEmitter<T> = new vscode.EventEmitter<T>(); protected _onSuccess: vscode.EventEmitter<T> = new vscode.EventEmitter<T>();
protected _isOpen: boolean = false;
public readonly onSuccess: vscode.Event<T> = this._onSuccess.event; public readonly onSuccess: vscode.Event<T> = this._onSuccess.event;
public dialog: azdata.window.Dialog; public dialog: azdata.window.Dialog;
@@ -36,34 +35,29 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
protected abstract async initializeDialog(dialog: azdata.window.Dialog); protected abstract async initializeDialog(dialog: azdata.window.Dialog);
public async openDialog(dialogName?: string) { public async openDialog(dialogName?: string) {
if (!this._isOpen) { let event = dialogName ? dialogName : null;
this._isOpen = true; this.dialog = azdata.window.createModelViewDialog(this.title, event);
let event = dialogName ? dialogName : null;
this.dialog = azdata.window.createModelViewDialog(this.title, event);
await this.model.initialize(); await this.model.initialize();
await this.initializeDialog(this.dialog); await this.initializeDialog(this.dialog);
this.dialog.okButton.label = AgentDialog.OkButtonText; this.dialog.okButton.label = AgentDialog.OkButtonText;
this.dialog.okButton.onClick(async () => await this.execute()); this.dialog.okButton.onClick(async () => await this.execute());
this.dialog.cancelButton.label = AgentDialog.CancelButtonText; this.dialog.cancelButton.label = AgentDialog.CancelButtonText;
this.dialog.cancelButton.onClick(async () => await this.cancel()); this.dialog.cancelButton.onClick(async () => await this.cancel());
azdata.window.openDialog(this.dialog); azdata.window.openDialog(this.dialog);
}
} }
protected async execute() { protected async execute() {
this.updateModel(); this.updateModel();
await this.model.save(); await this.model.save();
this._isOpen = false;
this._onSuccess.fire(this.model); this._onSuccess.fire(this.model);
} }
protected async cancel() { protected async cancel() {
this._isOpen = false;
} }
protected getActualConditionValue(checkbox: azdata.CheckBoxComponent, dropdown: azdata.DropDownComponent): azdata.JobCompletionActionCondition { protected getActualConditionValue(checkbox: azdata.CheckBoxComponent, dropdown: azdata.DropDownComponent): azdata.JobCompletionActionCondition {
@@ -83,8 +77,4 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
} }
} }
} }
public get isOpen(): boolean {
return this._isOpen;
}
} }

View File

@@ -169,9 +169,6 @@ export class JobDialog extends AgentDialog<JobData> {
this.nameTextBox.onTextChanged(() => { this.nameTextBox.onTextChanged(() => {
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) { if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
this.dialog.message = null; this.dialog.message = null;
// Change the job name immediately since steps
// depends on the job name
this.model.name = this.nameTextBox.value;
} }
}); });
this.ownerTextBox = view.modelBuilder.inputBox().component(); this.ownerTextBox = view.modelBuilder.inputBox().component();
@@ -232,7 +229,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.StepsTable_FailureColumnString this.StepsTable_FailureColumnString
], ],
data: data, data: data,
height: 500 height: 650
}).component(); }).component();
this.startStepDropdown = view.modelBuilder.dropDown().withProperties({ width: 180 }).component(); this.startStepDropdown = view.modelBuilder.dropDown().withProperties({ width: 180 }).component();
@@ -245,14 +242,12 @@ export class JobDialog extends AgentDialog<JobData> {
this.moveStepUpButton = view.modelBuilder.button() this.moveStepUpButton = view.modelBuilder.button()
.withProperties({ .withProperties({
label: this.MoveStepUpButtonString, label: this.MoveStepUpButtonString,
title: this.MoveStepUpButtonString,
width: 120 width: 120
}).component(); }).component();
this.moveStepDownButton = view.modelBuilder.button() this.moveStepDownButton = view.modelBuilder.button()
.withProperties({ .withProperties({
label: this.MoveStepDownButtonString, label: this.MoveStepDownButtonString,
title: this.MoveStepDownButtonString,
width: 120 width: 120
}).component(); }).component();
@@ -261,7 +256,6 @@ export class JobDialog extends AgentDialog<JobData> {
this.newStepButton = view.modelBuilder.button().withProperties({ this.newStepButton = view.modelBuilder.button().withProperties({
label: this.NewStepButtonString, label: this.NewStepButtonString,
title: this.NewStepButtonString,
width: 140 width: 140
}).component(); }).component();
@@ -289,13 +283,11 @@ export class JobDialog extends AgentDialog<JobData> {
this.editStepButton = view.modelBuilder.button().withProperties({ this.editStepButton = view.modelBuilder.button().withProperties({
label: this.EditStepButtonString, label: this.EditStepButtonString,
title: this.EditStepButtonString,
width: 140 width: 140
}).component(); }).component();
this.deleteStepButton = view.modelBuilder.button().withProperties({ this.deleteStepButton = view.modelBuilder.button().withProperties({
label: this.DeleteStepButtonString, label: this.DeleteStepButtonString,
title: this.DeleteStepButtonString,
width: 140 width: 140
}).component(); }).component();
@@ -659,9 +651,9 @@ export class JobDialog extends AgentDialog<JobData> {
let cols = []; let cols = [];
cols.push(jobStep.id); cols.push(jobStep.id);
cols.push(jobStep.stepName); cols.push(jobStep.stepName);
cols.push(JobStepData.convertToSubSystemDisplayName(jobStep.subSystem)); cols.push(jobStep.subSystem);
cols.push(JobStepData.convertToCompletionActionDisplayName(jobStep.successAction)); cols.push(jobStep.successAction);
cols.push(JobStepData.convertToCompletionActionDisplayName(jobStep.failureAction)); cols.push(jobStep.failureAction);
result.push(cols); result.push(cols);
}); });
return result; return result;
@@ -708,11 +700,6 @@ export class JobDialog extends AgentDialog<JobData> {
this.model.jobSteps = []; this.model.jobSteps = [];
} }
this.model.jobSteps = this.steps; this.model.jobSteps = this.steps;
// Change the last step's success action to quit because the
// default is "Go To Next Step"
if (this.model.jobSteps.length > 0) {
this.model.jobSteps[this.model.jobSteps.length - 1].successAction = azdata.StepCompletionAction.QuitWithSuccess;
}
if (!this.model.jobSchedules) { if (!this.model.jobSchedules) {
this.model.jobSchedules = []; this.model.jobSchedules = [];
} }

View File

@@ -60,23 +60,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
private readonly AllFilesLabelString: string = localize('jobStepDialog.allFiles', 'All Files (*)'); private readonly AllFilesLabelString: string = localize('jobStepDialog.allFiles', 'All Files (*)');
// Dropdown options // Dropdown options
public static readonly TSQLScript: string = localize('jobStepDialog.TSQL', 'Transact-SQL script (T-SQL)'); private readonly TSQLScript: string = localize('jobStepDialog.TSQL', 'Transact-SQL script (T-SQL)');
public static readonly Powershell: string = localize('jobStepDialog.powershell', 'PowerShell'); private readonly Powershell: string = localize('jobStepDialog.powershell', 'PowerShell');
public static readonly CmdExec: string = localize('jobStepDialog.CmdExec', 'Operating system (CmdExec)'); private readonly CmdExec: string = localize('jobStepDialog.CmdExec', 'Operating system (CmdExec)');
public static readonly ReplicationDistributor: string = localize('jobStepDialog.replicationDistribution', 'Replication Distributor'); private readonly AgentServiceAccount: string = localize('jobStepDialog.agentServiceAccount', 'SQL Server Agent Service Account');
public static readonly ReplicationMerge: string = localize('jobStepDialog.replicationMerge', 'Replication Merge'); private readonly NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step');
public static readonly ReplicationQueueReader: string = localize('jobStepDialog.replicationQueueReader', 'Replication Queue Reader'); private readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
public static readonly ReplicationSnapshot: string = localize('jobStepDialog.replicationSnapshot', 'Replication Snapshot'); private readonly QuitJobReportingFailure: string = localize('jobStepDialog.quitJobFailure', 'Quit the job reporting failure');
public static readonly ReplicationTransactionLogReader: string = localize('jobStepDialog.replicationTransactionLogReader', 'Replication Transaction-Log Reader');
public static readonly AnalysisServicesCommand: string = localize('jobStepDialog.analysisCommand', 'SQL Server Analysis Services Command');
public static readonly AnalysisServicesQuery: string = localize('jobStepDialog.analysisQuery', 'SQL Server Analysis Services Query');
public static readonly ServicesPackage: string = localize('jobStepDialog.servicesPackage', 'SQL Server Integration Service Package');
public static readonly AgentServiceAccount: string = localize('jobStepDialog.agentServiceAccount', 'SQL Server Agent Service Account');
public static readonly NextStep: string = localize('jobStepDialog.nextStep', 'Go to the next step');
public static readonly QuitJobReportingSuccess: string = localize('jobStepDialog.quitJobSuccess', 'Quit the job reporting success');
public static readonly QuitJobReportingFailure: string = localize('jobStepDialog.quitJobFailure', 'Quit the job reporting failure');
// Event Name strings // Event Name strings
private readonly NewStepDialog = 'NewStepDialogOpened'; private readonly NewStepDialog = 'NewStepDialogOpened';
@@ -157,14 +147,12 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.openButton = view.modelBuilder.button() this.openButton = view.modelBuilder.button()
.withProperties({ .withProperties({
label: this.OpenCommandText, label: this.OpenCommandText,
title: this.OpenCommandText,
width: '80px', width: '80px',
isFile: true isFile: true
}).component(); }).component();
this.parseButton = view.modelBuilder.button() this.parseButton = view.modelBuilder.button()
.withProperties({ .withProperties({
label: this.ParseCommandText, label: this.ParseCommandText,
title: this.ParseCommandText,
width: '80px', width: '80px',
isFile: false isFile: false
}).component(); }).component();
@@ -188,9 +176,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
height: 300, height: 300,
width: 400, width: 400,
multiline: true, multiline: true,
inputType: 'text', inputType: 'text'
ariaLabel: this.CommandLabelString,
placeHolder: this.CommandLabelString
}) })
.component(); .component();
} }
@@ -199,8 +185,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.generalTab.registerContent(async (view) => { this.generalTab.registerContent(async (view) => {
this.nameTextBox = view.modelBuilder.inputBox() this.nameTextBox = view.modelBuilder.inputBox()
.withProperties({ .withProperties({
ariaLabel: this.StepNameLabelString,
placeHolder: this.StepNameLabelString
}).component(); }).component();
this.nameTextBox.required = true; this.nameTextBox.required = true;
this.nameTextBox.onTextChanged(() => { this.nameTextBox.onTextChanged(() => {
@@ -211,8 +195,8 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.typeDropdown = view.modelBuilder.dropDown() this.typeDropdown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
value: JobStepDialog.TSQLScript, value: this.TSQLScript,
values: [JobStepDialog.TSQLScript, JobStepDialog.CmdExec, JobStepDialog.Powershell] values: [this.TSQLScript, this.CmdExec, this.Powershell]
}) })
.component(); .component();
this.runAsDropdown = view.modelBuilder.dropDown() this.runAsDropdown = view.modelBuilder.dropDown()
@@ -230,8 +214,6 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.processExitCodeBox = view.modelBuilder.inputBox() this.processExitCodeBox = view.modelBuilder.inputBox()
.withProperties({ .withProperties({
ariaLabel: this.ProcessExitCodeText,
placeHolder: this.ProcessExitCodeText
}).component(); }).component();
this.processExitCodeBox.enabled = false; this.processExitCodeBox.enabled = false;
@@ -264,7 +246,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
}).component(); }).component();
this.typeDropdown.onValueChanged((type) => { this.typeDropdown.onValueChanged((type) => {
switch (type.selected) { switch (type.selected) {
case (JobStepDialog.TSQLScript): case (this.TSQLScript):
this.runAsDropdown.value = ''; this.runAsDropdown.value = '';
this.runAsDropdown.values = ['']; this.runAsDropdown.values = [''];
this.runAsDropdown.enabled = false; this.runAsDropdown.enabled = false;
@@ -274,8 +256,8 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.processExitCodeBox.value = ''; this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false; this.processExitCodeBox.enabled = false;
break; break;
case (JobStepDialog.Powershell): case (this.Powershell):
this.runAsDropdown.value = JobStepDialog.AgentServiceAccount; this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value]; this.runAsDropdown.values = [this.runAsDropdown.value];
this.runAsDropdown.enabled = true; this.runAsDropdown.enabled = true;
this.databaseDropdown.enabled = false; this.databaseDropdown.enabled = false;
@@ -284,11 +266,11 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.processExitCodeBox.value = ''; this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false; this.processExitCodeBox.enabled = false;
break; break;
case (JobStepDialog.CmdExec): case (this.CmdExec):
this.databaseDropdown.enabled = false; this.databaseDropdown.enabled = false;
this.databaseDropdown.values = ['']; this.databaseDropdown.values = [''];
this.databaseDropdown.value = ''; this.databaseDropdown.value = '';
this.runAsDropdown.value = JobStepDialog.AgentServiceAccount; this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value]; this.runAsDropdown.values = [this.runAsDropdown.value];
this.runAsDropdown.enabled = true; this.runAsDropdown.enabled = true;
this.processExitCodeBox.enabled = true; this.processExitCodeBox.enabled = true;
@@ -304,7 +286,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
// Load values for edit scenario // Load values for edit scenario
if (this.isEdit) { if (this.isEdit) {
this.nameTextBox.value = this.model.stepName; this.nameTextBox.value = this.model.stepName;
this.typeDropdown.value = JobStepData.convertToSubSystemDisplayName(this.model.subSystem); this.typeDropdown.value = this.model.subSystem;
this.databaseDropdown.value = this.model.databaseName; this.databaseDropdown.value = this.model.databaseName;
this.commandTextBox.value = this.model.command; this.commandTextBox.value = this.model.command;
} }
@@ -316,16 +298,16 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.successActionDropdown = view.modelBuilder.dropDown() this.successActionDropdown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
width: '100%', width: '100%',
value: JobStepDialog.NextStep, value: this.NextStep,
values: [JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess, JobStepDialog.QuitJobReportingFailure] values: [this.NextStep, this.QuitJobReportingSuccess, this.QuitJobReportingFailure]
}) })
.component(); .component();
let retryFlexContainer = this.createRetryCounters(view); let retryFlexContainer = this.createRetryCounters(view);
this.failureActionDropdown = view.modelBuilder.dropDown() this.failureActionDropdown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
value: JobStepDialog.QuitJobReportingFailure, value: this.QuitJobReportingFailure,
values: [JobStepDialog.QuitJobReportingFailure, JobStepDialog.NextStep, JobStepDialog.QuitJobReportingSuccess] values: [this.QuitJobReportingFailure, this.NextStep, this.QuitJobReportingSuccess]
}) })
.component(); .component();
let optionsGroup = this.createTSQLOptions(view); let optionsGroup = this.createTSQLOptions(view);
@@ -361,7 +343,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
title: this.FailureActionLabel title: this.FailureActionLabel
}, { }, {
component: optionsGroup, component: optionsGroup,
title: JobStepDialog.TSQLScript title: this.TSQLScript
}, { }, {
component: logToTableContainer, component: logToTableContainer,
title: '' title: ''
@@ -383,10 +365,10 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
await view.initializeModel(formWrapper); await view.initializeModel(formWrapper);
if (this.isEdit) { if (this.isEdit) {
this.successActionDropdown.value = JobStepData.convertToCompletionActionDisplayName(this.model.successAction); this.successActionDropdown.value = this.model.successAction;
this.retryAttemptsBox.value = this.model.retryAttempts.toString(); this.retryAttemptsBox.value = this.model.retryAttempts.toString();
this.retryIntervalBox.value = this.model.retryInterval.toString(); this.retryIntervalBox.value = this.model.retryInterval.toString();
this.failureActionDropdown.value = JobStepData.convertToCompletionActionDisplayName(this.model.failureAction); this.failureActionDropdown.value = this.model.failureAction;
this.outputFileNameBox.value = this.model.outputFileName; this.outputFileNameBox.value = this.model.outputFileName;
this.appendToExistingFileCheckbox.checked = this.model.appendToLogFile; this.appendToExistingFileCheckbox.checked = this.model.appendToLogFile;
this.logToTableCheckbox.checked = this.model.appendLogToTable; this.logToTableCheckbox.checked = this.model.appendLogToTable;
@@ -545,13 +527,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.model.jobName = this.jobName; this.model.jobName = this.jobName;
this.model.id = this.stepId; this.model.id = this.stepId;
this.model.server = this.server; this.model.server = this.server;
this.model.subSystem = JobStepData.convertToAgentSubSystem(this.typeDropdown.value as string); this.model.subSystem = this.typeDropdown.value as string;
this.model.databaseName = this.databaseDropdown.value as string; this.model.databaseName = this.databaseDropdown.value as string;
this.model.script = this.commandTextBox.value; this.model.script = this.commandTextBox.value;
this.model.successAction = JobStepData.convertToStepCompletionAction(this.successActionDropdown.value as string); this.model.successAction = this.successActionDropdown.value as string;
this.model.retryAttempts = this.retryAttemptsBox.value ? +this.retryAttemptsBox.value : 0; this.model.retryAttempts = this.retryAttemptsBox.value ? +this.retryAttemptsBox.value : 0;
this.model.retryInterval = +this.retryIntervalBox.value ? +this.retryIntervalBox.value : 0; this.model.retryInterval = +this.retryIntervalBox.value ? +this.retryIntervalBox.value : 0;
this.model.failureAction = JobStepData.convertToStepCompletionAction(this.failureActionDropdown.value as string); this.model.failureAction = this.failureActionDropdown.value as string;
this.model.outputFileName = this.outputFileNameBox.value; this.model.outputFileName = this.outputFileNameBox.value;
this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked; this.model.appendToLogFile = this.appendToExistingFileCheckbox.checked;
this.model.command = this.commandTextBox.value ? this.commandTextBox.value : ''; this.model.command = this.commandTextBox.value ? this.commandTextBox.value : '';

View File

@@ -96,21 +96,12 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
private initializeGeneralTab() { private initializeGeneralTab() {
this.generalTab.registerContent(async view => { this.generalTab.registerContent(async view => {
this.nameTextBox = view.modelBuilder.inputBox().withProperties({ this.nameTextBox = view.modelBuilder.inputBox().component();
ariaLabel: OperatorDialog.NameLabel,
placeHolder: OperatorDialog.NameLabel
}).component();
this.nameTextBox.value = this.model.name; this.nameTextBox.value = this.model.name;
this.emailNameTextBox = view.modelBuilder.inputBox().withProperties({ this.emailNameTextBox = view.modelBuilder.inputBox().component();
ariaLabel: OperatorDialog.EmailNameTextLabel,
placeHolder: OperatorDialog.EmailNameTextLabel
}).component();
this.emailNameTextBox.value = this.model.emailAddress; this.emailNameTextBox.value = this.model.emailAddress;
this.pagerEmailNameTextBox = view.modelBuilder.inputBox().withProperties({ this.pagerEmailNameTextBox = view.modelBuilder.inputBox().component();
ariaLabel: OperatorDialog.PagerEmailNameTextLabel,
placeHolder: OperatorDialog.PagerEmailNameTextLabel
}).component();
this.pagerEmailNameTextBox.value = this.model.pagerAddress; this.pagerEmailNameTextBox.value = this.model.pagerAddress;
this.enabledCheckBox = view.modelBuilder.checkBox() this.enabledCheckBox = view.modelBuilder.checkBox()

View File

@@ -27,7 +27,6 @@ export class PickScheduleDialog {
// UI Components // UI Components
private dialog: azdata.window.Dialog; private dialog: azdata.window.Dialog;
private schedulesTable: azdata.TableComponent; private schedulesTable: azdata.TableComponent;
private loadingComponent: azdata.LoadingComponent;
private model: PickScheduleData; private model: PickScheduleData;
@@ -39,17 +38,7 @@ export class PickScheduleDialog {
} }
public async showDialog() { public async showDialog() {
this.model.initialize().then((result) => { await this.model.initialize();
this.loadingComponent.loading = false;
if (this.model.schedules) {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [schedule.id, schedule.name, schedule.description];
}
this.schedulesTable.data = data;
}
});
this.dialog = azdata.window.createModelViewDialog(this.DialogTitle); this.dialog = azdata.window.createModelViewDialog(this.DialogTitle);
this.initializeContent(); this.initializeContent();
this.dialog.okButton.onClick(async () => await this.execute()); this.dialog.okButton.onClick(async () => await this.execute());
@@ -79,9 +68,16 @@ export class PickScheduleDialog {
title: this.SchedulesLabelText title: this.SchedulesLabelText
}]).withLayout({ width: '100%' }).component(); }]).withLayout({ width: '100%' }).component();
this.loadingComponent = view.modelBuilder.loadingComponent().withItem(formModel).component(); await view.initializeModel(formModel);
this.loadingComponent.loading = true;
await view.initializeModel(this.loadingComponent); if (this.model.schedules) {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [schedule.id, schedule.name, schedule.description];
}
this.schedulesTable.data = data;
}
}); });
} }

View File

@@ -84,11 +84,8 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
this.generalTab.registerContent(async view => { this.generalTab.registerContent(async view => {
this.proxyNameTextBox = view.modelBuilder.inputBox() this.proxyNameTextBox = view.modelBuilder.inputBox()
.withProperties({ .withProperties({ width: 420 })
width: 420, .component();
ariaLabel: ProxyDialog.ProxyNameTextBoxLabel,
placeHolder: ProxyDialog.ProxyNameTextBoxLabel
}).component();
this.credentialNameDropDown = view.modelBuilder.dropDown() this.credentialNameDropDown = view.modelBuilder.dropDown()
.withProperties({ .withProperties({
@@ -103,10 +100,9 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
.withProperties({ .withProperties({
width: 420, width: 420,
multiline: true, multiline: true,
height: 300, height: 300
ariaLabel: ProxyDialog.DescriptionTextBoxLabel, })
placeHolder: ProxyDialog.DescriptionTextBoxLabel .component();
}).component();
this.subsystemCheckBox = view.modelBuilder.checkBox() this.subsystemCheckBox = view.modelBuilder.checkBox()
.withProperties({ .withProperties({

View File

@@ -22,13 +22,7 @@ const localize = nls.loadMessageBundle();
* The main controller class that initializes the extension * The main controller class that initializes the extension
*/ */
export class MainController { export class MainController {
protected _context: vscode.ExtensionContext; protected _context: vscode.ExtensionContext;
private jobDialog: JobDialog;
private jobStepDialog: JobStepDialog;
private alertDialog: AlertDialog;
private operatorDialog: OperatorDialog;
private proxyDialog: ProxyDialog;
// PUBLIC METHODS ////////////////////////////////////////////////////// // PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext) { public constructor(context: vscode.ExtensionContext) {
@@ -45,12 +39,8 @@ export class MainController {
*/ */
public activate(): void { public activate(): void {
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => { vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
if (!this.jobDialog || (this.jobDialog && !this.jobDialog.isOpen)) { let dialog = new JobDialog(ownerUri, jobInfo);
this.jobDialog = new JobDialog(ownerUri, jobInfo); dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
}
if (!this.jobDialog.isOpen) {
this.jobDialog.dialogName ? await this.jobDialog.openDialog(this.jobDialog.dialogName) : await this.jobDialog.openDialog();
}
}); });
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => { vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
AgentUtils.getAgentService().then(async (agentService) => { AgentUtils.getAgentService().then(async (agentService) => {
@@ -63,33 +53,20 @@ export class MainController {
let dialog = new PickScheduleDialog(ownerUri, jobName); let dialog = new PickScheduleDialog(ownerUri, jobName);
await dialog.showDialog(); await dialog.showDialog();
}); });
vscode.commands.registerCommand('agent.openAlertDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => { vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
if (!this.alertDialog || (this.alertDialog && !this.alertDialog.isOpen)) { AgentUtils.getAgentService().then(async (agentService) => {
await AgentUtils.getAgentService().then(async (agentService) => { let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService); let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
this.alertDialog = new AlertDialog(ownerUri, jobData, alertInfo, false); dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
}); });
}
if (!this.alertDialog.isOpen) {
this.alertDialog.dialogName ? await this.alertDialog.openDialog(this.alertDialog.dialogName) : await this.alertDialog.openDialog();
}
}); });
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => { vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
if (!this.operatorDialog || (this.operatorDialog && !this.operatorDialog.isOpen)) { let dialog = new OperatorDialog(ownerUri, operatorInfo);
this.operatorDialog = new OperatorDialog(ownerUri, operatorInfo); dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
}
if (!this.operatorDialog.isOpen) {
this.operatorDialog.dialogName ? await this.operatorDialog.openDialog(this.operatorDialog.dialogName) : await this.operatorDialog.openDialog();
}
}); });
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => { vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
if (!this.proxyDialog || (this.proxyDialog && !this.proxyDialog.isOpen)) { let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
this.proxyDialog = new ProxyDialog(ownerUri, proxyInfo, credentials); dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
}
if (!this.proxyDialog.isOpen) {
this.proxyDialog.dialogName ? await this.proxyDialog.openDialog(this.proxyDialog.dialogName) : await this.proxyDialog.openDialog();
}
this.proxyDialog.dialogName ? await this.proxyDialog.openDialog(this.proxyDialog.dialogName) : await this.proxyDialog.openDialog();
}); });
} }

View File

@@ -1,39 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 'mocha';
import * as should from 'should';
import { AgentSubSystem } from 'azdata';
import { JobStepDialog } from '../../dialogs/jobStepDialog';
import { JobStepData } from '../../data/jobStepData';
const subSytems: AgentSubSystem[] = [AgentSubSystem.TransactSql, AgentSubSystem.PowerShell,
AgentSubSystem.CmdExec, AgentSubSystem.Distribution, AgentSubSystem.Merge,
AgentSubSystem.QueueReader, AgentSubSystem.Snapshot, AgentSubSystem.LogReader, AgentSubSystem.AnalysisCommands,
AgentSubSystem.AnalysisQuery, AgentSubSystem.Ssis];
const subSystemDisplayNames: string[] = [JobStepDialog.TSQLScript, JobStepDialog.Powershell,
JobStepDialog.CmdExec, JobStepDialog.ReplicationDistributor, JobStepDialog.ReplicationMerge,
JobStepDialog.ReplicationQueueReader, JobStepDialog.ReplicationSnapshot, JobStepDialog.ReplicationTransactionLogReader,
JobStepDialog.AnalysisServicesCommand, JobStepDialog.AnalysisServicesQuery, JobStepDialog.ServicesPackage];
describe('Agent extension enum mapping sanity test', function (): void {
it('SubSystem to Display Name Mapping test', () => {
for (let i = 0; i < subSytems.length; i++) {
let subSystem = subSytems[i];
let convertedSubSystemName = JobStepData.convertToSubSystemDisplayName(subSystem);
should.equal(convertedSubSystemName, subSystemDisplayNames[i]);
}
});
it('SubSystem Display Name to SubSystem Mapping test', () => {
for (let i = 0; i < subSystemDisplayNames.length; i++) {
let subSystemDisplayName = subSystemDisplayNames[i];
let convertedSubSystem = JobStepData.convertToAgentSubSystem(subSystemDisplayName);
should.equal(convertedSubSystem, subSytems[i]);
}
});
});

View File

@@ -6,7 +6,7 @@
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"engines": { "engines": {
"vscode": "^1.30.1", "vscode": "^1.25.0",
"azdata": "*" "azdata": "*"
}, },
"activationEvents": [ "activationEvents": [
@@ -118,33 +118,6 @@
] ]
}, },
"menus": { "menus": {
"commandPalette": [
{
"command": "azure.resource.signin",
"when": "true"
},
{
"command": "azure.resource.refreshall",
"when": "true"
},
{
"command": "azure.resource.selectsubscriptions",
"when": "false"
},
{
"command": "azure.resource.refresh",
"when": "false"
},
{
"command": "azure.resource.connectsqlserver",
"when": "false"
},
{
"command": "azure.resource.connectsqldb",
"when": "false"
}
],
"view/title": [ "view/title": [
{ {
"command": "azure.resource.signin", "command": "azure.resource.signin",
@@ -196,7 +169,6 @@
"@types/request": "^2.48.1", "@types/request": "^2.48.1",
"mocha": "^5.2.0", "mocha": "^5.2.0",
"should": "^13.2.1", "should": "^13.2.1",
"typemoq": "^2.1.0", "typemoq": "^2.1.0"
"vscode": "1.1.26"
} }
} }

View File

@@ -6,9 +6,9 @@
"azure.resource.config.title": "Azure Resource Configuration", "azure.resource.config.title": "Azure Resource Configuration",
"azure.resource.config.filter.description": "The resource filter, each element is an account id, a subscription id and name separated by a slash", "azure.resource.config.filter.description": "The resource filter, each element is an account id, a subscription id and name separated by a slash",
"azure.resource.explorer.title": "Azure", "azure.resource.explorer.title": "Azure",
"azure.resource.refreshall.title": "Azure: Refresh All Accounts", "azure.resource.refreshall.title": "Refresh All",
"azure.resource.refresh.title": "Refresh", "azure.resource.refresh.title": "Refresh",
"azure.resource.signin.title": "Azure: Sign In", "azure.resource.signin.title": "Sign In",
"azure.resource.selectsubscriptions.title": "Select Subscriptions", "azure.resource.selectsubscriptions.title": "Select Subscriptions",
"azure.resource.connectsqlserver.title": "Connect", "azure.resource.connectsqlserver.title": "Connect",
"azure.resource.connectsqldb.title": "Add to Servers", "azure.resource.connectsqldb.title": "Add to Servers",

View File

@@ -103,16 +103,16 @@ export class AzureAccountProvider implements azdata.AccountProvider {
}); });
} }
public prompt(): Thenable<AzureAccount | azdata.PromptFailedResult> { public prompt(): Thenable<AzureAccount> {
return this.doIfInitialized(() => this.signIn(true)); return this.doIfInitialized(() => this.signIn(true));
} }
public refresh(account: AzureAccount): Thenable<AzureAccount | azdata.PromptFailedResult> { public refresh(account: AzureAccount): Thenable<AzureAccount> {
return this.doIfInitialized(() => this.signIn(false)); return this.doIfInitialized(() => this.signIn(false));
} }
// PRIVATE METHODS ///////////////////////////////////////////////////// // PRIVATE METHODS /////////////////////////////////////////////////////
private cancelAutoOAuth(): Promise<void> { private cancelAutoOAuth(): Thenable<void> {
let self = this; let self = this;
if (!this._inProgressAutoOAuth) { if (!this._inProgressAutoOAuth) {
@@ -137,23 +137,23 @@ export class AzureAccountProvider implements azdata.AccountProvider {
return Promise.resolve(); return Promise.resolve();
} }
private async clearAccountTokens(accountKey: azdata.AccountKey): Promise<void> { private clearAccountTokens(accountKey: azdata.AccountKey): Thenable<void> {
// Put together a query to look up any tokens associated with the account key // Put together a query to look up any tokens associated with the account key
let query = <adal.TokenResponse>{ userId: accountKey.accountId }; let query = <adal.TokenResponse>{ userId: accountKey.accountId };
// 1) Look up the tokens associated with the query // 1) Look up the tokens associated with the query
// 2) Remove them // 2) Remove them
let results = await this._tokenCache.findThenable(query); return this._tokenCache.findThenable(query)
this._tokenCache.removeThenable(results); .then(results => this._tokenCache.removeThenable(results));
} }
private doIfInitialized<T>(op: () => Promise<T>): Promise<T> { private doIfInitialized<T>(op: () => Thenable<T>): Thenable<T> {
return this._isInitialized return this._isInitialized
? op() ? op()
: Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action')); : Promise.reject(localize('accountProviderNotInitialized', 'Account provider not initialized, cannot perform action'));
} }
private getAccessTokens(account: AzureAccount, resource: azdata.AzureResource): Promise<AzureAccountSecurityTokenCollection> { private getAccessTokens(account: AzureAccount, resource: azdata.AzureResource): Thenable<AzureAccountSecurityTokenCollection> {
let self = this; let self = this;
const resourceIdMap = new Map<azdata.AzureResource, string>([ const resourceIdMap = new Map<azdata.AzureResource, string>([
@@ -228,7 +228,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
}); });
} }
private getDeviceLoginToken(oAuth: InProgressAutoOAuth, isAddAccount: boolean): Thenable<adal.TokenResponse | azdata.PromptFailedResult> { private getDeviceLoginToken(oAuth: InProgressAutoOAuth, isAddAccount: boolean): Thenable<adal.TokenResponse> {
let self = this; let self = this;
// 1) Open the auto OAuth dialog // 1) Open the auto OAuth dialog
@@ -239,15 +239,14 @@ export class AzureAccountProvider implements azdata.AccountProvider {
localize('refreshAccount', 'Refresh {0} account', self._metadata.displayName); localize('refreshAccount', 'Refresh {0} account', self._metadata.displayName);
return azdata.accounts.beginAutoOAuthDeviceCode(self._metadata.id, title, oAuth.userCodeInfo.message, oAuth.userCodeInfo.userCode, oAuth.userCodeInfo.verificationUrl) return azdata.accounts.beginAutoOAuthDeviceCode(self._metadata.id, title, oAuth.userCodeInfo.message, oAuth.userCodeInfo.userCode, oAuth.userCodeInfo.verificationUrl)
.then(() => { .then(() => {
return new Promise<adal.TokenResponse | azdata.PromptFailedResult>((resolve, reject) => { return new Promise<adal.TokenResponse>((resolve, reject) => {
let context = oAuth.context; let context = oAuth.context;
context.acquireTokenWithDeviceCode(self._metadata.settings.signInResourceId, self._metadata.settings.clientId, oAuth.userCodeInfo, context.acquireTokenWithDeviceCode(self._metadata.settings.signInResourceId, self._metadata.settings.clientId, oAuth.userCodeInfo,
(err, response) => { (err, response) => {
if (err) { if (err) {
if (self._autoOAuthCancelled) { if (self._autoOAuthCancelled) {
let result: azdata.PromptFailedResult = { canceled: true };
// Auto OAuth was cancelled by the user, indicate this with the error we return // Auto OAuth was cancelled by the user, indicate this with the error we return
resolve(result); reject(<azdata.UserCancelledSignInError>{ userCancelledSignIn: true });
} else { } else {
// Auto OAuth failed for some other reason // Auto OAuth failed for some other reason
azdata.accounts.endAutoOAuthDeviceCode(); azdata.accounts.endAutoOAuthDeviceCode();
@@ -369,73 +368,74 @@ export class AzureAccountProvider implements azdata.AccountProvider {
}); });
} }
private isPromptFailed(value: adal.TokenResponse | azdata.PromptFailedResult): value is azdata.PromptFailedResult { private signIn(isAddAccount: boolean): Thenable<AzureAccount> {
return value && (<azdata.PromptFailedResult>value).canceled; let self = this;
}
private async signIn(isAddAccount: boolean): Promise<AzureAccount | azdata.PromptFailedResult> {
// 1) Get the user code for this login // 1) Get the user code for this login
// 2) Get an access token from the device code // 2) Get an access token from the device code
// 3) Get the list of tenants // 3) Get the list of tenants
// 4) Generate the AzureAccount object and return it // 4) Generate the AzureAccount object and return it
let tokenResponse: adal.TokenResponse = null; let tokenResponse: adal.TokenResponse = null;
let result: InProgressAutoOAuth = await this.getDeviceLoginUserCode(); return this.getDeviceLoginUserCode()
this._autoOAuthCancelled = false; .then((result: InProgressAutoOAuth) => {
this._inProgressAutoOAuth = result; self._autoOAuthCancelled = false;
let response: adal.TokenResponse | azdata.PromptFailedResult = await this.getDeviceLoginToken(this._inProgressAutoOAuth, isAddAccount); self._inProgressAutoOAuth = result;
if (this.isPromptFailed(response)) { return self.getDeviceLoginToken(self._inProgressAutoOAuth, isAddAccount);
return response; })
} .then((response: adal.TokenResponse) => {
tokenResponse = response; tokenResponse = response;
this._autoOAuthCancelled = false; self._autoOAuthCancelled = false;
this._inProgressAutoOAuth = null; self._inProgressAutoOAuth = null;
let tenants: Tenant[] = await this.getTenants(tokenResponse.userId, tokenResponse.userId); return self.getTenants(tokenResponse.userId, tokenResponse.userId);
// Figure out where we're getting the identity from })
let identityProvider = tokenResponse.identityProvider; .then((tenants: Tenant[]) => {
if (identityProvider) { // Figure out where we're getting the identity from
identityProvider = identityProvider.toLowerCase(); let identityProvider = tokenResponse.identityProvider;
} if (identityProvider) {
identityProvider = identityProvider.toLowerCase();
}
// Determine if this is a microsoft account // Determine if this is a microsoft account
let msa = identityProvider && ( let msa = identityProvider && (
identityProvider.indexOf('live.com') !== -1 || identityProvider.indexOf('live.com') !== -1 ||
identityProvider.indexOf('live-int.com') !== -1 || identityProvider.indexOf('live-int.com') !== -1 ||
identityProvider.indexOf('f8cdef31-a31e-4b4a-93e4-5f571e91255a') !== -1 || identityProvider.indexOf('f8cdef31-a31e-4b4a-93e4-5f571e91255a') !== -1 ||
identityProvider.indexOf('ea8a4392-515e-481f-879e-6571ff2a8a36') !== -1); identityProvider.indexOf('ea8a4392-515e-481f-879e-6571ff2a8a36') !== -1);
// Calculate the display name for the user // Calculate the display name for the user
let displayName = (tokenResponse.givenName && tokenResponse.familyName) let displayName = (tokenResponse.givenName && tokenResponse.familyName)
? `${tokenResponse.givenName} ${tokenResponse.familyName}` ? `${tokenResponse.givenName} ${tokenResponse.familyName}`
: tokenResponse.userId; : tokenResponse.userId;
// Calculate the home tenant display name to use for the contextual display name // Calculate the home tenant display name to use for the contextual display name
let contextualDisplayName = msa let contextualDisplayName = msa
? localize('microsoftAccountDisplayName', 'Microsoft Account') ? localize('microsoftAccountDisplayName', 'Microsoft Account')
: tenants[0].displayName; : tenants[0].displayName;
// Calculate the account type // Calculate the account type
let accountType = msa let accountType = msa
? AzureAccountProvider.MicrosoftAccountType ? AzureAccountProvider.MicrosoftAccountType
: AzureAccountProvider.WorkSchoolAccountType; : AzureAccountProvider.WorkSchoolAccountType;
return <AzureAccount>{ return <AzureAccount>{
key: { key: {
providerId: this._metadata.id, providerId: self._metadata.id,
accountId: tokenResponse.userId accountId: tokenResponse.userId
}, },
name: tokenResponse.userId, name: tokenResponse.userId,
displayInfo: { displayInfo: {
accountType: accountType, accountType: accountType,
userId: tokenResponse.userId, userId: tokenResponse.userId,
contextualDisplayName: contextualDisplayName, contextualDisplayName: contextualDisplayName,
displayName: displayName displayName: displayName
}, },
properties: { properties: {
isMsAccount: msa, isMsAccount: msa,
tenants: tenants tenants: tenants
}, },
isStale: false isStale: false
}; };
});
} }
} }

View File

@@ -16,7 +16,6 @@ export enum AzureResourceItemType {
} }
export enum AzureResourceServiceNames { export enum AzureResourceServiceNames {
resourceService = 'AzureResourceService',
cacheService = 'AzureResourceCacheService', cacheService = 'AzureResourceCacheService',
accountService = 'AzureResourceAccountService', accountService = 'AzureResourceAccountService',
subscriptionService = 'AzureResourceSubscriptionService', subscriptionService = 'AzureResourceSubscriptionService',

View File

@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import { AzureResource, ExtensionNodeType } from 'azdata'; import { AzureResource } from 'azdata';
import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode'; import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from 'ms-rest';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
@@ -72,8 +72,7 @@ export class AzureResourceDatabaseTreeDataProvider implements azureResource.IAzu
saveProfile: false, saveProfile: false,
options: {} options: {}
}, },
childProvider: 'MSSQL', childProvider: 'MSSQL'
type: ExtensionNodeType.Database
} }
}); });
} }

View File

@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import { AzureResource, ExtensionNodeType } from 'azdata'; import { AzureResource } from 'azdata';
import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode'; import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from 'ms-rest';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
@@ -72,8 +72,7 @@ export class AzureResourceDatabaseServerTreeDataProvider implements azureResourc
saveProfile: false, saveProfile: false,
options: {} options: {}
}, },
childProvider: 'MSSQL', childProvider: 'MSSQL'
type: ExtensionNodeType.Server
} }
}); });
} }

View File

@@ -12,11 +12,11 @@ import { azureResource } from './azure-resource';
import { IAzureResourceNodeWithProviderId } from './interfaces'; import { IAzureResourceNodeWithProviderId } from './interfaces';
export class AzureResourceService { export class AzureResourceService {
private _areResourceProvidersLoaded: boolean = false; private constructor() {
private _resourceProviders: { [resourceProviderId: string]: azureResource.IAzureResourceProvider } = {}; }
private _treeDataProviders: { [resourceProviderId: string]: azureResource.IAzureResourceTreeDataProvider } = {};
public constructor() { public static getInstance(): AzureResourceService {
return AzureResourceService._instance;
} }
public async listResourceProviderIds(): Promise<string[]> { public async listResourceProviderIds(): Promise<string[]> {
@@ -121,4 +121,9 @@ export class AzureResourceService {
this._treeDataProviders[resourceProvider.providerId] = resourceProvider.getTreeDataProvider(); this._treeDataProviders[resourceProvider.providerId] = resourceProvider.getTreeDataProvider();
} }
private _areResourceProvidersLoaded: boolean = false;
private _resourceProviders: { [resourceProviderId: string]: azureResource.IAzureResourceProvider } = {};
private _treeDataProviders: { [resourceProviderId: string]: azureResource.IAzureResourceTreeDataProvider } = {};
private static readonly _instance = new AzureResourceService();
} }

View File

@@ -15,19 +15,14 @@ import { AzureResourceService } from './resourceService';
import { IAzureResourceNodeWithProviderId } from './interfaces'; import { IAzureResourceNodeWithProviderId } from './interfaces';
import { AzureResourceMessageTreeNode } from './messageTreeNode'; import { AzureResourceMessageTreeNode } from './messageTreeNode';
import { AzureResourceErrorMessageUtil } from './utils'; import { AzureResourceErrorMessageUtil } from './utils';
import { AppContext } from '../appContext';
import { AzureResourceServiceNames } from './constants';
export class AzureResourceResourceTreeNode extends TreeNode { export class AzureResourceResourceTreeNode extends TreeNode {
private _resourceService: AzureResourceService;
public constructor( public constructor(
public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId, public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId,
parent: TreeNode, parent: TreeNode
private appContext: AppContext
) { ) {
super(); super();
this._resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
this.parent = parent; this.parent = parent;
} }
@@ -41,12 +36,12 @@ export class AzureResourceResourceTreeNode extends TreeNode {
const children = await this._resourceService.getChildren(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode); const children = await this._resourceService.getChildren(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
if (children.length === 0) { if (children.length === 0) {
return [AzureResourceMessageTreeNode.create(localize('azure.resource.resourceTreeNode.noResourcesLabel', 'No Resources found'), this)]; return [AzureResourceMessageTreeNode.create(AzureResourceResourceTreeNode.noResourcesLabel, this)];
} else { } else {
return children.map((child) => { return children.map((child) => {
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered' // To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`; child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`;
return new AzureResourceResourceTreeNode(child, this, this.appContext); return new AzureResourceResourceTreeNode(child, this);
}); });
} }
} catch (error) { } catch (error) {
@@ -78,4 +73,7 @@ export class AzureResourceResourceTreeNode extends TreeNode {
return this.resourceNodeWithProviderId.resourceNode.treeItem.id; return this.resourceNodeWithProviderId.resourceNode.treeItem.id;
} }
private _resourceService = AzureResourceService.getInstance();
private static readonly noResourcesLabel = localize('azure.resource.resourceTreeNode.noResourcesLabel', 'No Resources found.');
} }

View File

@@ -15,7 +15,7 @@ import { azureResource } from '../azure-resource';
import { TreeNode } from '../treeNode'; import { TreeNode } from '../treeNode';
import { IAzureResourceNodeWithProviderId } from '../interfaces'; import { IAzureResourceNodeWithProviderId } from '../interfaces';
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes'; import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceItemType, AzureResourceServiceNames } from '../constants'; import { AzureResourceItemType } from '../constants';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler'; import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
import { AzureResourceMessageTreeNode } from '../messageTreeNode'; import { AzureResourceMessageTreeNode } from '../messageTreeNode';
import { AzureResourceErrorMessageUtil } from '../utils'; import { AzureResourceErrorMessageUtil } from '../utils';
@@ -39,7 +39,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
public async getChildren(): Promise<TreeNode[]> { public async getChildren(): Promise<TreeNode[]> {
try { try {
const resourceService = this.appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService); const resourceService = AzureResourceService.getInstance();
const children: IAzureResourceNodeWithProviderId[] = []; const children: IAzureResourceNodeWithProviderId[] = [];
@@ -53,7 +53,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
return children.map((child) => { return children.map((child) => {
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered' // To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
child.resourceNode.treeItem.id = `${this._id}.${child.resourceNode.treeItem.id}`; child.resourceNode.treeItem.id = `${this._id}.${child.resourceNode.treeItem.id}`;
return new AzureResourceResourceTreeNode(child, this, this.appContext); return new AzureResourceResourceTreeNode(child, this);
}); });
} }
} catch (error) { } catch (error) {

View File

@@ -6,7 +6,7 @@
'use strict'; 'use strict';
import { TreeDataProvider, EventEmitter, Event, TreeItem } from 'vscode'; import { TreeDataProvider, EventEmitter, Event, TreeItem } from 'vscode';
import * as azdata from 'azdata'; import { setInterval, clearInterval } from 'timers';
import { AppContext } from '../../appContext'; import { AppContext } from '../../appContext';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -16,40 +16,15 @@ import { AzureResourceAccountTreeNode } from './accountTreeNode';
import { AzureResourceAccountNotSignedInTreeNode } from './accountNotSignedInTreeNode'; import { AzureResourceAccountNotSignedInTreeNode } from './accountNotSignedInTreeNode';
import { AzureResourceMessageTreeNode } from '../messageTreeNode'; import { AzureResourceMessageTreeNode } from '../messageTreeNode';
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes'; import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceErrorMessageUtil, equals } from '../utils'; import { AzureResourceErrorMessageUtil } from '../utils';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler'; import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
import { IAzureResourceAccountService } from '../../azureResource/interfaces'; import { IAzureResourceAccountService } from '../../azureResource/interfaces';
import { AzureResourceServiceNames } from '../constants'; import { AzureResourceServiceNames } from '../constants';
export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler { export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
public isSystemInitialized: boolean = false; public constructor(
public readonly appContext: AppContext
private accountService: IAzureResourceAccountService; ) {
private accounts: azdata.Account[];
private _onDidChangeTreeData = new EventEmitter<TreeNode>();
private loadingAccountsPromise: Promise<void>;
public constructor(public readonly appContext: AppContext) {
if (appContext) {
this.hookAccountService(appContext);
}
}
private hookAccountService(appContext: AppContext): void {
this.accountService = appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService);
if (this.accountService) {
this.accountService.onDidChangeAccounts((e: azdata.DidChangeAccountsParams) => {
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
// this below check short-circuits the infinite callback loop
this.setSystemInitialized();
if (!equals(e.accounts, this.accounts)) {
this.accounts = e.accounts;
this.notifyNodeChanged(undefined);
}
});
}
} }
public async getChildren(element?: TreeNode): Promise<TreeNode[]> { public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
@@ -57,16 +32,34 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
return element.getChildren(true); return element.getChildren(true);
} }
if (!this.isSystemInitialized) { if (!this.isSystemInitialized && !this._loadingTimer) {
if (!this.loadingAccountsPromise) { this._loadingTimer = setInterval(async () => {
this.loadingAccountsPromise = this.loadAccounts(); try {
} // Call azdata.accounts.getAllAccounts() to determine whether the system has been initialized.
return [AzureResourceMessageTreeNode.create(localize('azure.resource.tree.treeProvider.loadingLabel', 'Loading ...'), undefined)]; await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
// System has been initialized
this.isSystemInitialized = true;
if (this._loadingTimer) {
clearInterval(this._loadingTimer);
}
this._onDidChangeTreeData.fire(undefined);
} catch (error) {
// System not initialized yet
this.isSystemInitialized = false;
}
}, AzureResourceTreeProvider.loadingTimerInterval);
return [AzureResourceMessageTreeNode.create(AzureResourceTreeProvider.loadingLabel, undefined)];
} }
try { try {
if (this.accounts && this.accounts.length > 0) { const accounts = await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
return this.accounts.map((account) => new AzureResourceAccountTreeNode(account, this.appContext, this));
if (accounts && accounts.length > 0) {
return accounts.map((account) => new AzureResourceAccountTreeNode(account, this.appContext, this));
} else { } else {
return [new AzureResourceAccountNotSignedInTreeNode()]; return [new AzureResourceAccountNotSignedInTreeNode()];
} }
@@ -75,23 +68,6 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
} }
} }
private async loadAccounts(): Promise<void> {
try {
this.accounts = await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
// System has been initialized
this.setSystemInitialized();
this._onDidChangeTreeData.fire(undefined);
} catch (err) {
// Skip for now, we can assume that the accounts changed event will eventually notify instead
this.isSystemInitialized = false;
}
}
private setSystemInitialized(): void {
this.isSystemInitialized = true;
this.loadingAccountsPromise = undefined;
}
public get onDidChangeTreeData(): Event<TreeNode> { public get onDidChangeTreeData(): Event<TreeNode> {
return this._onDidChangeTreeData.event; return this._onDidChangeTreeData.event;
} }
@@ -113,4 +89,12 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
public getTreeItem(element: TreeNode): TreeItem | Thenable<TreeItem> { public getTreeItem(element: TreeNode): TreeItem | Thenable<TreeItem> {
return element.getTreeItem(); return element.getTreeItem();
} }
public isSystemInitialized: boolean = false;
private _loadingTimer: NodeJS.Timer = undefined;
private _onDidChangeTreeData = new EventEmitter<TreeNode>();
private static readonly loadingLabel = localize('azure.resource.tree.treeProvider.loadingLabel', 'Loading ...');
private static readonly loadingTimerInterval = 5000;
} }

View File

@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import ControllerBase from './controllerBase';
import { DidChangeAccountsParams, Account } from 'azdata';
import {
IAzureResourceCacheService,
IAzureResourceAccountService,
IAzureResourceSubscriptionService,
IAzureResourceSubscriptionFilterService,
IAzureResourceTenantService
} from '../azureResource/interfaces';
import { AzureResourceServiceNames } from '../azureResource/constants';
import { AzureResourceTreeProvider } from '../azureResource/tree/treeProvider';
import { registerAzureResourceCommands } from '../azureResource/commands';
import { AzureResourceAccountService } from '../azureResource/services/accountService';
import { AzureResourceSubscriptionService } from '../azureResource/services/subscriptionService';
import { AzureResourceSubscriptionFilterService } from '../azureResource/services/subscriptionFilterService';
import { AzureResourceCacheService } from '../azureResource/services/cacheService';
import { AzureResourceTenantService } from '../azureResource/services/tenantService';
import { registerAzureResourceDatabaseServerCommands } from '../azureResource/providers/databaseServer/commands';
import { registerAzureResourceDatabaseCommands } from '../azureResource/providers/database/commands';
import { equals } from '../azureResource/utils';
export default class AzureResourceController extends ControllerBase {
public activate(): Promise<boolean> {
this.appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, new AzureResourceCacheService(this.extensionContext));
this.appContext.registerService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService, new AzureResourceAccountService(this.apiWrapper));
this.appContext.registerService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService, new AzureResourceSubscriptionService());
this.appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(this.extensionContext)));
this.appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService());
const azureResourceTree = new AzureResourceTreeProvider(this.appContext);
this.extensionContext.subscriptions.push(this.apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
let previousAccounts: Array<Account> = undefined;
this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).onDidChangeAccounts((e: DidChangeAccountsParams) => {
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
// this below check short-circuits the infinite callback loop
if (!equals(e.accounts, previousAccounts)) {
azureResourceTree.notifyNodeChanged(undefined);
}
previousAccounts = e.accounts;
});
registerAzureResourceCommands(this.appContext, azureResourceTree);
registerAzureResourceDatabaseServerCommands(this.appContext);
registerAzureResourceDatabaseCommands(this.appContext);
return Promise.resolve(true);
}
public deactivate(): void {
}
}

View File

@@ -0,0 +1,34 @@
/*---------------------------------------------------------------------------------------------
* 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 vscode from 'vscode';
import { AppContext } from '../appContext';
import { ApiWrapper } from '../apiWrapper';
export default abstract class ControllerBase implements vscode.Disposable {
public constructor(protected appContext: AppContext) {
}
protected get apiWrapper(): ApiWrapper {
return this.appContext.apiWrapper;
}
public get extensionContext(): vscode.ExtensionContext {
return this.appContext && this.appContext.extensionContext;
}
abstract activate(): Promise<boolean>;
abstract deactivate(): void;
public dispose(): void {
this.deactivate();
}
}

View File

@@ -9,7 +9,9 @@ import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import * as constants from './constants'; import * as constants from './constants';
import AzureResourceController from './controllers/azureResourceController';
import { AppContext } from './appContext'; import { AppContext } from './appContext';
import ControllerBase from './controllers/controllerBase';
import { ApiWrapper } from './apiWrapper'; import { ApiWrapper } from './apiWrapper';
import { AzureAccountProviderService } from './account-provider/azureAccountProviderService'; import { AzureAccountProviderService } from './account-provider/azureAccountProviderService';
@@ -17,20 +19,9 @@ import { AzureResourceDatabaseServerProvider } from './azureResource/providers/d
import { AzureResourceDatabaseServerService } from './azureResource/providers/databaseServer/databaseServerService'; import { AzureResourceDatabaseServerService } from './azureResource/providers/databaseServer/databaseServerService';
import { AzureResourceDatabaseProvider } from './azureResource/providers/database/databaseProvider'; import { AzureResourceDatabaseProvider } from './azureResource/providers/database/databaseProvider';
import { AzureResourceDatabaseService } from './azureResource/providers/database/databaseService'; import { AzureResourceDatabaseService } from './azureResource/providers/database/databaseService';
import { AzureResourceService } from './azureResource/resourceService';
import { IAzureResourceCacheService, IAzureResourceAccountService, IAzureResourceSubscriptionService, IAzureResourceSubscriptionFilterService, IAzureResourceTenantService } from './azureResource/interfaces';
import { AzureResourceServiceNames } from './azureResource/constants';
import { AzureResourceAccountService } from './azureResource/services/accountService';
import { AzureResourceSubscriptionService } from './azureResource/services/subscriptionService';
import { AzureResourceSubscriptionFilterService } from './azureResource/services/subscriptionFilterService';
import { AzureResourceCacheService } from './azureResource/services/cacheService';
import { AzureResourceTenantService } from './azureResource/services/tenantService';
import { registerAzureResourceCommands } from './azureResource/commands';
import { registerAzureResourceDatabaseServerCommands } from './azureResource/providers/databaseServer/commands';
import { registerAzureResourceDatabaseCommands } from './azureResource/providers/database/commands';
import { AzureResourceTreeProvider } from './azureResource/tree/treeProvider';
let extensionContext: vscode.ExtensionContext; let controllers: ControllerBase[] = [];
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't // 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. // work for now because the extension is running in different process.
@@ -48,29 +39,36 @@ export function getDefaultLogLocation() {
return path.join(getAppDataPath(), 'azuredatastudio'); return path.join(getAppDataPath(), 'azuredatastudio');
} }
function pushDisposable(disposable: vscode.Disposable): void {
extensionContext.subscriptions.push(disposable);
}
// this method is called when your extension is activated // this method is called when your extension is activated
// your extension is activated the very first time the command is executed // your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) { export function activate(extensionContext: vscode.ExtensionContext) {
extensionContext = context;
const apiWrapper = new ApiWrapper(); const apiWrapper = new ApiWrapper();
let appContext = new AppContext(extensionContext, apiWrapper); let appContext = new AppContext(extensionContext, apiWrapper);
let activations: Thenable<boolean>[] = [];
let storagePath = findOrMakeStoragePath(); // Create the folder for storing the token caches
if (!storagePath) { let storagePath = path.join(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 undefined; return undefined;
} }
// Create the provider service and activate // Create the provider service and activate
initAzureAccountProvider(extensionContext, storagePath); const accountProviderService = new AzureAccountProviderService(extensionContext, storagePath);
extensionContext.subscriptions.push(accountProviderService);
accountProviderService.activate();
registerAzureServices(appContext); const azureResourceController = new AzureResourceController(appContext);
const azureResourceTree = new AzureResourceTreeProvider(appContext); controllers.push(azureResourceController);
pushDisposable(apiWrapper.registerTreeDataProvider('azureResourceExplorer', azureResourceTree)); extensionContext.subscriptions.push(azureResourceController);
registerCommands(appContext, azureResourceTree); activations.push(azureResourceController.activate());
return { return {
provideResources() { provideResources() {
@@ -82,46 +80,9 @@ export function activate(context: vscode.ExtensionContext) {
}; };
} }
// Create the folder for storing the token caches // this method is called when your extension is deactivated
function findOrMakeStoragePath() { export function deactivate() {
let storagePath = path.join(getDefaultLogLocation(), constants.extensionName); for (let controller of controllers) {
try { controller.deactivate();
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 storagePath;
}
async function initAzureAccountProvider(extensionContext: vscode.ExtensionContext, storagePath: string): Promise<void> {
try {
const accountProviderService = new AzureAccountProviderService(extensionContext, storagePath);
extensionContext.subscriptions.push(accountProviderService);
await accountProviderService.activate();
} catch (err) {
console.log('Unexpected error starting account provider: ' + err.message);
} }
} }
function registerAzureServices(appContext: AppContext): void {
appContext.registerService<AzureResourceService>(AzureResourceServiceNames.resourceService, new AzureResourceService());
appContext.registerService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService, new AzureResourceAccountService(appContext.apiWrapper));
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, new AzureResourceCacheService(extensionContext));
appContext.registerService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService, new AzureResourceSubscriptionService());
appContext.registerService<IAzureResourceSubscriptionFilterService>(AzureResourceServiceNames.subscriptionFilterService, new AzureResourceSubscriptionFilterService(new AzureResourceCacheService(extensionContext)));
appContext.registerService<IAzureResourceTenantService>(AzureResourceServiceNames.tenantService, new AzureResourceTenantService());
}
function registerCommands(appContext: AppContext, azureResourceTree: AzureResourceTreeProvider): void {
registerAzureResourceCommands(appContext, azureResourceTree);
registerAzureResourceDatabaseServerCommands(appContext);
registerAzureResourceDatabaseCommands(appContext);
}

View File

@@ -142,7 +142,7 @@ describe('AzureResourceDatabaseTreeDataProvider.getChildren', function (): void
should(child.tenantId).equal(mockTenantId); should(child.tenantId).equal(mockTenantId);
should(child.treeItem.id).equal(`databaseServer_${database.serverFullName}.database_${database.name}`); should(child.treeItem.id).equal(`databaseServer_${database.serverFullName}.database_${database.name}`);
should(child.treeItem.label).equal(`${database.name} (${database.serverName})`); should(child.treeItem.label).equal(`${database.name} (${database.serverName})`);
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed); should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.None);
should(child.treeItem.contextValue).equal(AzureResourceItemType.database); should(child.treeItem.contextValue).equal(AzureResourceItemType.database);
} }
}); });

View File

@@ -142,7 +142,7 @@ describe('AzureResourceDatabaseServerTreeDataProvider.getChildren', function ():
should(child.tenantId).equal(mockTenantId); should(child.tenantId).equal(mockTenantId);
should(child.treeItem.id).equal(`databaseServer_${databaseServer.name}`); should(child.treeItem.id).equal(`databaseServer_${databaseServer.name}`);
should(child.treeItem.label).equal(databaseServer.name); should(child.treeItem.label).equal(databaseServer.name);
should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.Collapsed); should(child.treeItem.collapsibleState).equal(vscode.TreeItemCollapsibleState.None);
should(child.treeItem.contextValue).equal(AzureResourceItemType.databaseServer); should(child.treeItem.contextValue).equal(AzureResourceItemType.databaseServer);
} }
}); });

View File

@@ -43,7 +43,7 @@ let mockResourceProvider1: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>; let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>; let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
let resourceService: AzureResourceService; const resourceService: AzureResourceService = AzureResourceService.getInstance();
describe('AzureResourceService.listResourceProviderIds', function(): void { describe('AzureResourceService.listResourceProviderIds', function(): void {
beforeEach(() => { beforeEach(() => {
@@ -61,7 +61,6 @@ describe('AzureResourceService.listResourceProviderIds', function(): void {
mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2'); mockResourceProvider2.setup((o) => o.providerId).returns(() => 'mockResourceProvider2');
mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object); mockResourceProvider2.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider2.object);
resourceService = new AzureResourceService();
resourceService.clearResourceProviders(); resourceService.clearResourceProviders();
resourceService.areResourceProvidersLoaded = true; resourceService.areResourceProvidersLoaded = true;
}); });

View File

@@ -14,9 +14,8 @@ import 'mocha';
import { azureResource } from '../../azureResource/azure-resource'; import { azureResource } from '../../azureResource/azure-resource';
import { AzureResourceService } from '../../azureResource/resourceService'; import { AzureResourceService } from '../../azureResource/resourceService';
import { AzureResourceResourceTreeNode } from '../../azureResource/resourceTreeNode'; import { AzureResourceResourceTreeNode } from '../../azureResource/resourceTreeNode';
import { AppContext } from '../../appContext';
import { ApiWrapper } from '../../apiWrapper'; const resourceService = AzureResourceService.getInstance();
import { AzureResourceServiceNames } from '../../azureResource/constants';
// Mock test data // Mock test data
const mockAccount: azdata.Account = { const mockAccount: azdata.Account = {
@@ -86,8 +85,6 @@ const mockResourceNodes: azureResource.IAzureResourceNode[] = [mockResourceNode1
let mockResourceTreeDataProvider: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>; let mockResourceTreeDataProvider: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
let mockResourceProvider: TypeMoq.IMock<azureResource.IAzureResourceProvider>; let mockResourceProvider: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
let resourceService: AzureResourceService;
let appContext: AppContext;
describe('AzureResourceResourceTreeNode.info', function(): void { describe('AzureResourceResourceTreeNode.info', function(): void {
beforeEach(() => { beforeEach(() => {
@@ -98,20 +95,18 @@ describe('AzureResourceResourceTreeNode.info', function(): void {
mockResourceProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>(); mockResourceProvider = TypeMoq.Mock.ofType<azureResource.IAzureResourceProvider>();
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId); mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object); mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
resourceService = new AzureResourceService();
resourceService.clearResourceProviders(); resourceService.clearResourceProviders();
resourceService.registerResourceProvider(mockResourceProvider.object); resourceService.registerResourceProvider(mockResourceProvider.object);
resourceService.areResourceProvidersLoaded = true;
appContext = new AppContext(undefined, new ApiWrapper()); resourceService.areResourceProvidersLoaded = true;
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
}); });
it('Should be correct when created.', async function(): Promise<void> { it('Should be correct when created.', async function(): Promise<void> {
const resourceTreeNode = new AzureResourceResourceTreeNode({ const resourceTreeNode = new AzureResourceResourceTreeNode({
resourceProviderId: mockResourceProviderId, resourceProviderId: mockResourceProviderId,
resourceNode: mockResourceRootNode resourceNode: mockResourceRootNode
}, undefined, appContext); }, undefined);
should(resourceTreeNode.nodePathValue).equal(mockResourceRootNode.treeItem.id); should(resourceTreeNode.nodePathValue).equal(mockResourceRootNode.treeItem.id);
@@ -138,21 +133,17 @@ describe('AzureResourceResourceTreeNode.getChildren', function(): void {
mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId); mockResourceProvider.setup((o) => o.providerId).returns(() => mockResourceProviderId);
mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object); mockResourceProvider.setup((o) => o.getTreeDataProvider()).returns(() => mockResourceTreeDataProvider.object);
resourceService = new AzureResourceService();
resourceService.clearResourceProviders(); resourceService.clearResourceProviders();
resourceService.registerResourceProvider(mockResourceProvider.object); resourceService.registerResourceProvider(mockResourceProvider.object);
resourceService.areResourceProvidersLoaded = true;
appContext = new AppContext(undefined, new ApiWrapper()); resourceService.areResourceProvidersLoaded = true;
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
}); });
it('Should return resource nodes when it is container node.', async function(): Promise<void> { it('Should return resource nodes when it is container node.', async function(): Promise<void> {
const resourceTreeNode = new AzureResourceResourceTreeNode({ const resourceTreeNode = new AzureResourceResourceTreeNode({
resourceProviderId: mockResourceProviderId, resourceProviderId: mockResourceProviderId,
resourceNode: mockResourceRootNode resourceNode: mockResourceRootNode
}, }, undefined);
undefined, appContext);
const children = await resourceTreeNode.getChildren(); const children = await resourceTreeNode.getChildren();
@@ -182,7 +173,7 @@ describe('AzureResourceResourceTreeNode.getChildren', function(): void {
const resourceTreeNode = new AzureResourceResourceTreeNode({ const resourceTreeNode = new AzureResourceResourceTreeNode({
resourceProviderId: mockResourceProviderId, resourceProviderId: mockResourceProviderId,
resourceNode: mockResourceNode1 resourceNode: mockResourceNode1
}, undefined, appContext); }, undefined);
const children = await resourceTreeNode.getChildren(); const children = await resourceTreeNode.getChildren();

View File

@@ -23,7 +23,7 @@ import { IAzureResourceCacheService } from '../../../azureResource/interfaces';
import { generateGuid } from '../../../azureResource/utils'; import { generateGuid } from '../../../azureResource/utils';
// Mock services // Mock services
let appContext: AppContext; let mockAppContext: AppContext;
let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>; let mockExtensionContext: TypeMoq.IMock<vscode.ExtensionContext>;
let mockApiWrapper: TypeMoq.IMock<ApiWrapper>; let mockApiWrapper: TypeMoq.IMock<ApiWrapper>;
@@ -60,7 +60,7 @@ let mockResourceProvider1: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>; let mockResourceTreeDataProvider2: TypeMoq.IMock<azureResource.IAzureResourceTreeDataProvider>;
let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>; let mockResourceProvider2: TypeMoq.IMock<azureResource.IAzureResourceProvider>;
const resourceService: AzureResourceService = new AzureResourceService(); const resourceService: AzureResourceService = AzureResourceService.getInstance();
describe('AzureResourceSubscriptionTreeNode.info', function(): void { describe('AzureResourceSubscriptionTreeNode.info', function(): void {
beforeEach(() => { beforeEach(() => {
@@ -68,6 +68,10 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>(); mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>(); mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
mockAppContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
mockAppContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid()); mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>(); mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
@@ -89,16 +93,12 @@ describe('AzureResourceSubscriptionTreeNode.info', function(): void {
resourceService.clearResourceProviders(); resourceService.clearResourceProviders();
resourceService.registerResourceProvider(mockResourceProvider1.object); resourceService.registerResourceProvider(mockResourceProvider1.object);
resourceService.registerResourceProvider(mockResourceProvider2.object); resourceService.registerResourceProvider(mockResourceProvider2.object);
resourceService.areResourceProvidersLoaded = true; resourceService.areResourceProvidersLoaded = true;
appContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
}); });
it('Should be correct when created.', async function(): Promise<void> { it('Should be correct when created.', async function(): Promise<void> {
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, undefined); const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, mockAppContext, mockTreeChangeHandler.object, undefined);
should(subscriptionTreeNode.nodePathValue).equal(`account_${mockAccount.key.accountId}.subscription_${mockSubscription.id}.tenant_${mockTenantId}`); should(subscriptionTreeNode.nodePathValue).equal(`account_${mockAccount.key.accountId}.subscription_${mockSubscription.id}.tenant_${mockTenantId}`);
@@ -121,6 +121,9 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>(); mockApiWrapper = TypeMoq.Mock.ofType<ApiWrapper>();
mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>(); mockCacheService = TypeMoq.Mock.ofType<IAzureResourceCacheService>();
mockAppContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
mockAppContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid()); mockCacheService.setup((o) => o.generateKey(TypeMoq.It.isAnyString())).returns(() => generateGuid());
mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>(); mockTreeChangeHandler = TypeMoq.Mock.ofType<IAzureResourceTreeChangeHandler>();
@@ -142,16 +145,12 @@ describe('AzureResourceSubscriptionTreeNode.getChildren', function(): void {
resourceService.clearResourceProviders(); resourceService.clearResourceProviders();
resourceService.registerResourceProvider(mockResourceProvider1.object); resourceService.registerResourceProvider(mockResourceProvider1.object);
resourceService.registerResourceProvider(mockResourceProvider2.object); resourceService.registerResourceProvider(mockResourceProvider2.object);
resourceService.areResourceProvidersLoaded = true; resourceService.areResourceProvidersLoaded = true;
appContext = new AppContext(mockExtensionContext.object, mockApiWrapper.object);
appContext.registerService<IAzureResourceCacheService>(AzureResourceServiceNames.cacheService, mockCacheService.object);
appContext.registerService(AzureResourceServiceNames.resourceService, resourceService);
}); });
it('Should return resource containers.', async function(): Promise<void> { it('Should return resource containers.', async function(): Promise<void> {
const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, appContext, mockTreeChangeHandler.object, undefined); const subscriptionTreeNode = new AzureResourceSubscriptionTreeNode(mockAccount, mockSubscription, mockTenantId, mockAppContext, mockTreeChangeHandler.object, undefined);
const children = await subscriptionTreeNode.getChildren(); const children = await subscriptionTreeNode.getChildren();
mockResourceTreeDataProvider1.verify((o) => o.getChildren(), TypeMoq.Times.once()); mockResourceTreeDataProvider1.verify((o) => o.getChildren(), TypeMoq.Times.once());

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
*.vsix

View File

@@ -1,2 +0,0 @@
src/**
tsconfig.json

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{clip-path:url(#clip-path-2);}.cls-4{clip-path:url(#clip-path-3);}.cls-5{clip-path:url(#clip-path-4);}.cls-6{clip-path:url(#clip-path-5);}.cls-7{clip-path:url(#clip-path-6);}.cls-8{clip-path:url(#clip-path-7);}.cls-9{clip-path:url(#clip-path-8);}.cls-10{fill:#68217a;}</style><clipPath id="clip-path"><rect class="cls-1" x="39.15" y="47.45" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-2"><rect class="cls-1" x="-754.07" y="415.73" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-3"><rect class="cls-1" x="-753.07" y="415.73" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-4"><rect class="cls-1" x="-750.43" y="422" width="10.73" height="0.43"/></clipPath><clipPath id="clip-path-5"><rect class="cls-1" x="-750.13" y="420.77" width="10.14" height="0.43"/></clipPath><clipPath id="clip-path-6"><rect class="cls-1" x="-749.72" y="419.53" width="9.31" height="0.43"/></clipPath><clipPath id="clip-path-7"><rect class="cls-1" x="-749.32" y="418.29" width="8.5" height="0.43"/></clipPath><clipPath id="clip-path-8"><rect class="cls-1" x="-748.89" y="417.05" width="7.65" height="0.43"/></clipPath></defs><title>AKS</title><path class="cls-10" d="M14.66,10.18,9.79,12V4.16l4.86,1.73Z"/><path class="cls-10" d="M5.31,5.5v5.18L9,12.1V4.16Zm.38,4.8-.19-.06V6l.19-.06.19-.06.26-.06v4.67L6,10.37A1.45,1.45,0,0,1,5.7,10.3Zm1,.26L6.4,10.5V5.7l.26-.06.26-.06.26-.06v5.25l-.26-.06Zm1.15.38-.32-.13V5.38l.32-.06.32-.13.38-.13v6.08L8.13,11C8.13,11.07,7.81,10.94,7.81,10.94Z"/><path class="cls-10" d="M26.11,10.18,21.25,12V4.16l4.86,1.73Z"/><path class="cls-10" d="M16.77,5.5v5.18l3.65,1.41V4.16Zm.38,4.8L17,10.24V6l.19-.06.19-.06.26-.06v4.67l-.19-.06A1.45,1.45,0,0,1,17.15,10.3Zm1,.26-.26-.06V5.7l.26-.06.26-.06.26-.06v5.25l-.26-.06Zm1.15.38-.32-.13V5.38l.32-.06.32-.13L20,5.06v6.08L19.58,11C19.58,11.07,19.26,10.94,19.26,10.94Z"/><path class="cls-10" d="M14.66,25.92,9.79,27.78V19.9l4.86,1.73Z"/><path class="cls-10" d="M5.31,21.25v5.18L9,27.84V19.9ZM5.7,26,5.5,26V21.7l.19-.06.19-.06.19-.06v4.67l-.19-.06Zm1,.26-.26-.06v-4.8l.26-.06.26-.06.26-.06V26.5l-.26-.06C6.91,26.37,6.66,26.3,6.66,26.3Zm1.15.38-.32-.13V21.12l.32-.06.32-.13.38-.13v6.08l-.38-.13C8.13,26.82,7.81,26.69,7.81,26.69Z"/><path class="cls-10" d="M26.11,25.92l-4.86,1.86V19.9l4.86,1.73Z"/><path class="cls-10" d="M16.77,21.25v5.18l3.65,1.41V19.9Zm.38,4.8L17,26V21.7l.19-.06.19-.06.19-.06v4.67l-.19-.06Zm1,.26-.26-.06v-4.8l.26-.06.26-.06.26-.06V26.5l-.26-.06C18.37,26.37,18.11,26.3,18.11,26.3Zm1.15.38-.32-.13V21.12l.32-.06.32-.13L20,20.8v6.08l-.38-.13C19.58,26.82,19.26,26.69,19.26,26.69Z"/><path class="cls-10" d="M20.74,18,15.87,19.9V12l4.86,1.73Z"/><path class="cls-10" d="M11.39,13.31V18.5L15,19.9V12Zm.38,4.8L11.58,18V13.76l.19-.06.19-.06.19-.06v4.67L12,18.18C12,18.18,11.78,18.11,11.78,18.11Zm1,.32-.26-.06v-4.8l.26-.06.26-.06.26-.06v5.25L13,18.56C13,18.5,12.74,18.43,12.74,18.43Zm1.15.38-.32-.13V13.25l.32-.06.32-.13.38-.13V19l-.38-.13Z"/><path class="cls-10" d="M9.34,18,4.48,19.9V12l4.86,1.73Z"/><path class="cls-10" d="M0,13.31V18.5L3.65,19.9V12Zm.38,4.8L.19,18V13.76l.19-.06H.64l.19-.06V18.3l-.19-.13Zm1,.32-.26-.06v-4.8l.26-.13.26-.06.26-.06v5.25L1.6,18.5Zm1.15.38-.32-.13V13.25l.32-.06.32-.13.38-.13V19l-.38-.13A2.77,2.77,0,0,0,2.5,18.82Z"/><path class="cls-10" d="M32,18,27.14,19.9V12L32,13.76Z"/><path class="cls-10" d="M22.66,13.31V18.5L26.3,19.9V12Zm.38,4.8L22.85,18V13.76L23,13.7l.19-.06.19-.06v4.67l-.19-.06C23.3,18.18,23,18.11,23,18.11Zm1,.32-.26-.06v-4.8L24,13.5l.26-.06.26-.06v5.25l-.26-.06C24.26,18.5,24,18.43,24,18.43Zm1.15.38-.32-.13V13.25l.32-.06.32-.13.38-.13V19l-.38-.13Z"/></svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{clip-path:url(#clip-path-2);}.cls-4{clip-path:url(#clip-path-3);}.cls-5{clip-path:url(#clip-path-4);}.cls-6{clip-path:url(#clip-path-5);}.cls-7{clip-path:url(#clip-path-6);}.cls-8{clip-path:url(#clip-path-7);}.cls-9{clip-path:url(#clip-path-8);}.cls-10{fill:#326ce5;}.cls-11{fill:#fff;stroke:#fff;stroke-width:0.25px;}</style><clipPath id="clip-path"><rect class="cls-1" x="39.15" y="85.81" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-2"><rect class="cls-1" x="-754.07" y="454.09" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-3"><rect class="cls-1" x="-753.07" y="454.09" width="15.81" height="13.48"/></clipPath><clipPath id="clip-path-4"><rect class="cls-1" x="-750.43" y="460.36" width="10.73" height="0.43"/></clipPath><clipPath id="clip-path-5"><rect class="cls-1" x="-750.13" y="459.12" width="10.14" height="0.43"/></clipPath><clipPath id="clip-path-6"><rect class="cls-1" x="-749.72" y="457.88" width="9.31" height="0.43"/></clipPath><clipPath id="clip-path-7"><rect class="cls-1" x="-749.32" y="456.64" width="8.5" height="0.43"/></clipPath><clipPath id="clip-path-8"><rect class="cls-1" x="-748.89" y="455.4" width="7.65" height="0.43"/></clipPath></defs><title>Kubernetes</title><g id="layer1"><g id="g3052"><path id="path3055" class="cls-10" d="M15.89,0a2.09,2.09,0,0,0-.82.21L3.95,5.69A2.17,2.17,0,0,0,2.8,7.17L.05,19.47a2.21,2.21,0,0,0,.29,1.67l.12.17,7.7,9.87A2.11,2.11,0,0,0,9.83,32H22.17a2.11,2.11,0,0,0,1.66-.82l7.7-9.87a2.21,2.21,0,0,0,.41-1.84L29.2,7.17A2.17,2.17,0,0,0,28,5.69L16.92.22A2.09,2.09,0,0,0,15.89,0Z"/><path id="path3059" class="cls-11" d="M16,4.19a.72.72,0,0,0-.67.76V5c0,.06,0,.13,0,.18a5.89,5.89,0,0,0,.09.65A6.6,6.6,0,0,1,15.5,7a.75.75,0,0,1-.22.35l0,.29a8.46,8.46,0,0,0-5.55,2.75l-.24-.18a.51.51,0,0,1-.4,0,6.29,6.29,0,0,1-.9-.84,5.65,5.65,0,0,0-.44-.48l-.15-.12a.78.78,0,0,0-.46-.18.63.63,0,0,0-.53.24.74.74,0,0,0,.16,1h0l.14.11a5.51,5.51,0,0,0,.55.33,6.22,6.22,0,0,1,1,.72.78.78,0,0,1,.13.4l.21.2a9.1,9.1,0,0,0-1.36,6.19l-.28.08a.94.94,0,0,1-.29.3,6,6,0,0,1-1.19.2,5.41,5.41,0,0,0-.64.05l-.18,0h0a.73.73,0,0,0-.56.84.7.7,0,0,0,.86.5h0l.17,0a5.46,5.46,0,0,0,.6-.24,6.08,6.08,0,0,1,1.16-.35.72.72,0,0,1,.38.14l.29-.05a8.88,8.88,0,0,0,3.84,4.94l-.12.3a.7.7,0,0,1,.06.39,6.77,6.77,0,0,1-.6,1.12,5.76,5.76,0,0,0-.36.55l-.09.18a.74.74,0,0,0,.28,1,.7.7,0,0,0,.92-.39h0l.08-.17a5.85,5.85,0,0,0,.19-.63,4.88,4.88,0,0,1,.52-1.23.53.53,0,0,1,.29-.14l.15-.28a8.36,8.36,0,0,0,5,.37,8.45,8.45,0,0,0,1.14-.35l.14.26a.52.52,0,0,1,.34.21A6.52,6.52,0,0,1,20,26.54a5.87,5.87,0,0,0,.19.63l.08.18a.7.7,0,0,0,.92.39.74.74,0,0,0,.28-1l-.09-.18a5.74,5.74,0,0,0-.36-.55,6.47,6.47,0,0,1-.59-1.09.55.55,0,0,1,.05-.4,2.4,2.4,0,0,1-.11-.28,8.89,8.89,0,0,0,3.84-5l.28.05a.52.52,0,0,1,.37-.14,6.08,6.08,0,0,1,1.16.35,5.47,5.47,0,0,0,.6.24l.17,0h0a.7.7,0,0,0,.86-.5.73.73,0,0,0-.56-.84l-.19,0a5.41,5.41,0,0,0-.64-.05,6,6,0,0,1-1.19-.2.76.76,0,0,1-.29-.3l-.27-.08a9.13,9.13,0,0,0-.14-3.2,9,9,0,0,0-1.25-3l.24-.22a.55.55,0,0,1,.13-.39,6.22,6.22,0,0,1,1-.72,5.53,5.53,0,0,0,.55-.33l.15-.12a.74.74,0,0,0,.16-1,.69.69,0,0,0-1-.06l-.15.12a5.67,5.67,0,0,0-.44.48,6.31,6.31,0,0,1-.9.84.72.72,0,0,1-.4,0l-.25.19A8.63,8.63,0,0,0,16.73,7.7c0-.09,0-.26,0-.31A.54.54,0,0,1,16.5,7a6.62,6.62,0,0,1,.08-1.24,5.89,5.89,0,0,0,.09-.65c0-.06,0-.14,0-.2A.72.72,0,0,0,16,4.19Zm-.83,5.32-.2,3.6h0a.6.6,0,0,1-.59.58.57.57,0,0,1-.35-.12h0l-2.86-2.09a6.79,6.79,0,0,1,4-2Zm1.67,0a6.84,6.84,0,0,1,4,2L18,13.58h0a.58.58,0,0,1-.81-.11.61.61,0,0,1-.13-.35h0Zm-6.72,3.33,2.61,2.41h0a.62.62,0,0,1,.07.83.59.59,0,0,1-.3.21h0l-3.35,1A7.24,7.24,0,0,1,10.11,12.84Zm11.75,0A7.28,7.28,0,0,1,22.72,15a7.36,7.36,0,0,1,.15,2.3l-3.37-1h0a.61.61,0,0,1-.23-1h0l2.6-2.4Zm-6.4,2.6h1.07l.67.86L17,17.36l-1,.48-1-.48-.24-1.07Zm3.43,2.94H19l3.47.6a7,7,0,0,1-2.78,3.59l-1.35-3.35h0a.61.61,0,0,1,.28-.78.57.57,0,0,1,.22-.06Zm-5.82,0a.59.59,0,0,1,.56.47.62.62,0,0,1,0,.37h0l-1.33,3.32A7.07,7.07,0,0,1,9.52,19l3.44-.6h.12ZM16,19.84a.57.57,0,0,1,.27.06.59.59,0,0,1,.26.26h0l1.69,3.16a6.86,6.86,0,0,1-.68.2,6.69,6.69,0,0,1-3.76-.2l1.69-3.15h0A.59.59,0,0,1,16,19.84Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,111 +1,94 @@
{ {
"name": "big-data-cluster", "name": "big-data-cluster",
"displayName": "%text.sqlServerBigDataClusters%", "displayName": "SQL Server big data cluster",
"description": "%description%", "description": "SQL Server big data cluster",
"version": "0.0.1", "version": "0.0.1",
"publisher": "Microsoft", "publisher": "Microsoft",
"preview": true, "preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt", "license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
"icon": "images/sqlserver.png", "icon": "images/sqlserver.png",
"engines": { "aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"vscode": "*", "engines": {
"azdata": "*" "vscode": "*",
}, "azdata": "^1.4.0"
"activationEvents": [ },
"*" "activationEvents": [
], "*"
"repository": { ],
"type": "git", "main": "./out/main",
"url": "https://github.com/Microsoft/azuredatastudio.git" "repository": {
}, "type": "git",
"main": "./out/extension", "url": "https://github.com/Microsoft/azuredatastudio.git"
"contributes": { },
"dataExplorer": { "extensionDependencies": [
"sqlBigDataCluster": [ "Microsoft.mssql"
{ ],
"id": "sqlBigDataCluster", "contributes": {
"name": "%text.sqlServerBigDataClusters%" "configuration": {
} "type": "object",
] "title": "Kubernetes configuration",
}, "properties": {
"menus": { "mssql-bdc": {
"commandPalette": [ "type": "object",
{ "description": "Kubernetes configuration",
"command": "bigDataClusters.command.addController", "properties": {
"when": "false" "mssql-bdc.kubectl-path": {
}, "type": "string",
{ "description": "File path to a kubectl binary."
"command": "bigDataClusters.command.deleteController", },
"when": "false" "mssql-bdc.kubectl-path.windows": {
}, "type": "string",
{ "description": "File path to a kubectl binary."
"command": "bigDataClusters.command.refreshController", },
"when": "false" "mssql-bdc.kubectl-path.mac": {
} "type": "string",
], "description": "File path to a kubectl binary."
"view/title": [ },
{ "mssql-bdc.kubectl-path.linux": {
"command": "bigDataClusters.command.addController", "type": "string",
"when": "view == sqlBigDataCluster", "description": "File path to a kubectl binary."
"group": "navigation" },
} "mssql-bdc.kubeconfig": {
], "type": "string",
"view/item/context": [ "description": "File path to the kubeconfig file."
{ },
"command": "bigDataClusters.command.deleteController", "mssql-bdc.knownKubeconfigs": {
"when": "viewItem == bigDataClusters.itemType.controllerNode", "type": "array",
"group": "navigation@1" "description": "File paths to kubeconfig files from which you can select."
}, },
{ "mssql-bdc.outputFormat": {
"command": "bigDataClusters.command.refreshController", "enum": [
"when": "viewItem == bigDataClusters.itemType.controllerNode", "json",
"group": "navigation@1" "yaml"
} ],
] "type": "string",
}, "description": "Output format for Kubernetes specs. One of 'json' or 'yaml' (default)."
"configuration": { }
"type": "object", },
"title": "%text.sqlServerBigDataClusters%", "default": {
"properties": { "mssql-bdc.namespace": "",
"clusterControllers.controllers": { "mssql-bdc.kubectl-path": "",
"type": "array" "mssql-bdc.kubeconfig": "",
} "mssql-bdc.knownKubeconfigs": []
} }
}, }
"commands": [ }
{ },
"command": "bigDataClusters.command.addController", "commands": [
"title": "%command.addController.title%", {
"icon": { "command": "mssql.cluster.create",
"light": "resources/light/add.svg", "title": "Create SQL Server big data cluster",
"dark": "resources/dark/add_inverse.svg" "category": "SQL Server"
} }
}, ]
{ },
"command": "bigDataClusters.command.deleteController", "dependencies": {
"title": "%command.deleteController.title%", "vscode-nls": "^3.2.1",
"when": "viewItem == bigDataClusters.itemType.controllerNode" "download": "^6.2.5",
}, "shelljs": "^0.8.3"
{ },
"command": "bigDataClusters.command.refreshController", "devDependencies": {
"title": "%command.refreshController.title%", "mocha-junit-reporter": "^1.17.0",
"icon": { "mocha-multi-reporters": "^1.1.7"
"light": "resources/light/refresh.svg", }
"dark": "resources/dark/refresh_inverse.svg"
}
}
]
},
"dependencies": {
"request": "^2.88.0",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^8.0.24",
"mocha": "^5.2.0",
"should": "^13.2.1",
"typemoq": "^2.1.0",
"vscode": "^1.1.26"
}
} }

View File

@@ -1,7 +0,0 @@
{
"description": "Support for managing SQL Server Big Data Clusters",
"text.sqlServerBigDataClusters": "SQL Server Big Data Clusters",
"command.addController.title": "Connect to Controller",
"command.deleteController.title" : "Delete",
"command.refreshController.title" : "Refresh"
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-bg{fill:#c5c5c5;}</style></defs><title>add</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,16H0V0H16Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14,6v4H10v4H6V10H2V6H6V2h4V6Z"/></g><g id="iconBg"><path class="icon-vs-bg" d="M13,7V9H9v4H7V9H3V7H7V3H9V7Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 486 B

View File

@@ -1 +0,0 @@
<svg id="Icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><defs><style>.cls-1{opacity:0;}.cls-2{fill:#f6f6f6;}.cls-3{fill:#424242;}.cls-4{fill:#f0eff1;}</style></defs><title>centralmanagement_server_16x</title><g id="canvas" class="cls-1"><rect class="cls-2" width="16" height="16"/></g><path id="outline" class="cls-2" d="M16,0H7V1H3V5H0V16H8V13h8ZM6,4H7V5H6Z"/><g id="iconBG"><path class="cls-3" d="M8,1V12h7V1Zm6,10H13V10h1Zm0-6H9V4h5Zm0-2H9V2h5Z"/><path class="cls-3" d="M1,6v9H7V6Zm5,8H5V13H6Zm0-4H2V9H6ZM6,8H2V7H6Z"/><rect class="cls-3" x="6" y="2" width="1" height="1"/><rect class="cls-3" x="4" y="4" width="1" height="1"/><rect class="cls-3" x="4" y="2" width="1" height="1"/></g><g id="iconFG"><path class="cls-4" d="M14,3H9V2h5Zm0,1H9V5h5Zm0,6H13v1h1Z"/><path class="cls-4" d="M6,8H2V7H6ZM6,9H2v1H6Zm0,4H5v1H6Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 869 B

View File

@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.cls-1{fill:#231f20;}.cls-2{fill:#fff;}</style></defs><title>folder_inverse_16x16</title><polygon class="cls-1" points="13.59 2.34 13.58 2.35 13.58 2.33 13.59 2.34"/><text></text><path class="cls-2" d="M16,14.13H0v-12a1,1,0,0,1,.08-.39,1,1,0,0,1,.53-.53A1,1,0,0,1,1,1.13H4.75a2.16,2.16,0,0,1,.61.07,2.26,2.26,0,0,1,.45.18,2.14,2.14,0,0,1,.36.24l.32.24a1.8,1.8,0,0,0,.34.18,1.12,1.12,0,0,0,.43.07H15a1,1,0,0,1,.39.08,1,1,0,0,1,.53.53,1,1,0,0,1,.08.39ZM1,2.13v1H4.75a1.36,1.36,0,0,0,.33,0A1,1,0,0,0,5.34,3l.23-.16.25-.21-.25-.21-.23-.16a1,1,0,0,0-.26-.1,1.36,1.36,0,0,0-.33,0Zm14,11v-10H7.25a1.12,1.12,0,0,0-.43.07,1.8,1.8,0,0,0-.34.18l-.32.24a2.14,2.14,0,0,1-.36.24,2.26,2.26,0,0,1-.45.18,2.16,2.16,0,0,1-.61.07H1v9Z"/></svg>

Before

Width:  |  Height:  |  Size: 830 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#2D2D30"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#C5C5C5"/></svg>

Before

Width:  |  Height:  |  Size: 986 B

View File

@@ -1,46 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 16 16"
data-name="Layer 1"
id="Layer_1">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>sql_bigdata_cluster</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4">
<style
id="style2">.cls-1{fill:#212121;}.cls-2{fill:#231f20;}</style>
</defs>
<title
id="title6">sql_bigdata_cluster</title>
<path
style="fill:#ffffff;stroke-width:1.00282443"
id="path8"
d="M 7.995,0 C 5.605,0 1.575,0.45254557 1.465,2.1319925 V 13.737272 C 1.465,15.517285 5.575,16 7.995,16 c 2.42,0 6.54,-0.482715 6.54,-2.262728 V 2.1319925 C 14.435,0.45254557 10.405,0 7.995,0 Z m 5.45,13.737272 c -0.14,0.392206 -2.18,1.166562 -5.45,1.166562 -3.27,0 -5.32,-0.784412 -5.43,-1.166562 V 3.5097423 a 14.67,14.752986 0 0 0 5.43,0.8749214 14.71,14.793212 0 0 0 5.45,-0.8749214 z m 0,-11.5549967 c -0.17,0.3922062 -2.19,1.1062225 -5.45,1.1062225 -3.26,0 -5.2,-0.6939032 -5.43,-1.0861094 0.23,-0.4022627 2.22,-1.1062225 5.43,-1.1062225 3.21,0 5.27,0.7240729 5.45,1.0659963 v 0 z"
class="cls-1" />
<polygon
style="fill:#ffffff"
transform="translate(0.075)"
id="polygon10"
points="13.57,2.35 13.58,2.36 13.57,2.37 "
class="cls-2" />
<path
style="fill:#ffffff"
id="path12"
d="m 9.6501562,5.2372858 c -0.1362374,0 -0.2728654,0.026375 -0.4003906,0.082031 -0.123585,0.050567 -0.2358691,0.1260731 -0.3300781,0.2207031 -0.094256,0.096634 -0.1724299,0.2082024 -0.2304688,0.3300781 -0.062701,0.1283175 -0.099426,0.2676857 -0.109375,0.4101562 -0.00186,0.1267925 0.022265,0.2517914 0.070312,0.3691407 0.045212,0.1164344 0.1088696,0.2248797 0.1894531,0.3203125 L 8.2107031,7.9384577 C 8.011051,7.8519995 7.7980699,7.8002026 7.5798437,7.7997858 7.2852043,7.7997877 7.0158159,7.8890317 6.7790625,8.0283014 L 6.3435156,7.4677545 C 6.4851678,7.2819801 6.5620085,7.0548883 6.5622656,6.8212702 6.5623837,6.2311827 6.0839937,5.7527927 5.4939062,5.7529108 4.9038187,5.7527927 4.4254288,6.2311827 4.4255469,6.8212702 4.4254288,7.4113576 4.9038188,7.8897476 5.4939062,7.8896295 5.646983,7.8892233 5.7981841,7.8559185 5.9372656,7.7919733 l 0.4628906,0.5351562 c -0.2593431,0.2844532 -0.4218723,0.6589599 -0.421875,1.0742188 1.1e-6,0.1550931 0.029186,0.301527 0.070312,0.4433594 L 5.2692969,10.19041 C 5.0668671,9.9352433 4.7590727,9.7863779 4.4333593,9.7861139 3.8432718,9.7859958 3.3648819,10.264386 3.365,10.854473 c -1.179e-4,0.590087 0.478272,1.068477 1.0683593,1.068359 0.5900874,1.18e-4 1.0684773,-0.478272 1.0683594,-1.068359 -2.425e-4,-0.05958 -0.00547,-0.119029 -0.015625,-0.177734 l 0.7675782,-0.376953 c 0.2881162,0.42403 0.7748778,0.703124 1.3261718,0.703124 0.087028,-9e-5 0.1739047,-0.0073 0.2597656,-0.02148 l 0.2011719,0.597656 c -0.2806104,0.199117 -0.4474678,0.523359 -0.4472656,0.869137 -8.57e-5,0.586839 0.4721644,1.062587 1.0546875,1.0625 0.5825231,8.7e-5 1.054773,-0.475661 1.054687,-1.0625 8.6e-5,-0.586839 -0.4721639,-1.062587 -1.054687,-1.0625 -0.043779,5.16e-4 -0.087483,0.0038 -0.1308594,0.0098 L 8.3220312,10.819317 C 8.6909643,10.625493 8.9698168,10.295494 9.099375,9.8993953 l 0.5449219,0.089844 h 0.00195 c 0.05025,0.5310507 0.4958731,0.9369327 1.0292971,0.9374997 0.571737,8.6e-5 1.035243,-0.46342 1.035156,-1.0351567 C 11.710786,9.3198482 11.247281,8.8563402 10.675544,8.8564264 10.264465,8.85697 9.8926723,9.100743 9.7282783,9.4775202 L 9.1814062,9.3798639 C 9.1740509,8.9410593 8.9869509,8.524497 8.6638281,8.2275202 L 9.3103125,7.2607233 c 0.1095989,0.036162 0.2244742,0.051906 0.3398437,0.048828 0.1376991,0.0043 0.2729851,-0.023148 0.3984378,-0.080078 0.126162,-0.045588 0.239468,-0.119827 0.330078,-0.21875 0.09823,-0.093286 0.176943,-0.2056351 0.230469,-0.3300781 0.05137,-0.1271794 0.07858,-0.2632358 0.08008,-0.4003907 -4.88e-4,-0.140498 -0.02772,-0.2797842 -0.08008,-0.4101562 C 10.551096,5.7482226 10.472932,5.6366542 10.378672,5.5400202 10.284463,5.44539 10.172179,5.369883 10.048594,5.3193171 9.9210683,5.2636605 9.7863933,5.2372858 9.6501562,5.2372858 Z m -0.00195,0.4746094 C 9.9659223,5.7112473 10.223947,5.9683972 10.224378,6.2861139 10.225028,6.6045936 9.9666863,6.8629356 9.6482062,6.8622858 9.3304864,6.8618548 9.0733369,6.6038302 9.0739843,6.2861139 9.0744163,5.9691601 9.3312493,5.7123255 9.6482031,5.7118952 Z m -4.1543,0.4941406 C 5.8337444,6.2059063 6.1092701,6.481432 6.1091406,6.8212702 6.1092701,7.1611084 5.8337444,7.4366342 5.4939062,7.4365045 5.1540681,7.436634 4.8785424,7.1611083 4.8786719,6.8212702 4.8785424,6.481432 5.154068,6.2059063 5.4939062,6.2060358 Z M 7.5817969,8.3700983 A 1.0403689,1.0403689 0 0 1 8.6228125,9.4111139 1.0403689,1.0403689 0 0 1 7.5817969,10.450176 1.0403689,1.0403689 0 0 1 6.5427343,9.4111139 1.0403689,1.0403689 0 0 1 7.5817969,8.3700983 Z m 3.0585941,0.9277344 h 0.002 c 0.01432,-5.13e-4 0.02865,-5.13e-4 0.04297,0 0.331066,2.151e-4 0.599395,0.2685422 0.59961,0.5996096 -2.16e-4,0.3310657 -0.268544,0.5993937 -0.59961,0.5996087 -0.331828,8.64e-4 -0.601347,-0.26778 -0.601562,-0.5996087 -7.66e-4,-0.3150021 0.242463,-0.5768467 0.556641,-0.5996096 z M 4.4216406,10.260723 c 0.3398381,-1.3e-4 0.6153637,0.275396 0.6152344,0.615234 1.299e-4,0.339838 -0.2753959,0.615365 -0.6152344,0.615235 -0.3398385,1.3e-4 -0.6153643,-0.275397 -0.6152344,-0.615235 -1.293e-4,-0.339838 0.2753963,-0.615364 0.6152344,-0.615234 z m 4.2382813,1.589844 c 0.3452152,-8.4e-5 0.6250885,0.272792 0.625,0.609375 8.81e-5,0.336583 -0.2797848,0.609459 -0.625,0.609375 -0.3452157,8.4e-5 -0.6250889,-0.272792 -0.625,-0.609375 -8.86e-5,-0.336583 0.2797844,-0.609459 0.625,-0.609375 z" />
</svg>

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-bg{fill:#424242;}</style></defs><title>add</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,16H0V0H16Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14,6v4H10v4H6V10H2V6H6V2h4V6Z"/></g><g id="iconBg"><path class="icon-vs-bg" d="M13,7V9H9v4H7V9H3V7H7V3H9V7Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 486 B

View File

@@ -1 +0,0 @@
<svg id="Icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><defs><style>.cls-1{opacity:0;}.cls-2{fill:#f6f6f6;}.cls-3{fill:#424242;}.cls-4{fill:#f0eff1;}</style></defs><title>centralmanagement_server_16x</title><g id="canvas" class="cls-1"><rect class="cls-2" width="16" height="16"/></g><path id="outline" class="cls-2" d="M16,0H7V1H3V5H0V16H8V13h8ZM6,4H7V5H6Z"/><g id="iconBG"><path class="cls-3" d="M8,1V12h7V1Zm6,10H13V10h1Zm0-6H9V4h5Zm0-2H9V2h5Z"/><path class="cls-3" d="M1,6v9H7V6Zm5,8H5V13H6Zm0-4H2V9H6ZM6,8H2V7H6Z"/><rect class="cls-3" x="6" y="2" width="1" height="1"/><rect class="cls-3" x="4" y="4" width="1" height="1"/><rect class="cls-3" x="4" y="2" width="1" height="1"/></g><g id="iconFG"><path class="cls-4" d="M14,3H9V2h5Zm0,1H9V5h5Zm0,6H13v1h1Z"/><path class="cls-4" d="M6,8H2V7H6ZM6,9H2v1H6Zm0,4H5v1H6Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 869 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-fg{fill:#F0EFF1;} .icon-folder{fill:#DCB67A;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 2.5v10c0 .827-.673 1.5-1.5 1.5h-11.996c-.827 0-1.5-.673-1.5-1.5v-8c0-.827.673-1.5 1.5-1.5h2.886l1-2h8.11c.827 0 1.5.673 1.5 1.5z" id="outline"/><path class="icon-folder" d="M14.5 2h-7.492l-1 2h-3.504c-.277 0-.5.224-.5.5v8c0 .276.223.5.5.5h11.996c.275 0 .5-.224.5-.5v-10c0-.276-.225-.5-.5-.5zm-.496 2h-6.496l.5-1h5.996v1z" id="iconBg"/><path class="icon-vs-fg" d="M14 3v1h-6.5l.5-1h6z" id="iconFg"/></svg>

Before

Width:  |  Height:  |  Size: 740 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M13.451 5.609l-.579-.939-1.068.812-.076.094c-.335.415-.927 1.341-1.124 2.876l-.021.165.033.163.071.345c0 1.654-1.346 3-3 3-.795 0-1.545-.311-2.107-.868-.563-.567-.873-1.317-.873-2.111 0-1.431 1.007-2.632 2.351-2.929v2.926s2.528-2.087 2.984-2.461h.012l3.061-2.582-4.919-4.1h-1.137v2.404c-3.429.318-6.121 3.211-6.121 6.721 0 1.809.707 3.508 1.986 4.782 1.277 1.282 2.976 1.988 4.784 1.988 3.722 0 6.75-3.028 6.75-6.75 0-1.245-.349-2.468-1.007-3.536z" fill="#F6F6F6"/><path d="M12.6 6.134l-.094.071c-.269.333-.746 1.096-.91 2.375.057.277.092.495.092.545 0 2.206-1.794 4-4 4-1.098 0-2.093-.445-2.817-1.164-.718-.724-1.163-1.718-1.163-2.815 0-2.206 1.794-4 4-4l.351.025v1.85s1.626-1.342 1.631-1.339l1.869-1.577-3.5-2.917v2.218l-.371-.03c-3.176 0-5.75 2.574-5.75 5.75 0 1.593.648 3.034 1.695 4.076 1.042 1.046 2.482 1.694 4.076 1.694 3.176 0 5.75-2.574 5.75-5.75-.001-1.106-.318-2.135-.859-3.012z" fill="#424242"/></svg>

Before

Width:  |  Height:  |  Size: 986 B

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 16 16"
data-name="Layer 1"
id="Layer_1">
<metadata
id="metadata17">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>sql_bigdata_cluster</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4">
<style
id="style2">.cls-1{fill:#212121;}.cls-2{fill:#231f20;}</style>
</defs>
<title
id="title6">sql_bigdata_cluster</title>
<path
style="fill:#212121;stroke-width:1.00282443"
id="path8"
d="M 7.995,0 C 5.605,0 1.575,0.45254557 1.465,2.1319925 V 13.737272 C 1.465,15.517285 5.575,16 7.995,16 c 2.42,0 6.54,-0.482715 6.54,-2.262728 V 2.1319925 C 14.435,0.45254557 10.405,0 7.995,0 Z m 5.45,13.737272 c -0.14,0.392206 -2.18,1.166562 -5.45,1.166562 -3.27,0 -5.32,-0.784412 -5.43,-1.166562 V 3.5097423 a 14.67,14.752986 0 0 0 5.43,0.8749214 14.71,14.793212 0 0 0 5.45,-0.8749214 z m 0,-11.5549967 c -0.17,0.3922062 -2.19,1.1062225 -5.45,1.1062225 -3.26,0 -5.2,-0.6939032 -5.43,-1.0861094 0.23,-0.4022627 2.22,-1.1062225 5.43,-1.1062225 3.21,0 5.27,0.7240729 5.45,1.0659963 v 0 z"
class="cls-1" />
<polygon
style="fill:#231f20"
transform="translate(0.075)"
id="polygon10"
points="13.57,2.35 13.58,2.36 13.57,2.37 "
class="cls-2" />
<path
id="path12"
d="m 9.6501562,5.2372858 c -0.1362374,0 -0.2728654,0.026375 -0.4003906,0.082031 -0.123585,0.050567 -0.2358691,0.1260731 -0.3300781,0.2207031 -0.094256,0.096634 -0.1724299,0.2082024 -0.2304688,0.3300781 -0.062701,0.1283175 -0.099426,0.2676857 -0.109375,0.4101562 -0.00186,0.1267925 0.022265,0.2517914 0.070312,0.3691407 0.045212,0.1164344 0.1088696,0.2248797 0.1894531,0.3203125 L 8.2107031,7.9384577 C 8.011051,7.8519995 7.7980699,7.8002026 7.5798437,7.7997858 7.2852043,7.7997877 7.0158159,7.8890317 6.7790625,8.0283014 L 6.3435156,7.4677545 C 6.4851678,7.2819801 6.5620085,7.0548883 6.5622656,6.8212702 6.5623837,6.2311827 6.0839937,5.7527927 5.4939062,5.7529108 4.9038187,5.7527927 4.4254288,6.2311827 4.4255469,6.8212702 4.4254288,7.4113576 4.9038188,7.8897476 5.4939062,7.8896295 5.646983,7.8892233 5.7981841,7.8559185 5.9372656,7.7919733 l 0.4628906,0.5351562 c -0.2593431,0.2844532 -0.4218723,0.6589599 -0.421875,1.0742188 1.1e-6,0.1550931 0.029186,0.301527 0.070312,0.4433594 L 5.2692969,10.19041 C 5.0668671,9.9352433 4.7590727,9.7863779 4.4333593,9.7861139 3.8432718,9.7859958 3.3648819,10.264386 3.365,10.854473 c -1.179e-4,0.590087 0.478272,1.068477 1.0683593,1.068359 0.5900874,1.18e-4 1.0684773,-0.478272 1.0683594,-1.068359 -2.425e-4,-0.05958 -0.00547,-0.119029 -0.015625,-0.177734 l 0.7675782,-0.376953 c 0.2881162,0.42403 0.7748778,0.703124 1.3261718,0.703124 0.087028,-9e-5 0.1739047,-0.0073 0.2597656,-0.02148 l 0.2011719,0.597656 c -0.2806104,0.199117 -0.4474678,0.523359 -0.4472656,0.869137 -8.57e-5,0.586839 0.4721644,1.062587 1.0546875,1.0625 0.5825231,8.7e-5 1.054773,-0.475661 1.054687,-1.0625 8.6e-5,-0.586839 -0.4721639,-1.062587 -1.054687,-1.0625 -0.043779,5.16e-4 -0.087483,0.0038 -0.1308594,0.0098 L 8.3220312,10.819317 C 8.6909643,10.625493 8.9698168,10.295494 9.099375,9.8993953 l 0.5449219,0.089844 h 0.00195 c 0.05025,0.5310507 0.4958731,0.9369327 1.0292971,0.9374997 0.571737,8.6e-5 1.035243,-0.46342 1.035156,-1.0351567 C 11.710786,9.3198482 11.247281,8.8563402 10.675544,8.8564264 10.264465,8.85697 9.8926723,9.100743 9.7282783,9.4775202 L 9.1814062,9.3798639 C 9.1740509,8.9410593 8.9869509,8.524497 8.6638281,8.2275202 L 9.3103125,7.2607233 c 0.1095989,0.036162 0.2244742,0.051906 0.3398437,0.048828 0.1376991,0.0043 0.2729851,-0.023148 0.3984378,-0.080078 0.126162,-0.045588 0.239468,-0.119827 0.330078,-0.21875 0.09823,-0.093286 0.176943,-0.2056351 0.230469,-0.3300781 0.05137,-0.1271794 0.07858,-0.2632358 0.08008,-0.4003907 -4.88e-4,-0.140498 -0.02772,-0.2797842 -0.08008,-0.4101562 C 10.551096,5.7482226 10.472932,5.6366542 10.378672,5.5400202 10.284463,5.44539 10.172179,5.369883 10.048594,5.3193171 9.9210683,5.2636605 9.7863933,5.2372858 9.6501562,5.2372858 Z m -0.00195,0.4746094 C 9.9659223,5.7112473 10.223947,5.9683972 10.224378,6.2861139 10.225028,6.6045936 9.9666863,6.8629356 9.6482062,6.8622858 9.3304864,6.8618548 9.0733369,6.6038302 9.0739843,6.2861139 9.0744163,5.9691601 9.3312493,5.7123255 9.6482031,5.7118952 Z m -4.1543,0.4941406 C 5.8337444,6.2059063 6.1092701,6.481432 6.1091406,6.8212702 6.1092701,7.1611084 5.8337444,7.4366342 5.4939062,7.4365045 5.1540681,7.436634 4.8785424,7.1611083 4.8786719,6.8212702 4.8785424,6.481432 5.154068,6.2059063 5.4939062,6.2060358 Z M 7.5817969,8.3700983 A 1.0403689,1.0403689 0 0 1 8.6228125,9.4111139 1.0403689,1.0403689 0 0 1 7.5817969,10.450176 1.0403689,1.0403689 0 0 1 6.5427343,9.4111139 1.0403689,1.0403689 0 0 1 7.5817969,8.3700983 Z m 3.0585941,0.9277344 h 0.002 c 0.01432,-5.13e-4 0.02865,-5.13e-4 0.04297,0 0.331066,2.151e-4 0.599395,0.2685422 0.59961,0.5996096 -2.16e-4,0.3310657 -0.268544,0.5993937 -0.59961,0.5996087 -0.331828,8.64e-4 -0.601347,-0.26778 -0.601562,-0.5996087 -7.66e-4,-0.3150021 0.242463,-0.5768467 0.556641,-0.5996096 z M 4.4216406,10.260723 c 0.3398381,-1.3e-4 0.6153637,0.275396 0.6152344,0.615234 1.299e-4,0.339838 -0.2753959,0.615365 -0.6152344,0.615235 -0.3398385,1.3e-4 -0.6153643,-0.275397 -0.6152344,-0.615235 -1.293e-4,-0.339838 0.2753963,-0.615364 0.6152344,-0.615234 z m 4.2382813,1.589844 c 0.3452152,-8.4e-5 0.6250885,0.272792 0.625,0.609375 8.81e-5,0.336583 -0.2797848,0.609459 -0.625,0.609375 -0.3452157,8.4e-5 -0.6250889,-0.272792 -0.625,-0.609375 -8.86e-5,-0.336583 0.2797844,-0.609459 0.625,-0.609375 z" />
</svg>

Before

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -1,41 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 vscode from 'vscode';
export enum BdcItemType {
controllerRoot = 'bigDataClusters.itemType.controllerRootNode',
controller = 'bigDataClusters.itemType.controllerNode',
folder = 'bigDataClusters.itemType.folderNode',
sqlMaster = 'bigDataClusters.itemType.sqlMasterNode',
EndPoint = 'bigDataClusters.itemType.endPointNode',
addController = 'bigDataClusters.itemType.addControllerNode'
}
export class IconPath {
private static extensionContext: vscode.ExtensionContext;
public static controllerNode: { dark: string, light: string };
public static folderNode: { dark: string, light: string };
public static sqlMasterNode: { dark: string, light: string };
public static setExtensionContext(extensionContext: vscode.ExtensionContext) {
IconPath.extensionContext = extensionContext;
IconPath.controllerNode = {
dark: IconPath.extensionContext.asAbsolutePath('resources/dark/bigDataCluster_controller.svg'),
light: IconPath.extensionContext.asAbsolutePath('resources/light/bigDataCluster_controller.svg')
};
IconPath.folderNode = {
dark: IconPath.extensionContext.asAbsolutePath('resources/dark/folder_inverse.svg'),
light: IconPath.extensionContext.asAbsolutePath('resources/light/folder.svg')
};
IconPath.sqlMasterNode = {
dark: IconPath.extensionContext.asAbsolutePath('resources/dark/sql_bigdata_cluster_inverse.svg'),
light: IconPath.extensionContext.asAbsolutePath('resources/light/sql_bigdata_cluster.svg')
};
}
}

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