Compare commits

...

159 Commits

Author SHA1 Message Date
Benjin Dubishar
09b1554040 Fix for issue where bulk-adding scripts could perform a rescan after each script (#22665) (#22667)
* Changed bulk script add to delay reloading file list until end of operation.

* Adding style name to sqlproj typing file

* vBump to 1.0.1
2023-04-10 22:57:20 -07:00
Aasim Khan
b790d70089 updating sts (#22653) 2023-04-06 16:07:23 -07:00
Aasim Khan
4f341a0989 revert async changes (#22649) 2023-04-06 13:33:29 -07:00
Christopher Suh
094562ea9c Revert "Update remaining Axios calls (#22525)" (#22642)
This reverts commit ccd5775093.
2023-04-05 18:49:00 -07:00
Benjin Dubishar
fd7ab62a77 Porting GA README updates for SQL Database Projects extension (#22646)
* updating SQL projects extension readme (#22632)

* fixing setting description in sql projects readme (#22640)

---------

Co-authored-by: Drew Skwiers-Koballa <dzsquared@users.noreply.github.com>
2023-04-05 17:45:10 -07:00
Karl Burtram
b98983758f Bump STS to 4.6.1.3 to pickup NoConnect user bug fix (#22623) 2023-04-04 19:38:07 -07:00
Benjin Dubishar
56f8aa8b85 Adding patch to rename backup file when it already exists (#22613) (#22614) 2023-04-04 14:08:46 -07:00
Benjin Dubishar
11304d9090 Fix issue where errors during project update were swallowed (#22612) (#22615)
* adding errors

* Fixing bug where errors occurring during updating project got swallowed

* removing unnecessary "vscode"
2023-04-04 13:34:49 -07:00
Karl Burtram
9f9d84b4ee Bump STS for additional user management fixes (#22603) 2023-04-03 21:15:21 -07:00
Karl Burtram
d4a9878c29 Bump STS to pickup contained user bug fix (#22602) 2023-04-03 16:47:05 -07:00
Alan Ren
d1b18a2ee6 fix the empty schema issue (#22594) (#22597) 2023-04-03 16:04:54 -07:00
Aasim Khan
a8d851b1ed Removing oe service changes from release 1.43 (#22593)
* Revert "Fixing connection without saved password not connecting in Async Server Tree (#22535)"

This reverts commit d49ff85afc.

* Revert "Adding caching in OE service (#22539)"

This reverts commit a1acaf2096.
2023-04-03 16:04:28 -07:00
Benjin Dubishar
15ecdc8653 Fixing smattering of issues regarding updating projects for cross-plat (#22575)
* Fixing smattering of issues regarding updating projects for cross-plat

* Adding both options for modal

* Removing quickpick
2023-04-03 10:10:31 -07:00
Benjin Dubishar
267a830775 Disabling revert button when no changes to SQLCMD vars at publish time (#22552)
* disabling revert SQLCMD var value button when no changes to values; changing string

* Updating docstring

* Updating behavior to account for SQLCMD vars defined in publish profiles
2023-04-03 10:09:06 -07:00
Alex Hsu
55820e94f9 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230403154147337. (#22586) 2023-04-03 10:00:25 -07:00
Alex Hsu
59c5ca605c Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230402154501941. (#22581) 2023-04-03 08:29:45 -07:00
Alan Ren
2a14562ec7 update parse query action (#22577)
* update parse query action

* revert export notebook change

* comment
2023-03-31 18:24:47 -07:00
Alex Ma
0f21ecd531 Add fix to enter press on last row of Edit Data. (#22351)
* added fix to enter on null row for edit data

* added fix to displayValue after new row is added

* added suggested changes and fixes
2023-03-31 18:09:34 -07:00
Cory Rivera
1dbb2211e3 Use blue icon for dashboard New Notebook task (#22568) 2023-03-31 16:06:50 -07:00
Hai Cao
490ea592f2 bump STS (#22576) 2023-03-31 15:27:47 -07:00
Kim Santiago
2280c54d4d vbump sql projects to 1.0.0 (#22553)
* vbump sql projects to 1.0.0

* set preview to false
2023-03-31 13:35:43 -07:00
Christopher Suh
ccd5775093 Update remaining Axios calls (#22525)
* initial commit adding put and delete operations

* change response.data => response.body

* add client response interface

* add error to interface

* add reqHeaders
2023-03-31 12:22:31 -07:00
Cheena Malhotra
152eb32278 Fix saving profile from Azure tree nodes (#22518) 2023-03-31 11:58:49 -07:00
Cheena Malhotra
87b3ac1c05 Bump STS version (#22564) 2023-03-31 11:32:21 -07:00
brian-harris
887053c604 SQL-Migration: add retry migration prompt (#22555)
* add retry migration prompt

* updating review comments

* update context menu postion to match toolbar
2023-03-31 10:25:39 -07:00
Alex Ma
e948b4e842 Langpack source and XLF update for April 2023 Release (#22554) 2023-03-31 09:41:43 -07:00
Aasim Khan
d49ff85afc Fixing connection without saved password not connecting in Async Server Tree (#22535) 2023-03-31 09:19:01 -07:00
Aasim Khan
a1acaf2096 Adding caching in OE service (#22539) 2023-03-31 09:18:36 -07:00
Sakshi Sharma
9d8006562d Fix project name validation (#22547)
* Fix project name validation

* Add/update tests

* Address comments

* Fix error
2023-03-31 08:46:58 -07:00
Alan Ren
6cc5e9a70d fix object management dialog's validation issue (#22556)
* fix validation issue

* make message optional

* fix errors
2023-03-31 07:59:38 -07:00
Kim Santiago
e2d4d07c0b fix console error when trying to drag a sql project node (#22551)
* fix console error when trying to drag a sql project node

* fix typo

* update comment
2023-03-30 17:27:01 -07:00
Raymond Truong
3ca583760f [SQL Migration] Add additional checks for multiple database backups in same folder (#22483)
* Add info box about blob container folders

* Add warning banner if non-unique backup locations

* WIP - Add offline scenario

* Clean up

* Address PR comments
2023-03-30 17:19:59 -07:00
Kim Santiago
8e82f62164 cleanup sql projects readme (#22538)
* cleanup sql projects readme

* update to use code blocks for commands
2023-03-30 15:56:17 -07:00
Aasim Khan
4ff16885c1 Cleaning update children logic in async server tree (#22550) 2023-03-30 15:17:45 -07:00
Christopher Suh
2e1689b44d Add warning message when pii logging enabled (#22533)
* add warning message when pii logging enabled

* fix typo

* Update extensions/azurecore/src/localizedConstants.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* update warning message

---------

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
2023-03-30 14:44:25 -07:00
Alex Hsu
92f9b11012 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230330154329299. (#22545) 2023-03-30 14:34:28 -07:00
Cory Rivera
621f390eef Add New Notebook task to server and database dashboards. (#22548) 2023-03-30 12:41:03 -07:00
Kim Santiago
0feabc9a6f use fsPath instead of path when calculating relative path to sqlproj (#22534) 2023-03-30 10:01:06 -07:00
Alan Ren
ee2e59243a revert changes for testing (#22544) 2023-03-30 08:37:40 -07:00
Alan Ren
ff603fa911 handle table designer errors (#22527)
* handle table designer error

* log to console
2023-03-29 16:37:15 -07:00
Kim Santiago
4458a5bd57 move publish interfaces out of sqldbproj.d.ts (#22521) 2023-03-29 16:27:23 -07:00
Charles Gagnon
3320bb55c2 Update privacy documentation (#22520)
* Update privacy documentation

* move
2023-03-29 15:40:01 -07:00
Benjin Dubishar
edc2c5e200 Surfacing better error messages about SQLCMD var names (#22509)
* Surfacing better error messages about SQLCMD var names

* correcting docstring

* adding space to join char
2023-03-29 14:23:03 -07:00
Aasim Khan
2a9705c495 Fixing async server tree (#22511)
* Changing look of new OE

* Fixing styling

* Fixing moving of connected profile

* Fixing drag and drop where treenodes delete connection nodes

* Fixing Deleting and disconnecting in AsyncServerTree

* Adding constant for OE timeout

* Updated interfaces

* Removing test compilation errors

* Fixing most events in async server tree

* Fixing connection pane styling

* Fixing find node function

* Fixing some more operations

* Fixing some ops

* All operations done

* Fixed active connections

* Fixed data source

* Adding support for setting parents

* code cleanup

* Fixing icon styling issues

* Fix errors

* Fixing comment

* Fixing spacing

* Adding explanation to OE service.

* Reverting server delegate changes

* Reverting styling

* reverting more styling change

* reverting more styling

* Fixing has children

* Fixing drag and drop to tree nodes

* fixing drag and drop

* reverting timing

* fixing drag and drop

* cleaning some code

* Fixed server and group moving

* spell check

* consolidating some logic

* Fixed whitespace

* fixing moving to root group
2023-03-29 13:59:35 -07:00
Austin Bryan
7ecbbdf398 Fixing setTargetServerName in SqlMigration extension. Previously if a case was entered it would run all code in the following cases as well (#22477) 2023-03-29 13:44:29 -07:00
Raymond Truong
4867a3747c [SQL Migration] Add storage/MI connectivity validation (#22410)
* wip

* Add SQL VM POC

* Undo azurecore changes

* Add warning banner instead of blocking on next

* Fix warning banner behavior

* Add private endpoint support

* Fix navigation issue

* Add offline scenario

* Address PR comments

* Fix merge conflicts
2023-03-29 12:48:22 -07:00
Cheena Malhotra
e70865ff20 Send telemetry with Auth Library when adding/refreshing account (#22506) 2023-03-29 11:56:56 -07:00
Christopher Suh
87fb3f9b86 Add kusto endpoints for non-public clouds (#22515)
* add kusto endpoints for non-public clouds

* fix endpoints
2023-03-29 11:42:38 -07:00
Alan Ren
e01e3b0e8e update sts (#22516) 2023-03-29 10:45:06 -07:00
Alex Hsu
09b0488978 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230329154135186. (#22513) 2023-03-29 09:34:39 -07:00
Charles Gagnon
2ccd7405c0 Promote some proposed typings (#22508) 2023-03-29 09:06:44 -07:00
brian-harris
ef02e2bfce SQL-Migration: add new migration monitoring data to migration details (#22460)
* add new migration details

* move migraiton target type enum to utils

* address review feedback, refectore, text update

* fix variable name

* limit and filter migrations list to mi/vm/db
2023-03-29 07:48:30 -07:00
Alan Ren
afafee844c fix notebook serialization issue for non-mssql providers (#22504)
* use mssql as notebook serialization provider

* comment

* use fallback
2023-03-28 21:34:38 -07:00
Hai Cao
83e35ad7f8 fix hover for cells with null value (#22507) 2023-03-28 20:19:15 -07:00
Aasim Khan
f60bd1335c Adding promises and operation timeouts to fix race conditions and infinite loading in OE (#22475)
* Adding promises and operation timeouts to fix race conditions

* cleaning up logic

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing promise type

* Reverting back to old error logic

* Making onsessioncreated async

* Removed polling and converted to event based

* removing connection variable out of promise

* Combining promises

* Update src/sql/workbench/services/objectExplorer/browser/treeUpdateUtils.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing error messages and localizing user facing errors

* Fixing error message

* localizing config

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Update src/sql/workbench/services/objectExplorer/browser/objectExplorerService.ts

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* Fixing comment

---------

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
2023-03-28 18:36:45 -07:00
Charles Gagnon
5c6ea2890a Switch "Install" to "Download" for downloaded extensions (#22498) 2023-03-28 15:35:43 -07:00
Kim Santiago
19a9611407 vbump sql database projects (#22501) 2023-03-28 15:13:38 -07:00
Benjin Dubishar
15c0c68e44 SQL Database Projects backend swap to DacFx/Tools Service (#22451)
* Move call to STS move api into project.ts (#22071)

* move call to STS move api into project.ts

* remove undefined

* Remove convert to sdk style code (#22081)

* remove convert to sdk style code

* remove from package.json

* Merging latest from main (#22097)

* [SQL-Migration] Login migrations telemetry (#22038)

This PR enhances telemetry for login migrations (and in the following ways:

Add details for starting migration (number of logins migrating, type of logins)
Log Migration result (number of errors per step, duration of each step, type of logins, if system error occurred)
Add sql-migration extension to our telemetry
Adds details when trying to connect to target
Tracks clicking "done" from the wizard
Fixes bucketizing for navigating telemetry in the login migration wizard
Sample usage of kusto query for new telemetry:
RawEventsADS
| where EventName contains 'sql-migration'
| extend view = tostring(Properties['view'])
| extend action = tostring(Properties['action'])
| extend buttonPressed = tostring(Properties['buttonpressed'])
| extend pageTitle = tostring(Properties['pagetitle'])
| extend adsVersion = tostring(Properties['common.adsversion'])
| extend targetType = tostring(Properties['targettype'])
| extend tenantId = tostring(Properties['tenantid'])
| extend subscriptionId = tostring(Properties['subscriptionid'])
| where view contains "login"
//| where adsVersion contains "1.42.0-insider"
| where ClientTimestamp >= ago(18h)
| project EventName, ClientTimestamp, SessionId, view, pageTitle, action, buttonPressed, targetType
, tenantId, subscriptionId
, adsVersion, OSVersion, Properties

* Add Secure Enclaves dropdown with customizable Advanced options (#22019)

* Update extension READMEs (#22079)

* Fix query-history README images (#22084)

* [Loc] update to mssql and sql-migration xlf files (#22087)

* [Loc] small fix to Portuguese lcl file (#22088)

* [Loc] small fix to Portuguese lcl file

* remove newline

* Adding None bindings to the sqlProjects service (#22085)

* Adding None bindings

* updating names of None bindings

---------

Co-authored-by: AkshayMata <akam520@gmail.com>
Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com>
Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
Co-authored-by: Alex Ma <alma1@microsoft.com>

* Swap add and update sqlcmd variables in sql projects to use STS apis (#22086)

* delete sqlcmd variable working

* undo add

* remove variable from add and update sqlcmd variable apis

* hookup add and edit sqlcmd variable

* update vscode-mssql.d.ts

* move add and edit to project.ts

* update STS and tests

* move delete sqlcmd variable to project.ts (#22104)

* add test for add and edit sqlcmd variable (#22107)

* Swapping property access to STS (#22115)

* checkpoint

* Adding sqlproj property bindings

* Swapping out property loading and setting

* consolidating to this.sqlProjService

* Update dacpac reference to use STS api (#22116)

* Update add dacpac reference to use STS api

* remove changes for project ref

* validate unset settings from add database reference dialog

* update one more place getting sqlprojservice

* addressing comments

* fix path for dacpac reference (#22143)

* Swap add project reference to call STS (#22148)

* initial changes for swapping add project reference

* fix include path

* move common logic to helper function

* read sqlcmd variables from STS (#22147)

* Swapping .sqlproj- and crossplat compatibility-related functions to use STS (#22146)

* Supporting roundtrip

* Updating sqlproj style checks and cross-platform compatibility to use STS

* removing unnecessary awaits

* Fixing assertions

* Adding roundtrip update confirmations

* test cleanup

* cleaning up comment; localizing error

* Swap add system db reference (#22171)

* swap adding system database references

* fix tests

* remove only in test

* Read database references from STS (#22179)

* Read database references from STS

* fix system dacpac names

* fix project reference name

* Swap changeTargetPlatform to call STS (#22172)

* swap changeTargetPlatform to call STS

* Address comments

* De-duplicating enum for SystemDatabase (#22196)

* Deudping SystemDatabase enum

* simplifying enum refs

* Removing the now-unused imports code from SqlProjects (#22199)

* Removing unused importTargets entries

* whitespace; also to retrigger github checks on correct branch

* Hooking in Move() for Nones and PublishProfiles (#22200)

* Swap delete database reference to call STS (#22215)

* initial changes

* update contracts

* remove unnecessary info from SystemDatabaseReferenceProjectEntry

* uppercase master and msdb

* cleanup

* update test

* update comment

* undo change in projectController.ts

* remove unused system dacpac helper functions (#22204)

* more cleanup of project.ts (#22242)

* fix a couple database reference tests (#22248)

* Organizing sqlcmd variable and db reference code (#22284)

* organize database references and sqlcmd variable functions

* separate database reference tests

* Script and folder get + add support (#22166)

* Initial sqlobjectscripts

* adding mock filter

* test fixing

* another test passing

* swapping pre/post/none checkpoint

* awaiters

* convert addExistingItem

* swapping folders

* removing print

* stripping out project folder and file readers

* adding some regions

* Updating sqlproj style checks and cross-platform compatibility to use STS

* Updating sqlproj style checks and cross-platform compatibility to use STS

* added type property to tree items

* projectController swapovers

* removing imported targets

* Deleting the last of the TS XML parsing!

* Removing old functions

* renamed readNoneScripts to readNoneItems

* fixing path passed to STS calls

* remove system dacpac tests that were moved to DacFx (#22299)

* fix error when opening file after adding a file to sql project (#22309)

* fix error when opening file after adding a file to sql project

* remove unused import

* fix exclude for table and externalStreamingJob (#22310)

* add reload project (#22313)

* set DSP from STS (#22320)

* fix adding post-deployment script and existing item (#22317)

* Test cleanup for .sqlproj content operations (#22330)

* Fixing up tests

* sqlproj content operations tests

* remove only

* Cleanup

* Correcting collation

* cleanup constants.ts (#22336)

* fix folders not showing in project tree (#22319)

* Fix project controller tests (#22327)

* fixing ProjectController tests after swap

* remove only from database reference tests

* change system dbs back to lowercase in sql projects (#22353)

* Bump tools service

* Updated yarn.lock file

* pass SystemDacpacsLocation when building legacy style sql projects (#22329)

* Benjin/fix types (#22365)

* Updated yarn.lock file

* Fixing types

* fix projectController tests (#22375)

* Fixing the deletion flow for files and folders (#22366)

* checkpoint

* PR feedback

* Fixing up SDK-style operations project test group (#22377)

* Fixing up SDK-style project test group

* Removing .only

* Fixing up database reference tests (#22380)

* Fixing DB reference test group

* Extra cleanup

* removing only

* Consolidating None and PublishProfile; lighting up test (#22382)

* Lighting up project property tests (#22395)

* Checkpoint

* Lighting up project property tests

* removing timeout

* Fixing buildHelper test (#22400)

* Unskipping up roundtrip test (#22397)

* Refactoring database references to split literalVariable from databaseName (#22412)

* refactoring database references to split databaseVariableLiteralValue out from databaseName

* renaming more properties

* Removing branch in entry population

* removing only

* Fixing baselines for delete test

* PR feedback

* Fixing up ProjectTree tests (#22419)

* Fixing up projectTree tests

* remove only

* Updating projectController exclude test (#22413)

* Updating test

* moving filtering for external folders to readFolders() method

* Removing EntryType import

* fix ups (#22435)

* adding extra info for test failure

* hide exclude folder from context menu until it's supported (#22454)

* Adding current test name to generated folder to avoid conflicts (#22478)

* Adding current test name to generated folder to avoid conflicts

* passing correct test parameter in

* Adding trimming and entropy

* Deleting unused baselines (#22497)

* Replacing addToProject() with addSqlObjectScripts() (#22489)

* checkpoint

* Fixing test

* Updating file scraper function to filter only to .sql files (no folders, no txt)

* changing var names to reflect that the lists only contain .sql scripts

---------

Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com>
Co-authored-by: AkshayMata <akam520@gmail.com>
Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com>
Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
Co-authored-by: Alex Ma <alma1@microsoft.com>
2023-03-28 13:39:57 -07:00
Kim Santiago
a7ecff77dd turn on noUnusedParameters in Schema Compare (#22452)
* turn on noUnusedParameters in Schema Compare

* use _click

* Add names to unused parameters in test files
2023-03-28 11:17:14 -07:00
Kim Santiago
929184514e fix undefined error when opening Create Project from Database dialog (#22480) 2023-03-28 11:16:53 -07:00
Aasim Khan
3aee3f006a Fixing icon styling in tree (#22490) 2023-03-28 09:23:15 -07:00
Alan Ren
e15b612166 update manage extension action (#22488) 2023-03-27 20:40:26 -07:00
Alex Ma
fd8d8b0a27 [Loc] fix for webpack for sql-migration and update to XLFs two weeks prior to code complete. (#22484) 2023-03-27 17:07:14 -07:00
Cory Rivera
97eb69477e Remove unused files in sql and extensions folders (#22444) 2023-03-27 16:40:32 -07:00
junierch
e741fa0bbd telemetry for tde user actions (#22474)
* telemetry for user actions

* remove unused action

* try catch around admin function
2023-03-27 17:48:47 -04:00
Aasim Khan
e80c6f2dcb Fixing async tree styling (#22458) 2023-03-27 13:16:23 -07:00
Alan Ren
115062c0fc bring back ads edit (#22472) 2023-03-27 11:27:41 -07:00
Karl Burtram
7377feeb22 Bump STS to pick-up Intellicode fix (#22462) 2023-03-25 11:52:29 -07:00
Alan Ren
86e6b42bdc select the row on double click (#22456)
* select row on double click

* skip row number column
2023-03-24 20:10:05 -07:00
Alan Ren
35cb233851 support default action for OE node (#22455)
* support default action for OE node

* fix floating promise
2023-03-24 20:09:48 -07:00
Kim Santiago
3d2a531976 add hover text to icon buttons in sql projects extension (#22453) 2023-03-24 16:01:30 -07:00
Kim Santiago
8fdcafcca7 fix aria label for name input box in create project from db dialog (#22449) 2023-03-24 15:21:44 -07:00
Kim Santiago
c8d0edf048 add aria labels to a couple radio groups in sql database projects (#22446) 2023-03-24 15:21:33 -07:00
Christopher Suh
738987c4d5 Show message indicating that ADAL is being deprecated (#22432)
* show message indicating that ADAL is being deprecated

* pr comments update

* added settings deprecation message

* fix deprecation message
2023-03-24 14:42:45 -07:00
Kim Santiago
31ac636222 make screenreader announce task status (#22434) 2023-03-24 11:14:10 -07:00
Cheena Malhotra
d5c495f05a Address Secure enclaves feedback to show required indicator optionally (#22428) 2023-03-24 09:57:32 -07:00
Karl Burtram
ad6c202e34 Enable contained and Windows user types (#22440) 2023-03-24 09:11:16 -07:00
Cheena Malhotra
8d49b15b53 Skip forceRefresh for full (owning) tenant (#22421) 2023-03-23 21:01:03 -07:00
Charles Gagnon
dfc6469c9d Enable strict null in MSSQL extension (#22433) 2023-03-23 16:49:48 -07:00
Alan Ren
59ad572800 fix strict null issues (#22430) 2023-03-23 15:19:23 -07:00
Christopher Suh
00897fc513 Replace Axios calls with HttpClient (#22417)
* replace axios calls with httpClient

* add latest files

* fix url
2023-03-23 13:47:25 -07:00
Charles Gagnon
57c35ca255 More MSSQL strict null (#22420) 2023-03-23 11:13:04 -07:00
Charles Gagnon
2805f9f499 More MSSQL strict null (#22402) 2023-03-23 07:04:18 -07:00
Cheena Malhotra
43f97f4f56 Handle out of sync extension activations for encryption keys updated event (#22415) 2023-03-22 22:23:03 -07:00
Kim Santiago
0741e18533 vbump dacpac extension after release (#22418) 2023-03-22 17:47:56 -07:00
Christopher Suh
14ea5e9dd7 fix logic (#22405) 2023-03-22 12:57:49 -07:00
Charles Gagnon
ed37ad315f Clean up buildConnectionInfo (#22407)
* Clean up buildConnectionInfo

* Add test and cleanup
2023-03-22 12:54:29 -07:00
Cory Rivera
9f435e271a Establish connection after running New Notebook from Azure data explorer view (#22408) 2023-03-22 12:53:03 -07:00
erpett
94e779ef0d Changes for release (#22409) 2023-03-22 12:49:50 -07:00
Charles Gagnon
ca4722360a More strict SSL proxy setting fixes (#22404) 2023-03-22 12:45:51 -07:00
Cheena Malhotra
a3e77c674c Address console warnings with new connection dialog (#22293) 2023-03-22 12:31:25 -07:00
Cheena Malhotra
94b3261276 Notify STS when encryption keys are updated in azurecore (#22384) 2023-03-22 11:46:30 -07:00
Karl Burtram
1e4800a60c Support adding Windows users (#22399)
* Support adding Windows users

* Bump STS
2023-03-22 09:53:20 -07:00
Kim Santiago
3b68aaed72 change publish options to use declarative table (#22398) 2023-03-22 09:44:27 -07:00
Charles Gagnon
d7bd87fac0 Fix incorrect default for proxy setting when downloading STS (#22396) 2023-03-22 09:28:32 -07:00
Vsevolod Kukol
e3135aca4c Preserve name and group when using Connection String (#22341) 2023-03-22 07:55:18 -07:00
Kim Santiago
21bb7eb482 add aria label for checkboxes in declrative table (#22393) 2023-03-21 16:35:28 -07:00
Charles Gagnon
62ece298cc Some MSSQL strict null check fixes (#22383) 2023-03-21 16:10:57 -07:00
Kim Santiago
2be49a9911 switch exclude object types table to use declarative table component (#22390)
* switch exclude options to use declarative table component

* add to disposableListeners
2023-03-21 14:09:31 -07:00
Alan Ren
21f271671d new drop object request (#22387)
* simplify drop object requests

* update sts

* pr comments
2023-03-21 10:51:55 -07:00
Hai Cao
ffc7f05c10 Add background color for null cell in query editor result grid (#22370) 2023-03-20 15:55:57 -07:00
Aasim Khan
f9e72b0d93 Fixing connection group change for connections (#22379) 2023-03-20 15:37:47 -07:00
Charles Gagnon
7bf11118af Enable datavirtualization tests (#22378)
* Enable datavirtualization tests

* Remove unneeded
2023-03-20 14:45:13 -07:00
Charles Gagnon
47ce587fef Update ads-extension-telemetry to 3.0.1 (#22374) 2023-03-20 12:48:31 -07:00
Alex Hsu
b06398b32b Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230318154256685. (#22368) 2023-03-20 09:43:04 -07:00
Alan Ren
aa47729f90 fix find parent node issue (#22356)
* fix find parent node issue

* sts update

* fix errors

* pr comments and a fix
2023-03-20 08:20:11 -07:00
Benjin Dubishar
9d16a48dee Bump tools service (#22361) 2023-03-17 15:11:39 -07:00
Benjin Dubishar
0b3a9ca0f0 Updated yarn.lock file (#22363) 2023-03-17 15:11:11 -07:00
Alex Hsu
54e86e19a3 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230317154311330. (#22359) 2023-03-17 09:30:47 -07:00
Cheena Malhotra
4b02c26a52 MSAL cache encryption + log improvements (#22335) 2023-03-16 16:53:16 -07:00
Kim Santiago
931c44ac41 add ariaLive to publish options description (#22338)
* add ariaLive to publish options description

* use correct string and update typings

* update type

* remove comment update

* create type AriaLiveType

* update MockInputBoxComponent with AriaLiveValue

* update azdata-test and add comment
2023-03-16 16:08:24 -07:00
Alan Ren
20cf2489a2 support rename for login, user and a few other types (#22331)
* rename object

* add comment

* use URN property

* vbump STS

* revert loc string change

* fix name check

* pr comments
2023-03-16 15:00:07 -07:00
Alex Hsu
f5628ed8e3 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230316192338900. (#22350) 2023-03-16 12:33:19 -07:00
Alan Ren
1d99060443 update the display name (#22345) 2023-03-16 11:49:17 -07:00
Alex Hsu
8406ce8f93 Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230315234519077. (#22339) 2023-03-15 17:07:25 -07:00
Charles Gagnon
8c20e827ad Remove error messages from error events (#22337) 2023-03-15 15:19:16 -07:00
dependabot[bot]
a2d66a288c Bump webpack from 5.73.0 to 5.76.0 (#22326)
Bumps [webpack](https://github.com/webpack/webpack) from 5.73.0 to 5.76.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.73.0...v5.76.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-15 15:04:52 -07:00
junierch
cb66ef349e focus on tde edit button (#22314) 2023-03-15 13:30:34 -04:00
Alex Ma
8e6f747336 [Loc] SQL xlf update (Added node expansion labels) (#22328) 2023-03-14 17:15:10 -07:00
Alan Ren
91f64df29f update yarn.lock (#22324) 2023-03-14 14:00:44 -07:00
Aasim Khan
f0a5d296bf Fixing new connections not expanding in object explorer. (#22307)
* Fixing new connection node not expanding in OE

* Fixing new connections not expanding and fixing expand request not resolving because of some provider error.

* Fixing test

* Adding a setting for node expansion timeout

* Not saving when loading tree based connections

* Adding some logs

* Removing special casing for mssql provider

* Missing providers

* Adding user toast for node expansion timeout

* Adding notification service to test

* Fixing node type for mssql

* remove polling

* Fixing onNodeStatus

* Fixing stuff

* consolidating functions

* Consolidating resolve logic

* removing extra try catch

* code cleanup

* adding size checks

* Removing commented code

* Ignoring errors from other sessions and nodepaths.
2023-03-14 10:50:46 -07:00
Alex Ma
ef99e67cfe [Loc] update to XLFS for 3-13-2023 (#22318) 2023-03-13 17:18:30 -07:00
Karl Burtram
efc5938141 Fix casing of OE icon files to match source (#22315) 2023-03-13 15:04:15 -07:00
brian-harris
7c41d45e66 add SHIR registration for create service for sqldb (#22308) 2023-03-13 12:36:56 -07:00
Cheena Malhotra
8539b63a5c Upgrade http(s)-proxy-agent dependent npm packages (#22306) 2023-03-13 11:05:59 -07:00
Alan Ren
653293aad9 fix action bar size (#22301) 2023-03-10 14:39:45 -08:00
Alan Ren
7f3461c026 use latest STS version (#22297) 2023-03-10 11:36:46 -08:00
Cheena Malhotra
c163830bc4 Use Preferred username over email as 'user' property (#22288) 2023-03-09 20:25:07 -08:00
Cheena Malhotra
4c3f622250 Update @azure/msal-node to v1.16.0 (#22287) 2023-03-09 17:09:05 -08:00
Alex Ma
344ca478ef Fix for Edit Data grid newline on multiline strings (#22269)
* Fix for newline replacement

* added proper null regex and null character check

* removed cell class

* removed unnecessary function

* revert back to old check

* change onbeforeeditcell

* small fix to typo in onBeforeEditCell

* made changes based on feedback

* added comments clarifying isDBCellValue
2023-03-09 16:10:31 -08:00
Cheena Malhotra
f51fe75397 Null & Error handling in Azure core (#22259) 2023-03-09 14:34:39 -08:00
Kim Santiago
0bbc290790 fix accessibility issues in update project from db dialog (#22274)
* fix accessibility issues in update project from db dialog

* remove aria label on radio buttons
2023-03-09 14:21:43 -08:00
Kim Santiago
394d88445a undo remove project change in data workspace (#22283) 2023-03-09 14:14:39 -08:00
Alan Ren
6ace579986 user management fixes (#22282)
* fix a few user management bugs

* revert user dialog change
2023-03-09 14:11:04 -08:00
brian-harris
39f90afe6c add delete migration method in migration list and details pages (#22243)
* add delete migraiton, fix stale token detection

* address pr comments, fix api error response format
2023-03-09 13:52:48 -08:00
Kim Santiago
12a5bd0ef2 update target platform text for azure synapse sql pool (#22265) 2023-03-09 10:07:12 -08:00
Cheena Malhotra
d3d594e826 Revert "Update @azure/msal-node to 1.16.0 (#22255)" (#22268)
This reverts commit 87defc0367.
2023-03-09 09:27:30 -08:00
Kim Santiago
ab68c3060c Add required property in missing places in sql projects (#22253)
* add required property for missing places in sql projects

* remove comma
2023-03-09 08:45:21 -08:00
Alan Ren
ec515a3b23 allow nothing is selected as initial state (#22260) 2023-03-09 08:44:35 -08:00
Maddy
5fc69a0445 Fix find highlight on cell edits (#22080)
* update the rendered text onCellSourceChange

* fix test

* fix highlight in split mode

* update corresponding test

* update hasEditor with getEditor

* update event

* add comment
2023-03-08 22:26:07 -08:00
Cheena Malhotra
87defc0367 Update @azure/msal-node to 1.16.0 (#22255) 2023-03-08 20:25:37 -08:00
Cheena Malhotra
cc52eb9dd8 Include App Path in service launch arguments (#22233) 2023-03-08 18:44:17 -08:00
Charles Gagnon
8e5d89ef94 Fix datavirtualization wizard opening to wrong database (#22232)
* Fix datavirtualization wizard opening to wrong database

* vBump
2023-03-08 14:27:19 -08:00
Aasim Khan
9fddefc8fb Fixing execution plan not finding provider (#22238) 2023-03-08 12:55:49 -08:00
Aasim Khan
84c9a03bf9 Fixing icon for group by schema (#22212) 2023-03-08 12:13:49 -08:00
Kim Santiago
954d521a83 Fix delete database reference request (#22214) 2023-03-08 11:03:44 -08:00
Charles Gagnon
3937f62ce4 Fix query history storage folder creation (#22229) 2023-03-08 10:51:14 -08:00
Charles Gagnon
31fd467bec Add backup and restore keywords to sql grammar (#22226)
* Add BACKUP, STATS and CHECKSUM to keywords list

* LOG and REPLACE
2023-03-08 10:38:40 -08:00
Alan Ren
d19aad9b37 remove commands (#22218) 2023-03-08 08:10:11 -08:00
Alex Hsu
c78c2815cc Juno: check in to lego/hb_04604851-bac4-4681-9f74-73de611d6e48_20230307165240996. (#22191) 2023-03-07 09:42:54 -08:00
Benjin Dubishar
14b0e508cb Bumping sql tools service (#22188) 2023-03-07 09:59:22 -07:00
Charles Gagnon
a575eb1b87 Fix telemetry property names (#22190) 2023-03-07 08:31:24 -08:00
Karl Burtram
b4d5a08199 Bump STS to 4.6.0.1 (#22184) 2023-03-06 20:41:49 -08:00
Aasim Khan
d3f4f0daa4 Adding light contrast theme (#22028)
* Adding light contrast theme

* fixing oe icons

* Fixing more files

* Converting ep files to support hc light

* Revert "Copy Headers for Selected Columns (#21622)"

This reverts commit f74d6f6d9b.

* Adding more css rules

* Fixing modal

* Fixing azure icons
2023-03-06 17:31:27 -08:00
Alan Ren
29c1f5edd0 disable the checkbox for schemas owned by user (#22178) 2023-03-06 15:14:46 -08:00
Alex Ma
f25599119e [Loc] Massive fix for March Langpack (#22180) 2023-03-06 15:04:31 -08:00
Karl Burtram
8a71302aea Only support 'user with login' in dialog (#22175) 2023-03-06 14:32:30 -08:00
erpett
bf753309e7 Updating package.json to show the next build number now that the release branch has split for 1.42 (#22169) 2023-03-06 12:01:27 -08:00
Charles Gagnon
a657aa6cb5 Remove hasEditor from ICellEditorProvider (#22145) 2023-03-06 11:02:41 -08:00
628 changed files with 21680 additions and 14214 deletions

View File

@@ -1,5 +1,65 @@
# Change Log
## Version 1.42.0
* Release number: 1.42.0
* Release date: March 22, 2023
### What's new in 1.42.0
| New Item | Details |
| --- | --- |
| ARM64 Support for macOS | Implemented native arm64 SqlToolsService support for arm64 Windows and macOS. |
| Connection | Changed the icon under Linked Accounts when adding a new Azure account. |
| Connection | Introduced support for the Command Timeout connection property. |
| Connection | Added support for all three connection encryption options: Strict, Mandatory, and Optional. |
| Connection | Introduced HostNameInCertificate connection property under Security on the Advanced tab, for server with a certificate configured. |
| Connection | Added new advanced option in the Connection dialog to support Secure Enclaves. |
| Connection | Introduced a new setting, Mssql Enable Sql Authentication Provider to allow connections to be maintained without the concern of losing access token lifetime or getting dropped by server. Access tokens will be refreshed internally by the SqlClient driver whenever they are found to be expired. This option is disabled by default. |
| Connection | Added support for connections to Microsoft Dataverse using the TDS endpoint. |
| Connection | Introduced additional error reporting for Azure connections. |
| Connection | Introduced support for change password. |
| Connection | Added support for encryption options for Arc SQL Managed Instance when server certificates are not installed. |
| Deployment | Moved the New Deployment option from the Connections breadcrumb to the File Menu. |
| Object Explorer | Introduced ability to group objects in Object Explorer by database schema. This applies to all MSSQL connections when enabled or disabled. |
| Object Explorer | Introduced a new option to allow a custom timeout to be configured for Object Explorer. Within Settings, enable Mssql > Object Explorer: Expand Timeout. |
| Query Results | Added option to disable special handling for JSON strings. |
### Bug fixes in 1.42.0
| New Item | Details |
| --- | --- |
| Accessibility | Updated server group color display to improve visibility and contrast. |
| Backup | Addressed inability to select "Backup Set" checkbox. |
| Connection | Removed refresh action for connections which are disconnected. |
| Connection | Fixed issue with MSAL not properly set for connections. |
| Connection | Added ability to delete a server group if no connections exist for it. |
| Connection | Added connection display name to the Delete Connection dialog. |
| Connection | Azure connections with "Do not save" for the server group are no longer added to the default server group list. |
| Connection | Improved error handling in the connection dialog. |
| Connection | Fixed issue where saved passwords were not retained for Azure SQL connections. |
| Connection | Improved method to retrieve database access when connecting to Azure SQL. |
| Connection | Improved connection experience for cloud users. |
| Connection | Improved account and tenant selection when connecting to Azure SQL in the connection dialog. |
| Deployment | Improved narration for deployment wizard. |
| Installation | Updated default install location for the Windows on ARM installer. |
| MySQL Extension | Addressed issue where dialog boxes in the MySQL connection pane were not editable. |
| Notebooks | Fixed issue with updating the relative path in a Notebook cell. |
| Notebooks | Fixed issue that caused internal notebook links to break when editing characters in the page. |
| Notebooks | Addressed error thrown when opening a Notebook via a link. |
| Object Explorer | Fixed issue with Object Explorer node not expanding. |
| Query Editor | Fixed database dropdown list for contained users to display correctly. |
| Query Editor | Addressed issue where database dropdown list was not ordered the same as in Object Explorer. |
| Query Editor | Added the ability to properly escape special characters when they exist in object names. |
| Query Editor | Fixed issue which caused query timer to continue to run even though execution was complete. |
| Query Plan Viewer | Addressed an issue where a query plan would not render when opened via a URL. |
| Query Results | Improved precision formatting for datetimeoffset data type. |
For a full list of bug fixes addressed for the March 2023 release, visit the [bugs and issues list on GitHub](https://github.com/microsoft/azuredatastudio/milestone/95?closed=1).
#### Known issues
For a list of the current known issues, visit the [issues list on GitHub](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue).
## Version 1.41.2
* Release date: February 10, 2023
* Release status: General Availability

3
PRIVACY.md Normal file
View File

@@ -0,0 +1,3 @@
# Data Collection
The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at <https://go.microsoft.com/fwlink/?LinkID=824704>. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices.

View File

@@ -18,18 +18,18 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
| |.rpm |[64 bit][linux-rpm] |
|Mac |.zip |[Universal][osx-universal]&emsp;[Intel Chip][osx-zip]&emsp;[Apple Silicon][osx-arm64] |
[win-user]: https://go.microsoft.com/fwlink/?linkid=2222768
[win-system]: https://go.microsoft.com/fwlink/?linkid=2222769
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2223104
[win-user-arm64]: https://go.microsoft.com/fwlink/?linkid=2222660
[win-system-arm64]: https://go.microsoft.com/fwlink/?linkid=2222849
[win-zip-arm64]: https://go.microsoft.com/fwlink/?linkid=2222850
[osx-universal]: https://go.microsoft.com/fwlink/?linkid=2222873
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2222874
[osx-arm64]: https://go.microsoft.com/fwlink/?linkid=2222680
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2222918
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2223105
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2222875
[win-user]: https://go.microsoft.com/fwlink/?linkid=2228644
[win-system]: https://go.microsoft.com/fwlink/?linkid=2228645
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2228646
[win-user-arm64]: https://go.microsoft.com/fwlink/?linkid=2229004
[win-system-arm64]: https://go.microsoft.com/fwlink/?linkid=2228647
[win-zip-arm64]: https://go.microsoft.com/fwlink/?linkid=2229005
[osx-universal]: https://go.microsoft.com/fwlink/?linkid=2228649
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2228179
[osx-arm64]: https://go.microsoft.com/fwlink/?linkid=2228648
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2229006
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2228650
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2228180
Go to our [download page](https://aka.ms/getazuredatastudio) for more specific instructions.
@@ -95,8 +95,12 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
## Localization
Azure Data Studio is localized into 10 languages: French, Italian, German, Spanish, Simplified Chinese, Traditional Chinese, Japanese, Korean, Russian, and Portuguese (Brazil). The language packs are available in the Extension Manager marketplace. Simply, search for the specific language using the extension marketplace and install. Once you install the selected language, Azure Data Studio will prompt you to restart with the new language.
## Telemetry
Azure Data Studio collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the [disable telemetry reporting](https://aka.ms/ads-disable-telemetry) documentation.
## Privacy Statement
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
The [Microsoft Privacy Statement](https://go.microsoft.com/fwlink/?LinkID=824704) describes the privacy statement of this software.
## Contributions and "Thank You"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:

View File

@@ -103,7 +103,7 @@ stages:
steps:
- template: linux/sql-product-build-linux.yml
parameters:
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azcli", "azurecore", "cms", "dacpac", "data-workspace", "import", "machine-learning", "notebook", "resource-deployment", "schema-compare", "sql-bindings", "sql-database-projects"]
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azcli", "azurecore", "cms", "dacpac", "datavirtualization", "data-workspace", "import", "machine-learning", "notebook", "resource-deployment", "schema-compare", "sql-bindings", "sql-database-projects"]
timeoutInMinutes: 90
- stage: Windows

View File

@@ -4,7 +4,7 @@
"private": true,
"license": "MIT",
"devDependencies": {
"node-gyp": "^8.4.1"
"node-gyp": "^9.3.1"
},
"scripts": {
}

View File

@@ -2,33 +2,33 @@
# yarn lockfile v1
"@gar/promisify@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.2.tgz#30aa825f11d438671d585bd44e7fd564535fc210"
integrity sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==
"@gar/promisify@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
"@npmcli/fs@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.0.0.tgz#589612cfad3a6ea0feafcb901d29c63fd52db09f"
integrity sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==
"@npmcli/fs@^2.1.0":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865"
integrity sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==
dependencies:
"@gar/promisify" "^1.0.1"
"@gar/promisify" "^1.1.3"
semver "^7.3.5"
"@npmcli/move-file@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
"@npmcli/move-file@^2.0.0":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4"
integrity sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==
dependencies:
mkdirp "^1.0.4"
rimraf "^3.0.2"
"@tootallnate/once@1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
abbrev@1:
abbrev@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
@@ -40,13 +40,13 @@ agent-base@6, agent-base@^6.0.2:
dependencies:
debug "4"
agentkeepalive@^4.1.3:
version "4.1.4"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b"
integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==
agentkeepalive@^4.2.1:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255"
integrity sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==
dependencies:
debug "^4.1.0"
depd "^1.1.2"
depd "^2.0.0"
humanize-ms "^1.2.1"
aggregate-error@^3.0.0:
@@ -88,29 +88,36 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
cacache@^15.2.0:
version "15.3.0"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb"
integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
"@npmcli/fs" "^1.0.0"
"@npmcli/move-file" "^1.0.1"
balanced-match "^1.0.0"
cacache@^16.1.0:
version "16.1.3"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e"
integrity sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==
dependencies:
"@npmcli/fs" "^2.1.0"
"@npmcli/move-file" "^2.0.0"
chownr "^2.0.0"
fs-minipass "^2.0.0"
glob "^7.1.4"
fs-minipass "^2.1.0"
glob "^8.0.1"
infer-owner "^1.0.4"
lru-cache "^6.0.0"
minipass "^3.1.1"
lru-cache "^7.7.1"
minipass "^3.1.6"
minipass-collect "^1.0.2"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.2"
mkdirp "^1.0.3"
minipass-pipeline "^1.2.4"
mkdirp "^1.0.4"
p-map "^4.0.0"
promise-inflight "^1.0.1"
rimraf "^3.0.2"
ssri "^8.0.1"
tar "^6.0.2"
unique-filename "^1.1.1"
ssri "^9.0.0"
tar "^6.1.11"
unique-filename "^2.0.0"
chownr@^2.0.0:
version "2.0.0"
@@ -137,29 +144,36 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0:
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
debug@4, debug@^4.1.0, debug@^4.3.1:
debug@4, debug@^4.1.0:
version "4.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
dependencies:
ms "2.1.2"
debug@^4.3.3:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
depd@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
depd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
encoding@^0.1.12:
encoding@^0.1.13:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
@@ -176,7 +190,7 @@ err-code@^2.0.2:
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
fs-minipass@^2.0.0:
fs-minipass@^2.0.0, fs-minipass@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
@@ -215,6 +229,17 @@ glob@^7.1.3, glob@^7.1.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^8.0.1:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"
graceful-fs@^4.2.6:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
@@ -230,12 +255,12 @@ http-cache-semantics@^4.1.0:
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
http-proxy-agent@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
"@tootallnate/once" "1"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
@@ -289,10 +314,10 @@ inherits@2, inherits@^2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
ip@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
@@ -316,27 +341,32 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
make-fetch-happen@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968"
integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==
lru-cache@^7.7.1:
version "7.18.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
make-fetch-happen@^10.0.3:
version "10.2.1"
resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz#f5e3835c5e9817b617f2770870d9492d28678164"
integrity sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==
dependencies:
agentkeepalive "^4.1.3"
cacache "^15.2.0"
agentkeepalive "^4.2.1"
cacache "^16.1.0"
http-cache-semantics "^4.1.0"
http-proxy-agent "^4.0.1"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
is-lambda "^1.0.1"
lru-cache "^6.0.0"
minipass "^3.1.3"
lru-cache "^7.7.1"
minipass "^3.1.6"
minipass-collect "^1.0.2"
minipass-fetch "^1.3.2"
minipass-fetch "^2.0.3"
minipass-flush "^1.0.5"
minipass-pipeline "^1.2.4"
negotiator "^0.6.2"
negotiator "^0.6.3"
promise-retry "^2.0.1"
socks-proxy-agent "^6.0.0"
ssri "^8.0.0"
socks-proxy-agent "^7.0.0"
ssri "^9.0.0"
minimatch@^3.0.4:
version "3.1.2"
@@ -345,6 +375,13 @@ minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
dependencies:
brace-expansion "^2.0.1"
minipass-collect@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@@ -352,16 +389,16 @@ minipass-collect@^1.0.2:
dependencies:
minipass "^3.0.0"
minipass-fetch@^1.3.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6"
integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==
minipass-fetch@^2.0.3:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add"
integrity sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==
dependencies:
minipass "^3.1.0"
minipass "^3.1.6"
minipass-sized "^1.0.3"
minizlib "^2.0.0"
minizlib "^2.1.2"
optionalDependencies:
encoding "^0.1.12"
encoding "^0.1.13"
minipass-flush@^1.0.5:
version "1.0.5"
@@ -370,7 +407,7 @@ minipass-flush@^1.0.5:
dependencies:
minipass "^3.0.0"
minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4:
minipass-pipeline@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c"
integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==
@@ -384,14 +421,26 @@ minipass-sized@^1.0.3:
dependencies:
minipass "^3.0.0"
minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
minipass@^3.0.0, minipass@^3.1.1:
version "3.1.5"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732"
integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==
dependencies:
yallist "^4.0.0"
minizlib@^2.0.0, minizlib@^2.1.1:
minipass@^3.1.6:
version "3.3.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
dependencies:
yallist "^4.0.0"
minipass@^4.0.0:
version "4.2.5"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.5.tgz#9e0e5256f1e3513f8c34691dd68549e85b2c8ceb"
integrity sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==
minizlib@^2.1.1, minizlib@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
@@ -414,33 +463,33 @@ ms@^2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
negotiator@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
negotiator@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
node-gyp@^8.4.1:
version "8.4.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937"
integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==
node-gyp@^9.3.1:
version "9.3.1"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.3.1.tgz#1e19f5f290afcc9c46973d68700cbd21a96192e4"
integrity sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==
dependencies:
env-paths "^2.2.0"
glob "^7.1.4"
graceful-fs "^4.2.6"
make-fetch-happen "^9.1.0"
nopt "^5.0.0"
make-fetch-happen "^10.0.3"
nopt "^6.0.0"
npmlog "^6.0.0"
rimraf "^3.0.2"
semver "^7.3.5"
tar "^6.1.2"
which "^2.0.2"
nopt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
nopt@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d"
integrity sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==
dependencies:
abbrev "1"
abbrev "^1.0.0"
npmlog@^6.0.0:
version "6.0.0"
@@ -532,32 +581,32 @@ signal-exit@^3.0.0:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
smart-buffer@^4.1.0:
smart-buffer@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
socks-proxy-agent@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
socks-proxy-agent@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6"
integrity sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==
dependencies:
agent-base "^6.0.2"
debug "^4.3.1"
socks "^2.6.1"
debug "^4.3.3"
socks "^2.6.2"
socks@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==
socks@^2.6.2:
version "2.7.1"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==
dependencies:
ip "^1.1.5"
smart-buffer "^4.1.0"
ip "^2.0.0"
smart-buffer "^4.2.0"
ssri@^8.0.0, ssri@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
ssri@^9.0.0:
version "9.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057"
integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==
dependencies:
minipass "^3.1.1"
@@ -584,7 +633,19 @@ strip-ansi@^6.0.1:
dependencies:
ansi-regex "^5.0.1"
tar@^6.0.2, tar@^6.1.2:
tar@^6.1.11:
version "6.1.13"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b"
integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^4.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
tar@^6.1.2:
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
@@ -596,17 +657,17 @@ tar@^6.0.2, tar@^6.1.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
unique-filename@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
unique-filename@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2"
integrity sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==
dependencies:
unique-slug "^2.0.0"
unique-slug "^3.0.0"
unique-slug@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c"
integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==
unique-slug@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9"
integrity sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==
dependencies:
imurmurhash "^0.1.4"

View File

@@ -25,7 +25,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
## Telemetry
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://aka.ms/ads-disable-telemetry) documentation.
## Privacy Statement

View File

@@ -107,7 +107,7 @@
]
},
"dependencies": {
"@microsoft/ads-extension-telemetry": "^2.0.0",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"vscode-nls": "^4.1.2"
},
@@ -117,7 +117,7 @@
"mocha": "^7.1.1",
"should": "^13.2.3",
"@microsoft/vscodetestcover": "^1.2.1",
"@microsoft/azdata-test": "^2.0.3"
"@microsoft/azdata-test": "^3.0.1"
},
"__metadata": {
"id": "41",

View File

@@ -160,6 +160,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
TelemetryViews.SsmsMinDialog,
'LaunchSsmsDialogError',
execException,
false,
execException ? execException?.code?.toString() : '',
getTelemetryErrorType(err));
}

View File

@@ -16,6 +16,7 @@ export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.Obje
// Base properties
public connectionId: string;
public nodePath: string;
public parentNodePath: string;
public nodeType: string;
public nodeSubType: string;
public nodeStatus: string;

View File

@@ -182,10 +182,10 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/ads-extension-telemetry@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
"@microsoft/ads-extension-telemetry@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-3.0.1.tgz#82d4288f8ad96920512ab4edf87d009412e683bb"
integrity sha512-OsHLKvz4DEZg9THkI+Jk4aINgYv4X3qgbqnVAqY8f9zsWTiR+o4vt/F5w0w3kwpbU3ppRHa03yFTBEjYyGSg1g==
dependencies:
"@vscode/extension-telemetry" "0.6.1"
@@ -203,13 +203,13 @@
tmp "^0.0.33"
yauzl "^2.10.0"
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -250,13 +250,6 @@
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
dependencies:
es6-promisify "^5.0.0"
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -445,13 +438,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -555,18 +541,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"
escape-string-regexp@1.0.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"
@@ -778,14 +752,6 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
dependencies:
agent-base "4"
debug "3.1.0"
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
@@ -795,15 +761,7 @@ http-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
https-proxy-agent@^5.0.1:
https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==

View File

@@ -94,7 +94,7 @@
"should": "^13.2.1",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1",
"@microsoft/azdata-test": "^2.0.3"
"@microsoft/azdata-test": "^3.0.1"
},
"__metadata": {
"id": "10",

View File

@@ -182,13 +182,13 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -209,6 +209,11 @@
istanbul-reports "^3.0.0"
mocha "^7.1.1"
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/mocha@^7.0.2":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
@@ -219,12 +224,12 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -390,13 +395,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -404,6 +402,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -493,18 +498,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -697,21 +690,22 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1057,6 +1051,11 @@ ms@2.1.1, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
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"

View File

@@ -1599,7 +1599,7 @@
"@types/sinon": "^9.0.4",
"@types/uuid": "^8.3.0",
"@types/yamljs": "^0.2.31",
"@microsoft/azdata-test": "^2.0.3",
"@microsoft/azdata-test": "^3.0.1",
"mocha": "^7.1.1",
"should": "^13.2.3",
"sinon": "^9.0.2",

View File

@@ -3,16 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ControllerInfo } from 'arc';
import { v4 as uuid } from 'uuid';
import { ControllerModel } from '../../models/controllerModel';
import { AzureArcTreeDataProvider } from '../../ui/tree/azureArcTreeDataProvider';
// import { ControllerInfo } from 'arc';
// import { v4 as uuid } from 'uuid';
// import { ControllerModel } from '../../models/controllerModel';
// import { AzureArcTreeDataProvider } from '../../ui/tree/azureArcTreeDataProvider';
export class FakeControllerModel extends ControllerModel {
// export class FakeControllerModel extends ControllerModel {
constructor(treeDataProvider?: AzureArcTreeDataProvider, info?: Partial<ControllerInfo>) {
const _info: ControllerInfo = Object.assign({ id: uuid(), endpoint: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', namespace: '', username: '', rememberPassword: false, resources: [], resourceGroup: '', connectionMode: '', location: '', customLocation: '' }, info);
super(treeDataProvider!, _info);
}
// constructor(treeDataProvider?: AzureArcTreeDataProvider, info?: Partial<ControllerInfo>) {
// const _info: ControllerInfo = Object.assign({ id: uuid(), endpoint: '', kubeConfigFilePath: '', kubeClusterContext: '', name: '', namespace: '', username: '', rememberPassword: false, resources: [], resourceGroup: '', connectionMode: '', location: '', customLocation: '' }, info);
// super(treeDataProvider!, _info);
// }
}
// }

View File

@@ -10,10 +10,10 @@ import * as vscode from 'vscode';
import { Deferred } from '../../../common/promise';
import { FilePicker } from '../../../ui/components/filePicker';
import { createModelViewMock } from '@microsoft/azdata-test/out/mocks/azdata/modelView';
import { StubButton } from '@microsoft/azdata-test/out/stubs/modelView/stubButton';
import { StubButton } from '@microsoft/azdata-test/out/stubs/azdata/modelView';
let filePicker: FilePicker;
const initialPath = path.join('path', 'to', '.kube','config');
const initialPath = path.join('path', 'to', '.kube', 'config');
const newFileUri = vscode.Uri.file(path.join('path', 'to', 'new', '.kube', 'config'));
describe('filePicker', function (): void {
beforeEach(async () => {

View File

@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
import * as should from 'should';
import { RadioOptionsGroup, RadioOptionsInfo } from '../../../ui/components/radioOptionsGroup';
import { createModelViewMock } from '@microsoft/azdata-test/out/mocks/azdata/modelView';
import { StubRadioButton } from '@microsoft/azdata-test/out/stubs/modelView/stubRadioButton';
import { StubRadioButton } from '@microsoft/azdata-test/out/stubs/azdata/modelView';
import * as loc from '../../../localizedConstants';

View File

@@ -1,66 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
import { ControllerModel } from '../../../models/controllerModel';
export class PostgresDiagnoseAndSolveProblemsPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _context: vscode.ExtensionContext, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
}
protected get title(): string {
return loc.diagnoseAndSolveProblems;
}
protected get id(): string {
return 'postgres-diagnose-and-solve-problems';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.wrench;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.diagnoseAndSolveProblems,
CSSStyles: { ...cssStyles.title, 'margin-bottom': '20px' }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.clickTheTroubleshootButton('Postgres'),
CSSStyles: { ...cssStyles.text, 'margin-bottom': '20px' }
}).component());
const troubleshootButton = this.modelView.modelBuilder.button().withProps({
iconPath: IconPathHelper.wrench,
label: loc.troubleshoot,
width: '160px'
}).component();
this.disposables.push(
troubleshootButton.onDidClick(() => {
process.env['POSTGRES_SERVER_NAMESPACE'] = this._controllerModel.controllerConfig?.metadata.namespace ?? '';
process.env['POSTGRES_SERVER_NAME'] = this._postgresModel.info.name;
vscode.commands.executeCommand('bookTreeView.openBook', this._context.asAbsolutePath('notebooks/arcDataServices'), true, 'postgres/tsg100-troubleshoot-postgres');
}));
content.addItem(troubleshootButton);
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
return this.modelView.modelBuilder.toolbarContainer().component();
}
}

View File

@@ -1,119 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { KeyValueContainer, KeyValue, InputKeyValue, TextKeyValue, LinkKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
import { ControllerDashboard } from '../controller/controllerDashboard';
export class PostgresPropertiesPage extends DashboardPage {
private loading?: azdata.LoadingComponent;
private keyValueContainer?: KeyValueContainer;
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(this._postgresModel.onConfigUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleServiceUpdated())));
this.disposables.push(this._controllerModel.onRegistrationsUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleRegistrationsUpdated())));
}
protected get title(): string {
return loc.properties;
}
protected get id(): string {
return 'postgres-properties';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.properties;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.properties,
CSSStyles: { ...cssStyles.title, 'margin-bottom': '25px' }
}).component());
this.keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, this.getProperties());
this.keyValueContainer.container.updateCssStyles({ 'max-width': '750px' });
this.disposables.push(this.keyValueContainer);
this.loading = this.modelView.modelBuilder.loadingComponent()
.withItem(this.keyValueContainer.container)
.withProps({
loading: !this._postgresModel.configLastUpdated && !this._controllerModel.registrationsLastUpdated
}).component();
content.addItem(this.loading);
this.initialized = true;
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
this.loading!.loading = true;
await Promise.all([
this._postgresModel.refresh(),
this._controllerModel.refresh(false, this._controllerModel.info.namespace)
]);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private getProperties(): KeyValue[] {
const endpoint = this._postgresModel.endpoint;
const status = this._postgresModel.config?.status;
const controllerDashboard = new ControllerDashboard(this._controllerModel);
return [
new InputKeyValue(this.modelView.modelBuilder, loc.coordinatorEndpoint, endpoint ? `postgresql://postgres@${endpoint.ip}:${endpoint.port}` : ''),
new InputKeyValue(this.modelView.modelBuilder, loc.postgresAdminUsername, 'postgres'),
new InputKeyValue(this.modelView.modelBuilder, loc.subscriptionId, this._controllerModel.controllerConfig?.spec.settings.azure.subscription ?? ''),
new TextKeyValue(this.modelView.modelBuilder, loc.resourceGroup, this._controllerModel.controllerConfig?.spec.settings.azure.resourceGroup ?? ''),
new LinkKeyValue(this.modelView.modelBuilder, loc.dataController, this._controllerModel.controllerConfig?.metadata.name ?? '', () => controllerDashboard.showDashboard()),
new TextKeyValue(this.modelView.modelBuilder, loc.status, status ? `${status.state} (${status.readyPods} ${loc.podsReady})` : loc.unknown)
];
}
private handleRegistrationsUpdated() {
this.keyValueContainer?.refresh(this.getProperties());
this.loading!.loading = false;
}
private handleServiceUpdated() {
this.keyValueContainer?.refresh(this.getProperties());
this.loading!.loading = false;
}
}

View File

@@ -1,348 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, iconSize } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
export type PodHealthModel = {
condition: string,
details: azdata.Component,
lastUpdate: string
};
export enum PodConditionType {
initialized = 'Initialized',
ready = 'Ready',
containersReady = 'ContainersReady',
podScheduled = 'PodScheduled'
}
export class PostgresResourceHealthPage extends DashboardPage {
private podSummaryContainer!: azdata.DivContainer;
private podConditionsContainer!: azdata.DivContainer;
private podConditionsLoading!: azdata.LoadingComponent;
private podConditionsTable!: azdata.DeclarativeTableComponent;
private podConditionsTableIndexes: Map<string, number[]> = new Map();
private podDropDown!: azdata.DropDownComponent;
private coordinatorPodName!: string;
private coordinatorData: PodHealthModel[] = [];
private podsData: PodHealthModel[] = [];
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(
this._postgresModel.onConfigUpdated(() => this.eventuallyRunOnInitialized(() => this.handleConfigUpdated())));
}
protected get title(): string {
return loc.resourceHealth;
}
protected get id(): string {
return 'postgres-resource-health';
}
protected get icon(): { dark: string; light: string; } {
return IconPathHelper.health;
}
protected get container(): azdata.Component {
const root = this.modelView.modelBuilder.divContainer().component();
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '10px 20px 0px 20px' } });
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.resourceHealth,
CSSStyles: { ...cssStyles.title }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.resourceHealthDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component());
this.podSummaryContainer = this.modelView.modelBuilder.divContainer().component();
this.refreshPodSummarySection();
content.addItem(this.podSummaryContainer);
// Pod Conditions
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.podsPresent,
CSSStyles: { ...cssStyles.title }
}).component());
content.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.podsUsedDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'margin-top': '10px' }
}).component());
this.podConditionsContainer = this.modelView.modelBuilder.divContainer().component();
this.podConditionsTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
ariaLabel: loc.podConditionsTable,
columns: [
{
displayName: loc.condition,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '20%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.details,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '50%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: {
...cssStyles.tableRow,
'min-width': '150px'
}
},
{
displayName: loc.lastTransition,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
}
],
dataValues: this.createPodConditionsDataValues(this.coordinatorData)
}).component();
this.podDropDown = this.modelView.modelBuilder.dropDown().withProps({
width: '150px',
ariaLabel: loc.podsUsedDescriptionAria
}).component();
this.disposables.push(
this.podDropDown.onValueChanged(() => {
this.podConditionsTable.setFilter(this.podConditionsTableIndexes.get(String(this.podDropDown.value)));
})
);
this.podConditionsContainer.addItem(this.podDropDown, { CSSStyles: { 'margin': '10px 0px 10px 0px' } });
this.podConditionsContainer.addItem(this.podConditionsTable);
this.podConditionsLoading = this.modelView.modelBuilder.loadingComponent()
.withItem(this.podConditionsContainer)
.withProps({
loading: !this._postgresModel.configLastUpdated
}).component();
this.refreshPodConditions();
content.addItem(this.podConditionsLoading, { CSSStyles: cssStyles.text });
this.initialized = true;
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
this.podConditionsLoading!.loading = true;
await this._postgresModel.refresh();
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private createPodList(): string[] {
const podStatus = this._postgresModel.config?.status.podsStatus;
let podNames: string[] = [];
podStatus?.forEach(p => {
let podHealthModels: PodHealthModel[] = [];
let indexes: number[] = [];
p.conditions.forEach(c => {
let message: string;
let imageComponent = this.modelView.modelBuilder.image().withProps({
width: iconSize,
height: iconSize,
iconHeight: '15px',
iconWidth: '15px'
}).component();
if (c.status === 'False') {
imageComponent.iconPath = IconPathHelper.fail;
message = c.message ?? c.reason ?? '';
} else {
imageComponent.iconPath = IconPathHelper.success;
if (c.type === PodConditionType.initialized) {
message = loc.podInitialized;
} else if (c.type === PodConditionType.ready) {
message = loc.podReady;
} else if (c.type === PodConditionType.containersReady) {
message = loc.containerReady;
} else if (c.type === PodConditionType.podScheduled) {
message = loc.podScheduled;
} else {
message = c.message ?? c.reason ?? '';
}
}
const conditionContainer = this.modelView.modelBuilder.flexContainer().withProps({
CSSStyles: { 'alignItems': 'center', 'height': '15px' }
}).component();
conditionContainer.addItem(imageComponent, { CSSStyles: { 'margin-right': '0px' } });
conditionContainer.addItem(this.modelView.modelBuilder.text().withProps({
value: message,
}).component());
indexes.push(this.podsData.length);
this.podsData.push({
condition: c.type,
details: conditionContainer,
lastUpdate: c.lastTransitionTime
});
});
if (p.role.toUpperCase() !== loc.coordinator.toUpperCase()) {
podNames.push(p.name);
} else {
this.coordinatorData = podHealthModels;
this.coordinatorPodName = p.name;
podNames.unshift(p.name);
}
this.podConditionsTableIndexes.set(p.name, indexes);
});
this.podConditionsTable.setDataValues(this.createPodConditionsDataValues(this.podsData));
return podNames;
}
private createPodConditionsDataValues(podInfo: PodHealthModel[]): azdata.DeclarativeTableCellValue[][] {
let podDataValues: (string | azdata.Component)[][] = podInfo.map(p => [p.condition, p.details, p.lastUpdate]);
return podDataValues.map(p => {
return p.map((value): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
}
private findPodIssues(): string[] {
const podStatus = this._postgresModel.config?.status.podsStatus;
let issueCount = 0;
let podIssuesDetected: string[] = [];
podStatus?.forEach(p => {
p.conditions.forEach(c => {
if (c.status === 'False') {
issueCount++;
}
});
if (issueCount > 0) {
podIssuesDetected.push(loc.numberOfIssuesDetected(p.name, issueCount));
issueCount = 0;
}
});
return podIssuesDetected;
}
private refreshPodSummarySection(): void {
let podSummaryTitle = this.modelView.modelBuilder.flexContainer().withProps({
CSSStyles: { 'alignItems': 'center', 'height': '15px', 'margin-top': '20px' }
}).component();
if (!this._postgresModel.config) {
podSummaryTitle.addItem(this.modelView.modelBuilder.loadingComponent().component(), { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.loading,
CSSStyles: { ...cssStyles.title }
}).component());
this.podSummaryContainer.addItem(podSummaryTitle);
} else {
let components: azdata.Component[] = [];
let imageComponent = this.modelView.modelBuilder.image().withProps({
iconPath: IconPathHelper.success,
width: iconSize,
height: iconSize,
iconHeight: '20px',
iconWidth: '20px'
}).component();
let podIssues = this.findPodIssues();
if (podIssues.length === 0) {
imageComponent.iconPath = IconPathHelper.success;
podSummaryTitle.addItem(imageComponent, { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.available,
CSSStyles: { ...cssStyles.title, 'margin-left': '0px' }
}).component());
components.push(podSummaryTitle);
components.push(this.modelView.modelBuilder.text().withProps({
value: loc.noPodIssuesDetected,
CSSStyles: { ...cssStyles.text, 'margin-top': '20px' }
}).component());
} else {
imageComponent.iconPath = IconPathHelper.fail;
podSummaryTitle.addItem(imageComponent, { CSSStyles: { 'margin-right': '5px' } });
podSummaryTitle.addItem(this.modelView.modelBuilder.text().withProps({
value: loc.issuesDetected,
CSSStyles: { ...cssStyles.title }
}).component());
components.push(podSummaryTitle);
components.push(this.modelView.modelBuilder.text().withProps({
value: loc.podIssuesDetected,
CSSStyles: { ...cssStyles.text, 'margin-top': '20px 0px 10px 0px' }
}).component());
components.push(...podIssues.map(i => {
return this.modelView.modelBuilder.text().withProps({
value: i,
CSSStyles: { ...cssStyles.text, 'margin': '0px' }
}).component();
}));
}
this.podSummaryContainer.addItems(components);
}
}
private refreshPodConditions(): void {
if (this._postgresModel.config) {
this.podConditionsTableIndexes = new Map();
this.podsData = [];
this.podDropDown.values = this.createPodList();
this.podConditionsTable.setFilter(this.podConditionsTableIndexes.get(this.coordinatorPodName!));
this.podConditionsLoading.loading = false;
}
}
private handleConfigUpdated() {
this.podSummaryContainer.clearItems();
this.refreshPodSummarySection();
this.refreshPodConditions();
}
}

View File

@@ -1,99 +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 azdata from 'azdata';
import { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { PostgresModel } from '../../models/postgresModel';
export const validExtensions = ['citus', 'pgaudit', 'pgautofailover', 'pg_cron', 'pg_partman', 'plv8', 'postgis', 'postgis_raster', 'postgis_sfcgal', 'postgis_tiger_geocoder', 'tdigest'];
export class AddPGExtensionsDialog extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
protected extensionsListInputBox!: azdata.InputBoxComponent;
protected _completionPromise = new Deferred<string | undefined>();
constructor(protected _model: PostgresModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle);
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const info = this.modelBuilder.text().withProps({
value: loc.extensionsAddFunction(validExtensions.join(', ')),
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const link = this.modelBuilder.hyperlink().withProps({
label: loc.extensionsLearnMore,
url: 'https://docs.microsoft.com/azure/azure-arc/data/using-extensions-in-postgresql-hyperscale-server-group',
}).component();
const infoAndLink = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
infoAndLink.addItem(info, { CSSStyles: { 'margin-right': '5px' } });
infoAndLink.addItem(link);
this.extensionsListInputBox = this.modelBuilder.inputBox()
.withProps({
value: '',
ariaLabel: loc.extensionsAddList,
enabled: true,
validationErrorMessage: loc.extensionsAddErrorrMessage(validExtensions.join(','))
}).withValidation((component) => {
if (!component.value) {
return true;
}
let newExtensions = component.value.split(',');
return newExtensions.every(e => validExtensions.includes(e));
}).component();
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: infoAndLink
},
{
component: this.extensionsListInputBox,
title: loc.extensionsAddList,
required: true
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.extensionsListInputBox.focus();
this.initialized = true;
});
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.label = loc.loadExtensions;
dialog.cancelButton.label = loc.cancel;
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
this._completionPromise.resolve(this.extensionsListInputBox.value);
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<string | undefined> {
return this._completionPromise.promise;
}
}

View File

@@ -182,13 +182,13 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -245,6 +245,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/mocha@^7.0.2":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
@@ -277,12 +282,12 @@
resolved "https://registry.yarnpkg.com/@types/yamljs/-/yamljs-0.2.31.tgz#b1a620b115c96db7b3bfdf0cf54aee0c57139245"
integrity sha512-QcJ5ZczaXAqbVD3o8mw/mEBhRvO5UAdTtbvgwL/OgoWubvNBh6/MxLBAigtcgIFaq3shon9m3POIxQaLQt4fxQ==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -448,13 +453,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -462,6 +460,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -556,18 +561,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
dependencies:
es6-promise "^4.0.3"
escape-string-regexp@1.0.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"
@@ -748,21 +741,22 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1120,7 +1114,7 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@^2.1.1:
ms@2.1.2, 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==

View File

@@ -107,7 +107,7 @@
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1",
"@microsoft/azdata-test": "^2.0.3"
"@microsoft/azdata-test": "^3.0.1"
},
"__metadata": {
"id": "84",

View File

@@ -1,15 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
interface PlatformReleaseInfo {
version: string; // "20.0.1"
link?: string; // "https://aka.ms/az-msi"
}
export interface AzReleaseInfo {
win32: PlatformReleaseInfo,
darwin: PlatformReleaseInfo,
linux: PlatformReleaseInfo
}

View File

@@ -9,12 +9,12 @@
* @param promise The promise to verify was rejected
* @param message The message to include in the error if the promise isn't rejected
*/
export async function assertRejected(promise: Promise<any>, message: string): Promise<void> {
try {
await promise;
} catch {
return;
}
throw new Error(message);
}
// export async function assertRejected(promise: Promise<any>, message: string): Promise<void> {
// try {
// await promise;
// } catch {
// return;
// }
// throw new Error(message);
// }

View File

@@ -181,13 +181,13 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -244,6 +244,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/caseless@*":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
@@ -308,12 +313,12 @@
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.3.2.tgz#9c246fc0c93ded311c8512df2891fb41f6227fdf"
integrity sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ajv@^6.5.5:
version "6.12.3"
@@ -547,13 +552,6 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.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==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -561,6 +559,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -668,18 +673,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -928,13 +921,14 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
http-signature@~1.2.0:
version "1.2.0"
@@ -945,13 +939,13 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1366,7 +1360,7 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@^2.1.1:
ms@2.1.2, 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==

View File

@@ -126,7 +126,8 @@
"enumDescriptions": [
"Azure Active Directory Authentication Library",
"Microsoft Authentication Library"
]
],
"deprecationMessage": "Warning: ADAL has been deprecated, and is scheduled to be removed in a future release. Please use MSAL (default option) instead."
}
}
}
@@ -350,12 +351,11 @@
"dependencies": {
"@azure/arm-resourcegraph": "^4.0.0",
"@azure/arm-subscriptions": "^3.0.0",
"@azure/msal-node": "^1.9.0",
"@azure/msal-common": "^11.0.0",
"@azure/msal-node": "^1.16.0",
"@azure/storage-blob": "^12.6.0",
"axios": "^0.27.2",
"crypto": "^1.0.1",
"lockfile": "1.0.4",
"msal": "^1.4.16",
"node-fetch": "^2.6.7",
"qs": "^6.9.1",
"universalify": "^0.1.2",
@@ -363,7 +363,7 @@
"ws": "^7.4.6"
},
"devDependencies": {
"@microsoft/azdata-test": "^2.0.3",
"@microsoft/azdata-test": "^3.0.1",
"@microsoft/vscodetestcover": "^1.2.1",
"@types/keytar": "4.4.0",
"@types/lockfile": "^1.0.2",
@@ -377,8 +377,5 @@
"should": "^13.2.1",
"sinon": "^9.0.2",
"typemoq": "^2.1.0"
},
"resolutions": {
"jsonwebtoken": "9.0.0"
}
}

View File

@@ -18,13 +18,15 @@ import {
import { Deferred } from '../interfaces';
import * as url from 'url';
import * as Constants from '../../constants';
import { SimpleTokenCache } from '../simpleTokenCache';
import { SimpleTokenCache } from '../utils/simpleTokenCache';
import { MemoryDatabase } from '../utils/memoryDatabase';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { Logger } from '../../utils/Logger';
import * as qs from 'qs';
import { AzureAuthError } from './azureAuthError';
import { AccountInfo, AuthenticationResult, InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node';
import { HttpClient } from './httpClient';
import { getProxyEnabledHttpClient } from '../../utils';
const localize = nls.loadMessageBundle();
@@ -38,6 +40,7 @@ export abstract class AzureAuth implements vscode.Disposable {
protected readonly scopesString: string;
protected readonly clientId: string;
protected readonly resources: Resource[];
protected readonly httpClient: HttpClient;
private _authLibrary: string | undefined;
constructor(
@@ -94,6 +97,7 @@ export abstract class AzureAuth implements vscode.Disposable {
this.scopes = [...this.metadata.settings.scopes];
this.scopesString = this.scopes.join(' ');
this.httpClient = getProxyEnabledHttpClient();
}
public async startLogin(): Promise<AzureAccount | azdata.PromptFailedResult> {
@@ -139,11 +143,8 @@ export abstract class AzureAuth implements vscode.Disposable {
if (ex instanceof AzureAuthError) {
if (loginComplete) {
loginComplete.reject(ex);
Logger.error(ex);
} else {
void vscode.window.showErrorMessage(ex.message);
Logger.error(ex.originalMessageAndException);
}
Logger.error(ex.originalMessageAndException);
} else {
const message = ex.errorMessage || ex.message;
if (message) {
@@ -155,10 +156,11 @@ export abstract class AzureAuth implements vscode.Disposable {
};
}
Logger.error(ex);
}
return {
canceled: false
canceled: false,
errorCode: ex.errorCode,
errorMessage: ex.errorMessage || ex.message
};
}
}
@@ -347,13 +349,14 @@ export abstract class AzureAuth implements vscode.Disposable {
}
// construct request
// forceRefresh needs to be set true here in order to fetch the correct token, due to this issue
// forceRefresh needs to be set true here in order to fetch the correct token for non-full tenants, due to this issue
// https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/3687
const tokenRequest = {
account: account,
authority: `${this.loginEndpointUrl}${tenantId}`,
scopes: newScope,
forceRefresh: true
// Force Refresh when tenant is NOT full tenant or organizational id that this account belongs to.
forceRefresh: tenantId !== account.tenantId
};
try {
return await this.clientApplication.acquireTokenSilent(tokenRequest);
@@ -475,8 +478,20 @@ export abstract class AzureAuth implements vscode.Disposable {
try {
Logger.verbose('Fetching tenants with uri {0}', tenantUri);
let tenantList: string[] = [];
const tenantResponse = await this.makeGetRequest(tenantUri, token);
const tenants: Tenant[] = tenantResponse.data.value.map((tenantInfo: TenantResponse) => {
const tenantResponse = await this.httpClient.sendGetRequestAsync<any>(tenantUri, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
});
const data = tenantResponse.body;
if (data.error) {
Logger.error(`Error fetching tenants :${data.error.code} - ${data.error.message}`);
throw new Error(`${data.error.code} - ${data.error.message}`);
}
const tenants: Tenant[] = data.value.map((tenantInfo: TenantResponse) => {
if (tenantInfo.displayName) {
tenantList.push(tenantInfo.displayName);
} else {
@@ -501,7 +516,7 @@ export abstract class AzureAuth implements vscode.Disposable {
return tenants;
} catch (ex) {
Logger.error(`Error fetching tenants :${ex}`);
throw new Error('Error retrieving tenant information');
throw ex;
}
}
@@ -716,8 +731,8 @@ export abstract class AzureAuth implements vscode.Disposable {
accountIssuer = Constants.AccountIssuer.Msft;
}
const name = tokenClaims.name ?? tokenClaims.email ?? tokenClaims.unique_name ?? tokenClaims.preferred_username;
const email = tokenClaims.email ?? tokenClaims.unique_name ?? tokenClaims.preferred_username;
const name = tokenClaims.name ?? tokenClaims.preferred_username ?? tokenClaims.email ?? tokenClaims.unique_name;
const email = tokenClaims.preferred_username ?? tokenClaims.email ?? tokenClaims.unique_name;
let owningTenant: Tenant = this.commonTenant; // default to common tenant

View File

@@ -8,7 +8,7 @@ import { AzureAccountProviderMetadata, AzureAuthType, Resource, Tenant } from 'a
import { Deferred } from '../interfaces';
import * as vscode from 'vscode';
import * as crypto from 'crypto';
import { SimpleTokenCache } from '../simpleTokenCache';
import { SimpleTokenCache } from '../utils/simpleTokenCache';
import { SimpleWebServer } from '../utils/simpleWebServer';
import { AzureAuthError } from './azureAuthError';
import { Logger } from '../../utils/Logger';

View File

@@ -21,7 +21,7 @@ import {
} from 'azurecore';
import { Deferred } from '../interfaces';
import { AuthenticationResult, DeviceCodeRequest, PublicClientApplication } from '@azure/msal-node';
import { SimpleTokenCache } from '../simpleTokenCache';
import { SimpleTokenCache } from '../utils/simpleTokenCache';
import { Logger } from '../../utils/Logger';
const localize = nls.loadMessageBundle();

View File

@@ -0,0 +1,370 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { INetworkModule, NetworkRequestOptions, NetworkResponse } from '@azure/msal-common';
import * as http from 'http';
import * as https from 'https';
import { NetworkUtils } from './networkUtils';
/**
* http methods
*/
export enum HttpMethod {
GET = 'get',
POST = 'post'
}
export enum HttpStatus {
SUCCESS_RANGE_START = 200,
SUCCESS_RANGE_END = 299,
REDIRECT = 302,
CLIENT_ERROR_RANGE_START = 400,
CLIENT_ERROR_RANGE_END = 499,
SERVER_ERROR_RANGE_START = 500,
SERVER_ERROR_RANGE_END = 599
}
export enum ProxyStatus {
SUCCESS_RANGE_START = 200,
SUCCESS_RANGE_END = 299,
SERVER_ERROR = 500
}
/**
* This class implements the API for network requests.
*/
export class HttpClient implements INetworkModule {
private proxyUrl: string;
private customAgentOptions: http.AgentOptions | https.AgentOptions;
static readonly AUTHORIZATION_PENDING: string = 'authorization_pending';
constructor(
proxyUrl?: string,
customAgentOptions?: http.AgentOptions | https.AgentOptions
) {
this.proxyUrl = proxyUrl || '';
this.customAgentOptions = customAgentOptions || {};
}
/**
* Http Get request
* @param url
* @param options
*/
async sendGetRequestAsync<T>(
url: string,
options?: NetworkRequestOptions
): Promise<NetworkResponse<T>> {
if (this.proxyUrl) {
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.GET, options, this.customAgentOptions as http.AgentOptions);
} else {
return networkRequestViaHttps(url, HttpMethod.GET, options, this.customAgentOptions as https.AgentOptions);
}
}
/**
* Http Post request
* @param url
* @param options
*/
async sendPostRequestAsync<T>(
url: string,
options?: NetworkRequestOptions,
cancellationToken?: number
): Promise<NetworkResponse<T>> {
if (this.proxyUrl) {
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.POST, options, this.customAgentOptions as http.AgentOptions, cancellationToken);
} else {
return networkRequestViaHttps(url, HttpMethod.POST, options, this.customAgentOptions as https.AgentOptions, cancellationToken);
}
}
}
const networkRequestViaProxy = <T>(
destinationUrlString: string,
proxyUrlString: string,
httpMethod: string,
options?: NetworkRequestOptions,
agentOptions?: http.AgentOptions,
timeout?: number
): Promise<NetworkResponse<T>> => {
const destinationUrl = new URL(destinationUrlString);
const proxyUrl = new URL(proxyUrlString);
// 'method: connect' must be used to establish a connection to the proxy
const headers = options?.headers || {} as Record<string, string>;
const tunnelRequestOptions: https.RequestOptions = {
host: proxyUrl.hostname,
port: proxyUrl.port,
method: 'CONNECT',
path: destinationUrl.hostname,
headers: headers
};
if (timeout) {
tunnelRequestOptions.timeout = timeout;
}
if (agentOptions && Object.keys(agentOptions).length) {
tunnelRequestOptions.agent = new http.Agent(agentOptions);
}
// compose a request string for the socket
let postRequestStringContent: string = '';
if (httpMethod === HttpMethod.POST) {
const body = options?.body || '';
postRequestStringContent =
'Content-Type: application/x-www-form-urlencoded\r\n' +
`Content-Length: ${body.length}\r\n` +
`\r\n${body}`;
}
const outgoingRequestString = `${httpMethod.toUpperCase()} ${destinationUrl.href} HTTP/1.1\r\n` +
`Host: ${destinationUrl.host}\r\n` +
'Connection: close\r\n' +
postRequestStringContent +
'\r\n';
return new Promise<NetworkResponse<T>>(((resolve, reject) => {
const request = http.request(tunnelRequestOptions);
if (tunnelRequestOptions.timeout) {
request.on('timeout', () => {
request.destroy();
reject(new Error('Request time out'));
});
}
request.end();
// establish connection to the proxy
request.on('connect', (response, socket) => {
const proxyStatusCode = response?.statusCode || ProxyStatus.SERVER_ERROR;
if ((proxyStatusCode < ProxyStatus.SUCCESS_RANGE_START) || (proxyStatusCode > ProxyStatus.SUCCESS_RANGE_END)) {
request.destroy();
socket.destroy();
reject(new Error(`Error connecting to proxy. Http status code: ${response.statusCode}. Http status message: ${response?.statusMessage || 'Unknown'}`));
}
if (tunnelRequestOptions.timeout) {
socket.setTimeout(tunnelRequestOptions.timeout);
socket.on('timeout', () => {
request.destroy();
socket.destroy();
reject(new Error('Request time out'));
});
}
// make a request over an HTTP tunnel
socket.write(outgoingRequestString);
const data: Buffer[] = [];
socket.on('data', (chunk) => {
data.push(chunk);
});
socket.on('end', () => {
// combine all received buffer streams into one buffer, and then into a string
const dataString = Buffer.concat([...data]).toString();
// separate each line into it's own entry in an arry
const dataStringArray = dataString.split('\r\n');
// the first entry will contain the statusCode and statusMessage
const httpStatusCode = parseInt(dataStringArray[0].split(' ')[1], undefined);
// remove 'HTTP/1.1' and the status code to get the status message
const statusMessage = dataStringArray[0].split(' ').slice(2).join(' ');
// the last entry will contain the body
const body = dataStringArray[dataStringArray.length - 1];
// everything in between the first and last entries are the headers
const headersArray = dataStringArray.slice(1, dataStringArray.length - 2);
// build an object out of all the headers
const entries = new Map();
headersArray.forEach((header) => {
/**
* the header might look like 'Content-Length: 1531', but that is just a string
* it needs to be converted to a key/value pair
* split the string at the first instance of ':'
* there may be more than one ':' if the value of the header is supposed to be a JSON object
*/
const headerKeyValue = header.split(new RegExp(/:\s(.*)/s));
const headerKey = headerKeyValue[0];
let headerValue = headerKeyValue[1];
// check if the value of the header is supposed to be a JSON object
try {
const object = JSON.parse(headerValue);
// if it is, then convert it from a string to a JSON object
if (object && (typeof object === 'object')) {
headerValue = object;
}
} catch (e) {
// otherwise, leave it as a string
}
entries.set(headerKey, headerValue);
});
const parsedHeaders = Object.fromEntries(entries) as Record<string, string>;
const networkResponse = NetworkUtils.getNetworkResponse(
parsedHeaders,
parseBody(httpStatusCode, statusMessage, parsedHeaders, body) as T,
httpStatusCode
);
if (((httpStatusCode < HttpStatus.SUCCESS_RANGE_START) || (httpStatusCode > HttpStatus.SUCCESS_RANGE_END)) &&
// do not destroy the request for the device code flow
// @ts-ignore
networkResponse.body['error'] !== HttpClient.AUTHORIZATION_PENDING) {
request.destroy();
}
resolve(networkResponse);
});
socket.on('error', (chunk) => {
request.destroy();
socket.destroy();
reject(new Error(chunk.toString()));
});
});
request.on('error', (chunk) => {
request.destroy();
reject(new Error(chunk.toString()));
});
}));
};
const networkRequestViaHttps = <T>(
urlString: string,
httpMethod: string,
options?: NetworkRequestOptions,
agentOptions?: https.AgentOptions,
timeout?: number
): Promise<NetworkResponse<T>> => {
const isPostRequest = httpMethod === HttpMethod.POST;
const body: string = options?.body || '';
const url = new URL(urlString);
const optionHeaders = options?.headers || {} as Record<string, string>;
let customOptions: https.RequestOptions = {
method: httpMethod,
headers: optionHeaders,
...NetworkUtils.urlToHttpOptions(url)
};
if (timeout) {
customOptions.timeout = timeout;
}
if (agentOptions && Object.keys(agentOptions).length) {
customOptions.agent = new https.Agent(agentOptions);
}
if (isPostRequest) {
// needed for post request to work
customOptions.headers = {
...customOptions.headers,
'Content-Length': body.length
};
}
return new Promise<NetworkResponse<T>>((resolve, reject) => {
const request = https.request(customOptions);
if (timeout) {
request.on('timeout', () => {
request.destroy();
reject(new Error('Request time out'));
});
}
if (isPostRequest) {
request.write(body);
}
request.end();
request.on('response', (response) => {
const headers = response.headers;
const statusCode = response.statusCode as number;
const statusMessage = response.statusMessage;
const data: Buffer[] = [];
response.on('data', (chunk) => {
data.push(chunk);
});
response.on('end', () => {
// combine all received buffer streams into one buffer, and then into a string
const dataBody = Buffer.concat([...data]).toString();
const parsedHeaders = headers as Record<string, string>;
const networkResponse = NetworkUtils.getNetworkResponse(
parsedHeaders,
parseBody(statusCode, statusMessage, parsedHeaders, dataBody) as T,
statusCode
);
if (((statusCode < HttpStatus.SUCCESS_RANGE_START) || (statusCode > HttpStatus.SUCCESS_RANGE_END)) &&
// do not destroy the request for the device code flow
// @ts-ignore
networkResponse.body['error'] !== HttpClient.AUTHORIZATION_PENDING) {
request.destroy();
}
resolve(networkResponse);
});
});
request.on('error', (chunk) => {
request.destroy();
reject(new Error(chunk.toString()));
});
});
};
/**
* Check if extra parsing is needed on the repsonse from the server
* @param statusCode {number} the status code of the response from the server
* @param statusMessage {string | undefined} the status message of the response from the server
* @param headers {Record<string, string>} the headers of the response from the server
* @param body {string} the body from the response of the server
* @returns JSON parsed body or error object
*/
const parseBody = (statusCode: number, statusMessage: string | undefined, headers: Record<string, string>, body: string) => {
/*
* Informational responses (100 - 199)
* Successful responses (200 - 299)
* Redirection messages (300 - 399)
* Client error responses (400 - 499)
* Server error responses (500 - 599)
*/
let parsedBody;
try {
parsedBody = JSON.parse(body);
} catch (error) {
let errorType;
let errorDescriptionHelper;
if ((statusCode >= HttpStatus.CLIENT_ERROR_RANGE_START) && (statusCode <= HttpStatus.CLIENT_ERROR_RANGE_END)) {
errorType = 'client_error';
errorDescriptionHelper = 'A client';
} else if ((statusCode >= HttpStatus.SERVER_ERROR_RANGE_START) && (statusCode <= HttpStatus.SERVER_ERROR_RANGE_END)) {
errorType = 'server_error';
errorDescriptionHelper = 'A server';
} else {
errorType = 'unknown_error';
errorDescriptionHelper = 'An unknown';
}
parsedBody = {
error: errorType,
error_description: `${errorDescriptionHelper} error occured.\nHttp status code: ${statusCode}\nHttp status message: ${statusMessage || 'Unknown'}\nHeaders: ${JSON.stringify(headers)}`
};
}
return parsedBody;
};

View File

@@ -0,0 +1,43 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NetworkResponse } from '@azure/msal-common';
import * as https from 'https';
export class NetworkUtils {
static getNetworkResponse<Body>(headers: Record<string, string>, body: Body, statusCode: number): NetworkResponse<Body> {
return {
headers: headers,
body: body,
status: statusCode
};
}
/*
* Utility function that converts a URL object into an ordinary options object as expected by the
* http.request and https.request APIs.
*/
static urlToHttpOptions(url: URL): https.RequestOptions {
const options: https.RequestOptions & Partial<Omit<URL, 'port'>> = {
protocol: url.protocol,
hostname: url.hostname && url.hostname.startsWith('[') ?
url.hostname.slice(1, -1) :
url.hostname,
hash: url.hash,
search: url.search,
pathname: url.pathname,
path: `${url.pathname || ''}${url.search || ''}`,
href: url.href
};
if (url.port !== '') {
options.port = Number(url.port);
}
if (url.username || url.password) {
options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`;
}
return options;
}
}

View File

@@ -14,7 +14,7 @@ import {
} from 'azurecore';
import { Deferred } from './interfaces';
import { AuthenticationResult, PublicClientApplication } from '@azure/msal-node';
import { SimpleTokenCache } from './simpleTokenCache';
import { SimpleTokenCache } from './utils/simpleTokenCache';
import { Logger } from '../utils/Logger';
import { MultiTenantTokenResponse, Token, AzureAuth } from './auths/azureAuth';
import { AzureAuthCodeGrant } from './auths/azureAuthCodeGrant';
@@ -105,7 +105,7 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
private async _initialize(storedAccounts: AzureAccount[]): Promise<AzureAccount[]> {
const accounts: AzureAccount[] = [];
console.log(`Initializing stored accounts ${JSON.stringify(accounts)}`);
Logger.verbose(`Initializing stored accounts ${JSON.stringify(accounts)}`);
const updatedAccounts = filterAccounts(storedAccounts, this.authLibrary);
for (let account of updatedAccounts) {
const azureAuth = this.getAuthMethod(account);

View File

@@ -3,14 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import * as azdata from 'azdata';
import * as events from 'events';
import * as nls from 'vscode-nls';
import * as vscode from 'vscode';
import { SimpleTokenCache } from './simpleTokenCache';
import { promises as fsPromises } from 'fs';
import { SimpleTokenCache } from './utils/simpleTokenCache';
import providerSettings from './providerSettings';
import { AzureAccountProvider as AzureAccountProvider } from './azureAccountProvider';
import { AzureAccountProviderMetadata } from 'azurecore';
import { AzureAccountProviderMetadata, CacheEncryptionKeys } from 'azurecore';
import { ProviderSettings } from './interfaces';
import { MsalCachePluginProvider } from './utils/msalCachePlugin';
import * as loc from '../localizedConstants';
@@ -39,10 +41,12 @@ export class AzureAccountProviderService implements vscode.Disposable {
private _event: events.EventEmitter = new events.EventEmitter();
private readonly _uriEventHandler: UriEventHandler = new UriEventHandler();
public clientApplication!: PublicClientApplication;
private _onEncryptionKeysUpdated: vscode.EventEmitter<CacheEncryptionKeys>;
constructor(private _context: vscode.ExtensionContext,
private _userStoragePath: string,
private _authLibrary: string) {
this._onEncryptionKeysUpdated = new vscode.EventEmitter<CacheEncryptionKeys>();
this._disposables.push(vscode.window.registerUriHandler(this._uriEventHandler));
}
@@ -73,6 +77,17 @@ export class AzureAccountProviderService implements vscode.Disposable {
});
}
public getEncryptionKeysEmitter(): vscode.EventEmitter<CacheEncryptionKeys> {
return this._onEncryptionKeysUpdated;
}
public async getEncryptionKeys(): Promise<CacheEncryptionKeys> {
if (!this._cachePluginProvider) {
await this.onDidChangeConfiguration();
}
return this._cachePluginProvider!.getCacheEncryptionKeys();
}
public dispose() {
while (this._disposables.length) {
const item = this._disposables.pop();
@@ -144,8 +159,8 @@ export class AzureAccountProviderService implements vscode.Disposable {
const isSaw: boolean = vscode.env.appName.toLowerCase().indexOf(Constants.Saw) > 0;
const noSystemKeychain = vscode.workspace.getConfiguration(Constants.AzureSection).get<boolean>(Constants.NoSystemKeyChainSection);
const tokenCacheKey = `azureTokenCache-${provider.metadata.id}`;
// Hardcode the MSAL Cache Key so there is only one cache location
const tokenCacheKeyMsal = `azureTokenCacheMsal-azure_publicCloud`;
const tokenCacheKeyMsal = Constants.MSALCacheName;
await this.clearOldCacheIfExists();
try {
if (!this._credentialProvider) {
throw new Error('Credential provider not registered');
@@ -153,10 +168,16 @@ export class AzureAccountProviderService implements vscode.Disposable {
// ADAL Token Cache
let simpleTokenCache = new SimpleTokenCache(tokenCacheKey, this._userStoragePath, noSystemKeychain, this._credentialProvider);
await simpleTokenCache.init();
if (this._authLibrary === Constants.AuthLibrary.ADAL) {
await simpleTokenCache.init();
}
// MSAL Cache Plugin
this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath);
this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath, this._credentialProvider, this._onEncryptionKeysUpdated);
if (this._authLibrary === Constants.AuthLibrary.MSAL) {
// Initialize cache provider and encryption keys
await this._cachePluginProvider.init();
}
const msalConfiguration: Configuration = {
auth: {
@@ -185,6 +206,22 @@ export class AzureAccountProviderService implements vscode.Disposable {
}
}
/**
* Clears old cache file that is no longer needed on system.
*/
private async clearOldCacheIfExists(): Promise<void> {
let filePath = path.join(this._userStoragePath, Constants.oldMsalCacheFileName);
try {
await fsPromises.access(filePath);
await fsPromises.unlink('file:' + filePath);
Logger.verbose(`Old cache file removed successfully.`);
} catch (e) {
if (e.code !== 'ENOENT') {
Logger.verbose(`Error occurred while removing old cache file: ${e}`);
} // else file doesn't exist.
}
}
private getLoggerCallback(): ILoggerCallback {
return (level: number, message: string, containsPii: boolean) => {
if (!containsPii) {

View File

@@ -153,6 +153,11 @@ const usGovAzureSettings: ProviderSettings = {
endpointSuffix: '.core.usgovcloudapi.net/',
azureResourceId: AzureResource.AzureStorage
},
azureKustoResource: {
id: SettingIds.kusto,
endpoint: 'https://kusto.kusto.usgovcloudapi.net',
azureResourceId: AzureResource.AzureKusto,
},
powerBiResource: {
id: SettingIds.powerbi,
endpoint: 'https://analysis.windows.net/powerbi/api/',
@@ -217,6 +222,11 @@ const chinaAzureSettings: ProviderSettings = {
endpointSuffix: '.core.chinacloudapi.cn',
azureResourceId: AzureResource.AzureStorage
},
azureKustoResource: {
id: SettingIds.kusto,
endpoint: 'https://kusto.kusto.chinacloudapi.cn',
azureResourceId: AzureResource.AzureKusto,
},
powerBiResource: {
id: SettingIds.powerbi,
endpoint: 'https://analysis.windows.net/powerbi/api',

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { promises as fs, constants as fsConstants } from 'fs';
import { Logger } from '../../utils/Logger';
export type ReadWriteHook = (contents: string) => Promise<string>;
const noOpHook: ReadWriteHook = async (contents): Promise<string> => {
@@ -97,7 +98,7 @@ export class FileDatabase {
fileContents = await fs.readFile(this.dbPath, { encoding: 'utf8' });
fileContents = await this.readHook(fileContents);
} catch (ex) {
console.log(`file db does not exist ${ex}`);
Logger.error(`Error occurred when initializing File Database from file system cache, ADAL cache will be reset: ${ex}`);
await this.createFile();
this.db = {};
this.isDirty = true;
@@ -107,7 +108,7 @@ export class FileDatabase {
try {
this.db = JSON.parse(fileContents);
} catch (ex) {
console.log(`DB was corrupted, resetting it ${ex}`);
Logger.error(`Error occurred when reading file database contents as JSON, ADAL cache will be reset: ${ex}`);
await this.createFile();
this.db = {};
}
@@ -139,7 +140,7 @@ export class FileDatabase {
this.isDirty = false;
} catch (ex) {
console.log(`File saving is erroring! ${ex}`);
Logger.error(`Error occurred while saving cache contents to file storage, this may cause issues with ADAL cache persistence: ${ex}`);
} finally {
this.isSaving = false;
}

View File

@@ -3,32 +3,68 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as os from 'os';
import * as crypto from 'crypto';
import * as vscode from 'vscode';
import { AuthLibrary } from '../../constants';
import * as LocalizedConstants from '../../localizedConstants';
import { Logger } from '../../utils/Logger';
import { CacheEncryptionKeys } from 'azurecore';
export class FileEncryptionHelper {
constructor(
private _credentialService: azdata.CredentialProvider,
private _fileName: string,
) { }
private readonly _authLibrary: AuthLibrary,
private readonly _credentialService: azdata.CredentialProvider,
protected readonly _fileName: string,
private readonly _onEncryptionKeysUpdated?: vscode.EventEmitter<CacheEncryptionKeys>
) {
this._algorithm = this._authLibrary === AuthLibrary.MSAL ? 'aes-256-cbc' : 'aes-256-gcm';
this._bufferEncoding = this._authLibrary === AuthLibrary.MSAL ? 'utf16le' : 'hex';
this._binaryEncoding = this._authLibrary === AuthLibrary.MSAL ? 'base64' : 'hex';
}
private _algorithm: string;
private _bufferEncoding: BufferEncoding;
private _binaryEncoding: crypto.HexBase64BinaryEncoding;
private _ivBuffer: Buffer | undefined;
private _keyBuffer: Buffer | undefined;
async init(): Promise<void> {
const iv = await this._credentialService.readCredential(`${this._fileName}-iv`);
const key = await this._credentialService.readCredential(`${this._fileName}-key`);
if (!iv?.password || !key?.password) {
public async init(): Promise<void> {
const ivCredId = `${this._fileName}-iv`;
const keyCredId = `${this._fileName}-key`;
const iv = await this.readEncryptionKey(ivCredId);
const key = await this.readEncryptionKey(keyCredId);
if (!iv || !key) {
this._ivBuffer = crypto.randomBytes(16);
this._keyBuffer = crypto.randomBytes(32);
try {
await this._credentialService.saveCredential(`${this._fileName}-iv`, this._ivBuffer.toString('hex'));
await this._credentialService.saveCredential(`${this._fileName}-key`, this._keyBuffer.toString('hex'));
} catch (ex) {
console.log(ex);
if (!await this.saveEncryptionKey(ivCredId, this._ivBuffer.toString(this._bufferEncoding))
|| !await this.saveEncryptionKey(keyCredId, this._keyBuffer.toString(this._bufferEncoding))) {
Logger.error(`Encryption keys could not be saved in credential store, this will cause access token persistence issues.`);
await this.showCredSaveErrorOnWindows();
}
} else {
this._ivBuffer = Buffer.from(iv.password, 'hex');
this._keyBuffer = Buffer.from(key.password, 'hex');
this._ivBuffer = Buffer.from(iv, this._bufferEncoding);
this._keyBuffer = Buffer.from(key, this._bufferEncoding);
}
// Emit event with cache encryption keys to send notification to provider services.
if (this._authLibrary === AuthLibrary.MSAL && this._onEncryptionKeysUpdated) {
this._onEncryptionKeysUpdated.fire(this.getEncryptionKeys());
Logger.verbose('FileEncryptionHelper: Fired encryption keys updated event.');
}
}
/**
* Provides encryption keys in use for instant access.
*/
public getEncryptionKeys(): CacheEncryptionKeys {
return {
iv: this._ivBuffer!.toString(this._bufferEncoding),
key: this._keyBuffer!.toString(this._bufferEncoding)
}
}
@@ -36,21 +72,68 @@ export class FileEncryptionHelper {
if (!this._keyBuffer || !this._ivBuffer) {
await this.init();
}
const cipherIv = crypto.createCipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!);
return `${cipherIv.update(content, 'utf8', 'hex')}${cipherIv.final('hex')}%${cipherIv.getAuthTag().toString('hex')}`;
};
const cipherIv = crypto.createCipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!);
let cipherText = `${cipherIv.update(content, 'utf8', this._binaryEncoding)}${cipherIv.final(this._binaryEncoding)}`;
if (this._authLibrary === AuthLibrary.ADAL) {
cipherText += `%${(cipherIv as crypto.CipherGCM).getAuthTag().toString(this._binaryEncoding)}`;
}
return cipherText;
}
fileOpener = async (content: string): Promise<string> => {
if (!this._keyBuffer || !this._ivBuffer) {
await this.init();
}
const decipherIv = crypto.createDecipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!);
const split = content.split('%');
if (split.length !== 2) {
throw new Error('File didn\'t contain the auth tag.');
let plaintext = content;
const decipherIv = crypto.createDecipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!);
if (this._authLibrary === AuthLibrary.ADAL) {
const split = content.split('%');
if (split.length !== 2) {
throw new Error('File didn\'t contain the auth tag.');
}
(decipherIv as crypto.DecipherGCM).setAuthTag(Buffer.from(split[1], this._binaryEncoding));
plaintext = split[0];
}
decipherIv.setAuthTag(Buffer.from(split[1], 'hex'));
return `${decipherIv.update(split[0], 'hex', 'utf8')}${decipherIv.final('utf8')}`;
};
return `${decipherIv.update(plaintext, this._binaryEncoding, 'utf8')}${decipherIv.final('utf8')}`;
}
protected async readEncryptionKey(credentialId: string): Promise<string | undefined> {
return (await this._credentialService.readCredential(credentialId))?.password;
}
protected async saveEncryptionKey(credentialId: string, password: string): Promise<boolean> {
let status: boolean = false;
try {
await this._credentialService.saveCredential(credentialId, password)
.then((result) => {
status = result;
if (result) {
Logger.info(`FileEncryptionHelper: Successfully saved encryption key ${credentialId} for ${this._authLibrary} persistent cache encryption in system credential store.`);
}
}, (e => {
throw Error(`FileEncryptionHelper: Could not save encryption key: ${credentialId}: ${e}`);
}));
} catch (ex) {
if (os.platform() === 'win32') {
Logger.error(`FileEncryptionHelper: Please try cleaning saved credentials from Windows Credential Manager created by Azure Data Studio to allow creating new credentials.`);
}
Logger.error(ex);
throw ex;
}
return status;
}
protected async showCredSaveErrorOnWindows(): Promise<void> {
if (os.platform() === 'win32') {
await vscode.window.showWarningMessage(LocalizedConstants.azureCredStoreSaveFailedError,
LocalizedConstants.reloadChoice, LocalizedConstants.cancel)
.then(async (selection) => {
if (selection === LocalizedConstants.reloadChoice) {
await vscode.commands.executeCommand('workbench.action.reloadWindow');
}
}, error => {
Logger.error(error);
});
}
}
}

View File

@@ -8,33 +8,48 @@ import { promises as fsPromises } from 'fs';
import * as lockFile from 'lockfile';
import * as path from 'path';
import { AccountsClearTokenCacheCommand } from '../../constants';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { AccountsClearTokenCacheCommand, AuthLibrary } from '../../constants';
import { Logger } from '../../utils/Logger';
import { FileEncryptionHelper } from './fileEncryptionHelper';
import { CacheEncryptionKeys } from 'azurecore';
export class MsalCachePluginProvider {
constructor(
private readonly _serviceName: string,
private readonly _msalFilePath: string,
private readonly _credentialService: azdata.CredentialProvider,
private readonly _onEncryptionKeysUpdated: vscode.EventEmitter<CacheEncryptionKeys>
) {
this._msalFilePath = path.join(this._msalFilePath, this._serviceName);
this._serviceName = this._serviceName.replace(/-/, '_');
Logger.verbose(`MsalCachePluginProvider: Using cache path ${_msalFilePath} and serviceName ${_serviceName}`);
this._fileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.MSAL, this._credentialService, this._serviceName, this._onEncryptionKeysUpdated);
}
private _lockTaken: boolean = false;
private _fileEncryptionHelper: FileEncryptionHelper;
private getLockfilePath(): string {
return this._msalFilePath + '.lockfile';
}
public async init(): Promise<void> {
await this._fileEncryptionHelper.init();
}
public getCacheEncryptionKeys(): CacheEncryptionKeys {
return this._fileEncryptionHelper.getEncryptionKeys();
}
public getCachePlugin(): ICachePlugin {
const lockFilePath = this.getLockfilePath();
const beforeCacheAccess = async (cacheContext: TokenCacheContext): Promise<void> => {
await this.waitAndLock(lockFilePath);
try {
const cache = await fsPromises.readFile(this._msalFilePath, { encoding: 'utf8' });
const decryptedData = await this._fileEncryptionHelper.fileOpener(cache!);
try {
cacheContext.tokenCache.deserialize(cache);
cacheContext.tokenCache.deserialize(decryptedData);
} catch (e) {
// Handle deserialization error in cache file in case file gets corrupted.
// Clearing cache here will ensure account is marked stale so re-authentication can be triggered.
@@ -49,7 +64,8 @@ export class MsalCachePluginProvider {
}
else {
Logger.error(`MsalCachePlugin: Failed to read from cache file: ${e}`);
throw e;
Logger.verbose(`MsalCachePlugin: Error occurred when trying to read cache file, file contents will be cleared: ${e.message}`);
await fsPromises.writeFile(this._msalFilePath, '', { encoding: 'utf8' });
}
} finally {
lockFile.unlockSync(lockFilePath);
@@ -62,7 +78,8 @@ export class MsalCachePluginProvider {
await this.waitAndLock(lockFilePath);
try {
const data = cacheContext.tokenCache.serialize();
await fsPromises.writeFile(this._msalFilePath, data, { encoding: 'utf8' });
const encryptedData = await this._fileEncryptionHelper.fileSaver(data!);
await fsPromises.writeFile(this._msalFilePath, encryptedData, { encoding: 'utf8' });
Logger.verbose(`MsalCachePlugin: Token written to cache successfully.`);
} catch (e) {
Logger.error(`MsalCachePlugin: Failed to write to cache file. ${e}`);

View File

@@ -4,9 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import * as keytarType from 'keytar';
import { join, parse } from 'path';
import { FileDatabase } from './utils/fileDatabase';
import { FileDatabase } from './fileDatabase';
import * as azdata from 'azdata';
import { FileEncryptionHelper } from './utils/fileEncryptionHelper';
import { FileEncryptionHelper } from './fileEncryptionHelper';
import { AuthLibrary } from '../../constants';
function getSystemKeytar(): Keytar | undefined {
try {
@@ -25,7 +26,7 @@ const separator = '§';
async function getFileKeytar(filePath: string, credentialService: azdata.CredentialProvider): Promise<Keytar | undefined> {
const fileName = parse(filePath).base;
const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(credentialService, fileName);
const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.ADAL, credentialService, fileName);
const db = new FileDatabase(filePath, fileEncryptionHelper.fileOpener, fileEncryptionHelper.fileSaver);
await db.initialize();

View File

@@ -5,6 +5,7 @@
import * as http from 'http';
import * as url from 'url';
import { AddressInfo } from 'net';
import { Logger } from '../../utils/Logger';
export type WebHandler = (req: http.IncomingMessage, reqUrl: url.UrlWithParsedQuery, res: http.ServerResponse) => void;
@@ -24,7 +25,7 @@ export class SimpleWebServer {
const time = new Date().getTime();
if (time - this.lastUsed > this.autoShutoffTimer) {
console.log('Shutting off webserver...');
Logger.verbose('Shutting off webserver...');
this.shutdown().catch(console.error);
}
}, 1000);

View File

@@ -12,6 +12,7 @@ import * as azureResourceUtils from './azureResource/utils';
import * as constants from './constants';
import * as loc from './localizedConstants';
import * as utils from './utils';
import { Logger } from './utils/Logger';
const typesClause = [
azureResource.AzureResourceType.sqlDatabase,
@@ -60,10 +61,10 @@ export class AzureDataGridProvider implements azdata.DataGridProvider {
});
items.push(...newItems);
} catch (err) {
console.log(err);
Logger.error(err);
}
} catch (err) {
console.log(err);
Logger.error(err);
}
}));
}));

View File

@@ -41,6 +41,7 @@ export class AzureResourceMessageTreeNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: AzureResourceItemType.message,
nodeSubType: undefined,

View File

@@ -10,6 +10,7 @@ import { IAzureResourceService } from '../interfaces';
import { AzureResourceErrorMessageUtil } from '../utils';
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
import { AzureAccount, azureResource } from 'azurecore';
import { Logger } from '../../utils/Logger';
export abstract class ResourceTreeDataProviderBase<T extends azureResource.AzureResource> implements azureResource.IAzureResourceTreeDataProvider {
public browseConnectionMode: boolean = false;
@@ -32,7 +33,7 @@ export abstract class ResourceTreeDataProviderBase<T extends azureResource.Azure
treeItem: this.getTreeItemForResource(resource, element.account)
}).sort((a, b) => (<any>a.treeItem.label).localeCompare(b.treeItem.label));
} catch (error) {
console.log(AzureResourceErrorMessageUtil.getErrorMessage(error));
Logger.error(AzureResourceErrorMessageUtil.getErrorMessage(error));
throw error;
}
}
@@ -102,7 +103,7 @@ export async function queryGraphResources<T extends GraphData>(resourceClient: R
}
} catch (err2) {
// Just log, we still want to throw the original error if something happens parsing the error
console.log(`Unexpected error while parsing error from querying resources : ${err2}`);
Logger.error(`Unexpected error while parsing error from querying resources : ${err2}`);
}
throw err;
}

View File

@@ -65,6 +65,7 @@ export class AzureResourceResourceTreeNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: treeItem.contextValue || '',
nodeSubType: undefined,

View File

@@ -10,6 +10,7 @@ import * as WS from 'ws';
import { IAzureTerminalService } from '../interfaces';
import { AzureAccount, Tenant } from 'azurecore';
import { Logger } from '../../utils/Logger';
const localize = nls.loadMessageBundle();
@@ -68,8 +69,8 @@ export class AzureTerminalService implements IAzureTerminalService {
let userSettingsResult: AxiosResponse<any>;
try {
userSettingsResult = await axios.get(userSettingsUri, settings);
} catch (ex) {
console.log(ex, ex.response);
} catch (ex) {// Log as info as exception is handled
Logger.info(ex, ex.response);
await handleNeverUsed();
return;
}
@@ -85,8 +86,8 @@ export class AzureTerminalService implements IAzureTerminalService {
let provisionResult: AxiosResponse<any>;
try {
provisionResult = await axios.put(consoleRequestUri, {}, settings);
} catch (ex) {
console.log(ex, ex.response);
} catch (ex) {// Log as info as exception is handled
Logger.info(ex, ex.response);
await handleNeverUsed();
return;
}
@@ -215,7 +216,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
this.socket?.ping();
}, 5000);
} catch (ex) {
console.log(ex);
Logger.error(ex);
}
}
@@ -234,7 +235,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
}
});
} catch (ex) {
console.log(`Error establishing terminal. ${ex}, ${ex.response}`);
Logger.info(`Error establishing terminal. ${ex}, ${ex.response}`);
await handleNeverUsed();
return undefined;
}
@@ -246,8 +247,8 @@ class AzureTerminal implements vscode.Pseudoterminal {
}
if (!terminalUri) {
console.log(terminalResult);
throw new Error(terminalResult.data);
Logger.error(terminalResult);
throw Error(terminalResult.data);
}
return terminalUri;

View File

@@ -34,6 +34,7 @@ export class AzureResourceAccountNotSignedInTreeNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: AzureResourceItemType.message,
nodeSubType: undefined,

View File

@@ -120,6 +120,7 @@ export class AzureResourceAccountTreeNode extends AzureResourceContainerTreeNode
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: AzureResourceItemType.account,
nodeSubType: undefined,

View File

@@ -94,6 +94,7 @@ export class FlatAccountTreeNode extends AzureResourceContainerTreeNodeBase {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: AzureResourceItemType.account,
nodeSubType: undefined,

View File

@@ -1,213 +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 vscode from 'vscode';
import * as azdata from 'azdata';
import { AppContext } from '../../appContext';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { TreeNode } from '../treeNode';
import { AzureResourceMessageTreeNode } from '../messageTreeNode';
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceErrorMessageUtil, filterAccounts } from '../utils';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
import { IAzureResourceNodeWithProviderId, IAzureResourceSubscriptionService } from '../interfaces';
import { AzureResourceServiceNames } from '../constants';
import { AzureResourceService } from '../resourceService';
import { Logger } from '../../utils/Logger';
export class FlatAzureResourceTreeProvider implements vscode.TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
public isSystemInitialized: boolean = false;
private _onDidChangeTreeData = new vscode.EventEmitter<TreeNode | undefined>();
private resourceLoader: ResourceLoader | undefined;
public constructor(private readonly appContext: AppContext,
private readonly authLibrary: string) {
}
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
if (element) {
return element.getChildren(true);
}
if (!this.resourceLoader) {
this.resourceLoader = new ResourceLoader(this.appContext, this.authLibrary);
this.resourceLoader.onDidAddNewResource(e => this._onDidChangeTreeData.fire(e));
}
if (this.resourceLoader.state === LoaderState.NotStarted) {
this.resourceLoader.start().catch(err => console.error('Error loading Azure Resources for FlatAzureResourceTreeProvider ', err));
return [AzureResourceMessageTreeNode.create(localize('azure.resource.tree.treeProvider.loadingLabel', "Loading ..."), undefined)];
}
return this.resourceLoader.children;
}
public get onDidChangeTreeData(): vscode.Event<TreeNode | undefined> {
return this._onDidChangeTreeData.event;
}
public notifyNodeChanged(node: TreeNode): void {
this._onDidChangeTreeData.fire(node);
}
public async refresh(node: TreeNode, isClearingCache: boolean): Promise<void> {
if (isClearingCache) {
if ((node instanceof AzureResourceContainerTreeNodeBase)) {
node.clearCache();
}
}
this._onDidChangeTreeData.fire(node);
}
public getTreeItem(element: TreeNode): vscode.TreeItem | Thenable<vscode.TreeItem> {
return element.getTreeItem();
}
}
enum LoaderState {
NotStarted,
Loading,
Complete
}
class ResourceLoader {
private _state: LoaderState = LoaderState.NotStarted;
private readonly resourceGroups = new Map<string, AzureResourceResourceTreeNode>();
private readonly subscriptionService: IAzureResourceSubscriptionService;
private readonly resourceService: AzureResourceService;
private readonly _onDidAddNewResource = new vscode.EventEmitter<TreeNode | undefined>();
public readonly onDidAddNewResource = this._onDidAddNewResource.event;
constructor(private readonly appContext: AppContext,
private readonly authLibrary: string) {
this.subscriptionService = appContext.getService<IAzureResourceSubscriptionService>(AzureResourceServiceNames.subscriptionService);
this.resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
}
get state(): LoaderState {
return this._state;
}
get children(): AzureResourceResourceTreeNode[] {
return Array.from(this.resourceGroups.values());
}
async start(): Promise<void> {
if (this.state === LoaderState.Loading) {
throw new Error('Resource Loader already loading');
}
let doRefresh = false;
// if we just fire every time we get an a new resource we crash the application
// this effectively buffers the event so that we don't cause hangs.
let interval = setInterval(() => {
if (doRefresh) {
doRefresh = false;
this._onDidAddNewResource.fire(undefined);
}
}, 500);
this._state = LoaderState.Loading;
const accounts = filterAccounts(await azdata.accounts.getAllAccounts(), this.authLibrary);
for (const account of accounts) {
for (const tenant of account.properties.tenants) {
for (const subscription of await this.subscriptionService.getSubscriptions(account, [tenant.id])) {
for (const providerId of await this.resourceService.listResourceProviderIds()) {
for (const group of await this.resourceService.getRootChildren(providerId, account, subscription)) {
const children = await this.resourceService.getChildren(providerId, group.resourceNode);
let groupNode: AzureResourceResourceTreeNode | undefined = this.resourceGroups.get(group.resourceProviderId);
if (groupNode) {
groupNode.pushItems(...children);
} else {
groupNode = new AzureResourceResourceTreeNode(group, this.appContext);
this.resourceGroups.set(group.resourceProviderId, groupNode);
groupNode.pushItems(...children);
}
doRefresh = true;
}
}
}
}
}
Logger.verbose('finished loading all accounts and subscriptions');
clearInterval(interval);
this._state = LoaderState.Complete;
}
}
class AzureResourceResourceTreeNode extends TreeNode {
private _resourceService: AzureResourceService;
public constructor(
public readonly resourceNodeWithProviderId: IAzureResourceNodeWithProviderId,
private appContext: AppContext
) {
super();
this._resourceService = appContext.getService<AzureResourceService>(AzureResourceServiceNames.resourceService);
}
private _children: IAzureResourceNodeWithProviderId[] = [];
pushItems(...items: IAzureResourceNodeWithProviderId[]): void {
this._children.push(...items);
}
public async getChildren(): Promise<TreeNode[]> {
// It is a leaf node.
try {
if (this._children.length === 0) {
return [AzureResourceMessageTreeNode.create(localize('azure.resource.resourceTreeNode.noResourcesLabel', "No Resources found"), this)];
} else {
return this._children.map((child) => {
// To make tree node's id unique, otherwise, treeModel.js would complain 'item already registered'
child.resourceNode.treeItem.id = `${this.resourceNodeWithProviderId.resourceNode.treeItem.id}.${child.resourceNode.treeItem.id}`;
return new AzureResourceResourceTreeNode(child, this.appContext);
});
}
} catch (error) {
return [AzureResourceMessageTreeNode.create(AzureResourceErrorMessageUtil.getErrorMessage(error), this)];
}
}
public getTreeItem(): vscode.TreeItem | Promise<vscode.TreeItem> {
return this._resourceService.getTreeItem(this.resourceNodeWithProviderId.resourceProviderId, this.resourceNodeWithProviderId.resourceNode);
}
public getNodeInfo(): azdata.NodeInfo {
const treeItem = this.resourceNodeWithProviderId.resourceNode.treeItem;
return {
label: <any>treeItem.label,
isLeaf: treeItem.collapsibleState === vscode.TreeItemCollapsibleState.None ? true : false,
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
nodeStatus: undefined,
nodeType: treeItem.contextValue || '',
nodeSubType: undefined,
iconType: treeItem.contextValue
};
}
public get nodePathValue(): string {
return this.resourceNodeWithProviderId.resourceNode.treeItem.id || '';
}
}

View File

@@ -76,6 +76,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: AzureResourceItemType.subscription,
nodeSubType: undefined,

View File

@@ -5,7 +5,7 @@
declare module 'azurecore' {
import * as azdata from 'azdata';
import { TreeDataProvider } from 'vscode';
import * as vscode from 'vscode';
import { BlobItem } from '@azure/storage-blob';
/**
@@ -314,8 +314,17 @@ declare module 'azurecore' {
getRegionDisplayName(region?: string): string;
getProviderMetadataForAccount(account: AzureAccount): AzureAccountProviderMetadata;
provideResources(): azureResource.IAzureResourceProvider[];
runGraphQuery<T extends azureResource.AzureGraphResource>(account: AzureAccount, subscriptions: azureResource.AzureResourceSubscription[], ignoreErrors: boolean, query: string): Promise<ResourceQueryResult<T>>;
/**
* Event emitted when MSAL cache encryption keys are updated in credential store.
* Returns encryption keys used for encryption/decryption of MSAL cache that can be used
* by connection providers to read/write to the same access token cache for stable connectivity.
*/
onEncryptionKeysUpdated: vscode.Event<CacheEncryptionKeys>;
/**
* Fetches MSAL cache encryption keys currently in use.
*/
getEncryptionKeys(): Promise<CacheEncryptionKeys>;
}
export type GetSubscriptionsResult = { subscriptions: azureResource.AzureResourceSubscription[], errors: Error[] };
@@ -333,6 +342,7 @@ declare module 'azurecore' {
export type AzureRestResponse = { response: any, errors: Error[] };
export type GetBlobsResult = { blobs: azureResource.Blob[], errors: Error[] };
export type GetStorageAccountAccessKeyResult = { keyName1: string, keyName2: string, errors: Error[] };
export type CacheEncryptionKeys = { key: string; iv: string; }
export namespace azureResource {

View File

@@ -39,11 +39,18 @@ export const AzureTenantConfigSection = AzureSection + '.' + TenantSection + '.'
export const NoSystemKeyChainSection = 'noSystemKeychain';
export const oldMsalCacheFileName = 'azureTokenCacheMsal-azure_publicCloud';
export const piiLogging = 'piiLogging';
/** MSAL Account version */
export const AccountVersion = '2.0';
export const Bearer = 'Bearer';
/** HTTP Client */
export const httpConfigSectionName = 'http';
/**
* Use SHA-256 algorithm
*/
@@ -61,7 +68,9 @@ export const dataGridProviderId = 'azure-resources';
export const AzureTokenFolderName = 'Azure Accounts';
export const DefaultAuthLibrary = 'ADAL';
export const MSALCacheName = 'accessTokenCache';
export const DefaultAuthLibrary = 'MSAL';
export enum BuiltInCommands {
SetContext = 'setContext'

View File

@@ -97,40 +97,54 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
const authLibrary: string = vscode.workspace.getConfiguration(Constants.AzureSection).get(Constants.AuthenticationLibrarySection)
?? Constants.DefaultAuthLibrary;
const piiLogging = vscode.workspace.getConfiguration(Constants.AzureSection).get(Constants.piiLogging, false)
if (piiLogging) {
void vscode.window.showWarningMessage(loc.piiWarning, loc.disable, loc.dismiss).then(async (value) => {
if (value === loc.disable) {
await vscode.workspace.getConfiguration(Constants.AzureSection).update(Constants.piiLogging, false, vscode.ConfigurationTarget.Global);
}
});
}
updatePiiLoggingLevel();
let eventEmitter: vscode.EventEmitter<azurecore.CacheEncryptionKeys>;
// Create the provider service and activate
initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => console.log(err));
registerAzureServices(appContext);
const azureResourceTree = new AzureResourceTreeProvider(appContext, authLibrary);
const connectionDialogTree = new ConnectionDialogTreeProvider(appContext, authLibrary);
pushDisposable(vscode.window.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
pushDisposable(vscode.window.registerTreeDataProvider('connectionDialog/azureResourceExplorer', connectionDialogTree));
pushDisposable(vscode.workspace.onDidChangeConfiguration(e => onDidChangeConfiguration(e)));
registerAzureResourceCommands(appContext, azureResourceTree, connectionDialogTree, authLibrary);
azdata.dataprotocol.registerDataGridProvider(new AzureDataGridProvider(appContext, authLibrary));
vscode.commands.registerCommand('azure.dataGrid.openInAzurePortal', async (item: azdata.DataGridItem) => {
const portalEndpoint = item.portalEndpoint;
const subscriptionId = item.subscriptionId;
const resourceGroup = item.resourceGroup;
const type = item.type;
const name = item.name;
if (portalEndpoint && subscriptionId && resourceGroup && type && name) {
await vscode.env.openExternal(vscode.Uri.parse(`${portalEndpoint}/#resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/${type}/${name}`));
} else {
console.log(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
void vscode.window.showErrorMessage(loc.unableToOpenAzureLink);
}
});
let providerService = await initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => Logger.error(err));
if (providerService) {
eventEmitter = providerService.getEncryptionKeysEmitter();
registerAzureServices(appContext);
const azureResourceTree = new AzureResourceTreeProvider(appContext, authLibrary);
const connectionDialogTree = new ConnectionDialogTreeProvider(appContext, authLibrary);
pushDisposable(vscode.window.registerTreeDataProvider('azureResourceExplorer', azureResourceTree));
pushDisposable(vscode.window.registerTreeDataProvider('connectionDialog/azureResourceExplorer', connectionDialogTree));
pushDisposable(vscode.workspace.onDidChangeConfiguration(e => onDidChangeConfiguration(e)));
registerAzureResourceCommands(appContext, azureResourceTree, connectionDialogTree, authLibrary);
azdata.dataprotocol.registerDataGridProvider(new AzureDataGridProvider(appContext, authLibrary));
vscode.commands.registerCommand('azure.dataGrid.openInAzurePortal', async (item: azdata.DataGridItem) => {
const portalEndpoint = item.portalEndpoint;
const subscriptionId = item.subscriptionId;
const resourceGroup = item.resourceGroup;
const type = item.type;
const name = item.name;
if (portalEndpoint && subscriptionId && resourceGroup && type && name) {
await vscode.env.openExternal(vscode.Uri.parse(`${portalEndpoint}/#resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/${type}/${name}`));
} else {
Logger.error(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
void vscode.window.showErrorMessage(loc.unableToOpenAzureLink);
}
});
}
return {
getSubscriptions(account?: azurecore.AzureAccount, ignoreErrors?: boolean, selectedOnly: boolean = false): Promise<azurecore.GetSubscriptionsResult> {
return selectedOnly
? azureResourceUtils.getSelectedSubscriptions(appContext, account, ignoreErrors)
: azureResourceUtils.getSubscriptions(appContext, account, ignoreErrors);
},
getResourceGroups(account?: azurecore.AzureAccount, subscription?: azurecore.azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise<azurecore.GetResourceGroupsResult> { return azureResourceUtils.getResourceGroups(appContext, account, subscription, ignoreErrors); },
getResourceGroups(account?: azurecore.AzureAccount, subscription?: azurecore.azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise<azurecore.GetResourceGroupsResult> {
return azureResourceUtils.getResourceGroups(appContext, account, subscription, ignoreErrors);
},
getLocations(account?: azurecore.AzureAccount,
subscription?: azurecore.azureResource.AzureResourceSubscription,
ignoreErrors?: boolean): Promise<azurecore.GetLocationsResult> {
@@ -235,6 +249,13 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
ignoreErrors: boolean,
query: string): Promise<azurecore.ResourceQueryResult<T>> {
return azureResourceUtils.runResourceQuery(account, subscriptions, ignoreErrors, query);
},
onEncryptionKeysUpdated: eventEmitter!.event,
async getEncryptionKeys(): Promise<azurecore.CacheEncryptionKeys> {
if (!providerService) {
throw new Error("Failed to initialize Azure account provider.");
}
return await providerService!.getEncryptionKeys();
}
};
}
@@ -248,7 +269,7 @@ async function findOrMakeStoragePath() {
await fs.mkdir(defaultLogLocation, { recursive: true });
} catch (e) {
if (e.code !== 'EEXIST') {
console.log(`Creating the base directory failed... ${e}`);
Logger.error(`Creating the base directory failed... ${e}`);
return undefined;
}
}
@@ -257,23 +278,25 @@ async function findOrMakeStoragePath() {
await fs.mkdir(storagePath, { recursive: true });
} catch (e) {
if (e.code !== 'EEXIST') {
console.error(`Initialization of Azure account extension storage failed: ${e}`);
console.error('Azure accounts will not be available');
Logger.error(`Initialization of Azure account extension storage failed: ${e}`);
Logger.error('Azure accounts will not be available');
return undefined;
}
}
console.log('Initialized Azure account extension storage.');
Logger.verbose('Initialized Azure account extension storage.');
return storagePath;
}
async function initAzureAccountProvider(extensionContext: vscode.ExtensionContext, storagePath: string, authLibrary: string): Promise<void> {
async function initAzureAccountProvider(extensionContext: vscode.ExtensionContext, storagePath: string, authLibrary: string): Promise<AzureAccountProviderService | undefined> {
try {
const accountProviderService = new AzureAccountProviderService(extensionContext, storagePath, authLibrary);
extensionContext.subscriptions.push(accountProviderService);
await accountProviderService.activate();
return accountProviderService;
} catch (err) {
console.log('Unexpected error starting account provider: ' + err.message);
Logger.error('Unexpected error starting account provider: ' + err.message);
return undefined;
}
}
@@ -291,6 +314,9 @@ async function onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent): Pro
updatePiiLoggingLevel();
}
if (e.affectsConfiguration('azure.authenticationLibrary')) {
if (vscode.workspace.getConfiguration(Constants.AzureSection).get('authenticationLibrary') === 'ADAL') {
void vscode.window.showInformationMessage(loc.deprecatedOption);
}
await displayReloadAds();
}
}
@@ -313,4 +339,3 @@ async function displayReloadAds(): Promise<boolean> {
}
}

View File

@@ -10,6 +10,7 @@ export const extensionName = localize('azurecore.extensionName', "Azure Accounts
export const requiresReload = localize('azurecore.requiresReload', "Modifying this setting requires reloading the window for all changes to take effect.");
export const reload = localize('azurecore.reload', "Reload");
export const cancel = localize('azurecore.reload', "Cancel");
export const australiaCentral = localize('azurecore.australiacentral', "Australia Central");
export const australiaCentral2 = localize('azurecore.australiacentral2', "Australia Central 2");
@@ -65,6 +66,11 @@ export const typeIcon = localize('azurecore.typeIcon', "Type Icon");
export const reloadPrompt = localize('azurecore.reloadPrompt', "Authentication Library has changed, please reload Azure Data Studio.");
export const reloadChoice = localize('azurecore.reloadChoice', "Reload Azure Data Studio");
export const deprecatedOption = localize('azurecore.deprecated', "Warning: ADAL has been deprecated, and is scheduled to be removed in a future release. Please use MSAL instead.");
export const piiWarning = localize('azurecore.piiLogging.warning', "Warning: Azure PII Logging is enabled. Enabling this option allows personally identifiable information to be logged and should only be used for debugging purposes.");
export const disable = localize('azurecore.disable', 'Disable');
export const dismiss = localize('azurecore.dismiss', 'Dismiss');
// Azure Resource Types
export const sqlServer = localize('azurecore.sqlServer', "SQL server");
export const sqlDatabase = localize('azurecore.sqlDatabase', "SQL database");
@@ -84,3 +90,6 @@ export const invalidTenant = localize('azurecore.invalidTenant', "Invalid tenant
export function unableToFetchTokenError(tenant: string): string {
return localize('azurecore.unableToFetchToken', "Unable to get token for tenant {0}", tenant);
}
// Error Messages
export const azureCredStoreSaveFailedError = localize('azure.credStoreSaveFailedError', `Keys for token cache could not be saved in credential store, this may cause Azure access token persistence issues and connection instabilities. It's likely that SqlTools has reached credential storage limit on Windows, please clear at least 2 credentials that start with "Microsoft.SqlTools|" in Windows Credential Manager and reload.`);

View File

@@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { HttpProxyAgent, HttpProxyAgentOptions } from 'http-proxy-agent';
import { HttpsProxyAgent, HttpsProxyAgentOptions } from 'https-proxy-agent';
import { parse as parseUrl, Url } from 'url';
function getSystemProxyURL(requestURL: Url): string | undefined {
if (requestURL.protocol === 'http:') {
return process.env.HTTP_PROXY || process.env.http_proxy || undefined;
} else if (requestURL.protocol === 'https:') {
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || undefined;
}
return undefined;
}
export function isBoolean(obj: any): obj is boolean {
return obj === true || obj === false;
}
/*
* Returns the proxy agent using the proxy url in the parameters or the system proxy. Returns null if no proxy found
*/
export function getProxyAgent(requestURL: Url, proxy?: string, strictSSL?: boolean): HttpsProxyAgent | HttpProxyAgent | undefined {
const proxyURL = proxy || getSystemProxyURL(requestURL);
if (!proxyURL) {
return undefined;
}
const proxyEndpoint = parseUrl(proxyURL);
const opts = getProxyAgentOptions(requestURL, proxy, strictSSL);
return proxyEndpoint.protocol === 'https:' ? new HttpsProxyAgent(opts as HttpsProxyAgentOptions) : new HttpProxyAgent(opts as HttpProxyAgentOptions);
}
/*
* Returns the proxy agent using the proxy url in the parameters or the system proxy. Returns null if no proxy found
*/
export function getProxyAgentOptions(requestURL: Url, proxy?: string, strictSSL?: boolean): HttpsProxyAgentOptions | HttpProxyAgentOptions | undefined {
const proxyURL = proxy || getSystemProxyURL(requestURL);
if (!proxyURL) {
return undefined;
}
const proxyEndpoint = parseUrl(proxyURL);
if (!/^https?:$/.test(proxyEndpoint.protocol!)) {
return undefined;
}
const opts: HttpsProxyAgentOptions | HttpProxyAgentOptions = {
host: proxyEndpoint.hostname,
port: Number(proxyEndpoint.port),
auth: proxyEndpoint.auth,
rejectUnauthorized: isBoolean(strictSSL) ? strictSSL : true
};
return opts;
}

View File

@@ -1,33 +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 azdata from 'azdata';
/**
* Mock CredentialsProvider to be used for testing
*/
export class CredentialsTestProvider implements azdata.CredentialProvider {
handle: number = 0;
public storedCredentials: { [K: string]: azdata.Credential } = {};
saveCredential(credentialId: string, password: string): Thenable<boolean> {
this.storedCredentials[credentialId] = {
credentialId: credentialId,
password: password
};
return Promise.resolve(true);
}
readCredential(credentialId: string): Thenable<azdata.Credential> {
return Promise.resolve(this.storedCredentials[credentialId]);
}
deleteCredential(credentialId: string): Thenable<boolean> {
let exists = this.storedCredentials[credentialId] !== undefined;
delete this.storedCredentials[credentialId];
return Promise.resolve(exists);
}
}

View File

@@ -4,8 +4,19 @@
*--------------------------------------------------------------------------------------------*/
import * as loc from './localizedConstants';
import * as vscode from 'vscode';
import * as constants from './constants';
import { AzureRegion, azureResource } from 'azurecore';
import { AppContext } from './appContext';
import { HttpClient } from './account-provider/auths/httpClient';
import { parse } from 'url';
import { getProxyAgentOptions } from './proxy';
import { HttpsProxyAgentOptions } from 'https-proxy-agent';
const configProxy = 'proxy';
const configProxyStrictSSL = 'proxyStrictSSL';
const configProxyAuthorization = 'proxyAuthorization';
/**
* Converts a region value (@see AzureRegion) into the localized Display Name
@@ -125,6 +136,9 @@ export function getResourceTypeDisplayName(type: string): string {
}
return type;
}
function getHttpConfiguration(): vscode.WorkspaceConfiguration {
return vscode.workspace.getConfiguration(constants.httpConfigSectionName);
}
export function getResourceTypeIcon(appContext: AppContext, type: string): string {
switch (type) {
@@ -145,3 +159,23 @@ export function getResourceTypeIcon(appContext: AppContext, type: string): strin
}
return '';
}
export function getProxyEnabledHttpClient(): HttpClient {
const proxy = <string>getHttpConfiguration().get(configProxy);
const strictSSL = getHttpConfiguration().get(configProxyStrictSSL, true);
const authorization = getHttpConfiguration().get(configProxyAuthorization);
const url = parse(proxy);
let agentOptions = getProxyAgentOptions(url, proxy, strictSSL);
if (authorization && url.protocol === 'https:') {
let httpsAgentOptions = agentOptions as HttpsProxyAgentOptions;
httpsAgentOptions!.headers = Object.assign(httpsAgentOptions!.headers || {}, {
'Proxy-Authorization': authorization
});
agentOptions = httpsAgentOptions;
}
return new HttpClient(proxy, agentOptions);
}

View File

@@ -127,18 +127,18 @@
uuid "^3.3.2"
xml2js "^0.4.19"
"@azure/msal-common@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-7.6.0.tgz#b52e97ef540275f72611cff57937dfa0b34cdcca"
integrity sha512-XqfbglUTVLdkHQ8F9UQJtKseRr3sSnr9ysboxtoswvaMVaEfvyLtMoHv9XdKUfOc0qKGzNgRFd9yRjIWVepl6Q==
"@azure/msal-common@^11.0.0":
version "11.0.0"
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-11.0.0.tgz#d35bfa6cdd2a5b8c036ce427aa3fd36f8f985239"
integrity sha512-SZH8ObQ3Hq5v3ogVGBYJp1nNW7p+MtM4PH4wfNadBP9wf7K0beQHF9iOtRcjPOkwZf+ZD49oXqw91LndIkdk8g==
"@azure/msal-node@^1.9.0":
version "1.14.2"
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.14.2.tgz#8f236a19efa506133d6c715047393146af182e3a"
integrity sha512-t3whVhhLdZVVeDEtUPD2Wqfa8BDi3EDMnpWp8dbuRW0GhUpikBfs4AQU0Fe6P9zS87n9LpmUTLrIcPEEuzkvfA==
"@azure/msal-node@^1.16.0":
version "1.16.0"
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.16.0.tgz#0bd469916f5a9da22d844edc879ac7e8225c0ccb"
integrity sha512-eGXPp65i++mAIvziafbCH970TCeECB6iaQP7aRzZEjtU238cW4zKm40U8YxkiCn9rR1G2VeMHENB5h6WRk7ZCQ==
dependencies:
"@azure/msal-common" "^7.6.0"
jsonwebtoken "^8.5.1"
"@azure/msal-common" "^11.0.0"
jsonwebtoken "^9.0.0"
uuid "^8.3.0"
"@azure/storage-blob@^12.6.0":
@@ -335,13 +335,13 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -403,6 +403,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/caseless@*":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8"
@@ -494,12 +499,12 @@ abort-controller@^3.0.0:
dependencies:
event-target-shim "^5.0.0"
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -690,18 +695,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
crypto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -709,6 +702,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -815,18 +815,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -1049,21 +1037,22 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1297,7 +1286,7 @@ json5@^2.1.2:
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
jsonwebtoken@9.0.0, jsonwebtoken@^8.5.1:
jsonwebtoken@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d"
integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==
@@ -1482,18 +1471,11 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@^2.1.1:
ms@2.1.2, 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==
msal@^1.4.16:
version "1.4.17"
resolved "https://registry.yarnpkg.com/msal/-/msal-1.4.17.tgz#b78171c0471ede506eeaabc86343f8f4e2d01634"
integrity sha512-RjHwP2cCIWQ9iUIk1SziUMb9+jj5mC4OqG2w16E5yig8jySi/TwiFvKlwcjNrPsndph0HtgCtbENnk5julf3yQ==
dependencies:
tslib "^1.9.3"
nise@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd"
@@ -1932,7 +1914,7 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
tslib@^1.10.0, tslib@^1.9.3:
tslib@^1.10.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

View File

@@ -32,7 +32,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
## Telemetry
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://aka.ms/ads-disable-telemetry) documentation.
## Privacy Statement

View File

@@ -213,7 +213,7 @@
"figures": "^2.0.0",
"find-remove": "1.2.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"@microsoft/ads-extension-telemetry": "^2.0.0",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"vscode-languageclient": "5.2.1",
"vscode-nls": "^4.0.0"
},

View File

@@ -72,7 +72,7 @@ export class AzureMonitorServer {
this.config = JSON.parse(rawConfig.toString())!;
this.config.installDirectory = path.join(__dirname, this.config.installDirectory);
this.config.proxy = vscode.workspace.getConfiguration('http').get<string>('proxy')!;
this.config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL') || true;
this.config.strictSSL = vscode.workspace.getConfiguration('http').get('proxyStrictSSL', true);
const serverdownloader = new ServerProvider(this.config);
serverdownloader.eventEmitter.onAny(generateHandleServerProviderEvent());

View File

@@ -1,25 +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 { Transform } from 'stream';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export class CancelableStream extends Transform {
constructor(private cancelationToken: vscode.CancellationTokenSource) {
super();
}
public override _transform(chunk: any, _encoding: string, callback: Function): void {
if (this.cancelationToken && this.cancelationToken.token.isCancellationRequested) {
callback(new Error(localize('streamCanceled', 'Stream operation canceled by the user')));
} else {
this.push(chunk);
callback();
}
}
}

View File

@@ -209,6 +209,7 @@ class SqlClusterRootNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath()!,
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: 'sqlCluster:root',
nodeSubType: undefined,

View File

@@ -1,77 +0,0 @@
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window } from 'vscode';
import PromptFactory from './factory';
import EscapeException from './escapeException';
import { IQuestion, IPrompter, IPromptCallback, Answers } from './question';
// Supports simple pattern for prompting for user input and acting on this
export default class CodeAdapter implements IPrompter {
// TODO define question interface
private fixQuestion(question: IQuestion): any {
if (question.type === 'checkbox' && Array.isArray(question.choices)) {
// For some reason when there's a choice of checkboxes, they aren't formatted properly
// Not sure where the issue is
question.choices = question.choices.map(item => {
if (typeof (item) === 'string') {
return { checked: false, name: item, value: item };
} else {
return item;
}
});
}
}
public async promptSingle<T>(question: IQuestion, ignoreFocusOut?: boolean): Promise<T | undefined> {
let questions: IQuestion[] = [question];
const answers = await this.prompt<T>(questions, ignoreFocusOut);
if (answers) {
let response: T = answers[question.name];
return response || undefined;
}
return undefined;
}
public async prompt<T>(questions: IQuestion[], ignoreFocusOut?: boolean): Promise<Answers<T> | undefined> {
// Collapse multiple questions into a set of prompt steps
const promptResult = new Promise<Answers<T>>((resolve) => {
let answers: Answers<T> = {};
questions.forEach(async (question: IQuestion) => {
this.fixQuestion(question);
const prompt = PromptFactory.createPrompt(question, ignoreFocusOut);
if (!question.shouldPrompt || question.shouldPrompt(answers) === true) {
const result = await prompt.render();
answers[question.name] = result;
if (question.onAnswered) {
question.onAnswered(result);
}
return;
}
});
resolve(answers);
});
try {
return await promptResult;
} catch (err) {
if (err instanceof EscapeException || err instanceof TypeError) {
window.showErrorMessage(err.message);
}
return undefined;
}
}
// Helper to make it possible to prompt using callback pattern. Generally Promise is a preferred flow
public promptCallback(questions: IQuestion[], callback: IPromptCallback | undefined): void {
// Collapse multiple questions into a set of prompt steps
this.prompt(questions).then(answers => {
if (callback && answers) {
callback(answers);
}
});
}
}

View File

@@ -1,70 +0,0 @@
'use strict';
// This code is originally from https://github.com/DonJayamanne/bowerVSCode
// License: https://github.com/DonJayamanne/bowerVSCode/blob/master/LICENSE
import { window, StatusBarItem, StatusBarAlignment } from 'vscode';
export default class ProgressIndicator {
private _statusBarItem: StatusBarItem;
constructor() {
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
}
private _tasks: string[] = [];
public beginTask(task: string): void {
this._tasks.push(task);
this.displayProgressIndicator();
}
public endTask(_task: string): void {
if (this._tasks.length > 0) {
this._tasks.pop();
}
this.setMessage();
}
private setMessage(): void {
if (this._tasks.length === 0) {
this._statusBarItem.text = '';
this.hideProgressIndicator();
return;
}
this._statusBarItem.text = this._tasks[this._tasks.length - 1];
this._statusBarItem.show();
}
private _interval: any;
private displayProgressIndicator(): void {
this.setMessage();
this.hideProgressIndicator();
this._interval = setInterval(() => this.onDisplayProgressIndicator(), 100);
}
private hideProgressIndicator(): void {
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
this.ProgressCounter = 0;
}
private ProgressText = ['|', '/', '-', '\\', '|', '/', '-', '\\'];
private ProgressCounter = 0;
private onDisplayProgressIndicator(): void {
if (this._tasks.length === 0) {
return;
}
let txt = this.ProgressText[this.ProgressCounter];
this._statusBarItem.text = this._tasks[this._tasks.length - 1] + ' ' + txt;
this.ProgressCounter++;
if (this.ProgressCounter >= this.ProgressText.length - 1) {
this.ProgressCounter = 0;
}
}
}

View File

@@ -2,10 +2,10 @@
# yarn lockfile v1
"@microsoft/ads-extension-telemetry@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
"@microsoft/ads-extension-telemetry@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-3.0.1.tgz#82d4288f8ad96920512ab4edf87d009412e683bb"
integrity sha512-OsHLKvz4DEZg9THkI+Jk4aINgYv4X3qgbqnVAqY8f9zsWTiR+o4vt/F5w0w3kwpbU3ppRHa03yFTBEjYyGSg1g==
dependencies:
"@vscode/extension-telemetry" "0.6.1"

View File

@@ -692,7 +692,7 @@
"should": "^13.2.1",
"@microsoft/vscodetestcover": "^1.2.1",
"typemoq": "^2.1.0",
"@microsoft/azdata-test": "^2.0.3"
"@microsoft/azdata-test": "^3.0.1"
},
"__metadata": {
"id": "40",

View File

@@ -41,6 +41,7 @@ export class CmsResourceMessageTreeNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: CmsResourceItemType.cmsMessageNodeContainer,
nodeSubType: undefined,

View File

@@ -34,6 +34,7 @@ export class CmsResourceEmptyTreeNode extends TreeNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: CmsResourceItemType.cmsEmptyNodeContainer,
iconType: CmsResourceItemType.cmsEmptyNodeContainer,

View File

@@ -108,6 +108,7 @@ export class CmsResourceTreeNode extends CmsResourceTreeNodeBase {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: CmsResourceItemType.cmsNodeContainer,
nodeSubType: undefined,

View File

@@ -71,6 +71,7 @@ export class RegisteredServerTreeNode extends CmsResourceTreeNodeBase {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: CmsResourceItemType.registeredServer,
nodeSubType: undefined

View File

@@ -95,6 +95,7 @@ export class ServerGroupTreeNode extends CmsResourceTreeNodeBase {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: CmsResourceItemType.serverGroup,
nodeSubType: undefined

View File

@@ -182,13 +182,13 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -209,6 +209,11 @@
istanbul-reports "^3.0.0"
mocha "^7.1.1"
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/mocha@^7.0.2":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
@@ -219,12 +224,12 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11"
integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -390,13 +395,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -404,6 +402,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -493,18 +498,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -685,21 +678,22 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1045,7 +1039,7 @@ ms@2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@^2.1.1:
ms@2.1.2, 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==

View File

@@ -25,7 +25,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
## Telemetry
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://aka.ms/ads-disable-telemetry) documentation.
## Privacy Statement

View File

@@ -2,7 +2,7 @@
"name": "dacpac",
"displayName": "SQL Server Dacpac",
"description": "SQL Server Dacpac for Azure Data Studio.",
"version": "1.13.0",
"version": "1.14.0",
"publisher": "Microsoft",
"preview": false,
"engines": {
@@ -92,12 +92,12 @@
}
},
"dependencies": {
"@microsoft/ads-extension-telemetry": "^2.0.0",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"htmlparser2": "^3.10.1",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@microsoft/azdata-test": "^2.0.3",
"@microsoft/azdata-test": "^3.0.1",
"@microsoft/vscodetestcover": "^1.2.1",
"@types/htmlparser2": "^3.10.1",
"@types/mocha": "^7.0.2",

View File

@@ -92,7 +92,7 @@ describe('Dacfx Wizard Pages', function (): void {
testContext = createContext();
wizard.setPages();
sinon.stub(azdata.connection, 'getConnections').resolves([azdataTest.stubs.connectionProfile.createConnectionProfile()]);
sinon.stub(azdata.connection, 'getConnections').resolves([azdataTest.stubs.azdata.createConnectionProfile()]);
sinon.stub(azdata.connection, 'listDatabases').resolves(['fakeDatabaseName']);
sinon.stub(vscode.window, 'showOpenDialog').resolves([vscode.Uri.file(dacpacPath)]);
@@ -112,7 +112,7 @@ describe('Dacfx Wizard Pages', function (): void {
testContext = createContext();
wizard.setPages();
sinon.stub(azdata.connection, 'getConnections').resolves([azdataTest.stubs.connectionProfile.createConnectionProfile()]);
sinon.stub(azdata.connection, 'getConnections').resolves([azdataTest.stubs.azdata.createConnectionProfile()]);
sinon.stub(azdata.connection, 'listDatabases').resolves(['fakeDatabaseName', 'master', 'msdb', 'tempdb', 'model']);
let extractConfigPage = new TestExtractConfigPage(wizard, wizard.pages.get(PageName.deployConfig).wizardPage, wizard.model, testContext.viewContext.view);

View File

@@ -182,20 +182,20 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/ads-extension-telemetry@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
"@microsoft/ads-extension-telemetry@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-3.0.1.tgz#82d4288f8ad96920512ab4edf87d009412e683bb"
integrity sha512-OsHLKvz4DEZg9THkI+Jk4aINgYv4X3qgbqnVAqY8f9zsWTiR+o4vt/F5w0w3kwpbU3ppRHa03yFTBEjYyGSg1g==
dependencies:
"@vscode/extension-telemetry" "0.6.1"
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -252,6 +252,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/domutils@*":
version "1.7.4"
resolved "https://registry.yarnpkg.com/@types/domutils/-/domutils-1.7.4.tgz#bb5f1807673e295782614b0a383b4dc1ecd2af97"
@@ -300,12 +305,12 @@
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -471,13 +476,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -485,6 +483,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -612,18 +617,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -828,21 +821,22 @@ htmlparser2@^3.10.1:
inherits "^2.0.1"
readable-stream "^3.1.1"
http-proxy-agent@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1203,6 +1197,11 @@ ms@2.1.1, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nise@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd"

View File

@@ -18,7 +18,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
## Telemetry
This extensions collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described [here for Azure Data Studio](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) or [here for VS Code](https://code.visualstudio.com/docs/getstarted/telemetry#_disable-telemetry-reporting).
This extensions collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described [here for Azure Data Studio](https://aka.ms/ads-disable-telemetry) or [here for VS Code](https://code.visualstudio.com/docs/getstarted/telemetry#_disable-telemetry-reporting).
## Privacy Statement

View File

@@ -179,7 +179,7 @@
},
"dependencies": {
"fast-glob": "^3.2.7",
"@microsoft/ads-extension-telemetry": "^2.0.0",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
@@ -190,6 +190,6 @@
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1",
"@microsoft/azdata-test": "^2.0.3"
"@microsoft/azdata-test": "^3.0.1"
}
}

View File

@@ -67,7 +67,7 @@ export const whitespaceFilenameErrorMessage = localize('whitespaceFilenameErrorM
export const invalidFileCharsErrorMessage = localize('invalidFileCharsErrorMessage', "Invalid file characters");
export const reservedWindowsFilenameErrorMessage = localize('reservedWindowsFilenameErrorMessage', "This file name is reserved for use by Windows. Choose another name and try again");
export const reservedValueErrorMessage = localize('reservedValueErrorMessage', "Reserved file name. Choose another name and try again");
export const trailingWhitespaceErrorMessage = localize('trailingWhitespaceErrorMessage', "File name cannot end with a whitespace");
export const trailingWhitespaceErrorMessage = localize('trailingWhitespaceErrorMessage', "File name cannot start or end with whitespace");
export const tooLongFilenameErrorMessage = localize('tooLongFilenameErrorMessage', "File name cannot be over 255 characters");
//Open Existing Dialog

View File

@@ -59,7 +59,7 @@ export class DataWorkspaceExtension implements IExtension {
return isValidBasename(name);
}
isValidBasenameErrorMessage(name?: string): string {
isValidBasenameErrorMessage(name?: string): string | undefined {
return isValidBasenameErrorMessage(name);
}

View File

@@ -5,7 +5,6 @@
import * as constants from './constants';
import * as os from 'os';
import * as path from 'path';
const WINDOWS_INVALID_FILE_CHARS = /[\\/:\*\?"<>\|]/g;
const UNIX_INVALID_FILE_CHARS = /[\\/]/g;
@@ -39,7 +38,7 @@ export function isValidFilenameCharacter(c: string): boolean {
export function sanitizeStringForFilename(s: string): string {
// replace invalid characters with an underscore
let result = '';
for (let i = 0; i < s.length; ++i) {
for (let i = 0; i < s?.length; ++i) {
result += isValidFilenameCharacter(s[i]) ? s[i] : '_';
}
@@ -49,88 +48,57 @@ export function sanitizeStringForFilename(s: string): string {
/**
* Returns true if the string is a valid filename
* Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check
* @param fileName filename to check (without file path)
*/
export function isValidBasename(name?: string): boolean {
const invalidFileChars = isWindows ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS;
if (!name) {
return false;
export function isValidBasename(fileName?: string): boolean {
if (isValidBasenameErrorMessage(fileName) !== undefined) {
return false; //Return false depicting filename is invalid
} else {
return true;
}
if (isWindows && name[name.length - 1] === '.') {
return false; // Windows: file cannot end with a "."
}
let basename = path.parse(name).name;
if (!basename || basename.length === 0 || /^\s+$/.test(basename)) {
return false; // require a name that is not just whitespace
}
invalidFileChars.lastIndex = 0;
if (invalidFileChars.test(basename)) {
return false; // check for certain invalid file characters
}
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(basename)) {
return false; // check for certain invalid file names
}
if (basename === '.' || basename === '..') {
return false; // check for reserved values
}
if (isWindows && basename.length !== basename.trim().length) {
return false; // Windows: file cannot end with a whitespace
}
if (basename.length > 255) {
return false; // most file systems do not allow files > 255 length
}
return true;
}
/**
* Returns specific error message if file name is invalid
* Returns specific error message if file name is invalid otherwise returns undefined
* Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check
* @param fileName filename to check (without file path)
*/
export function isValidBasenameErrorMessage(name?: string): string {
export function isValidBasenameErrorMessage(fileName?: string): string | undefined {
const invalidFileChars = isWindows ? WINDOWS_INVALID_FILE_CHARS : UNIX_INVALID_FILE_CHARS;
if (!name) {
if (!fileName) {
return constants.undefinedFilenameErrorMessage;
}
if (isWindows && name[name.length - 1] === '.') {
if (isWindows && fileName[fileName.length - 1] === '.') {
return constants.filenameEndingIsPeriodErrorMessage; // Windows: file cannot end with a "."
}
let basename = path.parse(name).name;
if (!basename || basename.length === 0 || /^\s+$/.test(basename)) {
if (!fileName || fileName.length === 0 || /^\s+$/.test(fileName)) {
return constants.whitespaceFilenameErrorMessage; // require a name that is not just whitespace
}
invalidFileChars.lastIndex = 0;
if (invalidFileChars.test(basename)) {
if (invalidFileChars.test(fileName)) {
return constants.invalidFileCharsErrorMessage; // check for certain invalid file characters
}
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(basename)) {
if (isWindows && WINDOWS_FORBIDDEN_NAMES.test(fileName)) {
return constants.reservedWindowsFilenameErrorMessage; // check for certain invalid file names
}
if (basename === '.' || basename === '..') {
if (fileName === '.' || fileName === '..') {
return constants.reservedValueErrorMessage; // check for reserved values
}
if (isWindows && basename.length !== basename.trim().length) {
return constants.trailingWhitespaceErrorMessage; // Windows: file cannot end with a whitespace
if (isWindows && fileName.length !== fileName.trim().length) {
return constants.trailingWhitespaceErrorMessage; // Windows: file cannot start or end with a whitespace
}
if (basename.length > 255) {
if (fileName.length > 255) {
return constants.tooLongFilenameErrorMessage; // most file systems do not allow files > 255 length
}
return '';
return undefined;
}

View File

@@ -115,6 +115,14 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<Worksp
}
handleDrag(treeItems: readonly WorkspaceTreeItem[], dataTransfer: vscode.DataTransfer): void | Thenable<void> {
// Don't do anything if trying to drag the project node since it isn't supported. Because canSelectMany is set to false for WorkspaceTreeDataProvider,
// treeItems will only contain one treeItem, so we only need to check the first one in the list.
const relativePath = treeItems[0].element?.relativeProjectUri?.fsPath?.substring(1); // remove leading slash
const projBaseName = path.basename(treeItems[0].element?.projectFileUri?.fsPath, path.extname(treeItems[0].element?.projectFileUri?.fsPath));
if (relativePath === projBaseName) {
return;
}
dataTransfer.set('application/vnd.code.tree.WorkspaceTreeDataProvider', new vscode.DataTransferItem(treeItems.map(t => t.element)));
}

View File

@@ -75,11 +75,11 @@ declare module 'dataworkspace' {
isValidBasename(name: string | null | undefined): boolean;
/**
* Returns specific error message if file name is invalid
* Returns specific error message if file name is invalid otherwise returns undefined
* Logic is copied from src\vs\base\common\extpath.ts
* @param name filename to check
*/
isValidBasenameErrorMessage(name: string | null | undefined): string;
isValidBasenameErrorMessage(name: string | null | undefined): string | undefined;
}
/**

View File

@@ -69,7 +69,7 @@ export abstract class DialogBase {
};
}
public getErrorMessage(): azdataType.window.DialogMessage {
public getErrorMessage(): azdataType.window.DialogMessage | undefined {
return this.dialogObject.message;
}

View File

@@ -187,7 +187,7 @@ export class NewProjectDialog extends DialogBase {
this.register(projectNameTextBox.onTextChanged(text => {
const errorMessage = isValidBasenameErrorMessage(text);
if (errorMessage) {
if (errorMessage !== undefined) {
// Set validation error message if project name is invalid
return void projectNameTextBox.updateProperty('validationErrorMessage', errorMessage);
} else {
@@ -215,6 +215,7 @@ export class NewProjectDialog extends DialogBase {
const browseFolderButton = view.modelBuilder.button().withProps({
ariaLabel: constants.BrowseButtonText,
title: constants.BrowseButtonText,
iconPath: IconPathHelper.folder,
height: '16px',
width: '18px'
@@ -284,7 +285,6 @@ export class NewProjectDialog extends DialogBase {
this.formBuilder = view.modelBuilder.formContainer().withFormItems([
{
title: constants.TypeTitle,
required: true,
component: projectTypeRadioCardGroup
},
{

View File

@@ -9,7 +9,7 @@ import * as constants from '../common/constants';
import { directoryExist, showInfoMessageWithLearnMoreLink } from '../common/utils';
import { defaultProjectSaveLocation } from '../common/projectLocationHelper';
import { WorkspaceService } from '../services/workspaceService';
import { isValidBasename, isValidBasenameErrorMessage } from '../common/pathUtilsHelper';
import { isValidBasenameErrorMessage } from '../common/pathUtilsHelper';
/**
* Create flow for a New Project using only VS Code-native APIs such as QuickPick
@@ -40,7 +40,7 @@ export async function createNewProjectWithQuickpick(workspaceService: WorkspaceS
{
title: constants.EnterProjectName,
validateInput: (value) => {
return isValidBasename(value) ? undefined : isValidBasenameErrorMessage(value);
return isValidBasenameErrorMessage(value);
},
ignoreFocusOut: true
});

View File

@@ -163,6 +163,7 @@ export class OpenExistingDialog extends DialogBase {
const localClonePathBrowseFolderButton = view.modelBuilder.button().withProps({
ariaLabel: constants.BrowseButtonText,
title: constants.BrowseButtonText,
iconPath: IconPathHelper.folder,
width: '18px',
height: '16px',
@@ -203,6 +204,7 @@ export class OpenExistingDialog extends DialogBase {
const localProjectBrowseFolderButton = view.modelBuilder.button().withProps({
ariaLabel: constants.BrowseButtonText,
title: constants.BrowseButtonText,
iconPath: IconPathHelper.folder,
width: '18px',
height: '16px'

View File

@@ -90,7 +90,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
}));
context.subscriptions.push(vscode.commands.registerCommand('projects.removeProject', async (treeItem: WorkspaceTreeItem) => {
await workspaceService.removeProject(treeItem.element.projectFileUri);
await workspaceService.removeProject(vscode.Uri.file(treeItem.element.project.projectFilePath));
}));
context.subscriptions.push(vscode.commands.registerCommand('projects.manageProject', async (treeItem: WorkspaceTreeItem) => {

View File

@@ -29,12 +29,12 @@ suite('Open Existing Dialog', function (): void {
const validateResult = await dialog.validate();
const msg = constants.FileNotExistError('project', 'nonExistentProjectFile');
should.equal(dialog.dialogObject.message.text, msg);
should.equal(dialog.dialogObject.message?.text, msg);
should.equal(validateResult, false, 'Validation should fail because project file does not exist, but passed');
// create a project file
dialog.filePathTextBox!.value = await createProjectFile('testproj');
should.equal(await dialog.validate(), true, `Validation should pass because project file exists, but failed with: ${dialog.dialogObject.message.text}`);
should.equal(await dialog.validate(), true, `Validation should pass because project file exists, but failed with: ${dialog.dialogObject.message?.text}`);
});
@@ -50,13 +50,13 @@ suite('Open Existing Dialog', function (): void {
const validateResult = await dialog.validate();
const msg = constants.CloneParentDirectoryNotExistError(dialog.localClonePathTextBox!.value);
should.equal(dialog.dialogObject.message.text, msg, 'Dialog message should be correct');
should.equal(dialog.dialogObject.message?.text, msg, 'Dialog message should be correct');
should.equal(validateResult, false, 'Validation should fail because clone directory does not exist, but passed');
// validation should pass if directory exists
dialog.localClonePathTextBox!.value = os.tmpdir();
folderExistStub.resolves(true);
should.equal(await dialog.validate(), true, `Validation should pass because clone directory exists, but failed with: ${dialog.dialogObject.message.text}`);
should.equal(await dialog.validate(), true, `Validation should pass because clone directory exists, but failed with: ${dialog.dialogObject.message?.text}`);
});
test('project browse', async function (): Promise<void> {

View File

@@ -6,7 +6,6 @@
import * as should from 'should';
import * as constants from '../../common/constants';
import * as os from 'os';
import * as path from 'path';
import { isValidBasename, isValidBasenameErrorMessage } from '../../common/pathUtilsHelper';
const isWindows = os.platform() === 'win32';
@@ -14,21 +13,21 @@ const isWindows = os.platform() === 'win32';
suite('Check for invalid filename tests', function (): void {
test('Should determine invalid filenames', async () => {
// valid filename
should(isValidBasename(formatFileName('ValidName.sqlproj'))).equal(true);
should(isValidBasename('ValidName')).equal(true);
// invalid for both Windows and non-Windows
let invalidNames: string[] = [
' .sqlproj',
' .sqlproj',
' .sqlproj',
'..sqlproj',
'...sqlproj',
' ',
' ',
' ',
'.',
'..',
// most file systems do not allow files > 255 length
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.sqlproj'
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
];
for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(false);
should(isValidBasename(invalidName)).equal(false, `InvalidName that failed:${invalidName}`);
}
should(isValidBasename(undefined)).equal(false);
@@ -39,52 +38,55 @@ suite('Check for invalid filename tests', function (): void {
test('Should determine invalid Windows filenames', async () => {
let invalidNames: string[] = [
// invalid characters only for Windows
'?.sqlproj',
':.sqlproj',
'*.sqlproj',
'<.sqlproj',
'>.sqlproj',
'|.sqlproj',
'".sqlproj',
// Windows filenames cannot end with a whitespace
'test .sqlproj',
'test .sqlproj'
'?',
':',
'*',
'<',
'>',
'|',
'"',
'/',
'\\',
// Windows filenames cannot start or end with a whitespace
'test ',
'test ',
' test'
];
for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(isWindows ? false : true);
should(isValidBasename(invalidName)).equal(isWindows ? false : true, `InvalidName that failed:${invalidName}`);
}
});
test('Should determine Windows forbidden filenames', async () => {
let invalidNames: string[] = [
// invalid only for Windows
'CON.sqlproj',
'PRN.sqlproj',
'AUX.sqlproj',
'NUL.sqlproj',
'COM1.sqlproj',
'COM2.sqlproj',
'COM3.sqlproj',
'COM4.sqlproj',
'COM5.sqlproj',
'COM6.sqlproj',
'COM7.sqlproj',
'COM8.sqlproj',
'COM9.sqlproj',
'LPT1.sqlproj',
'LPT2.sqlproj',
'LPT3.sqlproj',
'LPT4.sqlproj',
'LPT5.sqlproj',
'LPT6.sqlproj',
'LPT7.sqlproj',
'LPT8.sqlproj',
'LPT9.sqlproj',
'CON',
'PRN',
'AUX',
'NUL',
'COM1',
'COM2',
'COM3',
'COM4',
'COM5',
'COM6',
'COM7',
'COM8',
'COM9',
'LPT1',
'LPT2',
'LPT3',
'LPT4',
'LPT5',
'LPT6',
'LPT7',
'LPT8',
'LPT9',
];
for (let invalidName of invalidNames) {
should(isValidBasename(formatFileName(invalidName))).equal(isWindows ? false : true);
should(isValidBasename(invalidName)).equal(isWindows ? false : true);
}
});
});
@@ -92,76 +94,77 @@ suite('Check for invalid filename tests', function (): void {
suite('Check for invalid filename error tests', function (): void {
test('Should determine invalid filenames', async () => {
// valid filename
should(isValidBasenameErrorMessage(formatFileName('ValidName.sqlproj'))).equal('');
should(isValidBasenameErrorMessage('ValidName')).equal(undefined);
// invalid for both Windows and non-Windows
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName(' .sqlproj'))).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(formatFileName('..sqlproj'))).equal(constants.reservedValueErrorMessage);
should(isValidBasenameErrorMessage(formatFileName('...sqlproj'))).equal(constants.reservedValueErrorMessage);
should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage('.')).equal(constants.filenameEndingIsPeriodErrorMessage);
should(isValidBasenameErrorMessage('..')).equal(constants.filenameEndingIsPeriodErrorMessage);
should(isValidBasenameErrorMessage(undefined)).equal(constants.undefinedFilenameErrorMessage);
should(isValidBasenameErrorMessage('\\')).equal(isWindows ? constants.whitespaceFilenameErrorMessage : constants.invalidFileCharsErrorMessage);
should(isValidBasenameErrorMessage('/')).equal(constants.whitespaceFilenameErrorMessage);
should(isValidBasenameErrorMessage('\\')).equal(constants.invalidFileCharsErrorMessage);
should(isValidBasenameErrorMessage('/')).equal(constants.invalidFileCharsErrorMessage);
should(isValidBasenameErrorMessage(' ')).equal(constants.whitespaceFilenameErrorMessage);
// most file systems do not allow files > 255 length
should(isValidBasenameErrorMessage(formatFileName('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.sqlproj'))).equal(constants.tooLongFilenameErrorMessage);
should(isValidBasenameErrorMessage('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).equal(constants.tooLongFilenameErrorMessage);
});
test('Should determine invalid Windows filenames', async () => {
let invalidNames: string[] = [
// invalid characters only for Windows
'?.sqlproj',
':.sqlproj',
'*.sqlproj',
'<.sqlproj',
'>.sqlproj',
'|.sqlproj',
'".sqlproj'
'?',
':',
'*',
'<',
'>',
'|',
'"',
'\\',
'/'
];
for (let invalidName of invalidNames) {
should(isValidBasenameErrorMessage(formatFileName(invalidName))).equal(isWindows ? constants.invalidFileCharsErrorMessage : '');
should(isValidBasenameErrorMessage(invalidName)).equal(isWindows ? constants.invalidFileCharsErrorMessage : '');
}
// Windows filenames cannot end with a whitespace
should(isValidBasenameErrorMessage(formatFileName('test .sqlproj'))).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
should(isValidBasenameErrorMessage(formatFileName('test .sqlproj'))).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
// Windows filenames cannot start or end with a whitespace
should(isValidBasenameErrorMessage('test ')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
should(isValidBasenameErrorMessage('test ')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
should(isValidBasenameErrorMessage(' test')).equal(isWindows ? constants.trailingWhitespaceErrorMessage : '');
});
test('Should determine Windows forbidden filenames', async () => {
let invalidNames: string[] = [
// invalid only for Windows
'CON.sqlproj',
'PRN.sqlproj',
'AUX.sqlproj',
'NUL.sqlproj',
'COM1.sqlproj',
'COM2.sqlproj',
'COM3.sqlproj',
'COM4.sqlproj',
'COM5.sqlproj',
'COM6.sqlproj',
'COM7.sqlproj',
'COM8.sqlproj',
'COM9.sqlproj',
'LPT1.sqlproj',
'LPT2.sqlproj',
'LPT3.sqlproj',
'LPT4.sqlproj',
'LPT5.sqlproj',
'LPT6.sqlproj',
'LPT7.sqlproj',
'LPT8.sqlproj',
'LPT9.sqlproj',
'CON',
'PRN',
'AUX',
'NUL',
'COM1',
'COM2',
'COM3',
'COM4',
'COM5',
'COM6',
'COM7',
'COM8',
'COM9',
'LPT1',
'LPT2',
'LPT3',
'LPT4',
'LPT5',
'LPT6',
'LPT7',
'LPT8',
'LPT9',
];
for (let invalidName of invalidNames) {
should(isValidBasenameErrorMessage(formatFileName(invalidName))).equal(isWindows ? constants.reservedWindowsFilenameErrorMessage : '');
should(isValidBasenameErrorMessage(invalidName)).equal(isWindows ? constants.reservedWindowsFilenameErrorMessage : '', `InvalidName that failed:${invalidName}`);
}
});
});
function formatFileName(filename: string): string {
return path.join(os.tmpdir(), filename);
}

View File

@@ -182,20 +182,20 @@
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd"
integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==
"@microsoft/ads-extension-telemetry@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-2.0.0.tgz#18ce267c7ed05c3b9dd99604a743e59f684c4e7c"
integrity sha512-hExe/akhgq15v/h19LAFqiKNV6N9VxD19lOwGxEmO55yoWUm3E2cYealxvoYCwGDmSJfCbjR9fz/KM8Yz4XWAA==
"@microsoft/ads-extension-telemetry@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/ads-extension-telemetry/-/ads-extension-telemetry-3.0.1.tgz#82d4288f8ad96920512ab4edf87d009412e683bb"
integrity sha512-OsHLKvz4DEZg9THkI+Jk4aINgYv4X3qgbqnVAqY8f9zsWTiR+o4vt/F5w0w3kwpbU3ppRHa03yFTBEjYyGSg1g==
dependencies:
"@vscode/extension-telemetry" "0.6.1"
"@microsoft/azdata-test@^2.0.3":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-2.0.3.tgz#652984efa2f5adc56cdae9029a4d5f33446b54d3"
integrity sha512-BgB6gGjQVXxnZHq7o5TlajZR/mJd/6AqbclrGzoyATvCEt92jRXhPzaY6XA/jMahdUGFSQwXpm45qRhZetwDig==
"@microsoft/azdata-test@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@microsoft/azdata-test/-/azdata-test-3.0.1.tgz#a8b89a12de42f277d33aae71c277d0c8efcfbee0"
integrity sha512-Zrctm/zKufwIRF9jfw8TOBzr5woLdKXAGNTlbAQl0IGLzVoIGULj9Gqdc1Ikhrov3rM0NkbAF/PY6j6BHiW8Tw==
dependencies:
http-proxy-agent "^2.1.0"
https-proxy-agent "^2.2.4"
http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
mocha-junit-reporter "^1.17.0"
mocha-multi-reporters "^1.1.7"
rimraf "^2.6.3"
@@ -273,6 +273,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
"@tootallnate/once@2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@types/mocha@^7.0.2":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
@@ -295,12 +300,12 @@
resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.6.1.tgz#f8d1f7145baf932b75077c48107edff48501fc14"
integrity sha512-Y4Oc8yGURGVF4WhCZcu+EVy+MAIeQDLDVeDlLn59H0C1w+7xr8dL2ZtDBioy+Hog1Edrd6zOwr3Na7xe1iC/UA==
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
agent-base@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
es6-promisify "^5.0.0"
debug "4"
ansi-colors@3.2.3:
version "3.2.3"
@@ -466,13 +471,6 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@3.2.6, debug@^3.1.0:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -480,6 +478,13 @@ debug@3.2.6, debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
debug@^2.2.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@@ -574,18 +579,6 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^4.0.3:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-promisify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==
dependencies:
es6-promise "^4.0.3"
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"
@@ -796,21 +789,22 @@ html-escaper@^2.0.0:
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"
integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
dependencies:
agent-base "4"
debug "3.1.0"
"@tootallnate/once" "2"
agent-base "6"
debug "4"
https-proxy-agent@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "^4.3.0"
debug "^3.1.0"
agent-base "6"
debug "4"
inflight@^1.0.4:
version "1.0.6"
@@ -1191,6 +1185,11 @@ ms@2.1.1, ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nise@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd"

View File

@@ -35,7 +35,7 @@ This extension adds Data Virtualization support for SQL Server 2019 and above. T
## Telemetry
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting#how-to-disable-telemetry-reporting) documentation.
This extension collects telemetry data, which is used to help understand how to improve the product. For example, this usage data helps to debug issues, such as slow start-up times, and to prioritize new features. While we appreciate the insights this data provides, we also know that not everyone wants to send usage data and you can disable telemetry as described in the Azure Data Studio [disable telemetry reporting](https://aka.ms/ads-disable-telemetry) documentation.
## Privacy Statement

View File

@@ -3,13 +3,7 @@
"relativeSourcePath": "..",
"relativeCoverageDir": "../../coverage",
"ignorePatterns": [
"**/node_modules/**",
"**/libs/**",
"**/lib/**",
"**/htmlcontent/**/*.js",
"**/*.bundle.js",
"**/markdown-language-features/**",
"**/media/*.js"
"**/node_modules/**"
],
"includePid": false,
"reports": [

View File

@@ -2,7 +2,7 @@
"name": "datavirtualization",
"displayName": "%title.datavirtualization%",
"description": "%config.extensionDescription%",
"version": "1.13.1",
"version": "1.13.2",
"publisher": "Microsoft",
"icon": "resources/extension.png",
"aiKey": "29a207bb14f84905966a8f22524cb730-25407f35-11b6-4d4e-8114-ab9e843cb52f-7380",
@@ -105,14 +105,14 @@
}
},
"dependencies": {
"@microsoft/ads-extension-telemetry": "^2.0.0",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.2",
"vscode-nls": "^5.2.0"
},
"devDependencies": {
"@microsoft/azdata-test": "^3.0.2",
"@microsoft/vscodetestcover": "^1.2.1",
"mocha": "^7.1.1",
"should": "^13.2.1",
"typemoq": "^2.1.0"
}

View File

@@ -6,11 +6,9 @@
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { ApiWrapper } from './apiWrapper';
import { TreeNode } from './treeNodes';
import { QuestionTypes, IPrompter, IQuestion } from './prompts/question';
import * as utils from './utils';
import * as constants from './constants';
import { AppContext } from './appContext';
@@ -121,55 +119,3 @@ export abstract class Command extends vscode.Disposable {
return [{ command: command, type: 'unknown', editor: editor }, args];
}
}
export abstract class ProgressCommand extends Command {
static progressId = 0;
constructor(private command: string, protected prompter: IPrompter, appContext: AppContext) {
super(command, appContext);
}
protected async executeWithProgress(
execution: (cancelToken: vscode.CancellationTokenSource) => Promise<void>,
label: string,
isCancelable: boolean = false,
onCanceled?: () => void
): Promise<void> {
let disposables: vscode.Disposable[] = [];
const tokenSource = new vscode.CancellationTokenSource();
const statusBarItem = this.apiWrapper.createStatusBarItem(vscode.StatusBarAlignment.Left);
disposables.push(vscode.Disposable.from(statusBarItem));
statusBarItem.text = localize('progress', '$(sync~spin) {0}...', label);
if (isCancelable) {
const cancelCommandId = `cancelProgress${ProgressCommand.progressId++}`;
disposables.push(this.apiWrapper.registerCommand(cancelCommandId, async () => {
if (await this.confirmCancel()) {
tokenSource.cancel();
}
}));
statusBarItem.tooltip = localize('cancelTooltip', 'Cancel');
statusBarItem.command = cancelCommandId;
}
statusBarItem.show();
try {
await execution(tokenSource);
} catch (error) {
if (isCancelable && onCanceled && tokenSource.token.isCancellationRequested) {
// The error can be assumed to be due to cancelation occurring. Do the callback
onCanceled();
} else {
throw error;
}
} finally {
disposables.forEach(d => d.dispose());
}
}
private async confirmCancel(): Promise<boolean> {
return await this.prompter.promptSingle<boolean>(<IQuestion>{
type: QuestionTypes.confirm,
message: localize('cancel', 'Cancel operation?'),
default: true
});
}
}

View File

@@ -79,6 +79,7 @@ export class FileNode extends HdfsFileSourceNode implements IFileNode {
errorMessage: undefined,
metadata: undefined,
nodePath: this.generateNodePath(),
parentNodePath: this.parent?.generateNodePath() ?? '',
nodeStatus: undefined,
nodeType: Constants.HdfsItems.File,
nodeSubType: this.getSubType(),

View File

@@ -30,7 +30,7 @@ export class ServiceClient {
const config: IConfig = JSON.parse(rawConfig.toString());
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
config.proxy = this.apiWrapper.getConfiguration('http').get('proxy');
config.strictSSL = this.apiWrapper.getConfiguration('http').get('proxyStrictSSL') || true;
config.strictSSL = this.apiWrapper.getConfiguration('http').get('proxyStrictSSL', true);
const serverdownloader = new ServerProvider(config);
serverdownloader.eventEmitter.onAny(this.generateHandleServerProviderEvent());

View File

@@ -3,26 +3,9 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as IstanbulTestRunner from '@microsoft/vscodetestcover';
let testRunner: any = IstanbulTestRunner;
import { getDefaultMochaOptions } from '@microsoft/azdata-test';
import * as testRunner from '@microsoft/vscodetestcover';
// You can directly control Mocha options by uncommenting the following lines
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
testRunner.configure(
// Mocha Options
{
ui: 'bdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
reporter: 'pm-mocha-jenkins-reporter',
reporterOptions: {
junit_report_name: 'Extension Tests',
junit_report_path: __dirname + '/../../test-reports/extension_tests.xml',
junit_report_stack: 1
},
useColors: true // colored output from test results
},
// Coverage configuration options
{
coverConfig: '../../coverconfig.json'
});
testRunner.configure(getDefaultMochaOptions('Data Virtualization Extension Tests'), { coverConfig: '../../coverConfig.json' });
module.exports = testRunner;
export = testRunner;

View File

@@ -1,47 +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 fs from 'fs';
import { IFileSource, IFile } from '../fileSources';
export class MockFileSource implements IFileSource {
filesToReturn: Map<string, IFile[]>;
constructor() {
this.filesToReturn = new Map<string, IFile[]>();
}
enumerateFiles(filePath: string): Promise<IFile[]> {
let files: IFile[] = this.filesToReturn.get(filePath);
return Promise.resolve(files);
}
mkdir(dirName: string, remoteBasePath: string): Promise<void> {
return Promise.resolve(undefined);
}
writeFile(localFile: IFile, remoteDir: string): Promise<string> {
return Promise.resolve(undefined);
}
delete(filePath: string): Promise<void> {
throw new Error('Method not implemented.');
}
readFile(filePath: string, maxBytes?: number): Promise<Buffer> {
throw new Error('Method not implemented.');
}
readFileLines(path: string, maxLines: number): Promise<Buffer> {
throw new Error("Method not implemented.");
}
createReadStream(filePath: string): fs.ReadStream {
throw new Error('Method not implemented.');
}
exists(filePath: string): Promise<boolean> {
throw new Error('Method not implemented.');
}
}

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