diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27da500e85..f09a0e120d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,16 +51,14 @@ jobs: name: Run Unit Tests (Electron) - run: DISPLAY=:10 ./scripts/test-extensions-unit.sh name: Run Extension Unit Tests (Electron) - # {{SQL CARBON EDIT}} Add coveralls. We merge first to get around issue where parallel builds weren't being combined correctly - - run: | - mkdir .build/coverage-combined - cat .build/coverage-single/lcov.info ./extensions/admin-tool-ext-win/coverage/lcov.info ./extensions/agent/coverage/lcov.info ./extensions/azurecore/coverage/lcov.info ./extensions/cms/coverage/lcov.info ./extensions/dacpac/coverage/lcov.info ./extensions/schema-compare/coverage/lcov.info ./extensions/notebook/coverage/lcov.info ./extensions/resource-deployment/coverage/lcov.info ./extensions/machine-learning/coverage/lcov.info ./extensions/sql-database-projects/coverage/lcov.info > .build/coverage-combined/lcov.info - name: Merge coverage reports + # {{SQL CARBON EDIT}} Add coveralls. We merge first to get around issue where parallel builds weren't being combined correctly + - run: node test/combineCoverage + name: Combine code coverage files - name: Upload Code Coverage uses: coverallsapp/github-action@v1.1.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: '.build/coverage-combined/lcov.info' + path-to-lcov: 'test/coverage/lcov.info' # Fails with cryptic error (e.g. https://github.com/microsoft/vscode/pull/90292/checks?check_run_id=433681926#step:13:9) # - run: DISPLAY=:10 yarn test-browser --browser chromium diff --git a/extensions/admin-tool-ext-win/coverConfig.json b/extensions/admin-tool-ext-win/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/admin-tool-ext-win/coverConfig.json +++ b/extensions/admin-tool-ext-win/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/admin-tool-ext-win/package.json b/extensions/admin-tool-ext-win/package.json index 10a01fafdb..703a463ac4 100644 --- a/extensions/admin-tool-ext-win/package.json +++ b/extensions/admin-tool-ext-win/package.json @@ -85,7 +85,7 @@ "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "should": "^13.2.3", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "__metadata": { "id": "41", diff --git a/extensions/admin-tool-ext-win/yarn.lock b/extensions/admin-tool-ext-win/yarn.lock index 00b489fa65..870e5ae50a 100644 --- a/extensions/admin-tool-ext-win/yarn.lock +++ b/extensions/admin-tool-ext-win/yarn.lock @@ -935,9 +935,10 @@ vscode-nls@^3.2.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4" integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/agent/coverConfig.json b/extensions/agent/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/agent/coverConfig.json +++ b/extensions/agent/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/agent/package.json b/extensions/agent/package.json index 260671dd73..d17f6a190e 100644 --- a/extensions/agent/package.json +++ b/extensions/agent/package.json @@ -90,7 +90,7 @@ "mocha-multi-reporters": "^1.1.7", "should": "^13.2.1", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "__metadata": { "id": "10", diff --git a/extensions/agent/yarn.lock b/extensions/agent/yarn.lock index c77216ebdf..dabaecd451 100644 --- a/extensions/agent/yarn.lock +++ b/extensions/agent/yarn.lock @@ -769,9 +769,10 @@ vscode-nls@^3.2.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4" integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/azurecore/coverConfig.json b/extensions/azurecore/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/azurecore/coverConfig.json +++ b/extensions/azurecore/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/azurecore/package.json b/extensions/azurecore/package.json index d950b228b4..ed9d84d429 100644 --- a/extensions/azurecore/package.json +++ b/extensions/azurecore/package.json @@ -146,10 +146,7 @@ { "command": "azure.resource.startterminal", "title": "%azure.resource.startterminal.title%", - "icon": { - "dark": "resources/dark/console.svg", - "light": "resources/light/console.svg" - } + "icon": "$(console)" }, { "command": "azure.resource.openInAzurePortal", @@ -288,6 +285,6 @@ "mocha-multi-reporters": "^1.1.7", "should": "^13.2.1", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" } } diff --git a/extensions/azurecore/resources/dark/console.svg b/extensions/azurecore/resources/dark/console.svg deleted file mode 100644 index 1e2d3b4ee1..0000000000 --- a/extensions/azurecore/resources/dark/console.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/extensions/azurecore/resources/light/console.svg b/extensions/azurecore/resources/light/console.svg deleted file mode 100644 index 429cb22b71..0000000000 --- a/extensions/azurecore/resources/light/console.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/extensions/azurecore/yarn.lock b/extensions/azurecore/yarn.lock index 616a526359..afd5436703 100644 --- a/extensions/azurecore/yarn.lock +++ b/extensions/azurecore/yarn.lock @@ -1331,9 +1331,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/cms/coverConfig.json b/extensions/cms/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/cms/coverConfig.json +++ b/extensions/cms/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/cms/package.json b/extensions/cms/package.json index ee4e796e8b..8814f24ed5 100644 --- a/extensions/cms/package.json +++ b/extensions/cms/package.json @@ -657,7 +657,7 @@ "mocha-multi-reporters": "^1.1.7", "mocha": "^5.2.0", "should": "^13.2.1", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6", + "vscodetestcover": "^1.0.9", "typemoq": "^2.1.0" }, "__metadata": { diff --git a/extensions/cms/yarn.lock b/extensions/cms/yarn.lock index f98f946d26..fc827d0150 100644 --- a/extensions/cms/yarn.lock +++ b/extensions/cms/yarn.lock @@ -1088,9 +1088,10 @@ vscode-nls@^4.0.0: resolved "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/dacpac/coverConfig.json b/extensions/dacpac/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/dacpac/coverConfig.json +++ b/extensions/dacpac/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/dacpac/coverageConfig.json b/extensions/dacpac/coverageConfig.json index 8fbe6b33ec..f461a00224 100644 --- a/extensions/dacpac/coverageConfig.json +++ b/extensions/dacpac/coverageConfig.json @@ -5,7 +5,6 @@ "ignorePatterns": [ "**/node_modules/**" ], - "includePid": false, "reports": [ "cobertura" ], @@ -14,4 +13,4 @@ "basePath": ".", "useAbsolutePaths": true } -} \ No newline at end of file +} diff --git a/extensions/dacpac/package.json b/extensions/dacpac/package.json index 71c0bb539b..f785582991 100644 --- a/extensions/dacpac/package.json +++ b/extensions/dacpac/package.json @@ -62,7 +62,7 @@ "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "should": "^13.2.1", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "__metadata": { "id": "33", diff --git a/extensions/dacpac/yarn.lock b/extensions/dacpac/yarn.lock index b8c6efe482..2a17c3227a 100644 --- a/extensions/dacpac/yarn.lock +++ b/extensions/dacpac/yarn.lock @@ -816,9 +816,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/integration-tests/coverConfig.json b/extensions/integration-tests/coverConfig.json new file mode 100644 index 0000000000..c6f734ea6f --- /dev/null +++ b/extensions/integration-tests/coverConfig.json @@ -0,0 +1,21 @@ +{ + "enabled": true, + "relativeSourcePath": "../../../", + "relativeCoverageDir": "../../coverage", + "ignorePatterns": [ + "**/coverage/**", + "**/generated/**", + "**/node_modules/**", + "**/test/**" + ], + "reports": [ + "cobertura", + "lcov", + "json" + ], + "verbose": false, + "remapOptions": { + "basePath": "../../../", + "useAbsolutePaths": true + } +} diff --git a/extensions/integration-tests/package.json b/extensions/integration-tests/package.json index 37e4a47baf..7dc25fc3ef 100644 --- a/extensions/integration-tests/package.json +++ b/extensions/integration-tests/package.json @@ -22,8 +22,7 @@ "Microsoft.azuredatastudio-postgresql" ], "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json", - "postinstall": "node ./node_modules/vscode/bin/install" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json" }, "devDependencies": { "@types/chai": "3.4.34", @@ -33,6 +32,6 @@ "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "ms-rest-azure": "^2.6.0", - "vscode": "1.1.5" + "vscodetestcover": "^1.0.9" } } diff --git a/extensions/integration-tests/src/tests/cms.test.ts b/extensions/integration-tests/src/test/cms.test.ts similarity index 100% rename from extensions/integration-tests/src/tests/cms.test.ts rename to extensions/integration-tests/src/test/cms.test.ts diff --git a/extensions/integration-tests/src/tests/dacpac.test.ts b/extensions/integration-tests/src/test/dacpac.test.ts similarity index 100% rename from extensions/integration-tests/src/tests/dacpac.test.ts rename to extensions/integration-tests/src/test/dacpac.test.ts diff --git a/extensions/integration-tests/src/test/index.ts b/extensions/integration-tests/src/test/index.ts new file mode 100644 index 0000000000..7af43652ec --- /dev/null +++ b/extensions/integration-tests/src/test/index.ts @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as testRunner from 'vscodetestcover'; + +const suite = 'Extension Integration Tests'; + +const mochaOptions: any = { + ui: 'tdd', + useColors: true, + timeout: 60000 +}; + +// set relevant mocha options from the environment +if (process.env.ADS_TEST_GREP) { + mochaOptions.grep = process.env.ADS_TEST_GREP; + console.log(`setting options.grep to: ${mochaOptions.grep}`); +} +if (process.env.ADS_TEST_INVERT_GREP) { + mochaOptions.invert = parseInt(process.env.ADS_TEST_INVERT_GREP); + console.log(`setting options.invert to: ${mochaOptions.invert}`); +} +if (process.env.ADS_TEST_TIMEOUT) { + mochaOptions.timeout = parseInt(process.env.ADS_TEST_TIMEOUT); + console.log(`setting options.timeout to: ${mochaOptions.timeout}`); +} +if (process.env.ADS_TEST_RETRIES) { + mochaOptions.retries = parseInt(process.env.ADS_TEST_RETRIES); + console.log(`setting options.retries to: ${mochaOptions.retries}`); +} + +if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { + mochaOptions.reporter = 'mocha-multi-reporters'; + mochaOptions.reporterOptions = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + testsuitesTitle: `${suite} ${process.platform}`, + mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) + } + }; +} + +testRunner.configure(mochaOptions, { coverConfig: '../../coverConfig.json' }); + +export = testRunner; diff --git a/extensions/integration-tests/src/tests/notebook.test.ts b/extensions/integration-tests/src/test/notebook.test.ts similarity index 98% rename from extensions/integration-tests/src/tests/notebook.test.ts rename to extensions/integration-tests/src/test/notebook.test.ts index c5fd6cad08..a70a5153e0 100644 --- a/extensions/integration-tests/src/tests/notebook.test.ts +++ b/extensions/integration-tests/src/test/notebook.test.ts @@ -84,7 +84,7 @@ suite('Notebook integration test suite', function () { } }); - test('Sql NB run cells above and below test', async function () { + test('Sql NB run cells above and below test @UNSTABLE@', async function () { let notebook = await openNotebook(sqlNotebookMultipleCellsContent, sqlKernelMetadata, this.test.title + this.invocationCount++); // When running all cells above a cell, ensure that only cells preceding current cell have output await runCells(notebook, true, undefined, notebook.document.cells[1]); @@ -101,13 +101,13 @@ suite('Notebook integration test suite', function () { assert(notebook.document.cells[2].contents.outputs.length === 3, `Expected length: '3', Actual: '${notebook.document.cells[2].contents.outputs.length}'`); }); - test('Clear cell output - SQL notebook', async function () { + test('Clear cell output - SQL notebook @UNSTABLE@', async function () { let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++); await runCell(notebook); await verifyClearOutputs(notebook); }); - test('Clear all outputs - SQL notebook ', async function () { + test('Clear all outputs - SQL notebook @UNSTABLE@', async function () { let notebook = await openNotebook(sqlNotebookContent, sqlKernelMetadata, this.test.title + this.invocationCount++); await runCell(notebook); await verifyClearAllOutputs(notebook); diff --git a/extensions/integration-tests/src/tests/notebook.util.ts b/extensions/integration-tests/src/test/notebook.util.ts similarity index 100% rename from extensions/integration-tests/src/tests/notebook.util.ts rename to extensions/integration-tests/src/test/notebook.util.ts diff --git a/extensions/integration-tests/src/tests/objectExplorer.test.ts b/extensions/integration-tests/src/test/objectExplorer.test.ts similarity index 100% rename from extensions/integration-tests/src/tests/objectExplorer.test.ts rename to extensions/integration-tests/src/test/objectExplorer.test.ts diff --git a/extensions/integration-tests/src/tests/schemaCompare.test.ts b/extensions/integration-tests/src/test/schemaCompare.test.ts similarity index 100% rename from extensions/integration-tests/src/tests/schemaCompare.test.ts rename to extensions/integration-tests/src/test/schemaCompare.test.ts diff --git a/extensions/integration-tests/src/tests/testConfig.ts b/extensions/integration-tests/src/test/testConfig.ts similarity index 100% rename from extensions/integration-tests/src/tests/testConfig.ts rename to extensions/integration-tests/src/test/testConfig.ts diff --git a/extensions/integration-tests/src/tests/utils.ts b/extensions/integration-tests/src/test/utils.ts similarity index 100% rename from extensions/integration-tests/src/tests/utils.ts rename to extensions/integration-tests/src/test/utils.ts diff --git a/extensions/integration-tests/src/tests/uuid.ts b/extensions/integration-tests/src/test/uuid.ts similarity index 100% rename from extensions/integration-tests/src/tests/uuid.ts rename to extensions/integration-tests/src/test/uuid.ts diff --git a/extensions/integration-tests/src/tests/index.ts b/extensions/integration-tests/src/tests/index.ts deleted file mode 100644 index 047811dde9..0000000000 --- a/extensions/integration-tests/src/tests/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as testRunner from 'vscode/lib/testrunner'; -import * as path from 'path'; - -const suite = 'Extension Integration Tests'; - -const options: any = { - ui: 'tdd', - useColors: true, - timeout: 600000 -}; - -// set relevant mocha options from the environment -if (process.env.ADS_TEST_GREP) { - options.grep = process.env.ADS_TEST_GREP; - console.log(`setting options.grep to: ${options.grep}`); -} -if (process.env.ADS_TEST_INVERT_GREP) { - const value = parseInt(process.env.ADS_TEST_INVERT_GREP); - options.invert = Boolean(value); - console.log(`setting options.invert to: ${options.invert}`); -} -if (process.env.ADS_TEST_TIMEOUT) { - options.timeout = parseInt(process.env.ADS_TEST_TIMEOUT); - console.log(`setting options.timeout to: ${options.timeout}`); -} -if (process.env.ADS_TEST_RETRIES) { - options.retries = parseInt(process.env.ADS_TEST_RETRIES); - console.log(`setting options.retries to: ${options.retries}`); -} - -if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { - console.log(`environment variable BUILD_ARTIFACTSTAGINGDIRECTORY is set to ${process.env.BUILD_ARTIFACTSTAGINGDIRECTORY} so configuring multiple reporters for test results.\n For this to work the ${process.env.BUILD_ARTIFACTSTAGINGDIRECTORY} must be fully qualified directory and must exist`); - options.reporter = 'mocha-multi-reporters'; - options.reporterOptions = { - reporterEnabled: 'spec, mocha-junit-reporter', - mochaJunitReporterReporterOptions: { - testsuitesTitle: `${suite} Tests ${process.platform}`, - mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) - } - }; -} - -testRunner.configure(options); - -export = testRunner; diff --git a/extensions/integration-tests/src/typings/ref.d.ts b/extensions/integration-tests/src/typings/ref.d.ts index 2d7a90ea8a..7c5bd314ae 100644 --- a/extensions/integration-tests/src/typings/ref.d.ts +++ b/extensions/integration-tests/src/typings/ref.d.ts @@ -5,4 +5,5 @@ /// /// /// +/// /// diff --git a/extensions/integration-tests/yarn.lock b/extensions/integration-tests/yarn.lock index 46d809bf88..4790183309 100644 --- a/extensions/integration-tests/yarn.lock +++ b/extensions/integration-tests/yarn.lock @@ -2,6 +2,186 @@ # yarn lockfile v1 +"@babel/code-frame@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" + integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== + dependencies: + "@babel/highlight" "^7.10.1" + +"@babel/core@^7.7.5": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.1.tgz#2a0ad0ea693601820defebad2140206503d89af3" + integrity sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/generator" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helpers" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.1.tgz#4d14458e539bcb04ffe34124143f5c489f2dbca9" + integrity sha512-AT0YPLQw9DI21tliuJIdplVfLHya6mcGa8ctkv7n4Qv+hYacJrKmNWIteAK1P9iyLikFIAkwqJ7HAOqIDLFfgA== + dependencies: + "@babel/types" "^7.10.1" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" + integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-get-function-arity@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" + integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-member-expression-to-functions@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" + integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-module-imports@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" + integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-module-transforms@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" + integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== + dependencies: + "@babel/helper-module-imports" "^7.10.1" + "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" + integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-replace-supers@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" + integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.1" + "@babel/helper-optimise-call-expression" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-simple-access@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" + integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-split-export-declaration@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" + integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-validator-identifier@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" + integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== + +"@babel/helpers@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" + integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/highlight@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" + integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== + dependencies: + "@babel/helper-validator-identifier" "^7.10.1" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.1.tgz#2e142c27ca58aa2c7b119d09269b702c8bbad28c" + integrity sha512-AUTksaz3FqugBkbTZ1i+lDLG5qy8hIzCaAxEtttU6C0BtZZU9pkNZtWSVAht4EW9kl46YBiyTGMp9xTTGqViNg== + +"@babel/template@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" + integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/traverse@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" + integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/generator" "^7.10.1" + "@babel/helper-function-name" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/types" "^7.10.1" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.1.tgz#6886724d31c8022160a7db895e6731ca33483921" + integrity sha512-L2yqUOpf3tzlW9GVuipgLEcZxnO+96SzR6fjXMuxxNkIgFJ5+07mHCZ+HkHqaeZu8+3LKnNJJ1bKbjBETQAsrA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.1" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + "@types/chai@3.4.34": version "3.4.34" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.34.tgz#d5335792823bb09cddd5e38c3d211b709183854d" @@ -42,103 +222,24 @@ ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" + color-convert "^1.9.0" -arr-diff@^2.0.0: +append-transform@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + default-require-extensions "^3.0.0" asn1@~0.2.3: version "0.2.3" @@ -204,18 +305,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - integrity sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak= - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -224,30 +313,21 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= +callsite@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -262,60 +342,31 @@ chai@3.5.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= - -clone@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -cloneable-readable@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" - integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" + color-name "1.1.3" -color-support@^1.1.3: +color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.7" @@ -324,26 +375,24 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -convert-source-map@^1.1.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= @@ -365,15 +414,10 @@ date-utils@*: resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= -dateformat@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" - integrity sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI= - -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= +debug@3.1.0, 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" @@ -384,19 +428,19 @@ debug@^2.2.0: dependencies: ms "2.0.0" -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== +debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: - ms "2.0.0" + ms "^2.1.1" -deep-assign@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" - integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= +decache@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/decache/-/decache-4.6.0.tgz#87026bc6e696759e82d57a3841c4e251a30356e8" + integrity sha512-PppOuLiz+DFeaUvFXEYZjLxAkKiMYH/do/b/MxpDe/8AgKBi5GhZxridoVIbBq72GDbL36e4p0Ce2jTGUwwU+w== dependencies: - is-obj "^1.0.0" + callsite "^1.0.0" deep-eql@^0.1.3: version "0.1.3" @@ -405,38 +449,28 @@ deep-eql@^0.1.3: dependencies: type-detect "0.1.1" +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" - integrity sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds= - dependencies: - readable-stream "~1.1.9" - -duplexer@^0.1.1, duplexer@~0.1.1: +duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= -duplexify@^3.2.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -451,99 +485,21 @@ ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer "^5.0.1" -end-of-stream@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== - dependencies: - once "^1.4.0" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -event-stream@3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - -event-stream@^3.3.1, event-stream@~3.3.4: - version "3.3.5" - resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" - integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== - dependencies: - duplexer "^0.1.1" - from "^0.1.7" - map-stream "0.0.7" - pause-stream "^0.0.11" - split "^1.0.1" - stream-combiner "^0.2.2" - through "^2.3.8" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= - dependencies: - fill-range "^2.1.0" - -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend@^3.0.0, extend@~3.0.2: +extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= - dependencies: - is-extglob "^1.0.0" - extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= -fancy-log@^1.1.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -554,46 +510,6 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= - dependencies: - for-in "^1.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -608,30 +524,15 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -from@^0.1.7, from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== getpass@^0.1.1: version "0.1.7" @@ -640,67 +541,31 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-stream@^5.3.2: - version "5.3.5" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" - integrity sha1-pVZlqajM3EGRWofHAeMtTgFvrSI= - dependencies: - extend "^3.0.0" - glob "^5.0.3" - glob-parent "^3.0.0" - micromatch "^2.3.7" - ordered-read-streams "^0.3.0" - through2 "^0.6.0" - to-absolute-glob "^0.1.1" - unique-stream "^2.0.2" - -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= +glob@^7.1.2: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: + fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "2 || 3" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3: +glob@^7.1.3: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== @@ -712,140 +577,15 @@ glob@^7.1.1, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.0.0, graceful-fs@^4.1.2: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== - -"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: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - -gulp-chmod@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" - integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= - dependencies: - deep-assign "^1.0.0" - stat-mode "^0.2.0" - through2 "^2.0.0" - -gulp-filter@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" - integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= - dependencies: - multimatch "^2.0.0" - plugin-error "^0.1.2" - streamfilter "^1.0.5" - -gulp-gunzip@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-0.0.3.tgz#7b6e07b0f58fd3d42515c48ead5a63df0572f62f" - integrity sha1-e24HsPWP09QlFcSOrVpj3wVy9i8= - dependencies: - through2 "~0.6.5" - vinyl "~0.4.6" - -gulp-remote-src@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/gulp-remote-src/-/gulp-remote-src-0.4.4.tgz#4a4d18fac0ffedde94a7855953de90db00a1d1b1" - integrity sha512-mo7lGgZmNXyTbcUzfjSnUVkx1pnqqiwv/pPaIrYdTO77hq0WNTxXLAzQdoYOnyJ0mfVLNmNl9AGqWLiAzTPMMA== - dependencies: - event-stream "3.3.4" - node.extend "~1.1.2" - request "^2.88.0" - through2 "~2.0.3" - vinyl "~2.0.1" - -gulp-sourcemaps@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" - integrity sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw= - dependencies: - convert-source-map "^1.1.1" - graceful-fs "^4.1.2" - strip-bom "^2.0.0" - through2 "^2.0.0" - vinyl "^1.0.0" - -gulp-symdest@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/gulp-symdest/-/gulp-symdest-1.1.1.tgz#b0a6df3d43a0537165946ab8e38c1b7080a66fac" - integrity sha512-UHd3MokfIN7SrFdsbV5uZTwzBpL0ZSTu7iq98fuDqBGZ0dlHxgbQBJwfd6qjCW83snkQ3Hz9IY4sMRMz2iTq7w== - dependencies: - event-stream "3.3.4" - mkdirp "^0.5.1" - queue "^3.1.0" - vinyl-fs "^2.4.3" - -gulp-untar@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.6.tgz#d6bdefde7e9a8e054c9f162385a0782c4be74000" - integrity sha1-1r3v3n6ajgVMnxYjhaB4LEvnQAA= - dependencies: - event-stream "~3.3.4" - gulp-util "~3.0.8" - streamifier "~0.1.1" - tar "^2.2.1" - through2 "~2.0.3" - -gulp-util@~3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - integrity sha1-AFTh50RQLifATBh8PsxQXdVLu08= - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp-vinyl-zip@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-1.4.0.tgz#56382f2ccb57231bb0478c78737ccd572973bee1" - integrity sha1-VjgvLMtXIxuwR4x4c3zNVylzvuE= - dependencies: - event-stream "^3.3.1" - queue "^3.0.10" - through2 "^0.6.3" - vinyl "^0.4.6" - vinyl-fs "^2.0.0" - yauzl "^2.2.1" - yazl "^2.2.1" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== har-schema@^2.0.0: version "2.0.0" @@ -860,37 +600,26 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - integrity sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4= - dependencies: - sparkles "^1.0.0" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -908,85 +637,17 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -is-buffer@^1.1.5, is-buffer@^1.1.6, is-buffer@~1.1.1: +is-buffer@^1.1.6, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= - -is-extglob@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= - -is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= @@ -996,48 +657,81 @@ is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" - integrity sha1-1LVcafUYhvm2XHDWwmItN+KfSP4= - -is@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" - integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== + +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" + source-map "^0.6.1" + +istanbul-reports@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1048,20 +742,17 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" jsprim@^1.2.2: version "1.4.1" @@ -1090,175 +781,25 @@ jws@3.x.x: jwa "^1.4.1" safe-buffer "^5.0.1" -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= - -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - integrity sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U= - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" - integrity sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - integrity sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo= - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - integrity sha1-WLx0xAZklTrgsSTYBpltrKQx4u0= - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI= - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" - integrity sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg= - dependencies: - lodash._root "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - -lodash.isequal@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - integrity sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8= - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - integrity sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU= - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - -lodash@^4.14.0, lodash@^4.16.4, lodash@^4.17.11: +lodash@^4.14.0, lodash@^4.16.4, lodash@^4.17.11, lodash@^4.17.13: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -map-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= - -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" md5@^2.1.0: version "2.2.1" @@ -1269,32 +810,6 @@ md5@^2.1.0: crypt "~0.0.1" is-buffer "~1.1.1" -merge-stream@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" - integrity sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE= - dependencies: - readable-stream "^2.0.1" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" @@ -1319,7 +834,7 @@ mime-types@~2.1.19: dependencies: mime-db "~1.38.0" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -1331,12 +846,12 @@ minimist@0.0.8: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -1362,23 +877,22 @@ mocha-multi-reporters@^1.1.7: debug "^3.1.0" lodash "^4.16.4" -mocha@^3.2.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" + glob "7.1.2" + growl "1.10.5" he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" + minimatch "3.0.4" mkdirp "0.5.1" - supports-color "3.1.2" + supports-color "5.4.0" moment@^2.21.0, moment@^2.22.2: version "2.24.0" @@ -1416,138 +930,42 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - integrity sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s= - dependencies: - duplexer2 "0.0.2" - -node.extend@~1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" - integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== - dependencies: - has "^1.0.3" - is "^3.2.1" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= - -object-assign@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -ordered-read-streams@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" - integrity sha1-cTfmmzKYuzQiR6G77jiByA4v14s= - dependencies: - is-stream "^1.0.1" - readable-stream "^2.0.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -pause-stream@0.0.11, pause-stream@^0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= - dependencies: - through "~2.3" - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== psl@^1.1.24: version "1.1.31" @@ -1569,93 +987,7 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - -queue@^3.0.10, queue@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/queue/-/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" - integrity sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU= - dependencies: - inherits "~2.0.0" - -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - 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: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -"request@>= 2.52.0", request@^2.79.0, request@^2.88.0: +"request@>= 2.52.0", request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -1681,15 +1013,17 @@ replace-ext@^1.0.0: tunnel-agent "^0.6.0" uuid "^3.3.2" -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" -rimraf@2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== +rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" @@ -1698,46 +1032,30 @@ safe-buffer@^5.0.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== -safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.1.2, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -semver@^5.3.0: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@^5.4.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -source-map-support@^0.4.11: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -source-map@^0.5.6: +source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= - dependencies: - through "2" - -split@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sshpk@^1.7.0: version "1.13.1" @@ -1754,62 +1072,6 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -stat-mode@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" - integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= - -stream-combiner@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" - integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= - dependencies: - duplexer "~0.1.1" - through "~2.3.4" - -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= - dependencies: - duplexer "~0.1.1" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -streamfilter@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" - integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== - dependencies: - readable-stream "^2.0.2" - -streamifier@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -1817,90 +1079,41 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-bom-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" - integrity sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4= +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== dependencies: - first-chunk-stream "^1.0.0" - strip-bom "^2.0.0" + has-flag "^3.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: - is-utf8 "^0.2.0" + has-flag "^3.0.0" -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== dependencies: - has-flag "^1.0.0" + has-flag "^4.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -through2-filter@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" - integrity sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw= - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^0.6.0, through2@^0.6.3, through2@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - -through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: +through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -to-absolute-glob@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" - integrity sha1-HN+kcqnvUMI57maZm2YsoOs5k38= - dependencies: - extend-shallow "^2.0.1" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= tough-cookie@~2.4.3: version "2.4.3" @@ -1942,14 +1155,6 @@ type-detect@^1.0.0: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -1957,19 +1162,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url-parse@^1.1.9: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - uuid@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -1980,11 +1172,6 @@ uuid@^3.2.1, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -vali-date@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" - integrity sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY= - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -1994,95 +1181,20 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: - version "2.4.4" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" - integrity sha1-vm/zJwy1Xf19MGNkDegfJddTIjk= +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: - duplexify "^3.2.0" - glob-stream "^5.3.2" - graceful-fs "^4.0.0" - gulp-sourcemaps "1.6.0" - is-valid-glob "^0.3.0" - lazystream "^1.0.0" - lodash.isequal "^4.0.0" - merge-stream "^1.0.0" - mkdirp "^0.5.0" - object-assign "^4.0.0" - readable-stream "^2.0.4" - strip-bom "^2.0.0" - strip-bom-stream "^1.0.0" - through2 "^2.0.0" - through2-filter "^2.0.0" - vali-date "^1.0.0" - vinyl "^1.0.0" - -vinyl-source-stream@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" - integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= - dependencies: - through2 "^2.0.3" - vinyl "^0.4.3" - -vinyl@^0.4.3, vinyl@^0.4.6, vinyl@~0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - integrity sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.0.2.tgz#0a3713d8d4e9221c58f10ca16c0116c9e25eda7c" - integrity sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw= - dependencies: - clone "^1.0.0" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - is-stream "^1.1.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vscode@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.5.tgz#10eb104001840c3dd0813815fd4a05f8fc882d14" - integrity sha1-EOsQQAGEDD3QgTgV/UoF+PyILRQ= - dependencies: - glob "^7.1.1" - gulp-chmod "^2.0.0" - gulp-filter "^5.0.0" - gulp-gunzip "0.0.3" - gulp-remote-src "^0.4.2" - gulp-symdest "^1.1.0" - gulp-untar "^0.0.6" - gulp-vinyl-zip "^1.4.0" - mocha "^3.2.0" - request "^2.79.0" - semver "^5.3.0" - source-map-support "^0.4.11" - url-parse "^1.1.9" - vinyl-source-stream "^1.1.0" + decache "^4.4.0" + glob "^7.1.2" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^3.0.0" + mocha "^5.2.0" wrappy@1: version "1.0.2" @@ -2103,23 +1215,3 @@ xpath.js@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/xpath.js/-/xpath.js-1.1.0.tgz#3816a44ed4bb352091083d002a383dd5104a5ff1" integrity sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ== - -"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= - -yauzl@^2.2.1: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - -yazl@^2.2.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" - integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== - dependencies: - buffer-crc32 "~0.2.3" diff --git a/extensions/machine-learning/config.json b/extensions/machine-learning/config.json index a206e4b3e7..84fe9414cc 100644 --- a/extensions/machine-learning/config.json +++ b/extensions/machine-learning/config.json @@ -3,7 +3,7 @@ "requiredPythonPackages": [ { "name": "sqlmlutils", - "version": "1.0.0" + "version": "1.0.1" } ], "requiredRPackages": [ diff --git a/extensions/machine-learning/coverConfig.json b/extensions/machine-learning/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/machine-learning/coverConfig.json +++ b/extensions/machine-learning/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/machine-learning/package.json b/extensions/machine-learning/package.json index c3f537c05d..132fb3878a 100644 --- a/extensions/machine-learning/package.json +++ b/extensions/machine-learning/package.json @@ -148,7 +148,7 @@ "mocha-multi-reporters": "^1.1.7", "should": "^13.2.1", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "__metadata": { "id": "65", diff --git a/extensions/machine-learning/src/packageManagement/sqlPythonPackageManageProvider.ts b/extensions/machine-learning/src/packageManagement/sqlPythonPackageManageProvider.ts index 642bbd0d92..9a8c5d8bbe 100644 --- a/extensions/machine-learning/src/packageManagement/sqlPythonPackageManageProvider.ts +++ b/extensions/machine-learning/src/packageManagement/sqlPythonPackageManageProvider.ts @@ -67,13 +67,14 @@ export class SqlPythonPackageManageProvider extends SqlPackageManageProviderBase let port = '1433'; let server = connection.serverName; let database = databaseName ? `, database="${databaseName}"` : ''; + const auth = connection.userName ? `, uid="${connection.userName}", pwd="${credentials[azdata.ConnectionOptionSpecialType.password]}"` : ''; let index = connection.serverName.indexOf(','); if (index > 0) { port = connection.serverName.substring(index + 1); server = connection.serverName.substring(0, index); } - let pythonConnectionParts = `server="${server}", port=${port}, uid="${connection.userName}", pwd="${credentials[azdata.ConnectionOptionSpecialType.password]}"${database})`; + let pythonConnectionParts = `server="${server}", port=${port}${auth}${database})`; let pythonCommandScript = scriptMode === ScriptMode.Install ? `pkgmanager.install(package="${packageDetails.name}", version="${packageDetails.version}")` : `pkgmanager.uninstall(package_name="${packageDetails.name}")`; diff --git a/extensions/machine-learning/src/prediction/predictService.ts b/extensions/machine-learning/src/prediction/predictService.ts index b3bec3a04a..37bfb27554 100644 --- a/extensions/machine-learning/src/prediction/predictService.ts +++ b/extensions/machine-learning/src/prediction/predictService.ts @@ -83,7 +83,7 @@ export class PredictService { language: 'sql', content: query }); - await this._apiWrapper.showTextDocument(document.uri); + await this._apiWrapper.executeCommand('vscode.open', document.uri); await this._apiWrapper.connect(document.uri.toString(), connection.connectionId); this._apiWrapper.runQuery(document.uri.toString(), undefined, false); return query; diff --git a/extensions/machine-learning/src/test/packageManagement/sqlPythonPackageManageProvider.test.ts b/extensions/machine-learning/src/test/packageManagement/sqlPythonPackageManageProvider.test.ts index d8a38148c6..bb30529b88 100644 --- a/extensions/machine-learning/src/test/packageManagement/sqlPythonPackageManageProvider.test.ts +++ b/extensions/machine-learning/src/test/packageManagement/sqlPythonPackageManageProvider.test.ts @@ -132,6 +132,7 @@ describe('SQL Python Package Manager', () => { let connection = new azdata.connection.ConnectionProfile(); connection.serverName = 'serverName'; connection.databaseName = 'databaseName'; + connection.userName = 'user'; let credentials = { [azdata.ConnectionOptionSpecialType.password]: 'password' }; testContext.apiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(connection); }); testContext.apiWrapper.setup(x => x.getCredentials(TypeMoq.It.isAny())).returns(() => { return Promise.resolve(credentials); }); @@ -173,6 +174,7 @@ describe('SQL Python Package Manager', () => { let connection = new azdata.connection.ConnectionProfile(); connection.serverName = 'serverName'; connection.databaseName = 'databaseName'; + connection.userName = 'user'; let credentials = { [azdata.ConnectionOptionSpecialType.password]: 'password' }; testContext.apiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(connection); }); testContext.apiWrapper.setup(x => x.getCredentials(TypeMoq.It.isAny())).returns(() => { return Promise.resolve(credentials); }); @@ -213,6 +215,7 @@ describe('SQL Python Package Manager', () => { let connection = new azdata.connection.ConnectionProfile(); connection.serverName = 'serverName,3433'; connection.databaseName = 'databaseName'; + connection.userName = 'user'; let credentials = { [azdata.ConnectionOptionSpecialType.password]: 'password' }; testContext.apiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(connection); }); testContext.apiWrapper.setup(x => x.getCredentials(TypeMoq.It.isAny())).returns(() => { return Promise.resolve(credentials); }); @@ -237,6 +240,88 @@ describe('SQL Python Package Manager', () => { should.deepEqual(packagesUpdated, true); }); + it('installPackages Should not include credential for windows auth', async function (): Promise { + let testContext = createContext(); + let packagesUpdated = false; + let packages: nbExtensionApis.IPackageDetails[] = [ + { + 'name': 'a-name', + 'version': '1.1.2' + }, + { + 'name': 'b-name', + 'version': '1.1.1' + } + ]; + + let connection = new azdata.connection.ConnectionProfile(); + connection.serverName = 'serverName,3433'; + connection.databaseName = 'databaseName'; + let credentials = { [azdata.ConnectionOptionSpecialType.password]: 'password' }; + testContext.apiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(connection); }); + testContext.apiWrapper.setup(x => x.getCredentials(TypeMoq.It.isAny())).returns(() => { return Promise.resolve(credentials); }); + testContext.processService.setup(x => x.execScripts(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((path, scripts: string[]) => { + + if (path && scripts.find(x => x.indexOf('install') > 0) && + scripts.find(x => x.indexOf('port=3433') > 0) && + scripts.find(x => x.indexOf('server="serverName"') > 0) && + scripts.find(x => x.indexOf('database="databaseName"') > 0) && + scripts.find(x => x.indexOf('package="a-name"') > 0) && + scripts.find(x => x.indexOf('version="1.1.2"') > 0) && + scripts.find(x => x.indexOf('pwd="password"') < 0)) { + packagesUpdated = true; + } + + return Promise.resolve(''); + }); + + let provider = createProvider(testContext); + await provider.installPackages(packages, false, connection.databaseName); + + should.deepEqual(packagesUpdated, true); + }); + + it('installPackages Should not include database if not specified', async function (): Promise { + let testContext = createContext(); + let packagesUpdated = false; + let packages: nbExtensionApis.IPackageDetails[] = [ + { + 'name': 'a-name', + 'version': '1.1.2' + }, + { + 'name': 'b-name', + 'version': '1.1.1' + } + ]; + + let connection = new azdata.connection.ConnectionProfile(); + connection.serverName = 'serverName,3433'; + connection.databaseName = ''; + let credentials = { [azdata.ConnectionOptionSpecialType.password]: 'password' }; + testContext.apiWrapper.setup(x => x.getCurrentConnection()).returns(() => { return Promise.resolve(connection); }); + testContext.apiWrapper.setup(x => x.getCredentials(TypeMoq.It.isAny())).returns(() => { return Promise.resolve(credentials); }); + testContext.processService.setup(x => x.execScripts(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((path, scripts: string[]) => { + + if (path && scripts.find(x => x.indexOf('install') > 0) && + scripts.find(x => x.indexOf('port=3433') > 0) && + scripts.find(x => x.indexOf('server="serverName"') > 0) && + scripts.find(x => x.indexOf('database="databaseName"') < 0) && + scripts.find(x => x.indexOf('package="a-name"') > 0) && + scripts.find(x => x.indexOf('version="1.1.2"') > 0) && + scripts.find(x => x.indexOf('pwd="password"') < 0)) { + packagesUpdated = true; + } + + return Promise.resolve(''); + }); + + let provider = createProvider(testContext); + await provider.installPackages(packages, false, connection.databaseName); + + should.deepEqual(packagesUpdated, true); + }); + it('installPackages Should not install any packages give empty list', async function (): Promise { let testContext = createContext(); let packagesUpdated = false; diff --git a/extensions/machine-learning/src/test/views/externalLanguages/languagesDialog.test.ts b/extensions/machine-learning/src/test/views/externalLanguages/languagesDialog.test.ts deleted file mode 100644 index 535f78e6a6..0000000000 --- a/extensions/machine-learning/src/test/views/externalLanguages/languagesDialog.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as should from 'should'; -import 'mocha'; -import { createContext } from './utils'; -import { LanguagesDialog } from '../../../views/externalLanguages/languagesDialog'; - -describe('External Languages Dialog', () => { - it('Should open dialog successfully ', async function (): Promise { - let testContext = createContext(); - let dialog = new LanguagesDialog(testContext.apiWrapper.object, ''); - dialog.showDialog(); - should.notEqual(dialog.addNewLanguageTab, undefined); - should.notEqual(dialog.currentLanguagesTab, undefined); - }); -}); diff --git a/extensions/machine-learning/yarn.lock b/extensions/machine-learning/yarn.lock index e3cf5506e3..276b063ec5 100644 --- a/extensions/machine-learning/yarn.lock +++ b/extensions/machine-learning/yarn.lock @@ -1242,9 +1242,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/mssql/coverConfig.json b/extensions/mssql/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/mssql/coverConfig.json +++ b/extensions/mssql/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index e25d3af458..c6d2eba556 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -1110,6 +1110,6 @@ "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" } } diff --git a/extensions/mssql/yarn.lock b/extensions/mssql/yarn.lock index fa8a1473fa..69fd902818 100644 --- a/extensions/mssql/yarn.lock +++ b/extensions/mssql/yarn.lock @@ -2,6 +2,186 @@ # yarn lockfile v1 +"@babel/code-frame@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" + integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== + dependencies: + "@babel/highlight" "^7.10.1" + +"@babel/core@^7.7.5": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.1.tgz#2a0ad0ea693601820defebad2140206503d89af3" + integrity sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/generator" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.1" + "@babel/helpers" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.1.tgz#4d14458e539bcb04ffe34124143f5c489f2dbca9" + integrity sha512-AT0YPLQw9DI21tliuJIdplVfLHya6mcGa8ctkv7n4Qv+hYacJrKmNWIteAK1P9iyLikFIAkwqJ7HAOqIDLFfgA== + dependencies: + "@babel/types" "^7.10.1" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" + integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-get-function-arity@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" + integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-member-expression-to-functions@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" + integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-module-imports@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" + integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-module-transforms@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" + integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== + dependencies: + "@babel/helper-module-imports" "^7.10.1" + "@babel/helper-replace-supers" "^7.10.1" + "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" + integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-replace-supers@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" + integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.1" + "@babel/helper-optimise-call-expression" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-simple-access@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" + integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/helper-split-export-declaration@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" + integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== + dependencies: + "@babel/types" "^7.10.1" + +"@babel/helper-validator-identifier@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" + integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== + +"@babel/helpers@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" + integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== + dependencies: + "@babel/template" "^7.10.1" + "@babel/traverse" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/highlight@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" + integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== + dependencies: + "@babel/helper-validator-identifier" "^7.10.1" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.1.tgz#2e142c27ca58aa2c7b119d09269b702c8bbad28c" + integrity sha512-AUTksaz3FqugBkbTZ1i+lDLG5qy8hIzCaAxEtttU6C0BtZZU9pkNZtWSVAht4EW9kl46YBiyTGMp9xTTGqViNg== + +"@babel/template@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" + integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/types" "^7.10.1" + +"@babel/traverse@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" + integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== + dependencies: + "@babel/code-frame" "^7.10.1" + "@babel/generator" "^7.10.1" + "@babel/helper-function-name" "^7.10.1" + "@babel/helper-split-export-declaration" "^7.10.1" + "@babel/parser" "^7.10.1" + "@babel/types" "^7.10.1" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.10.1": + version "7.10.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.1.tgz#6886724d31c8022160a7db895e6731ca33483921" + integrity sha512-L2yqUOpf3tzlW9GVuipgLEcZxnO+96SzR6fjXMuxxNkIgFJ5+07mHCZ+HkHqaeZu8+3LKnNJJ1bKbjBETQAsrA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.1" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== + "@types/bytes@^3.0.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/bytes/-/bytes-3.1.0.tgz#835a3e4aea3b4d7604aca216a78de372bff3ecc3" @@ -56,16 +236,6 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= - ads-kerberos@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/ads-kerberos/-/ads-kerberos-1.1.3.tgz#e424253c6f0df2b258aa4a31804f9e38562d0301" @@ -90,30 +260,11 @@ ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -amdefine@>=0.0.4, amdefine@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" @@ -131,11 +282,6 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - anymatch@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" @@ -144,6 +290,13 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + applicationinsights@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.6.tgz#bc201810de91cea910dab34e8ad35ecde488edeb" @@ -160,29 +313,6 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arr-diff@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" - integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= - dependencies: - arr-flatten "^1.0.1" - array-slice "^0.2.3" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" - integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= - -array-slice@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" - integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -207,11 +337,6 @@ async-retry@^1.2.3: dependencies: retry "0.12.0" -async@1.x: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -269,11 +394,6 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - buffer-stream-reader@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/buffer-stream-reader/-/buffer-stream-reader-0.1.1.tgz#ca8bf93631deedd8b8f8c3bb44991cc30951e259" @@ -311,7 +431,7 @@ chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -388,16 +508,18 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== -commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -442,6 +564,13 @@ debug@^2.2.0: dependencies: ms "2.0.0" +debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + decache@^4.4.0: version "4.5.1" resolved "https://registry.yarnpkg.com/decache/-/decache-4.5.1.tgz#94a977a88a4188672c96550ec4889582ceecdf49" @@ -461,10 +590,12 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" @@ -558,50 +689,16 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - eventemitter2@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-5.0.1.tgz#6197a095d5fb6b57e8942f6fd7eaad63a09c9452" integrity sha1-YZegldX7a1folC9v1+qtY6CclFI= -extend-shallow@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" - integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= - dependencies: - kind-of "^1.1.0" - extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -627,11 +724,6 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -725,6 +817,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -773,18 +870,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.5, glob@^7.1.2: +glob@^7.0.5, glob@^7.1.2, glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -796,23 +882,16 @@ glob@^7.0.5, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.0.1: - version "4.7.6" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" - integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -826,16 +905,16 @@ har-validator@~5.1.3: ajv "^6.5.5" har-schema "^2.0.0" -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -858,6 +937,11 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + 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" @@ -891,7 +975,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -989,27 +1073,67 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul@0.4.5, istanbul@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" +istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== -js-yaml@3.13.1, js-yaml@3.x: +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^2.0.5" + make-dir "^2.1.0" + rimraf "^2.6.3" + source-map "^0.6.1" + +istanbul-reports@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -1022,6 +1146,11 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1037,6 +1166,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -1047,19 +1183,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -kind-of@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" - integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -1068,7 +1191,7 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash@^4.16.4, lodash@^4.17.15, lodash@^4.17.4: +lodash@^4.16.4, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.4: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -1080,6 +1203,21 @@ log-symbols@3.0.0: dependencies: chalk "^2.4.2" +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + md5@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" @@ -1101,7 +1239,7 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.43.0" -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -1147,7 +1285,7 @@ mkdirp@0.5.3: dependencies: minimist "^1.2.5" -mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -1245,11 +1383,6 @@ nan@^2.14.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== -neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - node-environment-flags@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -1258,13 +1391,6 @@ node-environment-flags@1.0.6: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -1303,25 +1429,13 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -once@1.x, once@^1.3.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -1356,6 +1470,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -1376,32 +1495,16 @@ picomatch@^2.0.4: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== -plugin-error@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" - integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= - dependencies: - ansi-cyan "^0.1.1" - ansi-red "^0.1.1" - arr-diff "^1.0.1" - arr-union "^2.0.1" - extend-shallow "^1.1.2" +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== postinstall-build@^5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/postinstall-build/-/postinstall-build-5.0.3.tgz#238692f712a481d8f5bc8960e94786036241efc7" integrity sha512-vPvPe8TKgp4FLgY3+DfxCE5PIfoXBK2lyLfNCxsRbDsV6vS4oU5RG/IWxrblMn6heagbnMED3MemUQllQ2bQUg== -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -1444,18 +1547,6 @@ readable-stream@^2.1.4: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@~2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" - integrity sha1-j5A0HmilPMySh4jaz80Rs265t44= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - string_decoder "~0.10.x" - util-deprecate "~1.0.1" - readdirp@~3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" @@ -1463,18 +1554,6 @@ readdirp@~3.2.0: dependencies: picomatch "^2.0.4" -remap-istanbul@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/remap-istanbul/-/remap-istanbul-0.11.1.tgz#4ad9a06450d3556559bef6195418e05bd4ef6d61" - integrity sha512-Itv3XvYjD6G+9xDzAeFohx4GUwbFjfqFt0UXlC826jHR18E49fEiEGqZUxUASwMq4z7wwUv2H9/XF2d6qj0iaQ== - dependencies: - amdefine "^1.0.0" - istanbul "0.4.5" - minimatch "^3.0.3" - plugin-error "^0.1.2" - source-map "^0.6.1" - through2 "2.0.1" - request-light@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.3.0.tgz#04daa783e7f0a70392328dda4b546f3e27845f2d" @@ -1520,10 +1599,12 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" retry@0.12.0: version "0.12.0" @@ -1537,6 +1618,13 @@ rimraf@2.6.2: dependencies: glob "^7.0.5" +rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -1552,11 +1640,16 @@ 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" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^5.3.0, semver@^5.5.0, semver@^5.7.0: +semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + service-downloader@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/service-downloader/-/service-downloader-0.2.1.tgz#8bd756bc4bc0cbfdf04fe71d4337f19ce6196203" @@ -1576,26 +1669,16 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -source-map-support@^0.5.12: - version "0.5.17" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.17.tgz#29fe1b3c98b9dbd5064ada89052ee8ff070cb46c" - integrity sha512-bwdKOBZ5L0gFRh4KOxNap/J/MpvX9Yxsq9lFDx65s3o7F/NiHy7JRaGIS8MwW6tZPAq9UXE207Il0cfcb5yu/Q== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -1681,11 +1764,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -1707,6 +1785,11 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -1726,13 +1809,6 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1740,6 +1816,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + tar@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.1.tgz#7b3bd6c313cb6e0153770108f8d70ac298607efa" @@ -1752,14 +1835,6 @@ tar@^6.0.1: mkdirp "^1.0.3" yallist "^4.0.0" -through2@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9" - integrity sha1-OE51MU1J8y3hLuu4E2uOtrXVnak= - dependencies: - readable-stream "~2.0.0" - xtend "~4.0.0" - through2@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" @@ -1774,6 +1849,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -1810,13 +1890,6 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" @@ -1831,13 +1904,6 @@ typemoq@^2.1.0: lodash "^4.17.4" postinstall-build "^5.0.1" -uglify-js@^3.1.4: - version "3.9.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.1.tgz#a56a71c8caa2d36b5556cc1fd57df01ae3491539" - integrity sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA== - dependencies: - commander "~2.20.3" - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -1902,23 +1968,27 @@ vscode-nls@^4.0.0, vscode-nls@^4.1.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" integrity sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" - istanbul "^0.4.5" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^3.0.0" mocha "^5.2.0" - remap-istanbul "^0.11.1" - source-map-support "^0.5.12" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1, which@^1.1.1: +which@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -1932,16 +2002,6 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -1961,11 +2021,6 @@ xml@^1.0.0: resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= -xtend@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" diff --git a/extensions/notebook/coverConfig.json b/extensions/notebook/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/notebook/coverConfig.json +++ b/extensions/notebook/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/notebook/package.json b/extensions/notebook/package.json index 7825bedff5..175d6299c5 100644 --- a/extensions/notebook/package.json +++ b/extensions/notebook/package.json @@ -339,6 +339,12 @@ "when": "false" } ], + "notebooks/title": [ + { + "command": "notebook.command.createBook", + "group": "secondary" + } + ], "touchBar": [ { "command": "notebook.command.runactivecell", @@ -376,12 +382,12 @@ }, { "command": "notebook.command.searchUntitledBook", - "when": "view == unsavedBookTreeView && viewItem == unsavedBook && unsavedBooks", + "when": "view == providedBooksView && viewItem == providedBook && providedBooks", "group": "inline" }, { "command": "notebook.command.saveBook", - "when": "view == unsavedBookTreeView && viewItem == unsavedBook && unsavedBooks", + "when": "view == providedBooksView && viewItem == providedBook && providedBooks", "group": "inline" }, { @@ -400,8 +406,8 @@ "group": "navigation" }, { - "command": "notebook.command.createBook", - "when": "view == bookTreeView" + "command": "books.sqlserver2019", + "when": "view == providedBooksView" }, { "command": "notebook.command.openNotebookFolder", @@ -416,6 +422,18 @@ } ] }, + "views": { + "notebooks": [ + { + "id": "bookTreeView", + "name": "%title.SavedBooks%" + }, + { + "id": "providedBooksView", + "name": "%title.ProvidedBooks%" + } + ] + }, "keybindings": [ { "command": "notebook.command.runactivecell", @@ -507,27 +525,6 @@ "connectionProviderIds": [] } ] - }, - "viewsContainers": { - "activitybar": [ - { - "id": "books-explorer", - "title": "Notebooks", - "icon": "resources/dark/JupyterBook_2.svg" - } - ] - }, - "views": { - "books-explorer": [ - { - "id": "bookTreeView", - "name": "%title.SavedBooks%" - }, - { - "id": "unsavedBookTreeView", - "name": "%title.UnsavedBooks%" - } - ] } }, "dependencies": { @@ -564,7 +561,7 @@ "mocha-multi-reporters": "^1.1.7", "should": "^13.2.3", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "enableProposedApi": true } diff --git a/extensions/notebook/package.nls.json b/extensions/notebook/package.nls.json index 9c605670fc..ecc0747485 100644 --- a/extensions/notebook/package.nls.json +++ b/extensions/notebook/package.nls.json @@ -34,7 +34,7 @@ "title.trustBook": "Trust Book", "title.searchJupyterBook": "Search Book", "title.SavedBooks": "Notebooks", - "title.UnsavedBooks": "Provided Books", + "title.ProvidedBooks": "Provided Books", "title.PreviewLocalizedBook": "Get localized SQL Server 2019 guide", "title.openJupyterBook": "Open Jupyter Book", "title.closeJupyterBook": "Close Jupyter Book", diff --git a/extensions/notebook/resources/dark/JupyterBook_5.svg b/extensions/notebook/resources/dark/JupyterBook_5.svg deleted file mode 100644 index 7f381926c6..0000000000 --- a/extensions/notebook/resources/dark/JupyterBook_5.svg +++ /dev/null @@ -1,7 +0,0 @@ - - ADS_jupyterBook - - - - - diff --git a/extensions/notebook/src/book/bookTreeItem.ts b/extensions/notebook/src/book/bookTreeItem.ts index b52c0bac9d..7971ad4dbe 100644 --- a/extensions/notebook/src/book/bookTreeItem.ts +++ b/extensions/notebook/src/book/bookTreeItem.ts @@ -41,7 +41,7 @@ export class BookTreeItem extends vscode.TreeItem { this.collapsibleState = book.treeItemCollapsibleState; this._sections = book.page; if (book.isUntitled) { - this.contextValue = 'unsavedBook'; + this.contextValue = 'providedBook'; } else { this.contextValue = 'savedBook'; } diff --git a/extensions/notebook/src/book/bookTreeView.ts b/extensions/notebook/src/book/bookTreeView.ts index 948d516150..c3de56cffd 100644 --- a/extensions/notebook/src/book/bookTreeView.ts +++ b/extensions/notebook/src/book/bookTreeView.ts @@ -54,7 +54,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider { - await vscode.commands.executeCommand('setContext', 'unsavedBooks', this._openAsUntitled); + await vscode.commands.executeCommand('setContext', 'providedBooks', this._openAsUntitled); await Promise.all(workspaceFolders.map(async (workspaceFolder) => { try { await this.loadNotebooksInFolder(workspaceFolder.uri.fsPath); diff --git a/extensions/notebook/src/extension.ts b/extensions/notebook/src/extension.ts index 45877940d5..fd7511a3ac 100644 --- a/extensions/notebook/src/extension.ts +++ b/extensions/notebook/src/extension.ts @@ -24,21 +24,21 @@ const JUPYTER_NOTEBOOK_PROVIDER = 'jupyter'; const msgSampleCodeDataFrame = localize('msgSampleCodeDataFrame', "This sample code loads the file into a data frame and shows the first 10 results."); const noNotebookVisible = localize('noNotebookVisible', "No notebook editor is active"); const BOOKS_VIEWID = 'bookTreeView'; -const READONLY_BOOKS_VIEWID = 'unsavedBookTreeView'; +const PROVIDED_BOOKS_VIEWID = 'providedBooksView'; let controller: JupyterController; type ChooseCellType = { label: string, id: CellType }; export async function activate(extensionContext: vscode.ExtensionContext): Promise { const createBookPath: string = path.posix.join(extensionContext.extensionPath, 'resources', 'notebooks', 'JupyterBooksCreate.ipynb'); - extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openBook', (bookPath: string, openAsUntitled: boolean, urlToOpen?: string) => openAsUntitled ? untitledBookTreeViewProvider.openBook(bookPath, urlToOpen, true) : bookTreeViewProvider.openBook(bookPath, urlToOpen, true))); + extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openBook', (bookPath: string, openAsUntitled: boolean, urlToOpen?: string) => openAsUntitled ? providedBookTreeViewProvider.openBook(bookPath, urlToOpen, true) : bookTreeViewProvider.openBook(bookPath, urlToOpen, true))); extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openNotebook', (resource) => bookTreeViewProvider.openNotebook(resource))); - extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openUntitledNotebook', (resource) => untitledBookTreeViewProvider.openNotebookAsUntitled(resource))); + extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openUntitledNotebook', (resource) => providedBookTreeViewProvider.openNotebookAsUntitled(resource))); extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openMarkdown', (resource) => bookTreeViewProvider.openMarkdown(resource))); extensionContext.subscriptions.push(vscode.commands.registerCommand('bookTreeView.openExternalLink', (resource) => bookTreeViewProvider.openExternalLink(resource))); - extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.saveBook', () => untitledBookTreeViewProvider.saveJupyterBooks())); + extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.saveBook', () => providedBookTreeViewProvider.saveJupyterBooks())); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.trustBook', (resource) => bookTreeViewProvider.trustBook(resource))); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.searchBook', (item) => bookTreeViewProvider.searchJupyterBooks(item))); - extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.searchUntitledBook', () => untitledBookTreeViewProvider.searchJupyterBooks())); + extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.searchUntitledBook', () => providedBookTreeViewProvider.searchJupyterBooks())); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.openBook', () => bookTreeViewProvider.openNewBook())); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.closeBook', (book: any) => bookTreeViewProvider.closeBook(book))); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.closeNotebook', (book: any) => bookTreeViewProvider.closeBook(book))); @@ -114,7 +114,7 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi })); extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.revealInBooksViewlet', (uri: vscode.Uri, shouldReveal: boolean) => bookTreeViewProvider.revealActiveDocumentInViewlet(uri, shouldReveal))); - extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.revealInUntitledBooksViewlet', (uri: vscode.Uri, shouldReveal: boolean) => untitledBookTreeViewProvider.revealActiveDocumentInViewlet(uri, shouldReveal))); + extensionContext.subscriptions.push(vscode.commands.registerCommand('notebook.command.revealInUntitledBooksViewlet', (uri: vscode.Uri, shouldReveal: boolean) => providedBookTreeViewProvider.revealActiveDocumentInViewlet(uri, shouldReveal))); let appContext = new AppContext(extensionContext, new ApiWrapper()); controller = new JupyterController(appContext); @@ -126,9 +126,12 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi let workspaceFolders = vscode.workspace.workspaceFolders?.slice() ?? []; const bookTreeViewProvider = new BookTreeViewProvider(appContext.apiWrapper, workspaceFolders, extensionContext, false, BOOKS_VIEWID); await bookTreeViewProvider.initialized; - const untitledBookTreeViewProvider = new BookTreeViewProvider(appContext.apiWrapper, [], extensionContext, true, READONLY_BOOKS_VIEWID); - await untitledBookTreeViewProvider.initialized; + const providedBookTreeViewProvider = new BookTreeViewProvider(appContext.apiWrapper, [], extensionContext, true, PROVIDED_BOOKS_VIEWID); + await providedBookTreeViewProvider.initialized; + + extensionContext.subscriptions.push(vscode.window.registerTreeDataProvider(BOOKS_VIEWID, bookTreeViewProvider)); + extensionContext.subscriptions.push(vscode.window.registerTreeDataProvider(PROVIDED_BOOKS_VIEWID, providedBookTreeViewProvider)); return { getJupyterController() { return controller; diff --git a/extensions/notebook/src/jupyter/jupyterSessionManager.ts b/extensions/notebook/src/jupyter/jupyterSessionManager.ts index 07e809485c..01b613c973 100644 --- a/extensions/notebook/src/jupyter/jupyterSessionManager.ts +++ b/extensions/notebook/src/jupyter/jupyterSessionManager.ts @@ -282,6 +282,10 @@ export class JupyterSession implements nb.ISession { // %_do_not_call_change_endpoint is a SparkMagic command that lets users change endpoint options, // such as user/profile/host name/auth type + let credentials; + if (!this.isIntegratedAuth(connectionProfile)) { + credentials = await connection.getCredentials(connectionProfile.id); + } //Update server info with bigdata endpoint - Unified Connection if (connectionProfile.providerName === SQL_PROVIDER) { const endpoints = await this.getClusterEndpoints(connectionProfile.id); @@ -296,16 +300,16 @@ export class JupyterSession implements nb.ISession { // as a default now we'll still fall back to root if it's empty for some reason. (but the calls below should // get the actual correct value regardless) connectionProfile.options[USER] = connectionProfile.userName || 'root'; - - try { - const bdcApi = await vscode.extensions.getExtension(bdc.constants.extensionName).activate(); - const controllerEndpoint = endpoints.find(ep => ep.serviceName.toLowerCase() === CONTROLLER_ENDPOINT); - const controller = bdcApi.getClusterController(controllerEndpoint.endpoint, 'basic', connectionProfile.userName, connectionProfile.password); - connectionProfile.options[USER] = await controller.getKnoxUsername(connectionProfile.userName); - } catch (err) { - console.log(`Unexpected error getting Knox username for Spark kernel: ${err}`); + if (!this.isIntegratedAuth(connectionProfile)) { + try { + const bdcApi = await vscode.extensions.getExtension(bdc.constants.extensionName).activate(); + const controllerEndpoint = endpoints.find(ep => ep.serviceName.toLowerCase() === CONTROLLER_ENDPOINT); + const controller = bdcApi.getClusterController(controllerEndpoint.endpoint, 'basic', connectionProfile.userName, credentials.password); + connectionProfile.options[USER] = await controller.getKnoxUsername(connectionProfile.userName); + } catch (err) { + console.log(`Unexpected error getting Knox username for Spark kernel: ${err}`); + } } - } else { connectionProfile.options[KNOX_ENDPOINT_PORT] = this.getKnoxPortOrDefault(connectionProfile); @@ -318,7 +322,7 @@ export class JupyterSession implements nb.ISession { if (this.isIntegratedAuth(connectionProfile)) { doNotCallChangeEndpointParams = `%_do_not_call_change_endpoint --server=${server} --auth=Kerberos`; } else { - const credentials = await connection.getCredentials(connectionProfile.id); + doNotCallChangeEndpointParams = `%_do_not_call_change_endpoint --username=${connectionProfile.options[USER]} --password=${credentials.password} --server=${server} --auth=Basic_Access`; } let future = this.sessionImpl.kernel.requestExecute({ diff --git a/extensions/notebook/yarn.lock b/extensions/notebook/yarn.lock index 9dc2a523ab..ec2a186a59 100644 --- a/extensions/notebook/yarn.lock +++ b/extensions/notebook/yarn.lock @@ -1661,9 +1661,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002" integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/resource-deployment/coverConfig.json b/extensions/resource-deployment/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/resource-deployment/coverConfig.json +++ b/extensions/resource-deployment/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/resource-deployment/coverageConfig.json b/extensions/resource-deployment/coverageConfig.json deleted file mode 100644 index 9b87f7e033..0000000000 --- a/extensions/resource-deployment/coverageConfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "enabled": true, - "relativeSourcePath": "..", - "relativeCoverageDir": "../../coverage", - "ignorePatterns": [ - "**/node_modules/**" - ], - "includePid": false, - "reports": [ - "cobertura" - ], - "verbose": false, - "remapOptions": { - "basePath": ".", - "useAbsolutePaths": true - } -} \ No newline at end of file diff --git a/extensions/resource-deployment/package.json b/extensions/resource-deployment/package.json index 2018c215a4..2d42f7371f 100644 --- a/extensions/resource-deployment/package.json +++ b/extensions/resource-deployment/package.json @@ -362,6 +362,6 @@ "mocha-junit-reporter": "^1.17.0", "mocha-multi-reporters": "^1.1.7", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" } } diff --git a/extensions/resource-deployment/src/interfaces.ts b/extensions/resource-deployment/src/interfaces.ts index c8e712f4d4..55ab646151 100644 --- a/extensions/resource-deployment/src/interfaces.ts +++ b/extensions/resource-deployment/src/interfaces.ts @@ -42,7 +42,7 @@ export interface DialogDeploymentProvider extends DeploymentProviderBase { } export interface BdcWizardDeploymentProvider extends DeploymentProviderBase { - bdcWizard: WizardInfo; + bdcWizard: BdcWizardInfo; } export interface NotebookWizardDeploymentProvider extends DeploymentProviderBase { @@ -50,7 +50,7 @@ export interface NotebookWizardDeploymentProvider extends DeploymentProviderBase } export interface NotebookDeploymentProvider extends DeploymentProviderBase { - notebook: string | NotebookInfo; + notebook: string | NotebookPathInfo; } export interface WebPageDeploymentProvider extends DeploymentProviderBase { @@ -100,31 +100,32 @@ export interface DeploymentProviderBase { export type DeploymentProvider = DialogDeploymentProvider | BdcWizardDeploymentProvider | NotebookWizardDeploymentProvider | NotebookDeploymentProvider | WebPageDeploymentProvider | DownloadDeploymentProvider | CommandDeploymentProvider; -export interface WizardInfo { - notebook: string | NotebookInfo; +export interface BdcWizardInfo { + notebook: string | NotebookPathInfo; type: BdcDeploymentType; } export interface NotebookWizardInfo extends WizardInfoBase { - notebook: string | NotebookInfo; + notebook: string | NotebookPathInfo; + runNotebook?: boolean; + codeCellInsertionPosition?: number; + pages: NotebookWizardPageInfo[] } -export interface WizardInfoBase extends SharedFieldAttributes { +export interface WizardInfoBase extends FieldInfoBase { taskName?: string; type?: DeploymentType; - runNotebook?: boolean; actionText?: string; title: string; - pages: NotebookWizardPageInfo[]; - summaryPage: NotebookWizardPageInfo; - generateSummaryPage: boolean; + pages: PageInfoBase[]; + isSummaryPageAutoGenerated?: boolean } export interface NotebookWizardPageInfo extends PageInfoBase { description?: string; } export interface NotebookBasedDialogInfo extends DialogInfoBase { - notebook: string | NotebookInfo; + notebook: string | NotebookPathInfo; runNotebook?: boolean; taskName?: string; } @@ -153,18 +154,39 @@ export interface DialogInfoBase { export interface DialogTabInfo extends PageInfoBase { } -export interface PageInfoBase extends SharedFieldAttributes { +export interface PageInfoBase extends FieldInfoBase { title: string; isSummaryPage?: boolean; sections: SectionInfo[]; } -export interface SharedFieldAttributes { +export interface TextCSSStyles { + fontStyle?: FontStyle | undefined; + fontWeight?: FontWeight | undefined; + color?: string; + [key: string]: string | undefined; +} + +export type ComponentCSSStyles = { + [key: string]: string; +}; + + +export interface OptionsInfo { + values: string[] | azdata.CategoryValue[], + defaultValue: string, + optionsType?: OptionsType +} + +export interface FieldInfoBase { labelWidth?: string; inputWidth?: string; labelPosition?: LabelPosition; // Default value is top + fieldWidth?: string; + fieldHeight?: string; + fieldAlignItems?: azdata.AlignItemsType; } -export interface SectionInfo extends SharedFieldAttributes { +export interface SectionInfo extends FieldInfoBase { title?: string; fields?: FieldInfo[]; // Use this if the dialog is not wide. All fields will be displayed in one column, label will be placed on top of the input component. rows?: RowInfo[]; // Use this for wide dialog or wizard. label will be placed to the left of the input component. @@ -174,7 +196,8 @@ export interface SectionInfo extends SharedFieldAttributes { } export interface RowInfo { - fields: FieldInfo[]; + cssStyles?: ComponentCSSStyles; + items: FieldInfo[] | RowInfo[]; } export interface SubFieldInfo { @@ -182,7 +205,7 @@ export interface SubFieldInfo { variableName?: string; } -export interface FieldInfo extends SubFieldInfo, SharedFieldAttributes { +export interface FieldInfo extends SubFieldInfo, FieldInfoBase { subFields?: SubFieldInfo[]; type: FieldType; defaultValue?: string; @@ -194,22 +217,23 @@ export interface FieldInfo extends SubFieldInfo, SharedFieldAttributes { min?: number; max?: number; required?: boolean; - options?: string[] | azdata.CategoryValue[]; + options?: string[] | azdata.CategoryValue[] | OptionsInfo; placeHolder?: string; userName?: string; // needed for sql server's password complexity requirement check, password can not include the login name. description?: string; - fontStyle?: FontStyle; - labelFontWeight?: FontWeight; - textFontWeight?: FontWeight; + labelCSSStyles?: TextCSSStyles; + fontWeight?: FontWeight; links?: azdata.LinkArea[]; editable?: boolean; // for editable drop-down, enabled?: boolean; + isEvaluated?: boolean; } export interface KubeClusterContextFieldInfo extends FieldInfo { configFileVariableName?: string; } export interface AzureAccountFieldInfo extends AzureLocationsFieldInfo { + displaySubscriptionVariableName?: string; subscriptionVariableName?: string; resourceGroupVariableName?: string; } @@ -242,16 +266,20 @@ export enum FieldType { SQLPassword = 'sql_password', Password = 'password', Options = 'options', - RadioOptions = 'radio_options', ReadonlyText = 'readonly_text', Checkbox = 'checkbox', AzureAccount = 'azure_account', AzureLocations = 'azure_locations', FilePicker = 'file_picker', - KubeClusterContextPicker = 'kube_cluster_context_picker' + KubeClusterContextPicker = 'kube_cluster_context_picker', } -export interface NotebookInfo { +export enum OptionsType { + Dropdown = 'dropdown', + Radio = 'radio' +} + +export interface NotebookPathInfo { win32: string; darwin: string; linux: string; diff --git a/extensions/resource-deployment/src/services/notebookService.ts b/extensions/resource-deployment/src/services/notebookService.ts index 9935e5df28..9d32ceac2e 100644 --- a/extensions/resource-deployment/src/services/notebookService.ts +++ b/extensions/resource-deployment/src/services/notebookService.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import { isString } from 'util'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { NotebookInfo } from '../interfaces'; +import { NotebookPathInfo } from '../interfaces'; import { getDateTimeString, getErrorMessage } from '../utils'; import { IPlatformService } from './platformService'; const localize = nls.loadMessageBundle(); @@ -33,11 +33,13 @@ export interface NotebookExecutionResult { } export interface INotebookService { - launchNotebook(notebook: string | NotebookInfo): Thenable; - launchNotebookWithContent(title: string, content: string): Thenable; - getNotebook(notebook: string | NotebookInfo): Promise; + launchNotebook(notebook: string | NotebookPathInfo): Promise; + launchNotebookWithEdits(notebook: string | NotebookPathInfo, cellStatements: string[], insertionPosition?: number): Promise; + launchNotebookWithContent(title: string, content: string): Promise; + getNotebook(notebook: string | NotebookPathInfo): Promise; + getNotebookPath(notebook: string | NotebookPathInfo): string; executeNotebook(notebook: any, env?: NodeJS.ProcessEnv): Promise; - backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookInfo, tempNoteBookPrefix: string, platformService: IPlatformService): void; + backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookPathInfo | Notebook, tempNotebookPrefix: string, platformService: IPlatformService, env?: NodeJS.ProcessEnv): void; } export class NotebookService implements INotebookService { @@ -48,9 +50,26 @@ export class NotebookService implements INotebookService { * Launch notebook with file path * @param notebook the path of the notebook */ - launchNotebook(notebook: string | NotebookInfo): Thenable { - return this.getNotebookFullPath(notebook).then(notebookPath => { - return this.showNotebookAsUntitled(notebookPath); + async launchNotebook(notebook: string | NotebookPathInfo): Promise { + const notebookPath = await this.getNotebookFullPath(notebook); + return await this.showNotebookAsUntitled(notebookPath); + } + + /** + * Inserts cell code given by {@param cellStatements} in an existing notebook given by {@param notebook} file path at the location + * {@param insertionPosition} and then launches the edited notebook. + * + * @param notebook - the path to notebook that needs to be launched + * @param cellStatements - array of statements to be inserted in a cell + * @param insertionPosition - the position at which cells are inserted. Default is a new cell at the beginning of the notebook. + */ + async launchNotebookWithEdits(notebook: string, cellStatements: string[], insertionPosition: number = 0): Promise { + const openedNotebook = await this.launchNotebook(notebook); + await openedNotebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => { + editBuilder.insertCell({ + cell_type: 'code', + source: cellStatements + }, insertionPosition); }); } @@ -59,9 +78,9 @@ export class NotebookService implements INotebookService { * @param title the title of the notebook * @param content the notebook content */ - launchNotebookWithContent(title: string, content: string): Thenable { - const uri: vscode.Uri = vscode.Uri.parse(`untitled:${title}`); - return azdata.nb.showNotebookDocument(uri, { + async launchNotebookWithContent(title: string, content: string): Promise { + const uri: vscode.Uri = vscode.Uri.parse(`untitled:${this.findNextUntitledEditorName(title)}`); + return await azdata.nb.showNotebookDocument(uri, { connectionProfile: undefined, preview: false, initialContent: content, @@ -70,7 +89,7 @@ export class NotebookService implements INotebookService { } - async getNotebook(notebook: string | NotebookInfo): Promise { + async getNotebook(notebook: string | NotebookPathInfo): Promise { const notebookPath = await this.getNotebookFullPath(notebook); return JSON.parse(await this.platformService.readTextFile(notebookPath)); } @@ -83,7 +102,7 @@ export class NotebookService implements INotebookService { const outputFullPath = path.join(workingDirectory, `output-${fileName}`); const additionalEnvironmentVariables: NodeJS.ProcessEnv = env || {}; // Set the azdata eula - // Scenarios using the executeNotebook feature already have the EULA acceptted by the user before executing this. + // Scenarios using the executeNotebook feature already have the EULA accepted by the user before executing this. additionalEnvironmentVariables['ACCEPT_EULA'] = 'yes'; try { await this.platformService.saveTextFile(content, notebookFullPath); @@ -109,15 +128,17 @@ export class NotebookService implements INotebookService { } } - public backgroundExecuteNotebook(taskName: string | undefined, notebookInfo: string | NotebookInfo, tempNotebookPrefix: string, platformService: IPlatformService): void { + backgroundExecuteNotebook(taskName: string = 'Executing notebook', notebookInfo: string | NotebookPathInfo | Notebook, tempNotebookPrefix: string, platformService: IPlatformService, env?: NodeJS.ProcessEnv): void { azdata.tasks.startBackgroundOperation({ - displayName: taskName!, - description: taskName!, + displayName: taskName, + description: taskName, isCancelable: false, operation: async op => { op.updateStatus(azdata.TaskStatus.InProgress); - const notebook = await this.getNotebook(notebookInfo); - const result = await this.executeNotebook(notebook); + const notebook = (typeof notebookInfo === 'object' && 'cells' in notebookInfo) + ? notebookInfo + : await this.getNotebook(notebookInfo); + const result = await this.executeNotebook(notebook, env); if (result.succeeded) { op.updateStatus(azdata.TaskStatus.Succeeded); } else { @@ -129,7 +150,7 @@ export class NotebookService implements INotebookService { platformService.logToOutputChannel(taskFailedMessage); if (selectedOption === viewErrorDetail) { try { - this.launchNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook); + await this.launchNotebookWithContent(`${tempNotebookPrefix}-${getDateTimeString()}`, result.outputNotebook); } catch (error) { const launchNotebookError = localize('resourceDeployment.FailedToOpenNotebook', "An error occurred launching the output notebook. {1}{2}.", EOL, getErrorMessage(error)); platformService.logToOutputChannel(launchNotebookError); @@ -146,7 +167,7 @@ export class NotebookService implements INotebookService { }); } - async getNotebookFullPath(notebook: string | NotebookInfo): Promise { + async getNotebookFullPath(notebook: string | NotebookPathInfo): Promise { const notebookPath = this.getNotebookPath(notebook); let notebookExists = await this.platformService.fileExists(notebookPath); if (notebookExists) { @@ -168,7 +189,7 @@ export class NotebookService implements INotebookService { * get the notebook path for current platform * @param notebook the notebook path */ - getNotebookPath(notebook: string | NotebookInfo): string { + getNotebookPath(notebook: string | NotebookPathInfo): string { let notebookPath; if (notebook && !isString(notebook)) { const platform = this.platformService.platform(); @@ -199,17 +220,16 @@ export class NotebookService implements INotebookService { return title; } - showNotebookAsUntitled(notebookPath: string): Thenable { + async showNotebookAsUntitled(notebookPath: string): Promise { let targetFileName: string = this.findNextUntitledEditorName(notebookPath); const untitledFileName: vscode.Uri = vscode.Uri.parse(`untitled:${targetFileName}`); - return vscode.workspace.openTextDocument(notebookPath).then((document) => { - let initialContent = document.getText(); - return azdata.nb.showNotebookDocument(untitledFileName, { - connectionProfile: undefined, - preview: false, - initialContent: initialContent, - initialDirtyState: false - }); + const document = await vscode.workspace.openTextDocument(notebookPath); + let initialContent = document.getText(); + return await azdata.nb.showNotebookDocument(untitledFileName, { + connectionProfile: undefined, + preview: false, + initialContent: initialContent, + initialDirtyState: false }); } } diff --git a/extensions/resource-deployment/src/services/platformService.ts b/extensions/resource-deployment/src/services/platformService.ts index 0bfd67d552..11b2c7970b 100644 --- a/extensions/resource-deployment/src/services/platformService.ts +++ b/extensions/resource-deployment/src/services/platformService.ts @@ -124,7 +124,8 @@ export class PlatformService implements IPlatformService { } isNotebookNameUsed(title: string): boolean { - return (azdata.nb.notebookDocuments.findIndex(doc => doc.isUntitled && doc.fileName === title) > -1); + return (azdata.nb.notebookDocuments.findIndex(doc => doc.isUntitled && doc.fileName === title) > -1) + && (vscode.workspace.textDocuments.findIndex(doc => doc.isUntitled && doc.fileName === title) > -1); } async makeDirectory(path: string): Promise { diff --git a/extensions/resource-deployment/src/services/resourceTypeService.ts b/extensions/resource-deployment/src/services/resourceTypeService.ts index 7b8ec0615e..385450e8d9 100644 --- a/extensions/resource-deployment/src/services/resourceTypeService.ts +++ b/extensions/resource-deployment/src/services/resourceTypeService.ts @@ -13,7 +13,7 @@ import * as nls from 'vscode-nls'; import { INotebookService } from './notebookService'; import { IPlatformService } from './platformService'; import { IToolsService } from './toolsService'; -import { ResourceType, ResourceTypeOption, NotebookInfo, DeploymentProvider, instanceOfWizardDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfNotebookDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookWizardDeploymentProvider } from '../interfaces'; +import { ResourceType, ResourceTypeOption, NotebookPathInfo, DeploymentProvider, instanceOfWizardDeploymentProvider, instanceOfDialogDeploymentProvider, instanceOfNotebookDeploymentProvider, instanceOfDownloadDeploymentProvider, instanceOfWebPageDeploymentProvider, instanceOfCommandDeploymentProvider, instanceOfNotebookBasedDialogInfo, instanceOfNotebookWizardDeploymentProvider } from '../interfaces'; import { DeployClusterWizard } from '../ui/deployClusterWizard/deployClusterWizard'; import { DeploymentInputDialog } from '../ui/deploymentInputDialog'; @@ -77,7 +77,7 @@ export class ResourceTypeService implements IResourceTypeService { }); } - private updateNotebookPath(objWithNotebookProperty: { notebook: string | NotebookInfo } | undefined, extensionPath: string): void { + private updateNotebookPath(objWithNotebookProperty: { notebook: string | NotebookPathInfo } | undefined, extensionPath: string): void { if (objWithNotebookProperty && objWithNotebookProperty.notebook) { if (typeof objWithNotebookProperty.notebook === 'string') { objWithNotebookProperty.notebook = path.join(extensionPath, objWithNotebookProperty.notebook); @@ -239,10 +239,10 @@ export class ResourceTypeService implements IResourceTypeService { public startDeployment(provider: DeploymentProvider): void { const self = this; if (instanceOfWizardDeploymentProvider(provider)) { - const wizard = new DeployClusterWizard(provider.bdcWizard, new KubeService(), new AzdataService(this.platformService), this.notebookService); + const wizard = new DeployClusterWizard(provider.bdcWizard, new KubeService(), new AzdataService(this.platformService), this.notebookService, this.toolsService); wizard.open(); } else if (instanceOfNotebookWizardDeploymentProvider(provider)) { - const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService); + const wizard = new NotebookWizard(provider.notebookWizard, this.notebookService, this.platformService, this.toolsService); wizard.open(); } else if (instanceOfDialogDeploymentProvider(provider)) { const dialog = new DeploymentInputDialog(this.notebookService, this.platformService, provider.dialog); diff --git a/extensions/resource-deployment/src/services/toolsService.ts b/extensions/resource-deployment/src/services/toolsService.ts index 6627ce1984..1922498f30 100644 --- a/extensions/resource-deployment/src/services/toolsService.ts +++ b/extensions/resource-deployment/src/services/toolsService.ts @@ -11,10 +11,12 @@ import { IPlatformService } from './platformService'; export interface IToolsService { getToolByName(toolName: string): ITool | undefined; + toolsForCurrentProvider: ITool[]; } export class ToolsService implements IToolsService { private supportedTools: Map; + private currentTools: ITool[] = []; constructor(private _platformService: IPlatformService) { this.supportedTools = new Map( @@ -30,4 +32,12 @@ export class ToolsService implements IToolsService { getToolByName(toolName: string): ITool | undefined { return this.supportedTools.get(toolName); } + + get toolsForCurrentProvider(): ITool[] { + return this.currentTools; + } + + set toolsForCurrentProvider(tools: ITool[]) { + this.currentTools = tools; + } } diff --git a/extensions/resource-deployment/src/test/notebookService.test.ts b/extensions/resource-deployment/src/test/notebookService.test.ts index 4aa3fed11a..f7e619c15b 100644 --- a/extensions/resource-deployment/src/test/notebookService.test.ts +++ b/extensions/resource-deployment/src/test/notebookService.test.ts @@ -7,7 +7,7 @@ import * as TypeMoq from 'typemoq'; import 'mocha'; import { NotebookService } from '../services/notebookService'; import assert = require('assert'); -import { NotebookInfo } from '../interfaces'; +import { NotebookPathInfo } from '../interfaces'; import { IPlatformService } from '../services/platformService'; suite('Notebook Service Tests', function (): void { @@ -35,7 +35,7 @@ suite('Notebook Service Tests', function (): void { const notebookDarwin = 'test-notebook-darwin.ipynb'; const notebookLinux = 'test-notebook-linux.ipynb'; - const notebookInput: NotebookInfo = { + const notebookInput: NotebookPathInfo = { darwin: notebookDarwin, win32: notebookWin32, linux: notebookLinux diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts index e970d68f3e..2f047a83ca 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizard.ts @@ -4,28 +4,33 @@ *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; -import * as vscode from 'vscode'; -import { SummaryPage } from './pages/summaryPage'; -import { WizardBase } from '../wizardBase'; -import * as nls from 'vscode-nls'; -import { WizardInfo, BdcDeploymentType } from '../../interfaces'; -import { WizardPageBase } from '../wizardPageBase'; -import { AzureSettingsPage } from './pages/azureSettingsPage'; -import { ClusterSettingsPage } from './pages/clusterSettingsPage'; -import { ServiceSettingsPage } from './pages/serviceSettingsPage'; -import { TargetClusterContextPage } from './pages/targetClusterPage'; -import { IKubeService } from '../../services/kubeService'; -import { IAzdataService } from '../../services/azdataService'; -import { DeploymentProfilePage } from './pages/deploymentProfilePage'; -import { INotebookService } from '../../services/notebookService'; -import { DeployClusterWizardModel, AuthenticationMode } from './deployClusterWizardModel'; -import * as VariableNames from './constants'; +import * as fs from 'fs'; import * as os from 'os'; import { join } from 'path'; -import * as fs from 'fs'; +import * as vscode from 'vscode'; +import * as nls from 'vscode-nls'; +import { BdcDeploymentType, BdcWizardInfo } from '../../interfaces'; +import { IAzdataService } from '../../services/azdataService'; +import { IKubeService } from '../../services/kubeService'; +import { INotebookService } from '../../services/notebookService'; +import { IToolsService } from '../../services/toolsService'; +import { getErrorMessage } from '../../utils'; +import { InputComponents } from '../modelViewUtils'; +import { WizardBase } from '../wizardBase'; +import { WizardPageBase } from '../wizardPageBase'; +import * as VariableNames from './constants'; +import { AuthenticationMode, DeployClusterWizardModel } from './deployClusterWizardModel'; +import { AzureSettingsPage } from './pages/azureSettingsPage'; +import { ClusterSettingsPage } from './pages/clusterSettingsPage'; +import { DeploymentProfilePage } from './pages/deploymentProfilePage'; +import { ServiceSettingsPage } from './pages/serviceSettingsPage'; +import { SummaryPage } from './pages/summaryPage'; +import { TargetClusterContextPage } from './pages/targetClusterPage'; const localize = nls.loadMessageBundle(); -export class DeployClusterWizard extends WizardBase { +export class DeployClusterWizard extends WizardBase, DeployClusterWizardModel> { + private _inputComponents: InputComponents = {}; + private _saveConfigButton: azdata.window.Button; public get kubeService(): IKubeService { @@ -40,6 +45,10 @@ export class DeployClusterWizard extends WizardBase { + await this.scriptToNotebook(); } private getPages(): WizardPageBase[] { @@ -135,19 +144,15 @@ export class DeployClusterWizard extends WizardBase { this.setEnvironmentVariables(process.env); - this.notebookService.launchNotebook(this.wizardInfo.notebook).then((notebook: azdata.nb.NotebookEditor) => { - notebook.edit((editBuilder: azdata.nb.NotebookEditorEdit) => { - // 5 is the position after the 'Set variables' cell in the deployment notebooks - editBuilder.insertCell({ - cell_type: 'code', - source: this.model.getCodeCellContentForNotebook() - }, 5); - }); - }, (error) => { - vscode.window.showErrorMessage(error); - }); + const variableValueStatements = this.model.getCodeCellContentForNotebook(this._toolsService.toolsForCurrentProvider); + const insertionPosition = 5; // Cell number 5 is the position where the python variable setting statements need to be inserted in this.wizardInfo.notebook. + try { + await this.notebookService.launchNotebookWithEdits(this.wizardInfo.notebook, variableValueStatements, insertionPosition); + } catch (error) { + vscode.window.showErrorMessage(getErrorMessage(error)); + } } private setEnvironmentVariables(env: NodeJS.ProcessEnv): void { diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts index 00cf8625e9..47d7e04941 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/deployClusterWizardModel.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { EOL } from 'os'; import { delimiter } from 'path'; -import { BdcDeploymentType } from '../../interfaces'; +import { BdcDeploymentType, ITool } from '../../interfaces'; import { BigDataClusterDeploymentProfile, DataResource, HdfsResource, SqlServerMasterResource } from '../../services/bigDataClusterDeploymentProfile'; import { KubeCtlToolName } from '../../services/tools/kubeCtlTool'; -import { getRuntimeBinaryPathEnvironmentVariableName } from '../../utils'; +import { getRuntimeBinaryPathEnvironmentVariableName, setEnvironmentVariablesForInstallPaths } from '../../utils'; import { Model } from '../model'; -import * as VariableNames from './constants'; import { ToolsInstallPath } from './../../constants'; +import * as VariableNames from './constants'; export class DeployClusterWizardModel extends Model { constructor(public deploymentTarget: BdcDeploymentType) { @@ -138,7 +138,7 @@ export class DeployClusterWizardModel extends Model { return targetDeploymentProfile; } - public getCodeCellContentForNotebook(): string[] { + public getCodeCellContentForNotebook(tools: ITool[]): string[] { const profile = this.createTargetProfile(); const statements: string[] = []; if (this.deploymentTarget === BdcDeploymentType.NewAKS) { @@ -166,16 +166,13 @@ export class DeployClusterWizardModel extends Model { statements.push(`os.environ["DOCKER_PASSWORD"] = os.environ["${VariableNames.DockerPassword_VariableName}"]`); } const kubeCtlEnvVarName: string = getRuntimeBinaryPathEnvironmentVariableName(KubeCtlToolName); - statements.push(`os.environ["${kubeCtlEnvVarName}"] = "${this.escapeForNotebookCodeCell(process.env[kubeCtlEnvVarName]!)}"`); - statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${this.escapeForNotebookCodeCell(process.env[ToolsInstallPath]!)}"`); + const env: NodeJS.ProcessEnv = {}; + setEnvironmentVariablesForInstallPaths(tools, env); + statements.push(`os.environ["${kubeCtlEnvVarName}"] = "${this.escapeForNotebookCodeCell(env[kubeCtlEnvVarName]!)}"`); + statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${this.escapeForNotebookCodeCell(env[ToolsInstallPath]!)}"`); statements.push(`print('Variables have been set successfully.')`); return statements.map(line => line + EOL); } - - private escapeForNotebookCodeCell(original: string): string { - // Escape the \ character for the code cell string value - return original && original.replace(/\\/g, '\\\\'); - } } export enum AuthenticationMode { diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts index c912134e26..a8d009c86b 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/azureSettingsPage.ts @@ -7,7 +7,7 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces'; -import { createSection, getDropdownComponent, InputComponents, InputComponent, setModelValues, Validator } from '../../modelViewUtils'; +import { createSection, getDropdownComponent, InputComponentInfo, InputComponents, setModelValues, Validator } from '../../modelViewUtils'; import { WizardPageBase } from '../../wizardPageBase'; import { AksName_VariableName, Location_VariableName, ResourceGroup_VariableName, SubscriptionId_VariableName, VMCount_VariableName, VMSize_VariableName } from '../constants'; import { DeployClusterWizard } from '../deployClusterWizard'; @@ -29,7 +29,7 @@ export class AzureSettingsPage extends WizardPageBase { labelPosition: LabelPosition.Left, spaceBetweenFields: '5px', rows: [{ - fields: [{ + items: [{ type: FieldType.Text, label: localize('deployCluster.SubscriptionField', "Subscription id"), required: false, @@ -38,9 +38,7 @@ export class AzureSettingsPage extends WizardPageBase { description: localize('deployCluster.SubscriptionDescription', "The default subscription will be used if you leave this field blank.") }, { type: FieldType.ReadonlyText, - label: '', - labelWidth: '0px', - defaultValue: localize('deployCluster.SubscriptionHelpText', "{0}"), + label: '{0}', links: [ { text: localize('deployCluster.SubscriptionHelpLink', "View available Azure subscriptions"), @@ -49,7 +47,7 @@ export class AzureSettingsPage extends WizardPageBase { ] }] }, { - fields: [{ + items: [{ type: FieldType.DateTimeText, label: localize('deployCluster.ResourceGroupName', "New resource group name"), required: true, @@ -57,7 +55,7 @@ export class AzureSettingsPage extends WizardPageBase { defaultValue: 'mssql-' }] }, { - fields: [{ + items: [{ type: FieldType.Options, label: localize('deployCluster.Location', "Location"), required: true, @@ -79,9 +77,7 @@ export class AzureSettingsPage extends WizardPageBase { ] }, { type: FieldType.ReadonlyText, - label: '', - labelWidth: '0px', - defaultValue: localize('deployCluster.LocationHelpText', "{0}"), + label: '{0}', links: [ { text: localize('deployCluster.AzureLocationHelpLink', "View available Azure locations"), @@ -90,7 +86,7 @@ export class AzureSettingsPage extends WizardPageBase { ] }] }, { - fields: [{ + items: [{ type: FieldType.DateTimeText, label: localize('deployCluster.AksName', "AKS cluster name"), required: true, @@ -98,7 +94,7 @@ export class AzureSettingsPage extends WizardPageBase { defaultValue: 'mssql-', }] }, { - fields: [ + items: [ { type: FieldType.Number, label: localize('deployCluster.VMCount', "VM count"), @@ -110,7 +106,7 @@ export class AzureSettingsPage extends WizardPageBase { } ] }, { - fields: [{ + items: [{ type: FieldType.Text, label: localize('deployCluster.VMSize', "VM size"), required: true, @@ -118,9 +114,7 @@ export class AzureSettingsPage extends WizardPageBase { defaultValue: 'Standard_E8s_v3' }, { type: FieldType.ReadonlyText, - label: '', - labelWidth: '0px', - defaultValue: localize('deployCluster.VMSizeHelpText', "{0}"), + label: '{0}', links: [ { text: localize('deployCluster.VMSizeHelpLink', "View available VM sizes"), @@ -137,13 +131,14 @@ export class AzureSettingsPage extends WizardPageBase { onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - self.inputComponents[name] = { component: component }; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { + this.inputComponents[name] = { component: inputComponentInfo.component }; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); }, - container: this.wizard.wizardObject + container: this.wizard.wizardObject, + inputComponents: this.wizard.inputComponents }); const formBuilder = view.modelBuilder.formContainer().withFormItems( [{ @@ -184,5 +179,6 @@ export class AzureSettingsPage extends WizardPageBase { return true; }); setModelValues(this.inputComponents, this.wizard.model); + Object.assign(this.wizard.inputComponents, this.inputComponents); } } diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts index 7c404095b9..ab247351cf 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/clusterSettingsPage.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; +import { EOL } from 'os'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { DeployClusterWizard } from '../deployClusterWizard'; -import { SectionInfo, FieldType, LabelPosition } from '../../../interfaces'; -import { createSection, InputComponents, setModelValues, Validator, getInputBoxComponent, isValidSQLPassword, getInvalidSQLPasswordMessage, getPasswordMismatchMessage, InputComponent } from '../../modelViewUtils'; +import { FieldType, LabelPosition, SectionInfo } from '../../../interfaces'; +import { createSection, getInputBoxComponent, getInvalidSQLPasswordMessage, getPasswordMismatchMessage, InputComponentInfo, InputComponents, isValidSQLPassword, setModelValues, Validator } from '../../modelViewUtils'; import { WizardPageBase } from '../../wizardPageBase'; import * as VariableNames from '../constants'; -import { EOL } from 'os'; +import { DeployClusterWizard } from '../deployClusterWizard'; import { AuthenticationMode } from '../deployClusterWizardModel'; const localize = nls.loadMessageBundle(); @@ -174,7 +174,7 @@ export class ClusterSettingsPage extends WizardPageBase { variableName: VariableNames.DomainServiceAccountPassword_VariableName }, { type: FieldType.Text, - label: localize('deployCluster.AppOwers', "App owners"), + label: localize('deployCluster.AppOwners', "App owners"), required: false, variableName: VariableNames.AppOwners_VariableName, placeHolder: localize('deployCluster.AppOwnersPlaceHolder', "Use comma to separate the values."), @@ -193,12 +193,13 @@ export class ClusterSettingsPage extends WizardPageBase { const basicSettingsGroup = createSection({ view: view, container: self.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, sectionInfo: basicSection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - self.inputComponents[name] = { component: component }; + onNewInputComponentCreated: (name: string, inputComponent: InputComponentInfo): void => { + self.inputComponents[name] = { component: inputComponent.component }; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -207,12 +208,13 @@ export class ClusterSettingsPage extends WizardPageBase { const activeDirectorySettingsGroup = createSection({ view: view, container: self.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, sectionInfo: activeDirectorySection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - self.inputComponents[name] = { component: component }; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { + this.inputComponents[name] = { component: inputComponentInfo.component }; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -221,12 +223,13 @@ export class ClusterSettingsPage extends WizardPageBase { const dockerSettingsGroup = createSection({ view: view, container: self.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, sectionInfo: dockerSection, onNewDisposableCreated: (disposable: vscode.Disposable): void => { self.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - self.inputComponents[name] = { component: component }; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { + this.inputComponents[name] = { component: inputComponentInfo.component }; }, onNewValidatorCreated: (validator: Validator): void => { self.validators.push(validator); @@ -266,6 +269,7 @@ export class ClusterSettingsPage extends WizardPageBase { public onLeave() { setModelValues(this.inputComponents, this.wizard.model); + Object.assign(this.wizard.inputComponents, this.inputComponents); if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { const variableDNSPrefixMapping: { [s: string]: string } = {}; variableDNSPrefixMapping[VariableNames.AppServiceProxyDNSName_VariableName] = 'bdc-appproxy'; diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts index 476f74b31b..8fca7865d5 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/serviceSettingsPage.ts @@ -5,11 +5,11 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { DeployClusterWizard } from '../deployClusterWizard'; -import { SectionInfo, FieldType } from '../../../interfaces'; -import { Validator, InputComponents, InputComponent, createSection, createGroupContainer, createLabel, createFlexContainer, createTextInput, createNumberInput, setModelValues, getInputBoxComponent, getCheckboxComponent, getDropdownComponent } from '../../modelViewUtils'; +import { FieldType, SectionInfo } from '../../../interfaces'; +import { createFlexContainer, createGroupContainer, createLabel, createNumberInput, createSection, createTextInput, getCheckboxComponent, getDropdownComponent, getInputBoxComponent, InputComponentInfo, InputComponents, setModelValues, Validator } from '../../modelViewUtils'; import { WizardPageBase } from '../../wizardPageBase'; import * as VariableNames from '../constants'; +import { DeployClusterWizard } from '../deployClusterWizard'; import { AuthenticationMode } from '../deployClusterWizardModel'; const localize = nls.loadMessageBundle(); @@ -59,7 +59,7 @@ export class ServiceSettingsPage extends WizardPageBase { inputWidth: NumberInputWidth, spaceBetweenFields: '40px', rows: [{ - fields: [{ + items: [{ type: FieldType.Options, label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"), options: ['1', '3', '4', '5', '6', '7', '8', '9'], @@ -75,7 +75,7 @@ export class ServiceSettingsPage extends WizardPageBase { variableName: VariableNames.ComputePoolScale_VariableName, }] }, { - fields: [{ + items: [{ type: FieldType.Number, label: localize('deployCluster.DataPoolInstances', "Data pool instances"), min: 1, @@ -93,7 +93,7 @@ export class ServiceSettingsPage extends WizardPageBase { variableName: VariableNames.SparkPoolScale_VariableName }] }, { - fields: [ + items: [ { type: FieldType.Number, label: localize('deployCluster.StoragePoolInstances', "Storage pool (HDFS) instances"), @@ -119,12 +119,13 @@ export class ServiceSettingsPage extends WizardPageBase { return createSection({ view: view, container: this.wizard.wizardObject, + inputComponents: this.inputComponents, sectionInfo: sectionInfo, onNewDisposableCreated: (disposable: vscode.Disposable): void => { this.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - this.inputComponents[name] = { component: component }; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { + this.inputComponents[name] = { component: inputComponentInfo.component }; }, onNewValidatorCreated: (validator: Validator): void => { } @@ -400,6 +401,7 @@ export class ServiceSettingsPage extends WizardPageBase { public onLeave(): void { setModelValues(this.inputComponents, this.wizard.model); + Object.assign(this.wizard.inputComponents, this.inputComponents); this.wizard.wizardObject.registerNavigationValidator((pcInfo) => { return true; }); diff --git a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts index 1e4a92b5f5..b2699ff145 100644 --- a/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts +++ b/extensions/resource-deployment/src/ui/deployClusterWizard/pages/summaryPage.ts @@ -43,18 +43,17 @@ export class SummaryPage extends WizardPageBase { title: localize('deployCluster.DeploymentTarget', "Deployment target"), rows: [ { - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.Kubeconfig', "Kube config"), defaultValue: this.wizard.model.getStringValue(VariableNames.KubeConfigPath_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.ClusterContext', "Cluster context"), - defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterContext_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] } ] @@ -68,33 +67,33 @@ export class SummaryPage extends WizardPageBase { rows: [ { - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.DeploymentProfile', "Deployment profile"), defaultValue: this.wizard.model.getStringValue(VariableNames.DeploymentProfile_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.ClusterName', "Cluster name"), defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }, { - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.ControllerUsername', "Controller username"), defaultValue: this.wizard.model.getStringValue(VariableNames.AdminUserName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.AuthenticationMode', "Authentication mode"), defaultValue: this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory ? localize('deployCluster.AuthenticationMode.ActiveDirectory', "Active Directory") : localize('deployCluster.AuthenticationMode.Basic', "Basic"), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } } ] } @@ -103,72 +102,72 @@ export class SummaryPage extends WizardPageBase { if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { clusterSectionInfo.rows!.push({ - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.OuDistinguishedName', "Organizational unit"), defaultValue: this.wizard.model.getStringValue(VariableNames.OrganizationalUnitDistinguishedName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.DomainControllerFQDNs', "Domain controller FQDNs"), defaultValue: this.wizard.model.getStringValue(VariableNames.DomainControllerFQDNs_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); clusterSectionInfo.rows!.push({ - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.DomainDNSIPAddresses', "Domain DNS IP addresses"), defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSIPAddresses_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.DomainDNSName', "Domain DNS name"), defaultValue: this.wizard.model.getStringValue(VariableNames.DomainDNSName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); clusterSectionInfo.rows!.push({ - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.ClusterAdmins', "Cluster admin group"), defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterAdmins_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.ClusterUsers', "Cluster users"), defaultValue: this.wizard.model.getStringValue(VariableNames.ClusterUsers_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); clusterSectionInfo.rows!.push({ - fields: [ + items: [ { type: FieldType.ReadonlyText, - label: localize('deployCluster.AppOwers', "App owners"), + label: localize('deployCluster.AppOwners', "App owners"), defaultValue: this.wizard.model.getStringValue(VariableNames.AppOwners_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.AppReaders', "App readers"), defaultValue: this.wizard.model.getStringValue(VariableNames.AppReaders_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); clusterSectionInfo.rows!.push({ - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.DomainServiceAccountUserName', "Service account username"), defaultValue: this.wizard.model.getStringValue(VariableNames.DomainServiceAccountUserName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); } @@ -179,45 +178,45 @@ export class SummaryPage extends WizardPageBase { inputWidth: '200px', title: localize('deployCluster.AzureSettings', "Azure settings"), rows: [{ - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.SubscriptionId', "Subscription id"), defaultValue: this.wizard.model.getStringValue(VariableNames.SubscriptionId_VariableName) || localize('deployCluster.DefaultSubscription', "Default Azure Subscription"), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.ResourceGroup', "Resource group"), defaultValue: this.wizard.model.getStringValue(VariableNames.ResourceGroup_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } } ] }, { - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.Location', "Location"), defaultValue: this.wizard.model.getStringValue(VariableNames.Location_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.AksClusterName', "AKS cluster name"), defaultValue: this.wizard.model.getStringValue(VariableNames.AksName_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } } ] }, { - fields: [ + items: [ { type: FieldType.ReadonlyText, label: localize('deployCluster.VMSize', "VM size"), defaultValue: this.wizard.model.getStringValue(VariableNames.VMSize_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.VMCount', "VM count"), defaultValue: this.wizard.model.getStringValue(VariableNames.VMCount_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } } ] } @@ -231,35 +230,35 @@ export class SummaryPage extends WizardPageBase { title: localize('deployCluster.ScaleSettings', "Scale settings"), rows: [ { - fields: [{ + items: [{ type: FieldType.ReadonlyText, label: localize('deployCluster.MasterSqlServerInstances', "SQL Server master instances"), defaultValue: this.wizard.model.getStringValue(VariableNames.SQLServerScale_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.ComputePoolInstances', "Compute pool instances"), defaultValue: this.wizard.model.getStringValue(VariableNames.ComputePoolScale_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }, { - fields: [{ + items: [{ type: FieldType.ReadonlyText, label: localize('deployCluster.DataPoolInstances', "Data pool instances"), defaultValue: this.wizard.model.getStringValue(VariableNames.DataPoolScale_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }, { type: FieldType.ReadonlyText, label: localize('deployCluster.SparkPoolInstances', "Spark pool instances"), defaultValue: this.wizard.model.getStringValue(VariableNames.SparkPoolScale_VariableName), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }, { - fields: [{ + items: [{ type: FieldType.ReadonlyText, label: localize('deployCluster.StoragePoolInstances', "Storage pool (HDFS) instances"), defaultValue: `${this.wizard.model.getStringValue(VariableNames.HDFSPoolScale_VariableName)} ${this.wizard.model.getBooleanValue(VariableNames.IncludeSpark_VariableName) ? localize('deployCluster.WithSpark', "(Spark included)") : ''}`, - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] } ] @@ -270,6 +269,7 @@ export class SummaryPage extends WizardPageBase { title: '', component: createSection({ container: this.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, sectionInfo: sectionInfo, view: this.view, onNewDisposableCreated: () => { }, @@ -398,7 +398,7 @@ export class SummaryPage extends WizardPageBase { private createEndpointRow(name: string, dnsVariableName: string, portVariableName: string): azdata.FlexContainer { const items = []; - items.push(createLabel(this.view, { text: name, width: '150px', fontWeight: FontWeight.Bold })); + items.push(createLabel(this.view, { text: name, width: '150px', cssStyles: { fontWeight: FontWeight.Bold } })); if (this.wizard.model.authenticationMode === AuthenticationMode.ActiveDirectory) { items.push(createLabel(this.view, { text: this.wizard.model.getStringValue(dnsVariableName)!, width: '200px' diff --git a/extensions/resource-deployment/src/ui/deploymentInputDialog.ts b/extensions/resource-deployment/src/ui/deploymentInputDialog.ts index ba32444c89..30f024e4ff 100644 --- a/extensions/resource-deployment/src/ui/deploymentInputDialog.ts +++ b/extensions/resource-deployment/src/ui/deploymentInputDialog.ts @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; +import { EOL } from 'os'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { DialogBase } from './dialogBase'; -import { INotebookService } from '../services/notebookService'; import { DialogInfo, instanceOfNotebookBasedDialogInfo, NotebookBasedDialogInfo } from '../interfaces'; -import { Validator, initializeDialog, InputComponents, setModelValues, InputValueTransformer, InputComponent } from './modelViewUtils'; -import { Model } from './model'; -import { EOL } from 'os'; +import { INotebookService } from '../services/notebookService'; import { IPlatformService } from '../services/platformService'; +import { DialogBase } from './dialogBase'; +import { Model } from './model'; +import { initializeDialog, InputComponentInfo, InputComponents, setModelValues, Validator } from './modelViewUtils'; const localize = nls.loadMessageBundle(); @@ -42,11 +42,12 @@ export class DeploymentInputDialog extends DialogBase { initializeDialog({ dialogInfo: this.dialogInfo, container: this._dialogObject, + inputComponents: this.inputComponents, onNewDisposableCreated: (disposable: vscode.Disposable): void => { this._toDispose.push(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent, inputValueTransformer?: InputValueTransformer): void => { - this.inputComponents[name] = { component: component, inputValueTransformer: inputValueTransformer }; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo): void => { + this.inputComponents[name] = inputComponentInfo; }, onNewValidatorCreated: (validator: Validator): void => { validators.push(validator); diff --git a/extensions/resource-deployment/src/ui/model.ts b/extensions/resource-deployment/src/ui/model.ts index 0cf853fd38..536e389919 100644 --- a/extensions/resource-deployment/src/ui/model.ts +++ b/extensions/resource-deployment/src/ui/model.ts @@ -2,7 +2,14 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { NoteBookEnvironmentVariablePrefix } from '../interfaces'; +import { EOL } from 'os'; +import { ITool, NoteBookEnvironmentVariablePrefix } from '../interfaces'; +import { setEnvironmentVariablesForInstallPaths, getRuntimeBinaryPathEnvironmentVariableName } from '../utils'; +import { ToolsInstallPath } from '../constants'; +import { delimiter } from 'path'; + + +const NotebookEnvironmentVariablePrefixRegex = new RegExp(`^${NoteBookEnvironmentVariablePrefix}`); export class Model { private propValueObject: { [s: string]: string | undefined } = {}; @@ -32,13 +39,57 @@ export class Model { return value === undefined ? defaultValue : value === 'true'; } - public setEnvironmentVariables(): void { - Object.keys(this.propValueObject).filter(propertyName => propertyName.startsWith(NoteBookEnvironmentVariablePrefix)).forEach(propertyName => { - const value = this.getStringValue(propertyName); - if (value !== undefined && value !== '') { - process.env[propertyName] = value; - } - process.env[propertyName] = value === undefined ? '' : value; + /** + * Returns python code statements for setting variables starting with {@see NoteBookEnvironmentVariablePrefix} as python variables. + * The prefix {@see NoteBookEnvironmentVariablePrefix} is removed and variable name changed to all lowercase to arrive at python variable name. + * The statements returned are escaped for use in cell of a python notebook. + * + * @param tools - optional set of tools for which variable value setting statements need to be generated; + * @param inputFilter - optional parameter to filter out setting of specific variable names. Every variable for which this function returns false is not included + * in the emitted code. + */ + public getCodeCellContentForNotebook(tools: ITool[] = [], inputFilter: (varName: string) => boolean = () => true): string[] { + const statements: string[] = Object.keys(this.propValueObject) + .filter(propertyName => propertyName.startsWith(NoteBookEnvironmentVariablePrefix) && inputFilter(propertyName)) + .map(propertyName => { + const value = this.escapeForNotebookCodeCell(this.getStringValue(propertyName, '')); + const varName = propertyName.replace(NotebookEnvironmentVariablePrefixRegex, '').toLocaleLowerCase(); + return `${varName} = '${value}'${EOL}`; + }); + statements.push(`print('Variables have been set successfully.')${EOL}`); + const env: NodeJS.ProcessEnv = {}; + setEnvironmentVariablesForInstallPaths(tools, env); + tools.forEach(tool => { + const envVarName: string = getRuntimeBinaryPathEnvironmentVariableName(tool.name); + statements.push(`os.environ["${envVarName}"] = "${this.escapeForNotebookCodeCell(env[envVarName]!)}"${EOL}`); }); + if (env[ToolsInstallPath]) { + statements.push(`os.environ["PATH"] = os.environ["PATH"] + "${delimiter}" + "${this.escapeForNotebookCodeCell(env[ToolsInstallPath])}"${EOL}`); + } + statements.push(`print('Environment Variables for tools have been set successfully.')${EOL}`); + return statements; + } + + protected escapeForNotebookCodeCell(original?: string): string | undefined { + // Escape the \ character for the code cell string value + return original && original.replace(/\\/g, '\\\\'); + } + + /** + * Sets the environment variable for each model variable that starts with {@see NoteBookEnvironmentVariablePrefix} in the + * current process. + * + * @param env - env variable object in which the environment variables are populated. Default: process.env + * @param inputFilter - an optional filter to further restrict the variables that are set into the env object. + * Every variable for which this function returns false is not included does not get the env variable set. + * Default all variable meeting prefix requirements are set. + */ + public setEnvironmentVariables(env: NodeJS.ProcessEnv = process.env, inputFilter: (varName: string) => boolean = () => true): void { + Object.keys(this.propValueObject) + .filter(propertyName => propertyName.startsWith(NoteBookEnvironmentVariablePrefix) && inputFilter(propertyName)) + .forEach(propertyName => { + const value = this.getStringValue(propertyName); + env[propertyName] = value === undefined ? '' : value; + }); } } diff --git a/extensions/resource-deployment/src/ui/modelViewUtils.ts b/extensions/resource-deployment/src/ui/modelViewUtils.ts index b0d0ebbd99..50c354dda1 100644 --- a/extensions/resource-deployment/src/ui/modelViewUtils.ts +++ b/extensions/resource-deployment/src/ui/modelViewUtils.ts @@ -9,19 +9,28 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import * as azurecore from '../../../azurecore/src/azurecore'; import { azureResource } from '../../../azurecore/src/azureResource/azure-resource'; -import { AzureAccountFieldInfo, AzureLocationsFieldInfo, DialogInfoBase, FieldInfo, FieldType, FontStyle, FontWeight, LabelPosition, PageInfoBase, SectionInfo, KubeClusterContextFieldInfo } from '../interfaces'; +import { AzureAccountFieldInfo, AzureLocationsFieldInfo, ComponentCSSStyles, DialogInfoBase, FieldInfo, FieldType, KubeClusterContextFieldInfo, LabelPosition, NoteBookEnvironmentVariablePrefix, OptionsInfo, OptionsType, PageInfoBase, RowInfo, SectionInfo, TextCSSStyles } from '../interfaces'; import * as loc from '../localizedConstants'; import { getDefaultKubeConfigPath, getKubeConfigClusterContexts } from '../services/kubeService'; -import { getDateTimeString, getErrorMessage } from '../utils'; +import { assert, getDateTimeString, getErrorMessage } from '../utils'; import { WizardInfoBase } from './../interfaces'; import { Model } from './model'; +import { RadioGroupLoadingComponentBuilder } from './radioGroupLoadingComponentBuilder'; const localize = nls.loadMessageBundle(); export type Validator = () => { valid: boolean, message: string }; export type InputValueTransformer = (inputValue: string) => string; -export type InputComponent = azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent | azdata.RadioButtonComponent; -export type InputComponents = { [s: string]: { component: InputComponent; inputValueTransformer?: InputValueTransformer } }; +export type InputComponent = azdata.TextComponent | azdata.InputBoxComponent | azdata.DropDownComponent | azdata.CheckBoxComponent | RadioGroupLoadingComponentBuilder; +export type InputComponentInfo = { + component: InputComponent; + inputValueTransformer?: InputValueTransformer; + isPassword?: boolean +}; + +export type InputComponents = { + [s: string]: InputComponentInfo +}; export function getInputBoxComponent(name: string, inputComponents: InputComponents): azdata.InputBoxComponent { return inputComponents[name].component; @@ -39,40 +48,42 @@ export function getTextComponent(name: string, inputComponents: InputComponents) return inputComponents[name].component; } -export const DefaultInputComponentWidth = '400px'; -export const DefaultLabelComponentWidth = '200px'; +export const DefaultInputWidth = '400px'; +export const DefaultLabelWidth = '200px'; +export const DefaultFieldAlignItems = undefined; +export const DefaultFieldWidth = undefined; +export const DefaultFieldHeight = undefined; -export interface DialogContext extends CreateContext { +export interface DialogContext extends ContextBase { dialogInfo: DialogInfoBase; container: azdata.window.Dialog; } -export interface WizardPageContext extends CreateContext { +export interface WizardPageContext extends ContextBase { wizardInfo: WizardInfoBase; pageInfo: PageInfoBase; page: azdata.window.WizardPage; container: azdata.window.Wizard; } -export interface SectionContext extends CreateContext { +export interface SectionContext extends ContextBase { sectionInfo: SectionInfo; view: azdata.ModelView; } -interface FieldContext extends CreateContext { +export interface FieldContext extends ContextBase { fieldInfo: FieldInfo; components: azdata.Component[]; view: azdata.ModelView; } -interface FilePickerInputs { +export interface FilePickerInputs { input: azdata.InputBoxComponent; browseButton: azdata.ButtonComponent; } - -interface RadioOptionsInputs { - optionsList: azdata.DivContainer; - loader: azdata.LoadingComponent; +interface ReadOnlyFieldInputs { + label: azdata.TextComponent; + text?: azdata.TextComponent; } interface KubeClusterContextFieldContext extends FieldContext { @@ -87,11 +98,12 @@ interface AzureAccountFieldContext extends FieldContext { fieldInfo: AzureAccountFieldInfo; } -interface CreateContext { +interface ContextBase { container: azdata.window.Dialog | azdata.window.Wizard; + inputComponents: InputComponents; onNewValidatorCreated: (validator: Validator) => void; onNewDisposableCreated: (disposable: vscode.Disposable) => void; - onNewInputComponentCreated: (name: string, component: InputComponent, inputValueTransformer?: InputValueTransformer) => void; + onNewInputComponentCreated: (name: string, inputComponentInfo: InputComponentInfo) => void; } export function createTextInput(view: azdata.ModelView, inputInfo: { defaultValue?: string, ariaLabel: string, required?: boolean, placeHolder?: string, width?: string, enabled?: boolean }): azdata.InputBoxComponent { @@ -106,12 +118,20 @@ export function createTextInput(view: azdata.ModelView, inputInfo: { defaultValu }).component(); } -export function createLabel(view: azdata.ModelView, info: { text: string, description?: string, required?: boolean, width?: string, fontStyle?: FontStyle, fontWeight?: FontWeight, links?: azdata.LinkArea[] }): azdata.TextComponent { +export function createLabel(view: azdata.ModelView, info: { text: string, description?: string, required?: boolean, width?: string, links?: azdata.LinkArea[], cssStyles?: TextCSSStyles }): azdata.TextComponent { + let cssStyles: { [key: string]: string } = {}; + if (info.cssStyles !== undefined) { + cssStyles = Object.assign(cssStyles, info.cssStyles, { 'font-style': info.cssStyles.fontStyle || 'normal', 'font-weight': info.cssStyles.fontWeight || 'normal' }); + if (info.cssStyles.color !== undefined) { + cssStyles['color'] = info.cssStyles.color; + } + } + const text = view.modelBuilder.text().withProperties({ value: info.text, description: info.description, requiredIndicator: info.required, - CSSStyles: { 'font-style': info.fontStyle || 'normal', 'font-weight': info.fontWeight || 'normal' }, + CSSStyles: cssStyles, links: info.links }).component(); text.width = info.width; @@ -157,8 +177,11 @@ export function initializeDialog(dialogContext: DialogContext): void { const tab = azdata.window.createTab(tabInfo.title); tab.registerContent((view: azdata.ModelView) => { const sections = tabInfo.sections.map(sectionInfo => { - sectionInfo.inputWidth = sectionInfo.inputWidth || tabInfo.inputWidth || DefaultInputComponentWidth; - sectionInfo.labelWidth = sectionInfo.labelWidth || tabInfo.labelWidth || DefaultLabelComponentWidth; + sectionInfo.inputWidth = sectionInfo.inputWidth || tabInfo.inputWidth || DefaultInputWidth; + sectionInfo.labelWidth = sectionInfo.labelWidth || tabInfo.labelWidth || DefaultLabelWidth; + sectionInfo.fieldAlignItems = sectionInfo.fieldAlignItems || tabInfo.fieldAlignItems || DefaultFieldAlignItems; + sectionInfo.fieldWidth = sectionInfo.fieldWidth || tabInfo.fieldWidth || DefaultFieldWidth; + sectionInfo.fieldHeight = sectionInfo.fieldHeight || tabInfo.fieldHeight || DefaultFieldHeight; sectionInfo.labelPosition = sectionInfo.labelPosition || tabInfo.labelPosition; return createSection({ sectionInfo: sectionInfo, @@ -166,7 +189,8 @@ export function initializeDialog(dialogContext: DialogContext): void { onNewDisposableCreated: dialogContext.onNewDisposableCreated, onNewInputComponentCreated: dialogContext.onNewInputComponentCreated, onNewValidatorCreated: dialogContext.onNewValidatorCreated, - container: dialogContext.container + container: dialogContext.container, + inputComponents: dialogContext.inputComponents }); }); const formBuilder = view.modelBuilder.formContainer().withFormItems( @@ -189,12 +213,16 @@ export function initializeDialog(dialogContext: DialogContext): void { export function initializeWizardPage(context: WizardPageContext): void { context.page.registerContent((view: azdata.ModelView) => { const sections = context.pageInfo.sections.map(sectionInfo => { - sectionInfo.inputWidth = sectionInfo.inputWidth || context.pageInfo.inputWidth || context.wizardInfo.inputWidth || DefaultInputComponentWidth; - sectionInfo.labelWidth = sectionInfo.labelWidth || context.pageInfo.labelWidth || context.wizardInfo.labelWidth || DefaultLabelComponentWidth; + sectionInfo.inputWidth = sectionInfo.inputWidth || context.pageInfo.inputWidth || context.wizardInfo.inputWidth || DefaultInputWidth; + sectionInfo.labelWidth = sectionInfo.labelWidth || context.pageInfo.labelWidth || context.wizardInfo.labelWidth || DefaultLabelWidth; + sectionInfo.fieldAlignItems = sectionInfo.fieldAlignItems || context.pageInfo.fieldAlignItems || DefaultFieldAlignItems; + sectionInfo.fieldWidth = sectionInfo.fieldWidth || context.pageInfo.fieldWidth || context.wizardInfo.fieldWidth || DefaultFieldWidth; + sectionInfo.fieldHeight = sectionInfo.fieldHeight || context.pageInfo.fieldHeight || context.wizardInfo.fieldHeight || DefaultFieldHeight; sectionInfo.labelPosition = sectionInfo.labelPosition || context.pageInfo.labelPosition || context.wizardInfo.labelPosition; return createSection({ view: view, container: context.container, + inputComponents: context.inputComponents, onNewDisposableCreated: context.onNewDisposableCreated, onNewInputComponentCreated: context.onNewInputComponentCreated, onNewValidatorCreated: context.onNewValidatorCreated, @@ -215,16 +243,16 @@ export function initializeWizardPage(context: WizardPageContext): void { export function createSection(context: SectionContext): azdata.GroupContainer { const components: azdata.Component[] = []; - context.sectionInfo.inputWidth = context.sectionInfo.inputWidth || DefaultInputComponentWidth; - context.sectionInfo.labelWidth = context.sectionInfo.labelWidth || DefaultLabelComponentWidth; + context.sectionInfo.inputWidth = context.sectionInfo.inputWidth || DefaultInputWidth; + context.sectionInfo.labelWidth = context.sectionInfo.labelWidth || DefaultLabelWidth; + context.sectionInfo.fieldAlignItems = context.sectionInfo.fieldAlignItems || DefaultFieldAlignItems; + context.sectionInfo.fieldWidth = context.sectionInfo.fieldWidth || DefaultFieldWidth; + context.sectionInfo.fieldHeight = context.sectionInfo.fieldHeight || DefaultFieldHeight; if (context.sectionInfo.fields) { processFields(context.sectionInfo.fields, components, context); } else if (context.sectionInfo.rows) { context.sectionInfo.rows.forEach(rowInfo => { - const rowItems: azdata.Component[] = []; - processFields(rowInfo.fields, rowItems, context, context.sectionInfo.spaceBetweenFields || '50px'); - const row = createFlexContainer(context.view, rowItems); - components.push(row); + components.push(processRow(rowInfo, context)); }); } @@ -235,11 +263,26 @@ export function createSection(context: SectionContext): azdata.GroupContainer { }); } +function processRow(rowInfo: RowInfo, context: SectionContext): azdata.Component { + const items: azdata.Component[] = []; + if ('items' in rowInfo.items[0]) { // rowInfo.items is RowInfo[] + const rowItems = rowInfo.items as RowInfo[]; + items.push(...rowItems.map(rowInfo => processRow(rowInfo, context))); + } else { // rowInfo.items is FieldInfo[] + const fieldItems = rowInfo.items as FieldInfo[]; + processFields(fieldItems, items, context, context.sectionInfo.spaceBetweenFields === undefined ? '50px' : context.sectionInfo.spaceBetweenFields); + } + return createFlexContainer(context.view, items, true, context.sectionInfo.fieldWidth, context.sectionInfo.fieldHeight, context.sectionInfo.fieldAlignItems, rowInfo.cssStyles); +} + function processFields(fieldInfoArray: FieldInfo[], components: azdata.Component[], context: SectionContext, spaceBetweenFields?: string): void { for (let i = 0; i < fieldInfoArray.length; i++) { const fieldInfo = fieldInfoArray[i]; fieldInfo.labelWidth = fieldInfo.labelWidth || context.sectionInfo.labelWidth; fieldInfo.inputWidth = fieldInfo.inputWidth || context.sectionInfo.inputWidth; + fieldInfo.fieldAlignItems = fieldInfo.fieldAlignItems || context.sectionInfo.fieldAlignItems; + fieldInfo.fieldWidth = fieldInfo.fieldWidth || context.sectionInfo.fieldWidth; + fieldInfo.fieldHeight = fieldInfo.fieldHeight || context.sectionInfo.fieldHeight; fieldInfo.labelPosition = fieldInfo.labelPosition === undefined ? context.sectionInfo.labelPosition : fieldInfo.labelPosition; processField({ view: context.view, @@ -248,6 +291,7 @@ function processFields(fieldInfoArray: FieldInfo[], components: azdata.Component onNewValidatorCreated: context.onNewValidatorCreated, fieldInfo: fieldInfo, container: context.container, + inputComponents: context.inputComponents, components: components }); if (spaceBetweenFields && i < fieldInfoArray.length - 1) { @@ -256,24 +300,37 @@ function processFields(fieldInfoArray: FieldInfo[], components: azdata.Component } } -export function createFlexContainer(view: azdata.ModelView, items: azdata.Component[], rowLayout: boolean = true): azdata.FlexContainer { +export function createFlexContainer(view: azdata.ModelView, items: azdata.Component[], rowLayout: boolean = true, width?: string | number, height?: string | number, alignItems?: azdata.AlignItemsType, cssStyles?: ComponentCSSStyles): azdata.FlexContainer { const flexFlow = rowLayout ? 'row' : 'column'; - const alignItems = rowLayout ? 'center' : undefined; - const itemsStyle = rowLayout ? { CSSStyles: { 'margin-right': '5px' } } : {}; - return view.modelBuilder.flexContainer().withItems(items, itemsStyle).withLayout({ flexFlow: flexFlow, alignItems: alignItems }).component(); + alignItems = alignItems || (rowLayout ? 'center' : undefined); + const itemsStyle = rowLayout ? { CSSStyles: { 'margin-right': '5px', } } : {}; + const flexLayout: azdata.FlexLayout = { flexFlow: flexFlow }; + if (height) { + flexLayout.height = height; + } + if (width) { + flexLayout.width = width; + } + if (alignItems) { + flexLayout.alignItems = alignItems; + } + return view.modelBuilder.flexContainer().withItems(items, itemsStyle).withLayout(flexLayout).withProperties({ CSSStyles: cssStyles || {} }).component(); } export function createGroupContainer(view: azdata.ModelView, items: azdata.Component[], layout: azdata.GroupLayout): azdata.GroupContainer { return view.modelBuilder.groupContainer().withItems(items).withLayout(layout).component(); } -function addLabelInputPairToContainer(view: azdata.ModelView, components: azdata.Component[], label: azdata.Component, input: azdata.Component, labelPosition?: LabelPosition, additionalComponents?: azdata.Component[]) { - const inputs = [label, input]; +function addLabelInputPairToContainer(view: azdata.ModelView, components: azdata.Component[], label: azdata.Component, input: azdata.Component | undefined, fieldInfo: FieldInfo, additionalComponents?: azdata.Component[]) { + const inputs: azdata.Component[] = [label]; + if (input !== undefined) { + inputs.push(input); + } if (additionalComponents && additionalComponents.length > 0) { inputs.push(...additionalComponents); } - if (labelPosition && labelPosition === LabelPosition.Left) { - const row = createFlexContainer(view, inputs); + if (fieldInfo.labelPosition === LabelPosition.Left) { + const row = createFlexContainer(view, inputs, true, fieldInfo.fieldWidth, fieldInfo.fieldHeight, fieldInfo.fieldAlignItems); components.push(row); } else { components.push(...inputs); @@ -285,9 +342,6 @@ function processField(context: FieldContext): void { case FieldType.Options: processOptionsTypeField(context); break; - case FieldType.RadioOptions: - processRadioOptionsTypeField(context); - break; case FieldType.DateTimeText: processDateTimeTextField(context); break; @@ -325,21 +379,42 @@ function processField(context: FieldContext): void { } function processOptionsTypeField(context: FieldContext): void { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + assert(context.fieldInfo.options !== undefined, `FieldInfo.options must be defined for FieldType:${FieldType.Options}`); + if (Array.isArray(context.fieldInfo.options)) { + context.fieldInfo.options = { + values: context.fieldInfo.options, + defaultValue: context.fieldInfo.defaultValue, + optionsType: OptionsType.Dropdown + }; + } + assert(typeof context.fieldInfo.options === 'object', `FieldInfo.options must be an object if it is not an array`); + assert('optionsType' in context.fieldInfo.options, `When FieldInfo.options is an object it must have 'optionsType' property`); + if (context.fieldInfo.options.optionsType === OptionsType.Radio) { + processRadioOptionsTypeField(context); + } else { + assert(context.fieldInfo.options.optionsType === OptionsType.Dropdown, `When optionsType is not ${OptionsType.Radio} then it must be ${OptionsType.Dropdown}`); + processDropdownOptionsTypeField(context); + } +} + +function processDropdownOptionsTypeField(context: FieldContext): void { + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); + const options = context.fieldInfo.options as OptionsInfo; const dropdown = createDropdown(context.view, { - values: context.fieldInfo.options, - defaultValue: context.fieldInfo.defaultValue, + values: options.values, + defaultValue: options.defaultValue, width: context.fieldInfo.inputWidth, editable: context.fieldInfo.editable, required: context.fieldInfo.required, label: context.fieldInfo.label }); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, dropdown); - addLabelInputPairToContainer(context.view, context.components, label, dropdown, context.fieldInfo.labelPosition); + dropdown.fireOnTextChange = true; + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: dropdown }); + addLabelInputPairToContainer(context.view, context.components, label, dropdown, context.fieldInfo); } function processDateTimeTextField(context: FieldContext): void { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const defaultValue = context.fieldInfo.defaultValue + getDateTimeString(); const input = context.view.modelBuilder.inputBox().withProperties({ value: defaultValue, @@ -349,12 +424,12 @@ function processDateTimeTextField(context: FieldContext): void { placeHolder: context.fieldInfo.placeHolder }).component(); input.width = context.fieldInfo.inputWidth; - context.onNewInputComponentCreated(context.fieldInfo.variableName!, input); - addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo.labelPosition); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: input }); + addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo); } function processNumberField(context: FieldContext): void { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const input = createNumberInput(context.view, { defaultValue: context.fieldInfo.defaultValue, ariaLabel: context.fieldInfo.label, @@ -364,12 +439,12 @@ function processNumberField(context: FieldContext): void { width: context.fieldInfo.inputWidth, placeHolder: context.fieldInfo.placeHolder }); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, input); - addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo.labelPosition); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: input }); + addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo); } function processTextField(context: FieldContext): void { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const input = createTextInput(context.view, { defaultValue: context.fieldInfo.defaultValue, ariaLabel: context.fieldInfo.label, @@ -378,8 +453,8 @@ function processTextField(context: FieldContext): void { width: context.fieldInfo.inputWidth, enabled: context.fieldInfo.enabled }); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, input); - addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo.labelPosition); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: input }); + addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo); if (context.fieldInfo.textValidationRequired) { let validationRegex: RegExp = new RegExp(context.fieldInfo.textValidationRegex!); @@ -399,12 +474,11 @@ function processTextField(context: FieldContext): void { return { valid: inputIsValid, message: context.fieldInfo.textValidationDescription! }; }; context.onNewValidatorCreated(inputValidator); - } } function processPasswordField(context: FieldContext): void { - const passwordLabel = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + const passwordLabel = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const passwordInput = context.view.modelBuilder.inputBox().withProperties({ ariaLabel: context.fieldInfo.label, inputType: 'password', @@ -412,8 +486,8 @@ function processPasswordField(context: FieldContext): void { placeHolder: context.fieldInfo.placeHolder, width: context.fieldInfo.inputWidth }).component(); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, passwordInput); - addLabelInputPairToContainer(context.view, context.components, passwordLabel, passwordInput, context.fieldInfo.labelPosition); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: passwordInput, isPassword: true }); + addLabelInputPairToContainer(context.view, context.components, passwordLabel, passwordInput, context.fieldInfo); if (context.fieldInfo.type === FieldType.SQLPassword) { const invalidPasswordMessage = getInvalidSQLPasswordMessage(context.fieldInfo.label); @@ -430,7 +504,7 @@ function processPasswordField(context: FieldContext): void { if (context.fieldInfo.confirmationRequired) { const passwordNotMatchMessage = getPasswordMismatchMessage(context.fieldInfo.label); - const confirmPasswordLabel = createLabel(context.view, { text: context.fieldInfo.confirmationLabel!, required: true, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); + const confirmPasswordLabel = createLabel(context.view, { text: context.fieldInfo.confirmationLabel!, required: true, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const confirmPasswordInput = context.view.modelBuilder.inputBox().withProperties({ ariaLabel: context.fieldInfo.confirmationLabel, inputType: 'password', @@ -438,7 +512,7 @@ function processPasswordField(context: FieldContext): void { width: context.fieldInfo.inputWidth }).component(); - addLabelInputPairToContainer(context.view, context.components, confirmPasswordLabel, confirmPasswordInput, context.fieldInfo.labelPosition); + addLabelInputPairToContainer(context.view, context.components, confirmPasswordLabel, confirmPasswordInput, context.fieldInfo); context.onNewValidatorCreated((): { valid: boolean, message: string } => { const passwordMatches = passwordInput.value === confirmPasswordInput.value; return { valid: passwordMatches, message: passwordNotMatchMessage }; @@ -459,34 +533,85 @@ function processPasswordField(context: FieldContext): void { } } -function processReadonlyTextField(context: FieldContext): void { - let defaultValue = context.fieldInfo.defaultValue || ''; - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: false, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); - const text = createLabel(context.view, { text: defaultValue, description: '', required: false, width: context.fieldInfo.inputWidth, fontWeight: context.fieldInfo.textFontWeight, fontStyle: context.fieldInfo.fontStyle, links: context.fieldInfo.links }); - addLabelInputPairToContainer(context.view, context.components, label, text, context.fieldInfo.labelPosition); +function processReadonlyTextField(context: FieldContext, allowEvaluation: boolean = true): ReadOnlyFieldInputs { + if ((context.fieldInfo.links?.length ?? 0) > 0) { + return processHyperlinkedTextField(context); + } else if (context.fieldInfo.isEvaluated && allowEvaluation) { + return processEvaluatedTextField(context); + } + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: false, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); + const text = context.fieldInfo.defaultValue !== undefined + ? createLabel(context.view, { text: context.fieldInfo.defaultValue, description: '', required: false, width: context.fieldInfo.inputWidth }) + : undefined; + addLabelInputPairToContainer(context.view, context.components, label, text, context.fieldInfo); + return { label: label, text: text }; +} + +/** + * creates a text component that has text that contains hyperlinks. The context.fieldInfo.label contains {0},{1} ... + * placeholder(s) where contents of link array object are placed with that portion interpolated as a clickable link. + * + * @param context - the FieldContext object using which the field gets created + */ +function processHyperlinkedTextField(context: FieldContext): ReadOnlyFieldInputs { + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: false, width: context.fieldInfo.labelWidth, links: context.fieldInfo.links, cssStyles: context.fieldInfo.labelCSSStyles }); + context.components.push(label); + return { label: label }; +} + +function processEvaluatedTextField(context: FieldContext): ReadOnlyFieldInputs { + const readOnlyField = processReadonlyTextField(context, false /*allowEvaluation*/); + context.onNewInputComponentCreated(context.fieldInfo.variableName || context.fieldInfo.label, { + component: readOnlyField.text!, + inputValueTransformer: () => { + readOnlyField.text!.value = substituteVariableValues(context.inputComponents, context.fieldInfo.defaultValue); + return readOnlyField.text?.value!; + } + }); + return readOnlyField; +} + +/** + * Returns a string that interpolates all variable names in the {@param inputValue} string de-marked as $(VariableName) + * substituted with their corresponding values. + * + * Only variables in the current model starting with {@see NoteBookEnvironmentVariablePrefix} are replaced. + * + * @param inputValue + * @param inputComponents + */ +function substituteVariableValues(inputComponents: InputComponents, inputValue?: string): string | undefined { + Object.keys(inputComponents) + .filter(key => key.startsWith(NoteBookEnvironmentVariablePrefix)) + .forEach(key => { + const value = getInputComponentValue(inputComponents, key) ?? ''; + const re: RegExp = new RegExp(`\\\$\\\(${key}\\\)`, 'gi'); + inputValue = inputValue?.replace(re, value); + }); + return inputValue; } function processCheckboxField(context: FieldContext): void { const checkbox = createCheckbox(context.view, { initialValue: context.fieldInfo.defaultValue! === 'true', label: context.fieldInfo.label, required: context.fieldInfo.required }); context.components.push(checkbox); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, checkbox); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: checkbox }); } /** * A File Picker field consists of a text field and a browse button that allows a user to pick a file system file. * @param context The context to use to create the field */ -function processFilePickerField(context: FieldContext, defaultFilePath?: string): FilePickerInputs { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); +function processFilePickerField(context: FieldContext): FilePickerInputs { + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); const input = createTextInput(context.view, { - defaultValue: defaultFilePath || context.fieldInfo.defaultValue || '', + defaultValue: context.fieldInfo.defaultValue || '', ariaLabel: context.fieldInfo.label, required: context.fieldInfo.required, placeHolder: context.fieldInfo.placeHolder, width: context.fieldInfo.inputWidth, enabled: context.fieldInfo.enabled }); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, input); + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: input }); input.enabled = false; const browseFileButton = context.view!.modelBuilder.button().withProperties({ label: loc.browse }).component(); context.onNewDisposableCreated(browseFileButton.onDidClick(async () => { @@ -506,42 +631,22 @@ function processFilePickerField(context: FieldContext, defaultFilePath?: string) let fileUri = fileUris[0]; input.value = fileUri.fsPath; })); - addLabelInputPairToContainer(context.view, context.components, label, input, LabelPosition.Left, [browseFileButton]); + context.fieldInfo.labelPosition = LabelPosition.Left; + addLabelInputPairToContainer(context.view, context.components, label, input, context.fieldInfo, [browseFileButton]); return { input: input, browseButton: browseFileButton }; } /** - * An Kube Config Cluster picker field consists of a file system filee picker and radio button selector for cluster contexts defined in the config filed picked using the file picker. - * @param context The context to use to create the field + * This function returns a method that reads the cluster context from the {@param file}. This method then returns the cluster contexts + * read as an OptionsInfo object asynchronously. + * + * @param file - the file from which to fetch the cluster contexts */ -async function processKubeConfigClusterPickerField(context: KubeClusterContextFieldContext): Promise { - const kubeConfigFilePathVariableName = context.fieldInfo.configFileVariableName || 'AZDATA_NB_VAR_KUBECONFIG_PATH'; - const filePickerContext: FieldContext = { - container: context.container, - components: context.components, - view: context.view, - onNewValidatorCreated: context.onNewValidatorCreated, - onNewDisposableCreated: context.onNewDisposableCreated, - onNewInputComponentCreated: context.onNewInputComponentCreated, - fieldInfo: { - label: loc.kubeConfigFilePath, - type: FieldType.FilePicker, - labelWidth: context.fieldInfo.labelWidth, - variableName: kubeConfigFilePathVariableName, - required: true - } - }; - const filePicker = processFilePickerField(filePickerContext, getDefaultKubeConfigPath()); - context.fieldInfo.subFields = context.fieldInfo.subFields || []; - context.fieldInfo.subFields!.push({ - label: filePickerContext.fieldInfo.label, - variableName: kubeConfigFilePathVariableName - }); - context.onNewInputComponentCreated(kubeConfigFilePathVariableName, filePicker.input); - const getClusterContexts = async () => { +function getClusterContexts(file: string): (() => Promise) { + return async () => { try { let currentClusterContext = ''; - const clusterContexts: string[] = (await getKubeConfigClusterContexts(filePicker.input.value!)).map(kubeClusterContext => { + const clusterContexts: string[] = (await getKubeConfigClusterContexts(file)).map(kubeClusterContext => { if (kubeClusterContext.isCurrentContext) { currentClusterContext = kubeClusterContext.name; } @@ -551,76 +656,78 @@ async function processKubeConfigClusterPickerField(context: KubeClusterContextFi throw Error(loc.clusterContextNotFound); } return { values: clusterContexts, defaultValue: currentClusterContext }; - } catch (e) { - throw Error(localize('kubeConfigClusterPicker.errorLoadingClusters', "An error ocurred while loading or parsing the config file:{0}, error is:{1}", filePicker.input.value, getErrorMessage(e))); + } + catch (e) { + throw Error(localize('getClusterContexts.errorFetchingClusters', "An error ocurred while loading or parsing the config file:{0}, error is:{1}", file, getErrorMessage(e))); } }; - - createRadioOptions(context, getClusterContexts) - .then(clusterContextOptions => { - filePicker.input.onTextChanged(async () => { - await loadOrReloadRadioOptions(context, clusterContextOptions.optionsList, clusterContextOptions.loader, getClusterContexts); - }); - }).catch(error => { - console.log(`failed to create radio options, Error: ${error}`); - }); } -async function processRadioOptionsTypeField(context: FieldContext): Promise { +/** + * A Kube Config Cluster picker field consists of a file system file picker and radio button selector for cluster contexts defined in the config filed picked using the file picker. + * @param context The context to use to create the field + */ +async function processKubeConfigClusterPickerField(context: KubeClusterContextFieldContext): Promise { + const kubeConfigFilePathVariableName = context.fieldInfo.configFileVariableName || 'AZDATA_NB_VAR_KUBECONFIG_PATH'; + const filePickerContext: FieldContext = { + container: context.container, + inputComponents: context.inputComponents, + components: context.components, + view: context.view, + onNewValidatorCreated: context.onNewValidatorCreated, + onNewDisposableCreated: context.onNewDisposableCreated, + onNewInputComponentCreated: context.onNewInputComponentCreated, + fieldInfo: { + label: loc.kubeConfigFilePath, + type: FieldType.FilePicker, + defaultValue: getDefaultKubeConfigPath(), + inputWidth: context.fieldInfo.inputWidth, + labelWidth: context.fieldInfo.labelWidth, + variableName: kubeConfigFilePathVariableName, + required: true + } + }; + const filePicker = processFilePickerField(filePickerContext); + context.fieldInfo.subFields = context.fieldInfo.subFields || []; + context.fieldInfo.subFields.push({ + label: filePickerContext.fieldInfo.label, + variableName: kubeConfigFilePathVariableName + }); + + const radioOptionsGroup = await createRadioOptions(context, getClusterContexts(filePicker.input.value!)); + context.onNewDisposableCreated(filePicker.input.onTextChanged(async () => + await radioOptionsGroup.loadOptions(getClusterContexts(filePicker.input.value!)) + )); + +} + +async function processRadioOptionsTypeField(context: FieldContext): Promise { return await createRadioOptions(context); } -async function createRadioOptions(context: FieldContext, getRadioButtonInfo?: (() => Promise<{ values: string[] | azdata.CategoryValue[], defaultValue: string }>)) - : Promise { - const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, fontWeight: context.fieldInfo.labelFontWeight }); - const optionsList = context.view!.modelBuilder.divContainer().withProperties({ clickable: false }).component(); - const radioOptionsLoadingComponent = context.view!.modelBuilder.loadingComponent().withItem(optionsList).component(); - addLabelInputPairToContainer(context.view, context.components, label, radioOptionsLoadingComponent, LabelPosition.Left); - await loadOrReloadRadioOptions(context, optionsList, radioOptionsLoadingComponent, getRadioButtonInfo); - return { optionsList: optionsList, loader: radioOptionsLoadingComponent }; + +async function createRadioOptions(context: FieldContext, getRadioButtonInfo?: (() => Promise)) + : Promise { + if (context.fieldInfo.fieldAlignItems === undefined) { + context.fieldInfo.fieldAlignItems = 'flex-start'; // by default align the items to the top. + } + const label = createLabel(context.view, { text: context.fieldInfo.label, description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, cssStyles: context.fieldInfo.labelCSSStyles }); + const radioGroupLoadingComponentBuilder = new RadioGroupLoadingComponentBuilder(context.view, context.onNewDisposableCreated); + context.fieldInfo.labelPosition = LabelPosition.Left; + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: radioGroupLoadingComponentBuilder }); + addLabelInputPairToContainer(context.view, context.components, label, radioGroupLoadingComponentBuilder.component(), context.fieldInfo); + const options = context.fieldInfo.options as OptionsInfo; + await radioGroupLoadingComponentBuilder.loadOptions( + getRadioButtonInfo || options); // wait for the radioGroup to be fully initialized + return radioGroupLoadingComponentBuilder; } -async function loadOrReloadRadioOptions(context: FieldContext, optionsList: azdata.DivContainer, radioOptionsLoadingComponent: azdata.LoadingComponent, getRadioButtonInfo: (() => Promise<{ values: string[] | azdata.CategoryValue[]; defaultValue: string; }>) | undefined): Promise { - radioOptionsLoadingComponent.loading = true; - optionsList.clearItems(); - let options: (string[] | azdata.CategoryValue[]) = context.fieldInfo.options!; - let defaultValue: string = context.fieldInfo.defaultValue!; - try { - if (getRadioButtonInfo) { - const radioButtonsInfo = await getRadioButtonInfo(); - options = radioButtonsInfo.values; - defaultValue = radioButtonsInfo.defaultValue; - } - options.forEach((op: string | azdata.CategoryValue) => { - const option: azdata.CategoryValue = (typeof op === 'string') ? { name: op, displayName: op } : op as azdata.CategoryValue; - const radioOption = context.view!.modelBuilder.radioButton().withProperties({ - label: option.displayName, - checked: option.displayName === defaultValue, - name: option.name, - }).component(); - if (radioOption.checked) { - context.onNewInputComponentCreated(context.fieldInfo.variableName!, radioOption); - } - context.onNewDisposableCreated(radioOption.onDidClick(() => { - // reset checked status of all remaining radioButtons - optionsList.items.filter(otherOption => otherOption !== radioOption).forEach(otherOption => (otherOption as azdata.RadioButtonComponent).checked = false); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, radioOption!); - })); - optionsList.addItem(radioOption); - }); - } - catch (e) { - const errorLoadingRadioOptionsLabel = context.view!.modelBuilder.text().withProperties({ value: getErrorMessage(e) }).component(); - optionsList.addItem(errorLoadingRadioOptionsLabel); - } - radioOptionsLoadingComponent.loading = false; -} /** * An Azure Account field consists of 3 separate dropdown fields - Account, Subscription and Resource Group * @param context The context to use to create the field */ -function processAzureAccountField(context: AzureAccountFieldContext): void { +async function processAzureAccountField(context: AzureAccountFieldContext): Promise { context.fieldInfo.subFields = []; const accountValueToAccountMap = new Map(); const subscriptionValueToSubscriptionMap = new Map(); @@ -628,11 +735,12 @@ function processAzureAccountField(context: AzureAccountFieldContext): void { const subscriptionDropdown = createAzureSubscriptionDropdown(context, subscriptionValueToSubscriptionMap); const resourceGroupDropdown = createAzureResourceGroupsDropdown(context, accountDropdown, accountValueToAccountMap, subscriptionDropdown, subscriptionValueToSubscriptionMap); const locationDropdown = context.fieldInfo.locations && processAzureLocationsField(context); - accountDropdown.onValueChanged(selectedItem => { + accountDropdown.onValueChanged(async selectedItem => { const selectedAccount = accountValueToAccountMap.get(selectedItem.selected)!; - handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown); + await handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown); }); - azdata.accounts.getAllAccounts().then((accounts: azdata.Account[]) => { + try { + const accounts = await azdata.accounts.getAllAccounts(); // Append a blank value for the "default" option if the field isn't required, context will clear all the dropdowns when selected const dropdownValues = context.fieldInfo.required ? [] : ['']; accountDropdown.values = dropdownValues.concat(accounts.map(account => { @@ -641,8 +749,10 @@ function processAzureAccountField(context: AzureAccountFieldContext): void { return displayName; })); const selectedAccount = accountDropdown.value ? accountValueToAccountMap.get(accountDropdown.value.toString()) : undefined; - handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown); - }, (err: any) => console.log(`Unexpected error fetching accounts: ${err}`)); + await handleSelectedAccountChanged(context, selectedAccount, subscriptionDropdown, subscriptionValueToSubscriptionMap, resourceGroupDropdown, locationDropdown); + } catch (error) { + vscode.window.showErrorMessage(localize('azure.accounts.unexpectedAccountsError', 'Unexpected error fetching accounts: ${0}', getErrorMessage(error))); + } } function createAzureAccountDropdown(context: AzureAccountFieldContext): azdata.DropDownComponent { @@ -651,7 +761,7 @@ function createAzureAccountDropdown(context: AzureAccountFieldContext): azdata.D description: context.fieldInfo.description, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, - fontWeight: context.fieldInfo.labelFontWeight + cssStyles: context.fieldInfo.labelCSSStyles }); const accountDropdown = createDropdown(context.view, { width: context.fieldInfo.inputWidth, @@ -659,8 +769,9 @@ function createAzureAccountDropdown(context: AzureAccountFieldContext): azdata.D required: context.fieldInfo.required, label: loc.account }); - context.onNewInputComponentCreated(context.fieldInfo.variableName!, accountDropdown); - addLabelInputPairToContainer(context.view, context.components, label, accountDropdown, context.fieldInfo.labelPosition); + accountDropdown.fireOnTextChange = true; + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { component: accountDropdown }); + addLabelInputPairToContainer(context.view, context.components, label, accountDropdown, context.fieldInfo); return accountDropdown; } @@ -671,36 +782,48 @@ function createAzureSubscriptionDropdown( text: loc.subscription, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, - fontWeight: context.fieldInfo.labelFontWeight + cssStyles: context.fieldInfo.labelCSSStyles }); const subscriptionDropdown = createDropdown(context.view, { + defaultValue: (context.fieldInfo.required) ? undefined : '', width: context.fieldInfo.inputWidth, editable: false, required: context.fieldInfo.required, label: loc.subscription }); + subscriptionDropdown.fireOnTextChange = true; context.fieldInfo.subFields!.push({ label: label.value!, variableName: context.fieldInfo.subscriptionVariableName }); - context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName!, subscriptionDropdown, (inputValue: string) => { - return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue; + context.onNewInputComponentCreated(context.fieldInfo.subscriptionVariableName!, { + component: subscriptionDropdown, + inputValueTransformer: (inputValue: string) => { + return subscriptionValueToSubscriptionMap.get(inputValue)?.id || inputValue; + } }); - addLabelInputPairToContainer(context.view, context.components, label, subscriptionDropdown, context.fieldInfo.labelPosition); + if (context.fieldInfo.displaySubscriptionVariableName) { + context.fieldInfo.subFields!.push({ + label: label.value!, + variableName: context.fieldInfo.displaySubscriptionVariableName + }); + context.onNewInputComponentCreated(context.fieldInfo.displaySubscriptionVariableName, { component: subscriptionDropdown }); + } + addLabelInputPairToContainer(context.view, context.components, label, subscriptionDropdown, context.fieldInfo); return subscriptionDropdown; } -function handleSelectedAccountChanged( +async function handleSelectedAccountChanged( context: AzureAccountFieldContext, selectedAccount: azdata.Account | undefined, subscriptionDropdown: azdata.DropDownComponent, subscriptionValueToSubscriptionMap: Map, resourceGroupDropdown: azdata.DropDownComponent, locationDropdown?: azdata.DropDownComponent -): void { +): Promise { subscriptionValueToSubscriptionMap.clear(); subscriptionDropdown.values = []; - handleSelectedSubscriptionChanged(context, selectedAccount, undefined, resourceGroupDropdown); + await handleSelectedSubscriptionChanged(context, selectedAccount, undefined, resourceGroupDropdown); if (!selectedAccount) { subscriptionDropdown.values = ['']; if (locationDropdown) { @@ -715,7 +838,8 @@ function handleSelectedAccountChanged( } } - vscode.commands.executeCommand('azure.accounts.getSubscriptions', selectedAccount, true /*ignoreErrors*/).then(response => { + try { + const response = await vscode.commands.executeCommand('azure.accounts.getSubscriptions', selectedAccount, true /*ignoreErrors*/); if (!response) { return; } @@ -732,8 +856,10 @@ function handleSelectedAccountChanged( return displayName; }).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())); const selectedSubscription = subscriptionDropdown.values.length > 0 ? subscriptionValueToSubscriptionMap.get(subscriptionDropdown.values[0]) : undefined; - handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); - }, err => { vscode.window.showErrorMessage(localize('azure.accounts.unexpectedSubscriptionsError', "Unexpected error fetching subscriptions for account {0} ({1}): {2}", selectedAccount?.displayInfo.displayName, selectedAccount?.key.accountId, err.message)); }); + await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); + } catch (error) { + vscode.window.showErrorMessage(localize('azure.accounts.unexpectedSubscriptionsError', "Unexpected error fetching subscriptions for account {0} ({1}): {2}", selectedAccount?.displayInfo.displayName, selectedAccount?.key.accountId, getErrorMessage(error))); + } } function createAzureResourceGroupsDropdown( @@ -746,35 +872,42 @@ function createAzureResourceGroupsDropdown( text: loc.resourceGroup, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, - fontWeight: context.fieldInfo.labelFontWeight + cssStyles: context.fieldInfo.labelCSSStyles }); const resourceGroupDropdown = createDropdown(context.view, { + defaultValue: (context.fieldInfo.required) ? undefined : '', width: context.fieldInfo.inputWidth, editable: false, required: context.fieldInfo.required, label: loc.resourceGroup }); + resourceGroupDropdown.fireOnTextChange = true; context.fieldInfo.subFields!.push({ label: label.value!, variableName: context.fieldInfo.resourceGroupVariableName }); - context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName!, resourceGroupDropdown); - addLabelInputPairToContainer(context.view, context.components, label, resourceGroupDropdown, context.fieldInfo.labelPosition); - subscriptionDropdown.onValueChanged(selectedItem => { + const rgValueChangedEmitter = new vscode.EventEmitter(); + resourceGroupDropdown.onValueChanged(() => rgValueChangedEmitter.fire()); + context.onNewInputComponentCreated(context.fieldInfo.resourceGroupVariableName!, { component: resourceGroupDropdown }); + addLabelInputPairToContainer(context.view, context.components, label, resourceGroupDropdown, context.fieldInfo); + subscriptionDropdown.onValueChanged(async selectedItem => { const selectedAccount = !accountDropdown || !accountDropdown.value ? undefined : accountValueToAccountMap.get(accountDropdown.value.toString()); const selectedSubscription = subscriptionValueToSubscriptionMap.get(selectedItem.selected); - handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); + await handleSelectedSubscriptionChanged(context, selectedAccount, selectedSubscription, resourceGroupDropdown); + rgValueChangedEmitter.fire(); }); return resourceGroupDropdown; } -function handleSelectedSubscriptionChanged(context: AzureAccountFieldContext, selectedAccount: azdata.Account | undefined, selectedSubscription: azureResource.AzureResourceSubscription | undefined, resourceGroupDropdown: azdata.DropDownComponent): void { +async function handleSelectedSubscriptionChanged(context: AzureAccountFieldContext, selectedAccount: azdata.Account | undefined, selectedSubscription: azureResource.AzureResourceSubscription | undefined, resourceGroupDropdown: azdata.DropDownComponent): Promise { resourceGroupDropdown.values = ['']; if (!selectedAccount || !selectedSubscription) { // Don't need to execute command if we don't have both an account and subscription selected return; } - vscode.commands.executeCommand('azure.accounts.getResourceGroups', selectedAccount, selectedSubscription, true /*ignoreErrors*/).then(response => { + try { + const response = await vscode.commands.executeCommand('azure.accounts.getResourceGroups', selectedAccount, selectedSubscription, true /*ignoreErrors*/); + //.then(response => { if (!response) { return; } @@ -788,7 +921,9 @@ function handleSelectedSubscriptionChanged(context: AzureAccountFieldContext, se resourceGroupDropdown.values = (response.resourceGroups.length !== 0) ? response.resourceGroups.map(resourceGroup => resourceGroup.name).sort((a: string, b: string) => a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase())) : ['']; - }, err => { vscode.window.showErrorMessage(localize('azure.accounts.unexpectedResourceGroupsError', "Unexpected error fetching resource groups for subscription {0} ({1}): {2}", selectedSubscription?.name, selectedSubscription?.id, err.message)); }); + } catch (error) { + vscode.window.showErrorMessage(localize('azure.accounts.unexpectedResourceGroupsError', "Unexpected error fetching resource groups for subscription {0} ({1}): {2}", selectedSubscription?.name, selectedSubscription?.id, getErrorMessage(error))); + } } /** @@ -809,7 +944,7 @@ function processAzureLocationsField(context: AzureLocationsFieldContext): azdata text: context.fieldInfo.label || loc.location, required: context.fieldInfo.required, width: context.fieldInfo.labelWidth, - fontWeight: context.fieldInfo.labelFontWeight + cssStyles: context.fieldInfo.labelCSSStyles }); const locationDropdown = createDropdown(context.view, { width: context.fieldInfo.inputWidth, @@ -818,14 +953,18 @@ function processAzureLocationsField(context: AzureLocationsFieldContext): azdata label: loc.location, values: context.fieldInfo.locations }); + locationDropdown.fireOnTextChange = true; context.fieldInfo.subFields = context.fieldInfo.subFields || []; if (context.fieldInfo.locationVariableName) { context.fieldInfo.subFields!.push({ label: label.value!, variableName: context.fieldInfo.locationVariableName }); - context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, locationDropdown, (inputValue: string) => { - return knownAzureLocationNameMappings.get(inputValue) || inputValue; + context.onNewInputComponentCreated(context.fieldInfo.locationVariableName, { + component: locationDropdown, + inputValueTransformer: (inputValue: string) => { + return knownAzureLocationNameMappings.get(inputValue) || inputValue; + } }); } if (context.fieldInfo.displayLocationVariableName) { @@ -833,12 +972,15 @@ function processAzureLocationsField(context: AzureLocationsFieldContext): azdata label: label.value!, variableName: context.fieldInfo.displayLocationVariableName }); - context.onNewInputComponentCreated(context.fieldInfo.displayLocationVariableName, locationDropdown); + context.onNewInputComponentCreated(context.fieldInfo.displayLocationVariableName, { component: locationDropdown }); } - context.onNewInputComponentCreated(context.fieldInfo.variableName!, locationDropdown, (inputValue: string) => { - return knownAzureLocationNameMappings.get(inputValue) || inputValue; + context.onNewInputComponentCreated(context.fieldInfo.variableName!, { + component: locationDropdown, + inputValueTransformer: (inputValue: string) => { + return knownAzureLocationNameMappings.get(inputValue) || inputValue; + } }); - addLabelInputPairToContainer(context.view, context.components, label, locationDropdown, context.fieldInfo.labelPosition); + addLabelInputPairToContainer(context.view, context.components, label, locationDropdown, context.fieldInfo); return locationDropdown; } @@ -871,31 +1013,38 @@ export function getPasswordMismatchMessage(fieldName: string): string { export function setModelValues(inputComponents: InputComponents, model: Model): void { Object.keys(inputComponents).forEach(key => { - let value; - const input = inputComponents[key].component; - if ('name' in input && 'checked' in input) { //RadioButtonComponent - value = input.name; - } else if ('checked' in input) { // CheckBoxComponent - value = input.checked ? 'true' : 'false'; - } else if ('value' in input) { // InputBoxComponent or DropDownComponent - const inputValue = input.value; - if (typeof inputValue === 'string' || typeof inputValue === 'undefined') { - value = inputValue; - } else { - value = inputValue.name; - } - } else { - throw new Error(`Unknown input type with ID ${input.id}`); - } - - const inputValueTransformer = inputComponents[key].inputValueTransformer; - if (inputValueTransformer) { - value = inputValueTransformer(value || ''); - } + const value = getInputComponentValue(inputComponents, key); model.setPropertyValue(key, value); }); } +function getInputComponentValue(inputComponents: InputComponents, key: string): string | undefined { + const input = inputComponents[key].component; + if (input === undefined) { + return undefined; + } + let value; + if (input instanceof RadioGroupLoadingComponentBuilder) { + value = input.value; + } else if ('checked' in input) { // CheckBoxComponent + value = input.checked ? 'true' : 'false'; + } else if ('value' in input) { // InputBoxComponent or DropDownComponent + const inputValue = input.value; + if (typeof inputValue === 'string' || typeof inputValue === 'undefined') { + value = inputValue; + } else { + value = inputValue.name; + } + } else { + throw new Error(`Unknown input type with ID ${input.id}`); + } + const inputValueTransformer = inputComponents[key].inputValueTransformer; + if (inputValueTransformer) { + value = inputValueTransformer(value || ''); + } + return value; +} + export function isInputBoxEmpty(input: azdata.InputBoxComponent): boolean { return input.value === undefined || input.value === ''; } diff --git a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizard.ts b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizard.ts index 2bfa0a2ef1..f4c5fd6755 100644 --- a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizard.ts +++ b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizard.ts @@ -4,18 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import { INotebookService } from '../../services/notebookService'; +import { INotebookService, Notebook } from '../../services/notebookService'; +import { IToolsService } from '../../services/toolsService'; import { Model } from '../model'; +import { InputComponents, setModelValues } from '../modelViewUtils'; import { WizardBase } from '../wizardBase'; -import { WizardPageBase } from '../wizardPageBase'; import { DeploymentType, NotebookWizardInfo } from './../../interfaces'; import { IPlatformService } from './../../services/platformService'; +import { NotebookWizardAutoSummaryPage } from './notebookWizardAutoSummaryPage'; import { NotebookWizardPage } from './notebookWizardPage'; -import { NotebookWizardSummaryPage } from './notebookWizardSummaryPage'; const localize = nls.loadMessageBundle(); -export class NotebookWizard extends WizardBase { +export class NotebookWizard extends WizardBase { + private _inputComponents: InputComponents = {}; public get notebookService(): INotebookService { return this._notebookService; @@ -29,8 +31,15 @@ export class NotebookWizard extends WizardBase { return this._wizardInfo; } - constructor(private _wizardInfo: NotebookWizardInfo, private _notebookService: INotebookService, private _platformService: IPlatformService) { + public get inputComponents(): InputComponents { + return this._inputComponents; + } + + constructor(private _wizardInfo: NotebookWizardInfo, private _notebookService: INotebookService, private _platformService: IPlatformService, private _toolsService: IToolsService) { super(_wizardInfo.title, new Model()); + if (this._wizardInfo.codeCellInsertionPosition === undefined) { + this._wizardInfo.codeCellInsertionPosition = 0; + } this.wizardObject.doneButton.label = _wizardInfo.actionText || this.wizardObject.doneButton.label; } @@ -41,31 +50,63 @@ export class NotebookWizard extends WizardBase { protected initialize(): void { this.setPages(this.getPages()); this.wizardObject.generateScriptButton.hidden = true; - this.wizardInfo.actionText = this.wizardInfo.actionText || localize('deployCluster.ScriptToNotebook', "Script to Notebook"); + this.wizardInfo.actionText = this.wizardInfo.actionText || localize('notebookWizard.ScriptToNotebook', "Script to Notebook"); this.wizardObject.doneButton.label = this.wizardInfo.actionText; } protected onCancel(): void { } - protected onOk(): void { - this.model.setEnvironmentVariables(); - if (this.wizardInfo.runNotebook) { - this.notebookService.backgroundExecuteNotebook(this.wizardInfo.taskName, this.wizardInfo.notebook, 'deploy', this.platformService); - } else { - this.notebookService.launchNotebook(this.wizardInfo.notebook).then(() => { }, (error) => { - vscode.window.showErrorMessage(error); - }); + protected async onOk(): Promise { + setModelValues(this.inputComponents, this.model); + const env: NodeJS.ProcessEnv = {}; + this.model.setEnvironmentVariables(env, (varName) => { + const isPassword = !!this.inputComponents[varName]?.isPassword; + return isPassword; + }); + const notebook: Notebook = await this.notebookService.getNotebook(this.wizardInfo.notebook); + // generate python code statements for all variables captured by the wizard + const statements = this.model.getCodeCellContentForNotebook( + this._toolsService.toolsForCurrentProvider, + (varName) => { + const isPassword = !!this.inputComponents[varName]?.isPassword; + return !isPassword; + } + ); + // insert generated code statements into the notebook. + notebook.cells.splice( + this.wizardInfo.codeCellInsertionPosition ?? 0, + 0, + { + cell_type: 'code', + source: statements, + metadata: {}, + outputs: [], + execution_count: 0 + } + ); + try { + if (this.wizardInfo.runNotebook) { + this.notebookService.backgroundExecuteNotebook(this.wizardInfo.taskName, notebook, 'deploy', this.platformService, env); + } else { + Object.assign(process.env, env); + const notebookPath = this.notebookService.getNotebookPath(this.wizardInfo.notebook); + await this.notebookService.launchNotebookWithContent(notebookPath, JSON.stringify(notebook, undefined, 4)); + } + } catch (error) { + vscode.window.showErrorMessage(error); } } - private getPages(): WizardPageBase[] { - const pages: WizardPageBase[] = []; + private getPages(): NotebookWizardPage[] { + const pages: NotebookWizardPage[] = []; for (let pageIndex: number = 0; pageIndex < this.wizardInfo.pages.length; pageIndex++) { - pages.push(new NotebookWizardPage(this, pageIndex)); - } - if (this.wizardInfo.generateSummaryPage) { - pages.push(new NotebookWizardSummaryPage(this)); + if (this.wizardInfo.pages[pageIndex].isSummaryPage && this.wizardInfo.isSummaryPageAutoGenerated) { + // If we are auto-generating the summary page + pages.push(new NotebookWizardAutoSummaryPage(this, pageIndex)); + } else { + pages.push(new NotebookWizardPage(this, pageIndex)); + } } return pages; } diff --git a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardSummaryPage.ts b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardAutoSummaryPage.ts similarity index 60% rename from extensions/resource-deployment/src/ui/notebookWizard/notebookWizardSummaryPage.ts rename to extensions/resource-deployment/src/ui/notebookWizard/notebookWizardAutoSummaryPage.ts index b32f6b0ae1..9f9866bbad 100644 --- a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardSummaryPage.ts +++ b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardAutoSummaryPage.ts @@ -6,19 +6,23 @@ import * as azdata from 'azdata'; import * as nls from 'vscode-nls'; import { SubFieldInfo, FieldType, FontWeight, LabelPosition, SectionInfo } from '../../interfaces'; -import { createSection, DefaultInputComponentWidth, DefaultLabelComponentWidth } from '../modelViewUtils'; -import { WizardPageBase } from '../wizardPageBase'; +import { createSection, DefaultInputWidth, DefaultLabelWidth, DefaultFieldAlignItems, DefaultFieldWidth, DefaultFieldHeight } from '../modelViewUtils'; import { NotebookWizard } from './notebookWizard'; +import { NotebookWizardPage } from './notebookWizardPage'; const localize = nls.loadMessageBundle(); -export class NotebookWizardSummaryPage extends WizardPageBase { +export class NotebookWizardAutoSummaryPage extends NotebookWizardPage { private formItems: azdata.FormComponent[] = []; private form!: azdata.FormBuilder; private view!: azdata.ModelView; - constructor(wizard: NotebookWizard) { - super(localize('notebookWizard.summaryPageTitle', "Review your configuration"), '', wizard); + constructor(wizard: NotebookWizard, _pageIndex: number) { + super(wizard, + _pageIndex, + wizard.wizardInfo.pages[_pageIndex].title || localize('notebookWizard.autoSummaryPageTitle', "Review your configuration"), + wizard.wizardInfo.pages[_pageIndex].description || '' + ); } public initialize(): void { @@ -29,25 +33,31 @@ export class NotebookWizardSummaryPage extends WizardPageBase { }); } - public onLeave() { + public onLeave(): void { this.wizard.wizardObject.message = { text: '' }; } - public onEnter() { + public onEnter(): void { this.formItems.forEach(item => { this.form!.removeFormItem(item); }); this.formItems = []; - const inputWidth = this.wizard.wizardInfo.inputWidth || (this.wizard.wizardInfo.summaryPage && this.wizard.wizardInfo.summaryPage.inputWidth) || DefaultInputComponentWidth; - const labelWidth = this.wizard.wizardInfo.labelWidth || (this.wizard.wizardInfo.summaryPage && this.wizard.wizardInfo.summaryPage.labelWidth) || DefaultLabelComponentWidth; - const labelPosition = this.wizard.wizardInfo.labelPosition || (this.wizard.wizardInfo.summaryPage && this.wizard.wizardInfo.summaryPage.labelPosition) || LabelPosition.Left; + const fieldWidth = this.pageInfo.fieldWidth || this.wizard.wizardInfo.fieldWidth || DefaultFieldWidth; + const fieldHeight = this.pageInfo.fieldHeight || this.wizard.wizardInfo.fieldHeight || DefaultFieldHeight; + const fieldAlignItems = this.pageInfo.fieldAlignItems || this.wizard.wizardInfo.fieldAlignItems || DefaultFieldAlignItems; + const labelWidth = this.pageInfo.labelWidth || this.wizard.wizardInfo.labelWidth || DefaultLabelWidth; + const labelPosition = this.pageInfo.labelPosition || this.wizard.wizardInfo.labelPosition || LabelPosition.Left; + const inputWidth = this.pageInfo.inputWidth || this.wizard.wizardInfo.inputWidth || DefaultInputWidth; - this.wizard.wizardInfo.pages.forEach(pageInfo => { + this.wizard.wizardInfo.pages.filter((undefined, index) => index < this._pageIndex).forEach(pageInfo => { const summarySectionInfo: SectionInfo = { labelPosition: labelPosition, labelWidth: labelWidth, inputWidth: inputWidth, + fieldWidth: fieldWidth, + fieldHeight: fieldHeight, + fieldAlignItems: fieldAlignItems, title: '', rows: [] }; @@ -68,6 +78,7 @@ export class NotebookWizardSummaryPage extends WizardPageBase { title: pageInfo.title, component: createSection({ container: this.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, sectionInfo: summarySectionInfo, view: this.view, onNewDisposableCreated: () => { }, @@ -84,11 +95,11 @@ export class NotebookWizardSummaryPage extends WizardPageBase { private addSummaryForVariable(summarySectionInfo: SectionInfo, fieldInfo: SubFieldInfo) { summarySectionInfo!.rows!.push({ - fields: [{ + items: [{ type: FieldType.ReadonlyText, label: fieldInfo.label, defaultValue: this.wizard.model.getStringValue(fieldInfo.variableName!), - labelFontWeight: FontWeight.Bold + labelCSSStyles: { fontWeight: FontWeight.Bold } }] }); } diff --git a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardPage.ts b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardPage.ts index b2ae551714..5d25cd94f4 100644 --- a/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardPage.ts +++ b/extensions/resource-deployment/src/ui/notebookWizard/notebookWizardPage.ts @@ -7,58 +7,73 @@ import { EOL } from 'os'; import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import { NotebookWizardPageInfo } from '../../interfaces'; -import { initializeWizardPage, InputComponents, InputComponent, setModelValues, Validator } from '../modelViewUtils'; +import { initializeWizardPage, InputComponentInfo, setModelValues, Validator } from '../modelViewUtils'; import { WizardPageBase } from '../wizardPageBase'; import { NotebookWizard } from './notebookWizard'; const localize = nls.loadMessageBundle(); export class NotebookWizardPage extends WizardPageBase { - private inputComponents: InputComponents = {}; protected get pageInfo(): NotebookWizardPageInfo { return this.wizard.wizardInfo.pages[this._pageIndex]; } - constructor(wizard: NotebookWizard, private _pageIndex: number) { - super(wizard.wizardInfo.pages[_pageIndex].title, wizard.wizardInfo.pages[_pageIndex].description || '', wizard); + constructor( + wizard: NotebookWizard, + protected _pageIndex: number, + title?: string, + description?: string + ) { + super( + wizard.wizardInfo.pages[_pageIndex].title || title || '', + wizard.wizardInfo.pages[_pageIndex].description || description || '', + wizard + ); } public initialize(): void { - const self = this; initializeWizardPage({ container: this.wizard.wizardObject, + inputComponents: this.wizard.inputComponents, wizardInfo: this.wizard.wizardInfo, pageInfo: this.pageInfo, page: this.pageObject, onNewDisposableCreated: (disposable: vscode.Disposable): void => { - self.wizard.registerDisposable(disposable); + this.wizard.registerDisposable(disposable); }, - onNewInputComponentCreated: (name: string, component: InputComponent): void => { - self.inputComponents[name] = { component: component }; + onNewInputComponentCreated: ( + name: string, + inputComponentInfo: InputComponentInfo + ): void => { + if (name) { + this.wizard.inputComponents[name] = inputComponentInfo; + } }, onNewValidatorCreated: (validator: Validator): void => { - self.validators.push(validator); - } + this.validators.push(validator); + }, }); } - - public onLeave() { - setModelValues(this.inputComponents, this.wizard.model); + public onLeave(): void { // The following callback registration clears previous navigation validators. this.wizard.wizardObject.registerNavigationValidator((pcInfo) => { return true; }); } - public onEnter() { + public onEnter(): void { + if (this.pageInfo.isSummaryPage) { + setModelValues(this.wizard.inputComponents, this.wizard.model); + } + this.wizard.wizardObject.registerNavigationValidator((pcInfo) => { this.wizard.wizardObject.message = { text: '' }; if (pcInfo.newPage > pcInfo.lastPage) { const messages: string[] = []; - this.validators.forEach(validator => { + this.validators.forEach((validator) => { const result = validator(); if (!result.valid) { messages.push(result.message); @@ -67,9 +82,15 @@ export class NotebookWizardPage extends WizardPageBase { if (messages.length > 0) { this.wizard.wizardObject.message = { - text: messages.length === 1 ? messages[0] : localize('wizardPage.ValidationError', "There are some errors on this page, click 'Show Details' to view the errors."), + text: + messages.length === 1 + ? messages[0] + : localize( + "wizardPage.ValidationError", + "There are some errors on this page, click 'Show Details' to view the errors." + ), description: messages.length === 1 ? undefined : messages.join(EOL), - level: azdata.window.MessageLevel.Error + level: azdata.window.MessageLevel.Error, }; } return messages.length === 0; diff --git a/extensions/resource-deployment/src/ui/radioGroupLoadingComponentBuilder.ts b/extensions/resource-deployment/src/ui/radioGroupLoadingComponentBuilder.ts new file mode 100644 index 0000000000..2d1a3df750 --- /dev/null +++ b/extensions/resource-deployment/src/ui/radioGroupLoadingComponentBuilder.ts @@ -0,0 +1,82 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as azdata from 'azdata'; +import * as vscode from 'vscode'; +import { OptionsInfo } from '../interfaces'; +import { getErrorMessage } from '../utils'; + +export class RadioGroupLoadingComponentBuilder implements azdata.ComponentBuilder { + private _optionsDivContainer!: azdata.DivContainer; + private _optionsLoadingBuilder: azdata.LoadingComponentBuilder; + private _onValueChangedEmitter: vscode.EventEmitter = new vscode.EventEmitter(); + private _currentRadioOption!: azdata.RadioButtonComponent; + constructor(private _view: azdata.ModelView, private _onNewDisposableCreated: (disposable: vscode.Disposable) => void) { + this._optionsDivContainer = this._view!.modelBuilder.divContainer().withProperties({ clickable: false }).component(); + this._optionsLoadingBuilder = this._view!.modelBuilder.loadingComponent().withItem(this._optionsDivContainer); + } + + component(): azdata.LoadingComponent { + return this._optionsLoadingBuilder.component(); + } + + withProperties(properties: U): azdata.ComponentBuilder { + return this._optionsLoadingBuilder.withProperties(properties); + } + + withValidation(validation: (component: azdata.LoadingComponent) => boolean): azdata.ComponentBuilder { + return this._optionsLoadingBuilder.withValidation(validation); + } + + async loadOptions(optionsInfo: OptionsInfo | (() => Promise)): Promise { + if (typeof optionsInfo !== 'object') { + optionsInfo = await optionsInfo(); + } + this.component().loading = true; + this._optionsDivContainer.clearItems(); + let options: (string[] | azdata.CategoryValue[]) = optionsInfo.values!; + let defaultValue: string = optionsInfo.defaultValue!; + try { + options.forEach((op: string | azdata.CategoryValue) => { + const option: azdata.CategoryValue = (typeof op === 'string') + ? { name: op, displayName: op } + : op as azdata.CategoryValue; + const radioOption = this._view!.modelBuilder.radioButton().withProperties({ + label: option.displayName, + checked: option.displayName === defaultValue, + name: option.name, + }).component(); + if (radioOption.checked) { + this._currentRadioOption = radioOption; + this._onValueChangedEmitter.fire(); + } + this._onNewDisposableCreated(radioOption.onDidClick(() => { + this._optionsDivContainer.items + .filter(otherOption => otherOption !== radioOption) + .forEach(otherOption => (otherOption as azdata.RadioButtonComponent).checked = false); + this._currentRadioOption = radioOption; + this._onValueChangedEmitter.fire(); + })); + this._optionsDivContainer.addItem(radioOption); + }); + } + catch (e) { + const errorLoadingRadioOptionsLabel = this._view!.modelBuilder.text().withProperties({ value: getErrorMessage(e), CSSStyles: { 'color': 'Red' } }).component(); + this._optionsDivContainer.addItem(errorLoadingRadioOptionsLabel); + } + this.component().loading = false; + } + + get value(): string | undefined { + return this._currentRadioOption?.label; + } + + get checked(): azdata.RadioButtonComponent { + return this._currentRadioOption; + } + + get onValueChanged(): vscode.Event { + return this._onValueChangedEmitter.event; + } +} diff --git a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts index 6efaabaa83..4bef800891 100644 --- a/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts +++ b/extensions/resource-deployment/src/ui/resourceTypePickerDialog.ts @@ -8,7 +8,7 @@ import * as nls from 'vscode-nls'; import { AgreementInfo, DeploymentProvider, ITool, ResourceType, ToolStatus } from '../interfaces'; import { IResourceTypeService } from '../services/resourceTypeService'; import { IToolsService } from '../services/toolsService'; -import { getErrorMessage, setEnvironmentVariablesForInstallPaths } from '../utils'; +import { getErrorMessage } from '../utils'; import { DialogBase } from './dialogBase'; import { createFlexContainer } from './modelViewUtils'; @@ -337,7 +337,7 @@ export class ResourceTypePickerDialog extends DialogBase { } protected onComplete(): void { - setEnvironmentVariablesForInstallPaths(this._tools); + this.toolsService.toolsForCurrentProvider = this._tools; this.resourceTypeService.startDeployment(this.getCurrentProvider()); } diff --git a/extensions/resource-deployment/src/ui/wizardBase.ts b/extensions/resource-deployment/src/ui/wizardBase.ts index a963e5d34b..7282f9787e 100644 --- a/extensions/resource-deployment/src/ui/wizardBase.ts +++ b/extensions/resource-deployment/src/ui/wizardBase.ts @@ -10,9 +10,9 @@ import { WizardPageBase } from './wizardPageBase'; import { Model } from './model'; const localize = nls.loadMessageBundle(); -export abstract class WizardBase { +export abstract class WizardBase, M extends Model> { private customButtons: azdata.window.Button[] = []; - private pages: WizardPageBase[] = []; + public pages: P[] = []; public wizardObject: azdata.window.Wizard; public toDispose: vscode.Disposable[] = []; @@ -34,8 +34,8 @@ export abstract class WizardBase { newPage.onEnter(); })); - this.toDispose.push(this.wizardObject.doneButton.onClick(() => { - this.onOk(); + this.toDispose.push(this.wizardObject.doneButton.onClick(async () => { + await this.onOk(); this.dispose(); })); this.toDispose.push(this.wizardObject.cancelButton.onClick(() => { @@ -52,14 +52,14 @@ export abstract class WizardBase { } protected abstract initialize(): void; - protected abstract onOk(): void; + protected abstract async onOk(): Promise; protected abstract onCancel(): void; public addButton(button: azdata.window.Button) { this.customButtons.push(button); } - protected setPages(pages: WizardPageBase[]) { + protected setPages(pages: P[]) { this.wizardObject!.pages = pages.map(p => p.pageObject); this.pages = pages; this.pages.forEach((page) => { diff --git a/extensions/resource-deployment/src/utils.ts b/extensions/resource-deployment/src/utils.ts index 216e23165e..61e1e31e24 100644 --- a/extensions/resource-deployment/src/utils.ts +++ b/extensions/resource-deployment/src/utils.ts @@ -2,9 +2,9 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITool, NoteBookEnvironmentVariablePrefix } from './interfaces'; import * as path from 'path'; import { ToolsInstallPath } from './constants'; +import { ITool, NoteBookEnvironmentVariablePrefix } from './interfaces'; export function getErrorMessage(error: any): string { return (error instanceof Error) @@ -21,7 +21,7 @@ export function getRuntimeBinaryPathEnvironmentVariableName(toolName: string): s return `${NoteBookEnvironmentVariablePrefix}${toolName.toUpperCase().replace(/ |-/g, '_')}`; } -export function setEnvironmentVariablesForInstallPaths(tools: ITool[]): void { +export function setEnvironmentVariablesForInstallPaths(tools: ITool[], env: NodeJS.ProcessEnv = process.env): void { // Use Set class to make sure the collection only contains unique values. let installationPaths: Set = new Set(); tools.forEach(t => { @@ -30,12 +30,18 @@ export function setEnvironmentVariablesForInstallPaths(tools: ITool[]): void { // construct an env variable name with NoteBookEnvironmentVariablePrefix prefix // and tool.name as suffix, making sure of using all uppercase characters and only _ as separator const envVarName = getRuntimeBinaryPathEnvironmentVariableName(t.name); - process.env[envVarName] = t.installationPathOrAdditionalInformation; + env[envVarName] = t.installationPathOrAdditionalInformation; installationPaths.add(path.dirname(t.installationPathOrAdditionalInformation)); } }); if (installationPaths.size > 0) { const envVarToolsInstallationPath: string = [...installationPaths.values()].join(path.delimiter); - process.env[ToolsInstallPath] = envVarToolsInstallationPath; + env[ToolsInstallPath] = envVarToolsInstallationPath; + } +} + +export function assert(condition: boolean, message?: string): asserts condition { + if (!condition) { + throw new Error(message); } } diff --git a/extensions/resource-deployment/yarn.lock b/extensions/resource-deployment/yarn.lock index a29362edc6..71ba91d64c 100644 --- a/extensions/resource-deployment/yarn.lock +++ b/extensions/resource-deployment/yarn.lock @@ -766,9 +766,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/schema-compare/coverConfig.json b/extensions/schema-compare/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/schema-compare/coverConfig.json +++ b/extensions/schema-compare/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/schema-compare/package.json b/extensions/schema-compare/package.json index e80d996ce6..ca7cf00c8c 100644 --- a/extensions/schema-compare/package.json +++ b/extensions/schema-compare/package.json @@ -75,7 +75,7 @@ "mocha-multi-reporters": "^1.1.7", "should": "^13.2.1", "typemoq": "^2.1.0", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" }, "__metadata": { "id": "37", diff --git a/extensions/schema-compare/yarn.lock b/extensions/schema-compare/yarn.lock index 13669607e7..9ec4281c03 100644 --- a/extensions/schema-compare/yarn.lock +++ b/extensions/schema-compare/yarn.lock @@ -808,9 +808,10 @@ vscode-nls@^4.0.0: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/extensions/sql-database-projects/coverConfig.json b/extensions/sql-database-projects/coverConfig.json index 9d13013c7a..7c935463c5 100644 --- a/extensions/sql-database-projects/coverConfig.json +++ b/extensions/sql-database-projects/coverConfig.json @@ -6,10 +6,10 @@ "**/node_modules/**", "**/test/**" ], - "includePid": false, "reports": [ "cobertura", - "lcov" + "lcov", + "json" ], "verbose": false, "remapOptions": { diff --git a/extensions/sql-database-projects/package.json b/extensions/sql-database-projects/package.json index c71d8358e3..2eb79baad5 100644 --- a/extensions/sql-database-projects/package.json +++ b/extensions/sql-database-projects/package.json @@ -269,6 +269,6 @@ "tslint": "^5.8.0", "typemoq": "^2.1.0", "typescript": "^2.6.1", - "vscodetestcover": "github:corivera/vscodetestcover#1.0.6" + "vscodetestcover": "^1.0.9" } } diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts index c907b79989..8a734c39b6 100644 --- a/extensions/sql-database-projects/src/models/project.ts +++ b/extensions/sql-database-projects/src/models/project.ts @@ -141,7 +141,7 @@ export class Project { return fileEntry; } - private createProjectEntry(relativePath: string, entryType: EntryType): ProjectEntry { + public createProjectEntry(relativePath: string, entryType: EntryType): ProjectEntry { return new ProjectEntry(Uri.file(path.join(this.projectFolderPath, relativePath)), relativePath, entryType); } diff --git a/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts b/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts index cc6a08c791..9c45b4fa51 100644 --- a/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts +++ b/extensions/sql-database-projects/src/models/tree/fileFolderTreeItem.ts @@ -22,7 +22,7 @@ export class FolderNode extends BaseProjectTreeItem { } public get children(): BaseProjectTreeItem[] { - return Object.values(this.fileChildren).sort(); + return Object.values(this.fileChildren).sort(sortFileFolderNodes); } public get treeItem(): vscode.TreeItem { @@ -64,6 +64,23 @@ export class FileNode extends BaseProjectTreeItem { } } +/** + * Compares two folder/file tree nodes so that folders come before files, then alphabetically + * @param a a folder or file tree node + * @param b another folder or file tree node + */ +export function sortFileFolderNodes(a: (FolderNode | FileNode), b: (FolderNode | FileNode)): number { + if (a instanceof FolderNode && !(b instanceof FolderNode)) { + return -1; + } + else if (!(a instanceof FolderNode) && b instanceof FolderNode) { + return 1; + } + else { + return a.uri.fsPath.localeCompare(b.uri.fsPath); + } +} + /** * Converts a full filesystem URI to a project-relative URI that's compatible with the project tree */ @@ -75,8 +92,7 @@ function fsPathToProjectUri(fileSystemUri: vscode.Uri, projectNode: ProjectRootT localUri = fileSystemUri.fsPath.substring(projBaseDir.length); } else { - vscode.window.showErrorMessage('Project pointing to file outside of directory'); - throw new Error('Project pointing to file outside of directory'); + throw new Error(`Project (${projBaseDir}) pointing to file outside of directory (${fileSystemUri.fsPath})`); } return vscode.Uri.file(path.join(projectNode.uri.path, localUri)); diff --git a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts index 0a58f020fa..b7181b3576 100644 --- a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts +++ b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts @@ -32,14 +32,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem { const output: BaseProjectTreeItem[] = []; output.push(this.dataSourceNode); - // sort children so that folders come first, then alphabetical - const sortedChildren = Object.values(this.fileChildren).sort((a: (fileTree.FolderNode | fileTree.FileNode), b: (fileTree.FolderNode | fileTree.FileNode)) => { - if (a instanceof fileTree.FolderNode && !(b instanceof fileTree.FolderNode)) { return -1; } - else if (!(a instanceof fileTree.FolderNode) && b instanceof fileTree.FolderNode) { return 1; } - else { return a.uri.fsPath.localeCompare(b.uri.fsPath); } - }); - - return output.concat(sortedChildren); + return output.concat(Object.values(this.fileChildren).sort(fileTree.sortFileFolderNodes)); } public get treeItem(): vscode.TreeItem { @@ -53,6 +46,10 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem { for (const entry of this.project.files) { const parentNode = this.getEntryParentNode(entry); + if (Object.keys(parentNode.fileChildren).includes(path.basename(entry.fsUri.path))) { + continue; // ignore duplicate entries + } + let newNode: fileTree.FolderNode | fileTree.FileNode; switch (entry.type) { diff --git a/extensions/sql-database-projects/src/test/projectTree.test.ts b/extensions/sql-database-projects/src/test/projectTree.test.ts new file mode 100644 index 0000000000..7101d9a429 --- /dev/null +++ b/extensions/sql-database-projects/src/test/projectTree.test.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as should from 'should'; +import * as vscode from 'vscode'; +import * as os from 'os'; +import * as path from 'path'; + +import { Project, EntryType } from '../models/project'; +import { FolderNode, FileNode, sortFileFolderNodes } from '../models/tree/fileFolderTreeItem'; +import { ProjectRootTreeItem } from '../models/tree/projectTreeItem'; + +describe('Project Tree tests', function (): void { + it('Should correctly order tree nodes by type, then by name', async function (): Promise { + const root = os.platform() === 'win32' ? 'Z:\\' : '/'; + + const parent = new ProjectRootTreeItem(new Project(vscode.Uri.file(`${root}Fake.sqlproj`).fsPath)); + + let inputNodes: (FileNode | FolderNode)[] = [ + new FileNode(vscode.Uri.file(`${root}C`), parent), + new FileNode(vscode.Uri.file(`${root}D`), parent), + new FolderNode(vscode.Uri.file(`${root}Z`), parent), + new FolderNode(vscode.Uri.file(`${root}X`), parent), + new FileNode(vscode.Uri.file(`${root}B`), parent), + new FileNode(vscode.Uri.file(`${root}A`), parent), + new FolderNode(vscode.Uri.file(`${root}W`), parent), + new FolderNode(vscode.Uri.file(`${root}Y`), parent) + ]; + + inputNodes = inputNodes.sort(sortFileFolderNodes); + + const expectedNodes: (FileNode | FolderNode)[] = [ + new FolderNode(vscode.Uri.file(`${root}W`), parent), + new FolderNode(vscode.Uri.file(`${root}X`), parent), + new FolderNode(vscode.Uri.file(`${root}Y`), parent), + new FolderNode(vscode.Uri.file(`${root}Z`), parent), + new FileNode(vscode.Uri.file(`${root}A`), parent), + new FileNode(vscode.Uri.file(`${root}B`), parent), + new FileNode(vscode.Uri.file(`${root}C`), parent), + new FileNode(vscode.Uri.file(`${root}D`), parent) + ]; + + should(inputNodes.map(n => n.uri.path)).deepEqual(expectedNodes.map(n => n.uri.path)); + }); + + it('Should build tree from Project file correctly', async function (): Promise { + const root = os.platform() === 'win32' ? 'Z:\\' : '/'; + const proj = new Project(vscode.Uri.file(`${root}TestProj.sqlproj`).fsPath); + + // nested entries before explicit top-level folder entry + // also, ordering of files/folders at all levels + proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedTest.sql'), EntryType.File)); + proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedFolder'), EntryType.Folder)); + proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedTest.sql'), EntryType.File)); + proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedFolder'), EntryType.Folder)); + proj.files.push(proj.createProjectEntry('someFolder', EntryType.Folder)); + + // duplicate files + proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File)); + proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File)); + + // duplicate folders + proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder)); + proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder)); + + const tree = new ProjectRootTreeItem(proj); + should(tree.children.map(x => x.uri.path)).deepEqual([ + '/TestProj.sqlproj/Data Sources', + '/TestProj.sqlproj/duplicateFolder', + '/TestProj.sqlproj/someFolder', + '/TestProj.sqlproj/duplicate.sql']); + + should(tree.children.find(x => x.uri.path === '/TestProj.sqlproj/someFolder')?.children.map(y => y.uri.path)).deepEqual([ + '/TestProj.sqlproj/someFolder/aNestedFolder', + '/TestProj.sqlproj/someFolder/bNestedFolder', + '/TestProj.sqlproj/someFolder/aNestedTest.sql', + '/TestProj.sqlproj/someFolder/bNestedTest.sql']); + }); +}); diff --git a/extensions/sql-database-projects/yarn.lock b/extensions/sql-database-projects/yarn.lock index 3d5776a56c..aeda3ef270 100644 --- a/extensions/sql-database-projects/yarn.lock +++ b/extensions/sql-database-projects/yarn.lock @@ -901,9 +901,10 @@ vscode-nls@^3.2.1: resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.5.tgz#25520c1955108036dec607c85e00a522f247f1a4" integrity sha512-ITtoh3V4AkWXMmp3TB97vsMaHRgHhsSFPsUdzlueSL+dRZbSNTZeOmdQv60kjCV306ghPxhDeoNUEm3+EZMuyw== -"vscodetestcover@github:corivera/vscodetestcover#1.0.6": - version "1.0.5" - resolved "https://codeload.github.com/corivera/vscodetestcover/tar.gz/14e0f2c46346b31bc1af2c590febeaf69a9112eb" +vscodetestcover@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/vscodetestcover/-/vscodetestcover-1.0.9.tgz#0191f403dd59ba1153fc57979e281e992ce63731" + integrity sha512-8z2961KF9Tuz5XdHAC6RMV3CrzAoUcfIK7wLYjLIXD4dbHIT7ceZMhoxToW1olyi3pFnThlS4lRXtx8Q5iyMMQ== dependencies: decache "^4.4.0" glob "^7.1.2" diff --git a/samples/sample-resource-deployment/package.json b/samples/sample-resource-deployment/package.json index 91e5d2c3b2..4a5097d742 100644 --- a/samples/sample-resource-deployment/package.json +++ b/samples/sample-resource-deployment/package.json @@ -10,7 +10,7 @@ "aiKey": "AIF-37eefaf0-8022-4671-a3fb-64752724682e", "engines": { "vscode": "*", - "azdata": ">1.10.0" + "azdata": ">=1.19.0" }, "repository": { "type": "git", @@ -23,6 +23,257 @@ ], "contributes": { "resourceDeploymentTypes": [ + { + "name": "test-wizard", + "displayName": "%resource.type.wizard.display.name%", + "description": "%resource.type.wizard.description%", + "platforms": "*", + "icon": { + "light": "./images/book.svg", + "dark": "./images/book_inverse.svg" + }, + "providers": [ + { + "notebookWizard": { + "notebook": "%deployment-notebook-1%", + "type": "new-arc-control-plane", + "runNotebook": false, + "codeCellInsertionPosition": 1, + "actionText": "%deploy.wizard.action%", + "title": "%wizard.new.wizard.title%", + "name": "wizard.new.wizard", + "labelPosition": "left", + "generateSummaryPage": false, + "pages": [ + { + "title": "%wizard.select.cluster.title%", + "sections": [ + { + "fields": [ + { + "type": "kube_cluster_context_picker", + "label": "%wizard.kube.cluster.context%", + "required": true, + "inputWidth": "350px", + "variableName": "AZDATA_NB_VAR_CLUSTER_CONTEXT", + "configFileVariableName": "AZDATA_NB_VAR_CONFIG_FILE" + } + ] + } + ] + }, + { + "title": "%wizard.cluster.config.profile.title%", + "sections": [ + { + "fields": [ + { + "type": "readonly_text", + "label": "%wizard.project.details.description%", + "labelWidth": "600px" + }, + { + "type": "options", + "label": "%wizard.cluster.config.profile%", + "required": true, + "variableName": "AZDATA_NB_VAR_PROFILE", + "editable": false, + "options": { + "values":[ + "aks-dev-test", + "aks-dev-test-ha", + "aks-dev-test", + "aks-private-preview", + "kubeadm-dev-test", + "kubeadm-private-preview" + ], + "defaultValue": "aks-dev-test", + "optionsType": "radio" + } + }, + { + "label": "%wizard.dropdown.options.field%", + "variableName": "AZDATA_NB_VAR_DROPDOWN_OPTIONS", + "type": "options", + "options": { + "values": ["1","2","3"], + "defaultValue": "2", + "optionsType": "dropdown" + } + } + ] + } + ] + }, + { + "title": "%wizard.data.controller.create.summary.title%", + "isSummaryPage": true, + "fieldHeight": "16px", + "sections": [ + { + "title": "", + "collapsible": false, + "fieldWidth": "200px", + "fieldHeight": "12px", + "spaceBetweenFields": 0, + "rows": [ + { + "items": [ + { + "items": [ + { + "label": "%wizard.summary.data.controller%", + "type": "readonly_text", + "enabled": true, + "labelWidth": "185px" + } + ] + }, + { + "items": [ + { + "label": "%wizard.summary.estimated.cost.per.month%", + "type": "readonly_text", + "enabled": true, + "labelWidth": "190px", + "labelCSSStyles": { + "fontWeight": "Bold" + } + + } + ] + } + ] + }, + { + "items": [ + { + "items": [ + { + "label": "%wizard.summary.by.contoso%", + "type": "readonly_text", + "labelWidth": "185px" + } + ] + }, + { + "items": [ + { + "label": "%wizard.summary.free%", + "type": "readonly_text", + "enabled": true, + "defaultValue": "", + "labelWidth": "100px" + } + ] + } + ] + }, + { + "items": [ + { + "items": [ + { + "label": "{0}", + "type": "readonly_text", + "enabled": true, + "labelCSSStyles": { "color": "#0078D4" }, + "labelWidth": "67px", + "links": [ + { + "text": "%wizard.summary.terms.of.use%", + "url": "https://aka.ms/eula-azdata-en" + } + ] + }, + { + "label": "|", + "type": "readonly_text", + "enabled": true, + "defaultValue": "", + "labelWidth": "4px", + "fieldWidth": "6px" + }, + { + "label": "{0}", + "type": "readonly_text", + "enabled": true, + "labelCSSStyles": { "color": "#0078D4" }, + "labelWidth": "102px", + "links": [ + { + "text": "%wizard.summary.terms.privacy.policy%", + "url": "https://go.contoso.com/fwlink/?LinkId=853010" + } + ] + } + ] + } + ] + } + ] + }, + { + "title": "%wizard.summary.terms%", + "fieldHeight": "88px", + "fields":[ + { + "label": "%wizard.summary.terms.description%", + "type": "readonly_text", + "enabled": true, + "labelWidth": "750px" + } + ] + }, + { + "title": "%wizard.summary.kubernetes%", + "fields":[ + { + "label": "%wizard.summary.kube.config.file.path%", + "type": "readonly_text", + "isEvaluated": true, + "defaultValue": "$(AZDATA_NB_VAR_CONFIG_FILE)" + }, + { + "label": "%wizard.summary.cluster.context%", + "type": "readonly_text", + "isEvaluated": true, + "defaultValue": "$(AZDATA_NB_VAR_CLUSTER_CONTEXT)" + }, + { + "label": "%wizard.summary.profile%", + "type": "readonly_text", + "isEvaluated": true, + "defaultValue": "$(AZDATA_NB_VAR_PROFILE)" + } + ] + } + ] + } + ] + }, + "requiredTools": [ + { + "name": "kubectl" + } + ], + "when": true + } + ], + "agreement": { + "template": "%wizard.data.controller.agreement%", + "links": [ + { + "text": "%contoso.agreement.privacy.statement%", + "url": "https://go.contoso.com/fwlink/?LinkId=853010" + }, + { + "text": "%wizard.agreement.contosoCmd.eula%", + "url": "https://aka.ms/eula-contosoCmd-en" + } + ] + } + }, { "name": "x-data-service", "displayName": "%resource-type-display-name%", @@ -81,6 +332,14 @@ "defaultValue": "", "required": true }, + { + "type": "kube_cluster_context_picker", + "label": "%kube.cluster.context%", + "required": true, + "inputWidth": "350px", + "variableName": "AZDATA_NB_VAR_CLUSTER_CONTEXT", + "configFileVariableName": "AZDATA_NB_VAR_CONFIG_FILE" + }, { "label": "%number-field%", "variableName": "AZDATA_NB_VAR_NUMBER", @@ -159,7 +418,7 @@ "links": [ { "text": "%agreement-1-name%", - "url": "https://www.microsoft.com" + "url": "https://www.contoso.com" }, { "text": "%agreement-2-name%", diff --git a/samples/sample-resource-deployment/package.nls.json b/samples/sample-resource-deployment/package.nls.json index fce5465b73..126d4ab84e 100644 --- a/samples/sample-resource-deployment/package.nls.json +++ b/samples/sample-resource-deployment/package.nls.json @@ -12,9 +12,41 @@ "deployment-notebook-2": "./notebooks/deploy-x-data-service-2.ipynb", "text-field": "text field", "password-field": "password field", + "kube.cluster.context": "Kube cluster context", "number-field": "numeric field", "confirm-password": "confirm password", "agreement": "I accept {0} and {1}.", "agreement-1-name": "Agreement 1", - "agreement-2-name": "Agreement 2" + "agreement-2-name": "Agreement 2", + + "resource.type.wizard.display.name": "Test controller", + "resource.type.wizard.description": "Creates a Test controller", + + "wizard.new.wizard.title": "Create Test controller", + "wizard.cluster.environment.title": "What is your target existing Kubernetes cluster environment?", + "wizard.select.cluster.title": "Select from installed existing Kubernetes clusters", + "wizard.kube.cluster.context": "Cluster context", + "wizard.cluster.config.profile.title": "Choose the config profile", + "wizard.cluster.config.profile": "Config profile", + "wizard.dropdown.options.field": "dropdown field", + "wizard.project.details.title": "Project details", + "wizard.project.details.description": "Project details for Contoso corporation", + "wizard.data.controller.create.summary.title": "Review your configuration", + "wizard.summary.data.controller": "Test controller", + "wizard.summary.estimated.cost.per.month": "Estimated cost per month", + "wizard.summary.by.contoso" : "by Contoso", + "wizard.summary.free" : "Free", + "wizard.summary.terms.of.use" : "Terms of use", + "wizard.summary.terms.privacy.policy" : "Privacy policy", + "wizard.summary.terms" : "Terms", + "wizard.summary.terms.description": "By clicking 'Script to notebook', I (a) agree to the legal terms and privacy statement(s) associated with the doing business with Contoso.", + "wizard.summary.kubernetes": "Kubernetes", + "wizard.summary.kube.config.file.path": "Kube config file path", + "wizard.summary.cluster.context": "Cluster context", + "wizard.summary.profile": "Config profile", + "wizard.data.controller.agreement": "I accept {0} and {1}.", + "contoso.agreement.privacy.statement":"contoso Privacy Statement", + "wizard.agreement.contosoCmd.eula":"contoso cmd license terms", + "deploy.wizard.action":"Script to notebook" + } diff --git a/scripts/sql-test-integration.bat b/scripts/sql-test-integration.bat index 0bc551b0a8..fff177b87c 100644 --- a/scripts/sql-test-integration.bat +++ b/scripts/sql-test-integration.bat @@ -47,7 +47,7 @@ if "%SKIP_PYTHON_INSTALL_TEST%" == "1" ( ) call %INTEGRATION_TEST_ELECTRON_PATH% --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 ^ ---extensionDevelopmentPath=%~dp0\..\extensions\integration-tests --extensionTestsPath=%~dp0\..\extensions\integration-tests\out\tests --disable-telemetry --disable-crash-reporter --disable-updates -nogpu +--extensionDevelopmentPath=%~dp0\..\extensions\integration-tests --extensionTestsPath=%~dp0\..\extensions\integration-tests\out\test --disable-telemetry --disable-crash-reporter --disable-updates -nogpu rmdir /s /q %VSCODEUSERDATADIR% rmdir /s /q %VSCODEEXTENSIONSDIR% diff --git a/scripts/test-extensions-unit.bat b/scripts/test-extensions-unit.bat index 283caffa42..f191d70ca7 100755 --- a/scripts/test-extensions-unit.bat +++ b/scripts/test-extensions-unit.bat @@ -91,10 +91,10 @@ REM echo *** starting mssql tests *** REM echo ****************************************** REM call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\mssql --extensionTestsPath=%~dp0\..\extensions\mssql\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu -echo ******************************************** -echo *** starting sql-database-projects tests *** -echo ******************************************** -call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\sql-database-projects --extensionTestsPath=%~dp0\..\extensions\sql-database-projects\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu +REM echo ******************************************** +REM echo *** starting sql-database-projects tests *** +REM echo ******************************************** +REM call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\sql-database-projects --extensionTestsPath=%~dp0\..\extensions\sql-database-projects\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/src/sql/media/icons/book.svg b/src/sql/media/icons/book.svg new file mode 100644 index 0000000000..bae52cfcc8 --- /dev/null +++ b/src/sql/media/icons/book.svg @@ -0,0 +1,7 @@ + + Artboard 10 + + + + + diff --git a/extensions/notebook/resources/dark/JupyterBook_2.svg b/src/sql/media/icons/book_image.svg similarity index 100% rename from extensions/notebook/resources/dark/JupyterBook_2.svg rename to src/sql/media/icons/book_image.svg diff --git a/src/sql/media/icons/book_inverse.svg b/src/sql/media/icons/book_inverse.svg new file mode 100644 index 0000000000..464b3d228b --- /dev/null +++ b/src/sql/media/icons/book_inverse.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/sql/media/icons/common-icons.css b/src/sql/media/icons/common-icons.css index 11023dda22..803edf5b19 100644 --- a/src/sql/media/icons/common-icons.css +++ b/src/sql/media/icons/common-icons.css @@ -545,6 +545,13 @@ Includes non-masked style declarations. */ background-image: url("database_colored.svg"); } +.book.codicon { + + -webkit-mask-image: url("book_image.svg"); + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: 50% 50%; +} + .small { width: 16px; height: 16px; diff --git a/src/sql/workbench/contrib/notebook/browser/media/notebook.contribution.css b/src/sql/workbench/contrib/notebook/browser/media/notebook.contribution.css new file mode 100644 index 0000000000..0808ab3a26 --- /dev/null +++ b/src/sql/workbench/contrib/notebook/browser/media/notebook.contribution.css @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/* Activity Bar */ +.monaco-workbench .activitybar .monaco-action-bar .action-label.book { + background-color: rgba(255, 255, 255, 0.4); +} + +/* Activity Bar */ +.monaco-workbench .activitybar .monaco-action-bar .checked .action-label.book { + background-color: rgb(255, 255, 255); +} diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts index 41300ed99f..af34a86d4d 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -46,6 +46,9 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } fr import { NotebookThemingContribution } from 'sql/workbench/contrib/notebook/browser/notebookThemingContribution'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode'; +import { NotebookExplorerViewletViewsContribution, OpenNotebookExplorerViewletAction } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet'; +import 'vs/css!./media/notebook.contribution'; + Registry.as(EditorInputFactoryExtensions.EditorInputFactories) .registerEditorInputFactory(FileNotebookInput.ID, FileNoteBookEditorInputFactory); @@ -348,3 +351,16 @@ registerComponentType({ selector: MimeRendererComponent.SELECTOR }); registerCellComponent(TextCellComponent); + +const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); +workbenchRegistry.registerWorkbenchContribution(NotebookExplorerViewletViewsContribution, LifecyclePhase.Starting); +const registry = Registry.as(WorkbenchActionsExtensions.WorkbenchActions); +registry.registerWorkbenchAction( + SyncActionDescriptor.create( + OpenNotebookExplorerViewletAction, + OpenNotebookExplorerViewletAction.ID, + OpenNotebookExplorerViewletAction.LABEL, + { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_B }), + 'View: Show Notebook Explorer', + localize('notebookExplorer.view', "View") +); diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.css b/src/sql/workbench/contrib/notebook/browser/notebook.css index 75563360c0..44ef343540 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebook.css +++ b/src/sql/workbench/contrib/notebook/browser/notebook.css @@ -52,6 +52,7 @@ .notebookEditor .in-preview .actions-container .action-item .notebook-button { display: flex; background-size: 16px; + height: 100%; } .notebookEditor diff --git a/src/sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet.ts b/src/sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet.ts new file mode 100644 index 0000000000..6073109d23 --- /dev/null +++ b/src/sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet.ts @@ -0,0 +1,149 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { IAction } from 'vs/base/common/actions'; +import { append, $, addClass, toggleClass, Dimension } from 'vs/base/browser/dom'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; +import { Extensions as ViewContainerExtensions, IViewDescriptor, IViewsRegistry, IViewContainersRegistry, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IMenuService, MenuId } from 'vs/platform/actions/common/actions'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ShowViewletAction, Viewlet } from 'vs/workbench/browser/viewlet'; +import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; +import { ViewPaneContainer, ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; + +export const VIEWLET_ID = 'workbench.view.notebooks'; + +// Viewlet Action +export class OpenNotebookExplorerViewletAction extends ShowViewletAction { + public static ID = VIEWLET_ID; + public static LABEL = localize('showNotebookExplorer', "Show Notebooks"); + + constructor( + id: string, + label: string, + @IViewletService viewletService: IViewletService, + @IEditorGroupsService editorGroupService: IEditorGroupsService, + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService + ) { + super(id, label, VIEWLET_ID, viewletService, editorGroupService, layoutService); + } +} + +export class NotebookExplorerViewletViewsContribution implements IWorkbenchContribution { + + constructor() { + this.registerViews(); + } + + private registerViews(): void { + let viewDescriptors = []; + Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews(viewDescriptors, NOTEBOOK_VIEW_CONTAINER); + } +} + +export class NotebookExplorerViewlet extends Viewlet { + constructor( + @ITelemetryService telemetryService: ITelemetryService, + @IStorageService protected storageService: IStorageService, + @IInstantiationService protected instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService, + @IContextMenuService protected contextMenuService: IContextMenuService, + @IExtensionService protected extensionService: IExtensionService, + @IWorkspaceContextService protected contextService: IWorkspaceContextService, + @IWorkbenchLayoutService protected layoutService: IWorkbenchLayoutService, + @IConfigurationService protected configurationService: IConfigurationService + ) { + super(VIEWLET_ID, instantiationService.createInstance(NotebookExplorerViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService); + } +} + +export class NotebookExplorerViewPaneContainer extends ViewPaneContainer { + private root: HTMLElement; + + private notebookSourcesBox: HTMLElement; + + constructor( + @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, + @ITelemetryService telemetryService: ITelemetryService, + @IInstantiationService instantiationService: IInstantiationService, + @IThemeService themeService: IThemeService, + @IStorageService storageService: IStorageService, + @IWorkspaceContextService contextService: IWorkspaceContextService, + @IContextMenuService contextMenuService: IContextMenuService, + @IExtensionService extensionService: IExtensionService, + @IConfigurationService configurationService: IConfigurationService, + @IMenuService private menuService: IMenuService, + @IContextKeyService private contextKeyService: IContextKeyService, + @IViewDescriptorService viewDescriptorService: IViewDescriptorService + ) { + super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); + } + + create(parent: HTMLElement): void { + addClass(parent, 'notebookExplorer-viewlet'); + this.root = parent; + + this.notebookSourcesBox = append(this.root, $('.notebookSources')); + + return super.create(this.notebookSourcesBox); + } + + public updateStyles(): void { + super.updateStyles(); + } + + focus(): void { + } + + layout(dimension: Dimension): void { + toggleClass(this.root, 'narrow', dimension.width <= 300); + super.layout(new Dimension(dimension.width, dimension.height)); + } + + getOptimalWidth(): number { + return 400; + } + + getSecondaryActions(): IAction[] { + let menu = this.menuService.createMenu(MenuId.NotebookTitle, this.contextKeyService); + let actions = []; + menu.getActions({}).forEach(group => { + if (group[0] === 'secondary') { + actions.push(...group[1]); + } + }); + menu.dispose(); + return actions; + } + + protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): ViewPane { + let viewletPanel = this.instantiationService.createInstance(viewDescriptor.ctorDescriptor.ctor, options) as ViewPane; + this._register(viewletPanel); + return viewletPanel; + } +} + +export const NOTEBOOK_VIEW_CONTAINER = Registry.as(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({ + id: VIEWLET_ID, + name: localize('notebookExplorer.name', "Notebooks"), + ctorDescriptor: new SyncDescriptor(NotebookExplorerViewPaneContainer), + icon: 'book', + order: 6, + storageId: `${VIEWLET_ID}.state` +}, ViewContainerLocation.Sidebar); diff --git a/src/sql/workbench/contrib/notebook/test/browser/notebookExplorerViewlet.test.ts b/src/sql/workbench/contrib/notebook/test/browser/notebookExplorerViewlet.test.ts new file mode 100644 index 0000000000..0c5f30cd85 --- /dev/null +++ b/src/sql/workbench/contrib/notebook/test/browser/notebookExplorerViewlet.test.ts @@ -0,0 +1,94 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as Platform from 'vs/platform/registry/common/platform'; +import { ViewletDescriptor, Extensions, ViewletRegistry, Viewlet } from 'vs/workbench/browser/viewlet'; +import * as Types from 'vs/base/common/types'; +import { workbenchInstantiationService } from 'sql/workbench/test/workbenchTestServices'; +import { Extensions as ViewContainerExtensions, IViewDescriptor, IViewsRegistry } from 'vs/workbench/common/views'; +import { NotebookExplorerViewPaneContainer, NOTEBOOK_VIEW_CONTAINER } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; + +suite('Notebook Explorer Views', () => { + + class NotebookExplorerTestViewlet extends Viewlet { + + constructor() { + const instantiationService = workbenchInstantiationService(); + super('notebookExplorer', instantiationService.createInstance(NotebookExplorerViewPaneContainer), undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined); + } + + public layout(dimension: any): void { + throw new Error('Method not implemented.'); + } + + } + + test('ViewDescriptor API', function () { + let d = ViewletDescriptor.create(NotebookExplorerTestViewlet, 'id', 'name', 'class', 1); + assert.strictEqual(d.id, 'id'); + assert.strictEqual(d.name, 'name'); + assert.strictEqual(d.cssClass, 'class'); + assert.strictEqual(d.order, 1); + }); + + test('Editor Aware ViewletDescriptor API', function () { + let d = ViewletDescriptor.create(NotebookExplorerTestViewlet, 'id', 'name', 'class', 5); + assert.strictEqual(d.id, 'id'); + assert.strictEqual(d.name, 'name'); + + d = ViewletDescriptor.create(NotebookExplorerTestViewlet, 'id', 'name', 'class', 5); + assert.strictEqual(d.id, 'id'); + assert.strictEqual(d.name, 'name'); + }); + + test('NotebookExplorer Views registration', function () { + assert(Types.isFunction(Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews)); + assert(Types.isFunction(Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getViews)); + assert(Types.isFunction(Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getView)); + + Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([], NOTEBOOK_VIEW_CONTAINER); + + let oldcount = Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getViews(NOTEBOOK_VIEW_CONTAINER).length; + let d: IViewDescriptor = { id: 'notebookView-test-1', name: 'Notebooks', ctorDescriptor: new SyncDescriptor(NotebookExplorerViewPaneContainer) }; + Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([d], NOTEBOOK_VIEW_CONTAINER); + let retrieved = Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getView('notebookView-test-1'); + assert(d === retrieved, 'Could not register view :' + d.id + 'Retrieved: ' + retrieved); + let newCount = Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getViews(NOTEBOOK_VIEW_CONTAINER).length; + assert.equal(oldcount + 1, newCount, 'View registration failed'); + + + }); + + test('NotebookExplorer Views should not register duplicate views', function () { + let d: IViewDescriptor = { id: 'notebookView-test-1', name: 'Notebooks', ctorDescriptor: new SyncDescriptor(NotebookExplorerViewPaneContainer) }; + assert.throws(() => Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews([d], NOTEBOOK_VIEW_CONTAINER)); + }); + + test('NotebookExplorer Views deregistration', function () { + assert(Types.isFunction(Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).deregisterViews)); + assert(Types.isFunction(Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).getViews)); + + let d: IViewDescriptor = { id: 'notebookView-test-1', name: 'Notebooks', ctorDescriptor: new SyncDescriptor(NotebookExplorerViewPaneContainer) }; + assert.doesNotThrow(() => Platform.Registry.as(ViewContainerExtensions.ViewsRegistry).deregisterViews([d], NOTEBOOK_VIEW_CONTAINER)); + + }); + + test('NotebookExplorer Viewlet extension point should not register duplicate viewlets', function () { + let v1 = ViewletDescriptor.create(NotebookExplorerTestViewlet, 'notebookExplorer-test-id', 'name'); + Platform.Registry.as(Extensions.Viewlets).registerViewlet(v1); + let oldCount = Platform.Registry.as(Extensions.Viewlets).getViewlets().length; + + let v1Duplicate = ViewletDescriptor.create(NotebookExplorerTestViewlet, 'notebookExplorer-test-id', 'name'); + // Shouldn't register the duplicate. + Platform.Registry.as(Extensions.Viewlets).registerViewlet(v1Duplicate); + + let newCount = Platform.Registry.as(Extensions.Viewlets).getViewlets().length; + assert.equal(oldCount, newCount, 'Duplicate registration of views.'); + + }); + +}); diff --git a/src/sql/workbench/contrib/profiler/browser/profiler.contribution.ts b/src/sql/workbench/contrib/profiler/browser/profiler.contribution.ts index 48bc870424..91bca4c1ef 100644 --- a/src/sql/workbench/contrib/profiler/browser/profiler.contribution.ts +++ b/src/sql/workbench/contrib/profiler/browser/profiler.contribution.ts @@ -57,7 +57,7 @@ const profilerViewTemplateSchema: IJSONSchema = { }, { name: 'LoginName', - eventsMapped: ['server_principal_name'] + eventsMapped: ['server_principal_name', 'username'] }, { name: 'ClientProcessID', @@ -159,7 +159,7 @@ const profilerViewTemplateSchema: IJSONSchema = { }, { name: 'LoginName', - eventsMapped: ['server_principal_name'] + eventsMapped: ['server_principal_name', 'username'] } ] }, @@ -184,7 +184,7 @@ const profilerViewTemplateSchema: IJSONSchema = { }, { name: 'LoginName', - eventsMapped: ['server_principal_name'] + eventsMapped: ['server_principal_name', 'username'] }, { name: 'ClientProcessID', diff --git a/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/ServerLevelServerTrigger_Disabled.svg b/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/ServerLevelServerTrigger_Disabled.svg new file mode 100644 index 0000000000..43bf361a2c --- /dev/null +++ b/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/ServerLevelServerTrigger_Disabled.svg @@ -0,0 +1 @@ +Trigger_disabled_16x \ No newline at end of file diff --git a/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/objecttypes.css b/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/objecttypes.css index 047b85635a..a4499e396b 100644 --- a/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/objecttypes.css +++ b/src/sql/workbench/services/objectExplorer/browser/media/objectTypes/objecttypes.css @@ -408,6 +408,12 @@ background: url("ServerLevelServerTrigger.svg") center center no-repeat; } +.vs .icon.serverlevelservertrigger_disabled, +.vs-dark .icon.serverlevelservertrigger_disabled, +.hc-black .icon.serverlevelservertrigger_disabled { + background: url("ServerLevelServerTrigger_Disabled.svg") center center no-repeat; +} + .vs .icon.service, .vs-dark .icon.service, .hc-black .icon.service { diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 538a3a9d97..43852b867d 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -127,6 +127,7 @@ export class MenuId { static readonly DataExplorerAction = new MenuId('DataExplorerAction'); // {{SQL CARBON EDIT}} static readonly ExplorerWidgetContext = new MenuId('ExplorerWidgetContext'); // {{SQL CARBON EDIT}} static readonly DashboardToolbar = new MenuId('DashboardToolbar'); // {{SQL CARBON EDIT}} + static readonly NotebookTitle = new MenuId('NotebookTitle'); // {{SQL CARBON EDIT}} static readonly TimelineItemContext = new MenuId('TimelineItemContext'); static readonly TimelineTitle = new MenuId('TimelineTitle'); static readonly TimelineTitleContext = new MenuId('TimelineTitleContext'); diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts index defac45631..a85e72f3ae 100644 --- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts +++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts @@ -20,6 +20,7 @@ import { VIEWLET_ID as EXPLORER } from 'vs/workbench/contrib/files/common/files' import { VIEWLET_ID as SCM } from 'vs/workbench/contrib/scm/common/scm'; import { VIEWLET_ID as DEBUG } from 'vs/workbench/contrib/debug/common/debug'; import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/common/remote.contribution'; +import { VIEWLET_ID as NOTEBOOK } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet'; // {{SQL CARBON EDIT}} import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet'; @@ -175,6 +176,13 @@ const viewsContribution: IJSONSchema = { type: 'array', items: remoteViewDescriptor, default: [] + }, + // {{SQL CARBON EDIT}} + 'notebooks': { + description: localize('views.notebooks', "Contributes views to Notebooks container in the Activity bar."), + type: 'array', + items: viewDescriptor, + default: [] } }, additionalProperties: { @@ -500,6 +508,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution { case 'debug': return this.viewContainersRegistry.get(DEBUG); case 'scm': return this.viewContainersRegistry.get(SCM); case 'remote': return this.viewContainersRegistry.get(REMOTE); + case 'notebooks': return this.viewContainersRegistry.get(NOTEBOOK); // {{SQL CARBON EDIT}} default: return this.viewContainersRegistry.get(`workbench.view.extension.${value}`); } } diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index 9e8f5aacdb..5ff107eaf5 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -52,6 +52,7 @@ namespace schema { case 'notebook/toolbar': return MenuId.NotebookToolbar; case 'dataExplorer/context': return MenuId.DataExplorerContext; case 'dataExplorer/action': return MenuId.DataExplorerAction; + case 'notebooks/title': return MenuId.NotebookTitle; case 'comments/commentThread/title': return MenuId.CommentThreadTitle; case 'comments/commentThread/context': return MenuId.CommentThreadActions; case 'comments/comment/title': return MenuId.CommentTitle; diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 918bac0869..dd0b94050d 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -600,6 +600,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi case 'remote': viewletId = 'workbench.view.remote'; break; + // {{SQL CARBON EDIT}} add notebook view container to views + case 'notebooks': + viewletId = 'workbench.view.notebooks'; + break; default: viewletId = `workbench.view.extension.${container.id}`; } diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 562b26022d..1380ad4f7c 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -398,6 +398,8 @@ import 'sql/workbench/contrib/query/common/resultsGrid.contribution'; // data explorer import 'sql/workbench/contrib/dataExplorer/browser/dataExplorer.contribution'; import 'sql/workbench/contrib/dataExplorer/browser/nodeActions.common.contribution'; +import 'sql/workbench/contrib/dataExplorer/browser/extensions.contribution'; + //editor replacement import 'sql/workbench/contrib/editorReplacement/common/editorReplacer.contribution'; diff --git a/test/README.md b/test/README.md index b584fee64d..de15fa7556 100644 --- a/test/README.md +++ b/test/README.md @@ -24,3 +24,9 @@ Code coverage is enabled by default. Reports can be found in the coverage folder ### Integration tests These are the group of tests that have dependencies on outside resources such as SQL instances. See the [README](../extensions/integration-tests/readme.md) for more information. + +## Code Coverage + +To generate a report combining the code coverage for extensions + core run `node ./test/combineCoverage`. Currently this will combine coverage from the Core Unit Tests, Extension Unit Tests and Extension Integration tests - see above docs for instructions on how to run those to generate coverage. + +Once ran the combined coverage report will be located in `./test/coverage`. diff --git a/test/combineCoverage.js b/test/combineCoverage.js new file mode 100644 index 0000000000..dfb5416783 --- /dev/null +++ b/test/combineCoverage.js @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const iLibCoverage = require('istanbul-lib-coverage'); +const iLibReport = require('istanbul-lib-report'); +const iReports = require('istanbul-reports'); +const fs = require('fs'); +const path = require('path'); +const glob = require('glob'); + +const coverageMap = iLibCoverage.createCoverageMap(); +const repoRoot = path.join(path.dirname(__filename), '..'); + +// .build contain the core coverage files +// extensions each may container their own coverage file +const coverageFiles = glob.sync('{extensions,.build}/**/coverage-final.json', + { + cwd: repoRoot, + ignore: ['**/node_modules/**'] + } +); + +coverageFiles.forEach(file => { + console.log(`Merging coverage file ${path.join(repoRoot, file)}`); + coverageMap.merge(JSON.parse(fs.readFileSync(file))); +}); + +const context = iLibReport.createContext({ + dir: path.join(path.dirname(__filename), 'coverage'), + coverageMap: coverageMap +}); + +const tree = context.getTree('flat'); +tree.visit(iReports.create('lcov'), context); diff --git a/test/unit/coverage.js b/test/unit/coverage.js index 09c2318850..a12c0177b4 100644 --- a/test/unit/coverage.js +++ b/test/unit/coverage.js @@ -56,6 +56,7 @@ exports.createReport = function (isSingle) { let reports = []; if (isSingle) { reports.push(iReports.create('lcovonly')); + reports.push(iReports.create('json')); // {{SQL CARBON EDIT}} add json for code coverage merging } else { reports.push(iReports.create('json')); reports.push(iReports.create('lcov'));