Compare commits

...

161 Commits

Author SHA1 Message Date
erpett
bdb81bc9b1 Updating Changelog with Hotfix notes (#18760) 2022-03-17 11:15:28 -07:00
Kim Santiago
023e10b496 Add preview and bump versions (#18749) 2022-03-17 10:47:50 -07:00
csigs
27cb693bd5 LEGO: check in for main to temporary branch. (#18759) 2022-03-17 10:29:37 -07:00
Barbara Valdez
80a9d94648 Update SQL Bindings API (#18748)
* refactor addSqlBindingQuickpick so they can be called using sql-bindings api
2022-03-17 00:21:49 -07:00
Alex Ma
6fad30bf3c added changes to sql xlf (#18753) 2022-03-16 17:00:06 -07:00
Aasim Khan
a0c2dc199e Adding Execution Plan Editor to ADS (#18696)
* Pushing Execution Plan Editor

* Renaming class
Handling error

* Awaiting for handlers to be registered

* Addressing some PR comments

* Fixing return type for provider

* Fixing editor id and removing unnecessary overrides

* Adding a namespace

* adding execution plan namespace

* Adding protocol comment

* Fixing if logic

* Fixing error message

* Cleaning up code

* cleanup code

* Adding help comments

* Fixing method call

* Using path.ts to get the base file name

* converting to lambda functions

* Adding comment for run action

* Fixing pr comments

* Fixing editor label

* Fixing doc comments

* Adding some more comments

* Fixign branding in comments
2022-03-16 15:07:29 -07:00
Cory Rivera
95980130c8 Correctly handle creating and saving untitled notebook .dib files. (#18744) 2022-03-16 14:37:21 -07:00
Alex Ma
8cc0fdfdc5 [Loc] update to data-workspace xlf (#18747) 2022-03-16 12:23:01 -07:00
csigs
f83605cbf4 LEGO: check in for main to temporary branch. (#18746) 2022-03-16 09:29:36 -07:00
Kim Santiago
90d6defa05 Add select target platform to new project quickpick (#18731)
* add step to choose target platform in new project quickpick

* add comment

* only splice if the default target platform index isn't -1

* change 3 to 5 in comment
2022-03-15 18:07:41 -07:00
Alan Ren
ca904ed380 Add comment for serialization provider api (#18718)
* promote serialization provider api

* Revert "promote serialization provider api"

This reverts commit df9bec3e58ff78dc611886ccda34381f365ef73e.

* update

* make dataType a string
2022-03-15 17:55:35 -07:00
Alan Ren
784a9270c8 fix the issue that chart axis's min/max value can't be zero (#18743)
* fix chart option issue

* pr comment
2022-03-15 17:55:16 -07:00
Vasu Bhog
d585e75706 Add rest of sql-bindings/azure funcs logic to sql bindings ext (#18733)
* refactor the rest of azure function and sql binding

* remove vscode-mssql typings that are moved to our sql-bindings ext
2022-03-15 15:10:42 -07:00
Alex Ma
01509de495 [Loc] small update to sql-migration xlf (#18740) 2022-03-15 12:19:24 -07:00
Raymond Truong
fa227c88c9 [SQL Migration] Add state check to target MI resource on target selection page (#18673)
* Add MI ready state check and error message

* Fix a typo

* Update error message logic

* Update '(Unavailable)' prefix to be localized string

* Show error messsage when non-Ready MI is initially selected (not just on Next button)

* Update error message with appropriate casing and actionable step
2022-03-15 10:45:43 -07:00
Alex Ma
cb607e34d7 [Loc] update to data-workspace and sql-bindings xlfs (#18732) 2022-03-14 17:20:28 -07:00
Kim Santiago
de9a4e02b1 add SDK style option to new project quickpick (#18724)
* add SDK style option to new project quickpick

* addressing comments
2022-03-14 16:10:51 -07:00
Alan Ren
820838fae8 vbump sts (#18727) 2022-03-14 15:49:27 -07:00
Alan Ren
85f1f3e0dc vbump slickgrid to bring in an accessibility fix (#18722)
* vbump slickgrid

* include yarn.lock

* update remote folder

* yarn.lock for remote folder

* web
2022-03-14 14:20:48 -07:00
Vasu Bhog
2d1ffeb47c Refactor vscode-mssql sql bindings logic to sql bindings ext (#18725)
* wip for refactor of mssql to sql-bindings

* remove STS dependency

* work to bring function over and setup with vscodeMsql APIs

* copy typings from vscode-mssql
2022-03-14 13:07:27 -07:00
Alex Ma
a86301312c [Loc] update to data-workspace xlf and sql xlf (#18726) 2022-03-14 13:00:53 -07:00
Cory Rivera
206188f3ab Add missing onNotebook:* activation event for VS Code notebook compatibility. (#18710) 2022-03-14 10:32:26 -07:00
Aditya Bist
d8a8107dc6 default to native credential service in linux (#18716) 2022-03-14 10:13:18 -07:00
Alex Ma
26e6cd28c2 Add account loading screen until provider accounts have finished loading (#18692)
* Added wait for accounts to be loaded to prevent premature loading

* revert changes

* WIP loading screen

* added work in progress emitter.

* added test event fire

* added test for accountDialogController emitter

* fixed test

* added event emitters inside accountDialog

* WIP changes to loading

* added fixed filter removed unnecessary emitters

* added working loading page

* fix for spaces

* added improvements

* fixed space

* added loading provider label xlf

* moved spinner = false to show views

* Added loadingSpinner

* removed additional localization

* removed change to css

* removed newline

* small changes

* fixed spaces

* fixed line positions

* removed loadingComplete

* added spinner container (so that account loading spinner appears on top)

* added small fix

* changed wording

* changed wording slightly

* removed comment
2022-03-14 09:44:09 -07:00
csigs
02093f8497 LEGO: check in for main to temporary branch. (#18715) 2022-03-14 09:25:17 -07:00
csigs
62a0bcc69f LEGO: check in for main to temporary branch. (#18713) 2022-03-14 09:25:01 -07:00
Kim Santiago
7181d4c79e Make SDK-style project a checkbox option instead of separate template (#18698)
* switch to using a checkbox instead of separate template for new SDK style project

* let project provider provide sdk learn more url

* Reorder
2022-03-11 16:54:53 -08:00
Alan Ren
4551329db0 table designer bug fixes (#18701)
* table designer bug fixes

* pr comments

* fix debounce issue
2022-03-11 12:14:51 -08:00
Alex Ma
5c14fe4f4c [Loc] small update to sql-migration (#18708) 2022-03-11 10:09:22 -08:00
Raymond Truong
d1d6b229ce [SQL Migration] Add more help text to database backup page (#18671)
* Add help text for backups with checksums and Azure storage accounts with private endpoints

* Update help text wording
2022-03-11 09:53:50 -08:00
Raymond Truong
94b4437a6a [SQL Migration] Fix SKU recommendations not working for named (non-default) instances (#18697)
* WIP

* Change instance name from machine name to full instance name returned by assessment

* Get full instance name from source connection profile instead of relying on assessment result

* Combine correct machine name with correct instance name
2022-03-11 09:49:44 -08:00
csigs
ebdfea25ad LEGO: check in for main to temporary branch. (#18706) 2022-03-11 09:30:37 -08:00
Kim Santiago
5f2d8b2bd5 remove sql server 2005 and 2008 as options for sql database projects (#18664)
* remove sql server 2005 and 2008 from target platforms

* also remove 2005 and 2008 from SqlTargetPlatform enum

* fix a windows test
2022-03-10 18:11:49 -08:00
Raymond Truong
85d6b2ef46 [SQL Migration] Fix overflow behavior on migration cutover dialog to avoid truncating backup file names (#18679) 2022-03-10 15:50:28 -08:00
Vasu Bhog
f424bea0de Fixes issues with SQL Bindings vscode dev (#18695)
* fixes issues with vscode development
2022-03-10 15:37:23 -08:00
Charles Gagnon
364684c79e Move some more azdata APIs to stable (#18691)
* Move some more apis to stable

* update
2022-03-10 11:01:11 -08:00
Alan Ren
4d7467a5d5 promote some APIs to stable api set. (#18689) 2022-03-09 19:29:06 -08:00
Aasim Khan
b299f7ed3f Making infobox clickable (#18676)
* Making infobox clickable

* Making it accessible

* Moving API to proposed

* Matching styling from portal

* Fixing some styling

* Moving to proposed

* Removing extra spacing

* Registering and Unregistering listeners

* Fixing listeners

* Registering emitter only once.

* Changing emitter type from undefined to void

* Adding arialabel to clickable link

* Changing property name to suit its purpose
2022-03-09 18:43:39 -08:00
Vasu Bhog
0c54c12772 Add SQL Binding Tests (#18687)
* add tests
2022-03-09 16:35:51 -08:00
Alex Ma
65b4847874 [Loc] add table designer XLF (#18688) 2022-03-09 16:07:59 -08:00
Alex Ma
33d2735970 Added fix to sql-bindings nls file (#18686)
* Added fix to sql-bindings nls file

* small fix to text
2022-03-09 15:49:14 -08:00
Aditya Bist
822199c9be add ability for md + text reports (#18667)
* add ability for md + text reports

* change report type

* re add types for ads

* match fields and add enum for mimetype

* rename preview report

* update type

* rename generate report type

* fix comment
2022-03-09 15:48:21 -08:00
Alan Ren
e50bded5d1 table designer new features (#18682)
* support graph tables

* ignore script compare

* ability to refresh view after edit

* reserve focus after refresh view

* primary key and default constraint

* bug fixes

* vbump sts

* comments

* update type

* fix issue
2022-03-09 14:17:01 -08:00
Charles Gagnon
27763c860c Add option to not publish source maps (#18683)
* Test PR

* fix
2022-03-09 11:12:58 -08:00
Alex Ma
634b9f8d08 [Loc] update to sql-bindings xlf file (#18685) 2022-03-09 09:39:10 -08:00
Karl Burtram
3844638156 Turn off Windows Test step (#18684) 2022-03-09 09:33:49 -08:00
Vasu Bhog
eb77d86136 Refactor SQL Binding code over from sql-database-projects (#18674)
* add sql binding prompt / logic

* remove controller and move to extension

* remove unused dependencies
2022-03-09 01:02:37 -08:00
Charles Gagnon
025e0831e7 Add var to let smoke tests fail build (#18677)
* Add var to let smoke tests fail build

* force failure

* try another

* fix

* undo failure

* update titles
2022-03-08 13:44:57 -08:00
Kim Santiago
5bb35d4eed update Microsoft.Build.Sql version to 0.1.3-preview in templates (#18659) 2022-03-07 17:34:30 -08:00
Cory Rivera
f013a88163 Only update active cell if the cell isn't currently in edit mode. (#18672) 2022-03-07 17:11:05 -08:00
Alex Ma
4f9d45335e [Loc] added small fix to sql-bindings (#18669) 2022-03-07 15:25:16 -08:00
Vasu Bhog
fee8e78011 fix display name and description key (#18666) 2022-03-07 13:22:44 -08:00
Aditya Bist
1be5c926d3 added markdown renderer for publish dialog (#18645) 2022-03-07 10:57:37 -08:00
csigs
72632bc376 LEGO: check in for main to temporary branch. (#18658)
Co-authored-by: Alex Ma <alma1@microsoft.com>
2022-03-07 10:21:51 -08:00
csigs
9890cc79c0 LEGO: check in for main to temporary branch. (#18656) 2022-03-07 09:40:13 -08:00
csigs
b3107dc4b1 LEGO: check in for main to temporary branch. (#18653) 2022-03-07 09:40:01 -08:00
Cory Rivera
eccb77aca3 Preserve previous code cell's language when creating a new code cell from an existing context. (#18646) 2022-03-06 21:35:57 -08:00
Alex Ma
5d0f0afdc6 [Loc] Updates to sql files with changes (#18648) 2022-03-04 16:41:04 -08:00
Rachel Kim
33259764f7 [Sql Migration] Stabilize save and close logic and fix related ux bugs (#18579)
* add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo

* * add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo
* replaced savedInfo.miggrationServiceId string with sqlMigrationServer object
* selectDatbasesFromList helper function to check previously selected dbs in dbSelectorPage and sqlDatabaseTree

* * remove savedInfo references from targetSelectionPage, migrationModePage
* add selectDefaultDropdownValue helper to stateMachine to handle unify savedInfo selection logic
* add updateDropdownLoadingStatus to targetSelectionPage
* check if values exist before making api calls in statemachine

* removed savedInfo references from databaseBackupPage, integrationRuntimePage

* databaseBackupPage - targetDatabaseNames, networkShares, blobs need to rely on savedInfo as user may update the list of migrationdbs during the retry/saveAndClose

* re-add serverAssessments to savedInfo; only getAssessments if it does not exist or needs to be updated; fix networkShare type savedInfo

* rename _assessmentDbs to _databasesForAssessment; _migrationDbs to _databasesForMigration

* load blobs/networkshares savedinfo; move selectDefaultDropdownValue to utils

* fix selectDefaultDropdownValue; refreshDatabaseBackupPage when user changes target subscription or location
2022-03-04 16:00:44 -08:00
Vasu Bhog
c9aa3e9f4b Boilerplate for SQL Bindings Extension (#18624)
* boilerplate for sql bindings extension

* edit gulpfile task as it was trying to find specific menus within package.json
2022-03-04 15:16:45 -08:00
Leila Lali
8e9957adbe SQLProj: No docker image build needed for deploying a database to docker (#18629) 2022-03-04 14:32:43 -08:00
Charles Gagnon
442c16bc3c Fix tempdb icon not showing on dev builds (#18633) 2022-03-04 13:10:46 -08:00
Charles Gagnon
1c83aa61d7 Fix error displayed when insights files can't be found and fix server-report insights in dev build (#18635)
* Fix error

* fix queries
2022-03-04 13:10:35 -08:00
Kim Santiago
9e3d678536 add learn more link for sdk style in create project from db dialog (#18637) 2022-03-04 13:00:21 -08:00
Charles Gagnon
9a944b614d Fix some more images not loading (#18632) 2022-03-04 11:03:13 -08:00
Alex Ma
bc78f6a573 [Loc] fixed path for editableDropdown (#18634) 2022-03-04 10:29:24 -08:00
csigs
da076c152c LEGO: check in for main to temporary branch. (#18628) 2022-03-04 09:57:56 -08:00
Aditya Bist
a2c39369c9 Add and move editable dropdown (#18589)
* add and move editable dropdown

* merge dropdowns

* merge dropdown cell factories

* add new column and hide in properties

* remove editable property
2022-03-03 20:23:20 -08:00
Alex Ma
be6b23eff0 [Loc] added small change to kernelRequiresConnection (#18627) 2022-03-03 16:25:26 -08:00
Cory Rivera
0ab4752643 Add new errorCode property to notebook errors to see if starting a notebook session failed. (#18617) 2022-03-03 14:05:54 -08:00
Charles Gagnon
10ff8aa116 Fix pinned app name (#18623)
* Fix pinned name on Windows

* fix distro
2022-03-03 12:43:28 -08:00
Neetu Singh
4f61be2495 Fixing telemetry (#18616)
* Fix Telemetry

* Removing unused imports
2022-03-03 11:39:52 -08:00
csigs
d5fa5fca3a LEGO: check in for main to temporary branch. (#18620) 2022-03-03 09:43:28 -08:00
Barbara Valdez
8b543d1d12 check find widget is not focused (#18506)
* remove logic to check that the find widget is visible
2022-03-02 16:57:37 -08:00
Alex Ma
87f1e26e39 [Loc] added changes for sql xlf (#18613) 2022-03-02 14:49:43 -08:00
Karl Burtram
9990f7c8e2 Disable smoke tests (#18611) 2022-03-02 12:56:33 -08:00
dependabot[bot]
d6a08a60d9 Bump plist from 3.0.1 to 3.0.4 (#18604)
Bumps [plist](https://github.com/TooTallNate/node-plist) from 3.0.1 to 3.0.4.
- [Release notes](https://github.com/TooTallNate/node-plist/releases)
- [Changelog](https://github.com/TooTallNate/plist.js/blob/master/History.md)
- [Commits](https://github.com/TooTallNate/node-plist/commits)

---
updated-dependencies:
- dependency-name: plist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-02 12:12:00 -08:00
csigs
628c8da716 LEGO: check in for main to temporary branch. (#18609) 2022-03-02 11:49:17 -08:00
Cory Rivera
79cda5cbe5 Add language picker to notebook cells. (#18601) 2022-03-02 10:25:55 -08:00
dependabot[bot]
c34de52a03 Bump plist from 3.0.1 to 3.0.4 in /build (#18607)
Bumps [plist](https://github.com/TooTallNate/node-plist) from 3.0.1 to 3.0.4.
- [Release notes](https://github.com/TooTallNate/node-plist/releases)
- [Changelog](https://github.com/TooTallNate/plist.js/blob/master/History.md)
- [Commits](https://github.com/TooTallNate/node-plist/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-02 09:59:15 -08:00
dependabot[bot]
eb928e0b8f Bump url-parse from 1.5.8 to 1.5.10 in /extensions/notebook (#18608)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.8 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.8...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-02 09:56:51 -08:00
Christopher Suh
84001139cc Update CI to windows-2019 (#18606)
* Revert "Update CI for new windows-latest (#18585)"

This reverts commit ebd4c6844b.

* update to windows-2019
2022-03-01 18:26:58 -08:00
Charles Gagnon
00f98457e8 Add a couple Notebook smoke tests for rendering links/imgs (#18600) 2022-03-01 13:14:19 -08:00
Christopher Suh
ebd4c6844b Update CI for new windows-latest (#18585)
* change to windows-2019

* fix for windows-latest
2022-02-28 18:20:12 -08:00
Charles Gagnon
3b4800de51 Remove duplicate AzureResource enum (#18501)
* Remove duplicate AzureResource enum

* comment
2022-02-28 12:19:38 -08:00
Charles Gagnon
7b5117b185 Fix yarn.lock version resolution (#18575) 2022-02-28 11:50:39 -08:00
Alex Ma
d36b755d6d [Loc] update to sql.xlf (#18574) 2022-02-28 10:18:26 -08:00
csigs
96729a4817 LEGO: check in for main to temporary branch. (#18564) 2022-02-28 09:50:09 -08:00
csigs
d8fd5b36f7 LEGO: check in for main to temporary branch. (#18509)
Co-authored-by: Alex Ma <alma1@microsoft.com>
2022-02-28 09:49:45 -08:00
Christopher Suh
dfa6799fcc Add label instructions for Needs Logs - Azure (#18559)
* added instructions for Needs Logs - Azure label

* formatting fixes
2022-02-27 15:21:16 -08:00
Benjin Dubishar
c64655ae71 Benjin/project update bug (#18532)
* correct result.success

* shifting success message to actually check success

* keying on errorMessage rather than success
2022-02-25 16:59:28 -08:00
erpett
5e93f2ca9b bumping version to 1.36 following 1.35's release (#18560) 2022-02-25 16:31:19 -08:00
erpett
7db7c2927c fixing links that got swapped (#18557) 2022-02-25 12:46:02 -08:00
Cory Rivera
ffdefd3b52 Add notebook extension support for .NET Interactive. (#18334)
* Also updated kernel dropdown to only include SQL aliased kernels when using SQL notebook provider.
2022-02-25 11:58:59 -08:00
Aasim Khan
02341088eb Renaming query plan to execution plan (#18551) 2022-02-25 00:49:34 -08:00
Charles Gagnon
8032f59d41 Update ubuntu-latest for update typings pipeline (#18552) 2022-02-24 16:02:38 -08:00
erpett
0193f8a6dc Updating Readme and Changelog for 1.35.0 release (#18543) 2022-02-24 14:46:25 -08:00
Charles Gagnon
23cbb98162 Fix Mac signing (#18534)
* Install .NET SDK for Mac signing

* Install runtime

* Specify 2.1.0

* Install SDK
2022-02-23 08:31:14 -08:00
Charles Gagnon
9b3d65b1d4 Bump url-parse (#18535) 2022-02-23 07:22:26 -08:00
Alan Ren
e2b4dd5a79 define the color in theme files (#18529) 2022-02-22 16:03:58 -08:00
Aasim Khan
19c7971630 Bringing back leftover changes (#18527) 2022-02-22 15:44:01 -08:00
Aasim Khan
5731366a1c Fixing query editor smoke test (#18515)
* Fixing query editor smoke test

* Fixing notification toast for telemetry opt out

* Adding SQL Carbon edit
2022-02-22 14:15:12 -08:00
Candice Ye
ef100b8e82 Bumped versions of arc and azcli to 1.0.0 for GA (#18516)
* Changed versions in package.jsons

* Bumped azdata version requirements to 1.35
2022-02-22 13:56:50 -08:00
Kim Santiago
7b92c9eb65 only show confirmation message for apply all changes, not for view changes in schema compare (#18520) 2022-02-22 13:33:24 -08:00
Charles Gagnon
5547c2baba Add AzureAccount service (#18502) 2022-02-22 09:00:07 -08:00
Alan Ren
40ee82ee3e highlight problematic property in the designer when error is selected (#18512)
* navigate to property when selecting error message

* use list component

* highlight problematic property

* remove unnecessary call

* comment

* comment
2022-02-21 20:49:12 -08:00
csigs
3c84575755 LEGO: check in for main to temporary branch. (#18503) 2022-02-21 12:21:12 -08:00
Aditya Bist
696db01dc8 Fix opt out prompt behavior (#18498)
* fix header

* fix product name
2022-02-18 15:53:59 -08:00
Karl Burtram
e0cb88599d Port - Restrict which sites out webview iframe can frame (#18495)
* protocol handler - normalize paths

* use `extUri` for normalizing paths

* :lipstick;

* Add content security policy to top level webview

This change hardens our webviews by adding a fairly restrictive csp to them. This CSP should only apply to the outer webview iframe, not to the inner iframe which is controlled by extensions

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
Co-authored-by: Matt Bierner <matb@microsoft.com>
2022-02-18 15:12:21 -08:00
Aasim Khan
eff847f35a Removing extra toUrl call (#18492) 2022-02-18 14:49:02 -08:00
Alex Ma
2da0428454 [Loc] small update to sql xlf with table designer (#18489) 2022-02-18 13:31:05 -08:00
Alex Ma
1b63fec4e5 removed max_memory as it should be dynamically managed by sqlserver (#18481) 2022-02-18 12:32:57 -08:00
Karl Burtram
f137174719 Add mxgraph to thirdyparty notices (#18486) 2022-02-18 12:09:07 -08:00
Barbara Valdez
75d9246f5e Fix search experience in notebooks (#18474)
* fix search on notebooks

* keep focus on findwidget
2022-02-18 10:53:45 -08:00
Barbara Valdez
cbaffd0b0d fix section markdown and html link (#18478)
* fix section markdown and html link
2022-02-18 10:08:33 -08:00
Kim Santiago
b33afe3efb add back SDK style project template (#18448) 2022-02-18 09:54:10 -08:00
csigs
19f63ea88f LEGO: check in for main to temporary branch. (#18479) 2022-02-18 09:30:14 -08:00
Charles Gagnon
a1a1793221 Add timeout delay to Notebook cell connect (#18475) 2022-02-18 09:05:13 -08:00
Charles Gagnon
8da49ff14e Remove connection error popup notification (#18476)
* Remove connection error popup notification

* Fix compile
2022-02-18 09:04:13 -08:00
dependabot[bot]
f0ebc6ed60 Bump url-parse from 1.5.2 to 1.5.6 in /samples/sqlservices (#18473)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.2 to 1.5.6.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.2...1.5.6)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-17 22:29:25 -08:00
Neetu Singh
aaf174e85c Update package.json with latest azdata version 1.35 (#18462)
* updating package.json with latest  azdata version 1.35

* bump sql-migration version to 0.1.13
2022-02-17 20:33:01 -08:00
Alan Ren
13dd74efcc fix a typo in table designer (#18464) 2022-02-17 18:24:24 -08:00
Christopher Suh
bafbca492b Clear account tokens before refresh (#18452)
* clear account tokens on refresh

* update refresh button after refresh
2022-02-17 17:25:05 -08:00
Lewis Sanchez
3472e229f1 Adds a tooltip title prop to the diagram node. (#18458)
* Adds a tooltip title prop to the diagram node.

* Updates azdataGraph package version to 0.0.16
2022-02-17 16:18:49 -08:00
Charles Gagnon
3a04235001 Add option to disable running integration tests (#18454) (#18456)
* Add option to disable running integration tests

* succeeded

(cherry picked from commit 932865ceee)
2022-02-17 15:26:22 -08:00
Vasu Bhog
0f385b386f Add SQL Binding Disconnected Scenario (#18440)
* disconnected scenario

* match parameters in mssql
2022-02-17 14:20:13 -08:00
Alan Ren
28ab7372d2 table designer validation support (#18438)
* table designer validation

* vbump sts
2022-02-17 13:07:19 -08:00
Alex Ma
e66192cbfd [loc] changes to sql-migration and sql xlfs (#18447) 2022-02-17 11:11:41 -08:00
Lewis Sanchez
63cff7a5ab Adds Operational Cost to Query Plan Vertex Labels. (#18435)
* Adds operational cost to graph node labels.

* Code clean up.
2022-02-17 10:09:24 -08:00
csigs
f1b23c96a9 LEGO: check in for main to temporary branch. (#18443) 2022-02-17 09:51:28 -08:00
Barbara Valdez
ede0937c2b fix holding down key scrolling issue (#18322)
* Stop propagation + debounce scroll

Co-authored-by: chgagnon <chgagnon@microsoft.com>
2022-02-17 00:25:01 -08:00
Candice Ye
83698a14b0 Fixed color contrast for error message in connect a dc window. (#18411)
* Fixed color contrast for error message in connect a dc window.

* Remove color check for error message

* Remove more unneeded checks

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
2022-02-16 21:06:51 -08:00
Charles Gagnon
2be1394748 Fix contributed icons for ModelView trees not showing (#18430)
* Fix contributed icons for ModelView trees not showing

* Use asCssUrl
2022-02-16 18:10:45 -08:00
Neetu Singh
8135867e06 Updating readme with new gif that includes SKU Recommendation (#18432) 2022-02-16 17:58:34 -08:00
Barbara Valdez
87d5da00bf Fix on click edit mode states (#18321)
* fix click code cell

* modified editmode when updating active cell
2022-02-16 15:52:05 -08:00
Aasim Khan
678f2e3878 Fixing the height of the query plan (#18409)
* Fixing the height of the query plan

* Fixing layout issues
2022-02-16 15:44:33 -08:00
Aasim Khan
81e8eb9a82 Adding zoom button (#18407)
* Adding zoom button

* Fixing string
2022-02-16 15:26:14 -08:00
Aasim Khan
fe360afec7 Fixing context menu strings (#18404)
* Fixing context menu strings

* Fixing string
2022-02-16 15:21:35 -08:00
Neetu Singh
80c8b06ec8 [SKU Recommendation] Adding telemetry for errors happening during data collection/ get recommendation and telemetry (#18345)
* Adding telemetry for errors happening during data collection/ telemetry for sku recommendation

* log and error happended during get sku recommendation

* Resolving comments from PR https://github.com/microsoft/azuredatastudio/pull/18252. 1) Adding click and close events to dispoable collection to avoid leaks. 2) Adding readable constant for number representing minutes.

* Changes - 1) updating migration workflow strings, 2) adding more onclick events to disposable collection.

* Remove PaaS, IaaS terms from string

* Changes -
1) Renamed 'Saved assessment result' to 'saved session'.
2) Removed Title from 'saved session' page.
3) Added stop data collection on migration start.
2022-02-16 14:44:28 -08:00
Alan Ren
7ff42eeb08 make sure the content is not undefined (#18406) 2022-02-16 13:51:50 -08:00
Charles Gagnon
3dbd5ac2c1 Bump url-parse (#18422) 2022-02-16 13:09:19 -08:00
csigs
3c321ee8b7 LEGO: check in for main to temporary branch. (#18419) 2022-02-16 12:22:32 -08:00
csigs
f6128d262b LEGO: check in for main to temporary branch. (#18417) 2022-02-16 12:21:59 -08:00
Kim Santiago
d24a289af5 fix SDK style projects not being able to find system dacpacs (#18218)
* fix SDK style projects not being able to find system dacpacs

* fix tests
2022-02-16 09:36:01 -08:00
Alan Ren
89cc59a2fd avoid auto language detection for sql editor (#18402)
* avoid auto lang detection for sql editor

* update comment
2022-02-15 17:11:43 -08:00
Aasim Khan
25f563229f Adding tooltips and fixing spacing (#18400) 2022-02-15 16:24:40 -08:00
Lewis Sanchez
33ea2d8ee6 azdataGraph version bump to 0.0.15 (#18388)
* azdataGraph version bump to 0.0.15

* Updates azdataGraph version in remote package.json

* Updates azdataGraph version in remote web package.json
2022-02-15 11:57:55 -08:00
Alex Ma
9e8b01fd1e [Loc] small update to sql-database-projects xlf (#18396) 2022-02-15 11:54:03 -08:00
Alex Ma
bb468a5b98 Small update to the changelog (#18369) 2022-02-15 09:50:59 -08:00
Alex Ma
9a28d47c5b Added small fix for locFunc (#18364) 2022-02-14 17:21:46 -08:00
Alex Ma
45763e12b4 Update to langpacks and xlfs for February Release, (#18354)
* Update to langpacks and xlfs

* fixed id for git
2022-02-14 16:36:57 -08:00
Aasim Khan
316c6a536f Fixing graph editing (#18361) 2022-02-14 16:34:30 -08:00
Charles Gagnon
f5392e3c8f Bump ansi_up (#18190) 2022-02-14 16:06:23 -08:00
Aasim Khan
4dd59c6b8d Using proper zoom icon (#18338) 2022-02-14 15:38:55 -08:00
Z Chen
9e574ae602 Database Projects - Add existing file (#18066)
* Add existing file to sqlproj

* Address PR comments

* Fix failing test

* Add convertSlashesForSqlProj to test failure
2022-02-14 15:04:57 -08:00
dependabot[bot]
1dd7e93063 Bump ajv from 6.12.0 to 6.12.6 in /extensions/mssql (#18316)
Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.0 to 6.12.6.
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.0...v6.12.6)

---
updated-dependencies:
- dependency-name: ajv
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 14:19:33 -08:00
dependabot[bot]
13276cf52e Bump follow-redirects from 1.14.7 to 1.14.8 in /extensions/azurecore (#18350)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 11:59:27 -08:00
dependabot[bot]
baa6e4b380 Bump follow-redirects in /extensions/github-authentication (#18348)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 11:59:07 -08:00
Alex Ma
3bc5306258 [Loc] update to sql.xlf and sql-migration (#18352) 2022-02-14 11:39:08 -08:00
csigs
c45cfaf01b LEGO: check in for main to temporary branch. (#18347)
Co-authored-by: Alex Ma <alma1@microsoft.com>
2022-02-14 11:04:35 -08:00
dependabot[bot]
0612a8ac35 Bump follow-redirects in /extensions/resource-deployment (#18349)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-14 10:38:28 -08:00
724 changed files with 111524 additions and 14377 deletions

View File

@@ -212,6 +212,7 @@
"restrictions": [
"vs/nls",
"azdata",
"azurecore",
"**/{vs,sql}/base/common/**",
"**/{vs,sql}/base/parts/*/common/**",
"**/{vs,sql}/platform/*/common/**"
@@ -472,6 +473,7 @@
"restrictions": [
"vscode",
"azdata",
"azurecore",
"vs/nls",
"**/{vs,sql}/base/common/**",
"**/{vs,sql}/platform/*/common/**",
@@ -577,6 +579,7 @@
"vs/nls",
"vs/css!./**/*",
"azdata",
"azurecore",
"vscode",
"**/{vs,sql}/base/**/{common,browser,worker}/**",
"**/{vs,sql}/platform/**/{common,browser}/**",

View File

@@ -27,6 +27,22 @@ There are two types of logs to collect:
- This will open the log folder locally. Please zip up this folder and attach it to the issue."
# actions for Needs Logs - Azure label
Needs Logs - Azure:
comment: "We need more info to debug your Azure Active Directory issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
- In the settings menu, find the setting titled `Azure: Logging Level` and select the `Verbose` option
- Run the process that produces your error
- Open command palette (Click **View** -> **Command Palette**)
- Run the command: **`Developer: Open Logs Folder`**
- Follow this path to find the Azure Accounts log file: `[default log folder]/exthost1/output_logging_[earliest timestamp]/#-Azure Acounts.log`
- Please attach the Azure-Accounts.log file to the issue."
# actions for Out of Scope label
Out of Scope:
comment: "Thank you for opening this suggestion! This enhancement is not planned in our

View File

@@ -13,7 +13,7 @@ on:
jobs:
windows:
name: Windows
runs-on: windows-latest
runs-on: windows-2019
timeout-minutes: 30
env:
CHILD_CONCURRENCY: "1"

View File

@@ -1,5 +1,43 @@
# Change Log
## Version 1.35.1
* Release date: March 17, 2022
* Release status: General Availability
## Hotfix release
- Fix for [Excel number format #18615](https://github.com/microsoft/azuredatastudio/issues/18615)
- Fix for [Geometry Data Type Returned as Unknown Charset in Results Grid #18630](https://github.com/microsoft/azuredatastudio/issues/18630)
| Platform |
| --------------------------------------- |
| [Windows User Installer][win-user] |
| [Windows System Installer][win-system] |
| [Windows ZIP][win-zip] |
| [macOS ZIP][osx-zip] |
| [Linux TAR.GZ][linux-zip] |
| [Linux RPM][linux-rpm] |
| [Linux DEB][linux-deb] |
[win-user]: https://go.microsoft.com/fwlink/?linkid=2187459
[win-system]: https://go.microsoft.com/fwlink/?linkid=2187520
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2187460
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2187461
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2187462
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2187521
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2187522
## Version 1.35.0
* Release date: February 24, 2022
* Release status: General Availability
## What's new in this version
* New Features:
* Table Designer - Added functionality for creation and management of tables for SQL Servers. Built using DacFx framework
* Query Plan Viewer - Added functionality for users to view a graphic view of estimated and actual query plans without need for an extension
* Azure Arc Extension - Updated the Data Controller deployment wizard and the SQL Managed Instance - Azure Arc deployment wizard to reflect the deployment experience in Azure Portal
* Bug Fixes:
* Azure Arc Extension - SQL Managed Instance-Azure Arc is now fixed for both indirect connectivity mode and direct connectivity mode
* Notebooks - Support for keyboard navigation between cells to minimize mouse clicking
## Version 1.34.0
* Release date: December 15, 2021
* Release status: General Availability
@@ -31,26 +69,6 @@
- Fix for [#16535 Unable to See Saved Connections in Restricted Mode](https://github.com/microsoft/azuredatastudio/issues/17535)
- Fix for [#17579 Can't type in Notebook code cell after editing text cell](https://github.com/microsoft/azuredatastudio/issues/17579)
| Platform |
| --------------------------------------- |
| [Windows User Installer][win-user] |
| [Windows System Installer][win-system] |
| [Windows ZIP][win-zip] |
| [macOS ZIP][osx-zip] |
| [Linux TAR.GZ][linux-zip] |
| [Linux RPM][linux-rpm] |
| [Linux DEB][linux-deb] |
[win-user]: https://go.microsoft.com/fwlink/?linkid=2176805
[win-system]: https://go.microsoft.com/fwlink/?linkid=2175910
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2176806
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2176807
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2176505
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2176005
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2176006
## Version 1.33.0
* Release date: October 27, 2021
* Release status: General Availability

View File

@@ -131,10 +131,10 @@ Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [Source EULA](LICENSE.txt).
[win-user]: https://go.microsoft.com/fwlink/?linkid=2183280
[win-system]: https://go.microsoft.com/fwlink/?linkid=2183423
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2183190
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2183189
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2183277
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2183342
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2183341
[win-user]: https://go.microsoft.com/fwlink/?linkid=2187459
[win-system]: https://go.microsoft.com/fwlink/?linkid=2187520
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2187460
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2187461
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2187522
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2187521
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2187462

View File

@@ -45,6 +45,7 @@ make-error: https://github.com/JsCommunity/make-error
mark.js: https://github.com/julmot/mark.js
minimist: https://github.com/substack/minimist
moment: https://github.com/moment/moment
mxgraph: https://github.com/jgraph/mxgraph
native-keymap: https://github.com/Microsoft/node-native-keymap
native-watchdog: https://github.com/Microsoft/node-native-watchdog
ng2-charts: https://github.com/valor-software/ng2-charts
@@ -1538,6 +1539,193 @@ OTHER DEALINGS IN THE SOFTWARE.
=========================================
END OF moment NOTICES AND INFORMATION
%% mxgraph NOTICES AND INFORMATION BEGIN HERE
=========================================
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
(e) Neither the Work nor Derivative Works may be used or form any
part of a larger work that integrates or is supposed to be
integrated with a product or service owned or marketed by an
Atlassian entity, including its successors and assignees in title.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
//SEIBERT/MEDIA GmbH, Wiesbaden, Germany is the exclusive licensee of
JGraph for software products based on this codebase within the Atlassian
ecosystem of products.
=========================================
END OF mxgraph NOTICES AND INFORMATION
%% native-keymap NOTICES AND INFORMATION BEGIN HERE
=========================================
Copyright (c) Microsoft Corporation

View File

@@ -17,6 +17,13 @@ steps:
mv azuredatastudio-darwin-unsigned.zip azuredatastudio-darwin.zip
displayName: 'Rename the file'
- task: UseDotNet@2
displayName: 'Install .NET Core sdk for signing'
inputs:
packageType: sdk
version: 2.1.x
installationPath: $(Agent.ToolsDirectory)/dotnet
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
displayName: 'ESRP CodeSigning'
inputs:

View File

@@ -128,14 +128,24 @@ steps:
yarn gulp compile-extensions
displayName: Compile Extensions
# Per https://developercommunity.visualstudio.com/t/variablesexpressions-dont-work-with-continueonerro/1187733 we can't use variables
# in continueOnError directly so instead make two copies of the task and only run one or the other based on the SMOKE_FAIL_ON_ERROR value
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log" --extensionsDir "$(build.sourcesdirectory)/extensions"
displayName: Run smoke tests (Electron)
displayName: Run smoke tests (Electron) (Continue on Error)
continueOnError: true
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log" --extensionsDir "$(build.sourcesdirectory)/extensions"
displayName: Run smoke tests (Electron) (Fail on Error)
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), eq(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
# - script: |
# set -e

View File

@@ -6,6 +6,9 @@ trigger:
pr: none
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:

View File

@@ -47,7 +47,7 @@ jobs:
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-database-projects"]
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"]
timeoutInMinutes: 90
- job: Windows
@@ -60,16 +60,17 @@ jobs:
- template: win32/sql-product-build-win32.yml
timeoutInMinutes: 90
- job: Windows_Test
condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
pool:
name: mssqltools
dependsOn:
- Linux
- Windows
steps:
- template: win32/sql-product-test-win32.yml
timeoutInMinutes: 90
# disable due to invalid machine pool (karlb 3/9/2022)
# - job: Windows_Test
# condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
# pool:
# name: mssqltools
# dependsOn:
# - Linux
# - Windows
# steps:
# - template: win32/sql-product-test-win32.yml
# timeoutInMinutes: 90
- job: Release
condition: and(succeeded(), or(eq(variables['VSCODE_RELEASE'], 'true'), and(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['Build.Reason'], 'Schedule'))))
@@ -79,7 +80,8 @@ jobs:
- macOS
- Linux
- Windows
- Windows_Test
# disable due to invalid machine pool (karlb 3/9/2022)
# - Windows_Test
- macOS_Signing
steps:
- template: sql-release.yml

View File

@@ -93,6 +93,7 @@ steps:
AZURE_STORAGE_ACCESS_KEY="$(sourcemap-storage-key)" \
node build/azure-pipelines/upload-sourcemaps
displayName: Upload sourcemaps
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
- script: |
set -e

View File

@@ -104,14 +104,26 @@ steps:
yarn gulp compile-extensions
displayName: Compile Extensions
- script: |
set -e
node ./node_modules/playwright/install.js
APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
displayName: Run smoke tests (Browser)
continueOnError: true
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
# disable smoke tests (karlb 3/2/2022)
# # Per https://developercommunity.visualstudio.com/t/variablesexpressions-dont-work-with-continueonerro/1187733 we can't use variables
# # in continueOnError directly so instead make two copies of the task and only run one or the other based on the SMOKE_FAIL_ON_ERROR value
# - script: |
# set -e
# node ./node_modules/playwright/install.js
# APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
# xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
# displayName: Run smoke tests (Browser) (Continue on Error)
# continueOnError: true
# condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
# disable smoke tests (karlb 3/2/2022)
# - script: |
# set -e
# node ./node_modules/playwright/install.js
# APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
# xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
# displayName: Run smoke tests (Browser) (Fail on Error)
# condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), eq(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
# - script: |
# set -e

View File

@@ -51,7 +51,7 @@ steps:
$AppNameShort = $AppProductJson.nameShort
exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; $env:INTEGRATION_TEST_CLI_PATH = "$AppRoot\bin\$AppNameShort"; .\scripts\sql-test-integration.bat }
continueOnError: false
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['RUN_INTEGRATION_TESTS'], 'false')))
displayName: Run stable tests
env:
BDC_BACKEND_USERNAME: $(ads-integration-test-bdc-server-username)
@@ -75,7 +75,7 @@ steps:
$AppNameShort = $AppProductJson.nameShort
exec { $env:INTEGRATION_TEST_ELECTRON_PATH = "$AppRoot\$AppNameShort.exe"; .\scripts\sql-test-integration-unstable.bat }
continueOnError: true
condition: and(succeeded(), eq(variables['RUN_UNSTABLE_TESTS'], 'true'))
condition: and(succeeded(), and(eq(variables['RUN_UNSTABLE_TESTS'], 'true'), ne(variables['RUN_INTEGRATION_TESTS'], 'false')))
displayName: Run unstable integration tests
env:
BDC_BACKEND_USERNAME: $(ads-integration-test-bdc-server-username)
@@ -99,4 +99,4 @@ steps:
mergeTestResults: true
failTaskOnFailedTests: true
continueOnError: true
condition: and(succeededOrFailed(), eq(variables['RUN_TESTS'], 'true'))
condition: and(succeededOrFailed(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['RUN_INTEGRATION_TESTS'], 'false')))

View File

@@ -129,16 +129,19 @@ gulp.task('package-external-extensions', task.series(
const packageManifestPath = path.join(packageDir, 'package.json');
const json = require('gulp-json-editor');
const packageJsonStream = gulp.src(packageManifestPath) // Create stream for the original package.json
.pipe(json(data => { // And now use gulp-json-editor to modify the contents
.pipe(json(data => {
// And now use gulp-json-editor to modify the contents
const updateData = JSON.parse(fs.readFileSync(vscodeManifestFullPath)); // Read in the set of values to replace from package.vscode.json
Object.keys(updateData).forEach(key => {
data[key] = updateData[key];
});
// Remove ADS-only menus. This is a subset of the menus listed in https://github.com/microsoft/azuredatastudio/blob/main/src/vs/workbench/api/common/menusExtensionPoint.ts
// More can be added to the list as needed.
['objectExplorer/item/context', 'dataExplorer/context', 'dashboard/toolbar'].forEach(menu => {
delete data.contributes.menus[menu];
});
if(data.contributes?.menus){
// Remove ADS-only menus. This is a subset of the menus listed in https://github.com/microsoft/azuredatastudio/blob/main/src/vs/workbench/api/common/menusExtensionPoint.ts
// More can be added to the list as needed.
['objectExplorer/item/context', 'dataExplorer/context', 'dashboard/toolbar'].forEach(menu => {
delete data.contributes.menus[menu];
});
}
return data;
}, { beautify: false }))
.pipe(gulp.dest(packageDir));

View File

@@ -135,6 +135,7 @@ const extensionsFilter = filter([
'**/schema-compare.xlf',
'**/server-report.xlf',
'**/sql-assessment.xlf',
'**/sql-bindings.xlf',
'**/sql-database-projects.xlf',
'**/sql-migration.xlf',
'**/xml-language-features.xlf'

View File

@@ -231,6 +231,7 @@ const externalExtensions = [
'schema-compare',
'server-report',
'sql-assessment',
'sql-bindings',
'sql-database-projects',
'sql-migration'
];

View File

@@ -267,6 +267,7 @@ const externalExtensions = [
'schema-compare',
'server-report',
'sql-assessment',
'sql-bindings',
'sql-database-projects',
'sql-migration'
];

View File

@@ -18,6 +18,13 @@ const File = require("vinyl");
const rimraf = require("rimraf");
const gulp = require("gulp");
const vfs = require("vinyl-fs");
/**
* If you need to compile this file for any changes, please run: yarn tsc -p ./build/tsconfig.json
*/
//List of extensions that we changed from vscode, so we can exclude them from having "Microsoft." appended in front.
const alteredVSCodeExtensions = [
'git'
];
const root = path.dirname(path.dirname(__dirname));
// Modified packageLocalExtensionsStream from extensions.ts, but for langpacks.
function packageLangpacksStream() {
@@ -134,10 +141,13 @@ function modifyI18nPackFiles(existingTranslationFolder, resultingTranslationPath
for (let extension in extensionsPacks) {
const translatedExtFile = i18n.createI18nFile(`extensions/${extension}`, extensionsPacks[extension]);
this.queue(translatedExtFile);
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
const adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
let adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
}
this.queue(null);
})
@@ -162,7 +172,6 @@ const VSCODEExtensions = [
"bat",
"configuration-editing",
"docker",
"extension-editing",
"git-ui",
"git",
"github-authentication",

View File

@@ -17,6 +17,15 @@ import * as rimraf from 'rimraf';
import * as gulp from 'gulp';
import * as vfs from 'vinyl-fs';
/**
* If you need to compile this file for any changes, please run: yarn tsc -p ./build/tsconfig.json
*/
//List of extensions that we changed from vscode, so we can exclude them from having "Microsoft." appended in front.
const alteredVSCodeExtensions = [
'git'
]
const root = path.dirname(path.dirname(__dirname));
// Modified packageLocalExtensionsStream from extensions.ts, but for langpacks.
@@ -68,7 +77,7 @@ function updateMainI18nFile(existingTranslationFilePath: string, originalFilePat
// Delete any SQL strings that are no longer part of ADS in current langpack.
for (let contentKey of Object.keys(objectContents)) {
if(contentKey.startsWith('sql') && messages.contents[contentKey] === undefined){
if (contentKey.startsWith('sql') && messages.contents[contentKey] === undefined) {
delete objectContents[`${contentKey}`]
}
}
@@ -148,10 +157,14 @@ export function modifyI18nPackFiles(existingTranslationFolder: string, resulting
const translatedExtFile = i18n.createI18nFile(`extensions/${extension}`, extensionsPacks[extension]);
this.queue(translatedExtFile);
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
const adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
let adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
}
this.queue(null);
})
@@ -399,7 +412,7 @@ export function renameVscodeLangpacks(): Promise<void> {
//Copy files to vscode langpack, then remove the ADS langpack, and finally rename the vscode langpack to match the ADS one.
globMDArray.forEach(element => {
fs.copyFileSync(element, path.join(locVSCODEFolder,path.parse(element).base));
fs.copyFileSync(element, path.join(locVSCODEFolder, path.parse(element).base));
});
rimraf.sync(locADSFolder);
fs.renameSync(locVSCODEFolder, locADSFolder);

View File

@@ -48,6 +48,7 @@ exports.dirs = [
'extensions/server-report',
'extensions/simple-browser',
'extensions/sql-assessment',
'extensions/sql-bindings',
'extensions/sql-database-projects',
'extensions/sql-migration',
'extensions/vscode-test-resolver',

View File

@@ -60,7 +60,7 @@
"mime": "^1.4.1",
"mkdirp": "^1.0.4",
"p-limit": "^3.1.0",
"plist": "^3.0.1",
"plist": "^3.0.4",
"rollup": "^1.20.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",

View File

@@ -783,7 +783,7 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-js@^1.2.3:
base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@@ -2038,14 +2038,13 @@ pify@^3.0.0:
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
plist@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c"
integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==
plist@^3.0.1, plist@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.4.tgz#a62df837e3aed2bb3b735899d510c4f186019cbe"
integrity sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==
dependencies:
base64-js "^1.2.3"
base64-js "^1.5.1"
xmlbuilder "^9.0.7"
xmldom "0.1.x"
"postcss@5 - 7":
version "7.0.36"
@@ -2676,11 +2675,6 @@ xmlbuilder@~11.0.0:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
xmldom@0.1.x:
version "0.1.31"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff"
integrity sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"

View File

@@ -2,13 +2,13 @@
"name": "arc",
"displayName": "%arc.displayName%",
"description": "%arc.description%",
"version": "0.12.0",
"version": "1.0.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
"engines": {
"vscode": "*",
"azdata": ">=1.32.0"
"azdata": ">=1.35.0"
},
"activationEvents": [
"onCommand:arc.connectToController",

View File

@@ -52,9 +52,6 @@ describe('radioOptionsGroup', function (): void {
const label = radioOptionsGroup.items[0] as azdata.TextComponent;
should(label.value).not.be.undefined();
label.value!.should.deepEqual(loc.loadingClusterContextsError(loadingError));
should(label.CSSStyles).not.be.undefined();
should(label.CSSStyles!.color).not.be.undefined();
label.CSSStyles!.color.should.equal('Red');
});
describe('getters and setters', async () => {

View File

@@ -67,7 +67,7 @@ export class RadioOptionsGroup {
this.component().loadingCompletedText = this._loadingCompleteMessage;
}
catch (e) {
const errorLabel = this._modelBuilder.text().withProps({ value: loc.loadingClusterContextsError(e), CSSStyles: { 'color': 'Red' } }).component();
const errorLabel = this._modelBuilder.text().withProps({ value: loc.loadingClusterContextsError(e), textType: azdata.TextType.Error }).component();
this._divContainer.addItem(errorLabel);
this.component().loadingCompletedText = this._loadingCompleteErrorMessage(e);
}

View File

@@ -2,13 +2,13 @@
"name": "azcli",
"displayName": "%azcli.arc.displayName%",
"description": "%azcli.arc.description%",
"version": "0.4.0",
"version": "1.0.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
"engines": {
"vscode": "*",
"azdata": ">=1.26.0"
"azdata": ">=1.35.0"
},
"activationEvents": [
"*"

View File

@@ -172,6 +172,11 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
}
refresh(account: AzureAccount): Thenable<AzureAccount | azdata.PromptFailedResult> {
return this._refresh(account);
}
private async _refresh(account: AzureAccount): Promise<AzureAccount | azdata.PromptFailedResult> {
await this._clear(account.key);
return this.prompt();
}

View File

@@ -263,6 +263,12 @@ declare module 'azurecore' {
}
export interface IExtension {
/**
* Gets the list of subscriptions for the specified AzureAccount
* @param account The account to get the subscriptions for
* @param ignoreErrors If true any errors are not thrown and instead collected and returned as part of the result
* @param selectedOnly Whether to only list subscriptions the user has selected to filter to for this account
*/
getSubscriptions(account?: AzureAccount, ignoreErrors?: boolean, selectedOnly?: boolean): Promise<GetSubscriptionsResult>;
getResourceGroups(account?: AzureAccount, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise<GetResourceGroupsResult>;
getLocations(account?: AzureAccount, subscription?: azureResource.AzureResourceSubscription, ignoreErrors?: boolean): Promise<GetLocationsResult>;

View File

@@ -655,9 +655,9 @@ events@^3.0.0:
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
follow-redirects@^1.14.0:
version "1.14.7"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
form-data@^2.5.0:
version "2.5.1"

View File

@@ -2,7 +2,7 @@
"name": "data-workspace",
"displayName": "Data Workspace",
"description": "Additional common functionality for database projects",
"version": "0.1.1",
"version": "0.2.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",

View File

@@ -49,6 +49,13 @@ export const SelectProjectType = localize('dataworkspace.selectProjectType', "Se
export const SelectProjectLocation = localize('dataworkspace.selectProjectLocation', "Select Project Location");
export const NameCannotBeEmpty = localize('dataworkspace.nameCannotBeEmpty', "Name cannot be empty");
export const TargetPlatform = localize('dataworkspace.targetPlatform', "Target Platform");
export const SdkStyleProject = localize('dataworkspace.sdkStyleProject', "SDK-style project (Preview)");
export const LearnMore = localize('dataworkspace.learnMore', "Learn More");
export const YesRecommended = localize('dataworkspace.yesRecommended', "Yes (Recommended)");
export const No = localize('dataworkspace.no', "No");
export const SdkLearnMorePlaceholder = localize('dataworkspace.sdkLearnMorePlaceholder', "Click \"Learn More\" button for more information about SDK-style projects");
export const Default = localize('dataworkspace.default', "Default");
export const SelectTargetPlatform = localize('dataworkspace.selectTargetPlatform', "Select Target Platform");
//Open Existing Dialog
export const OpenExistingDialogTitle = localize('dataworkspace.openExistingDialogTitle', "Open Existing Project");

View File

@@ -74,8 +74,9 @@ export interface IWorkspaceService {
* @param location The location of the project
* @param projectTypeId The project type id
* @param projectTargetPlatform The target platform of the project
* @param sdkStyleProject Whether or not the project is SDK-style
*/
createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetPlatform?: string): Promise<vscode.Uri>;
createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetPlatform?: string, sdkStyleProject?: boolean): Promise<vscode.Uri>;
/**
* Clones git repository and adds projects to workspace

View File

@@ -67,8 +67,9 @@ declare module 'dataworkspace' {
* @param location the parent directory of the project
* @param projectTypeId the identifier of the selected project type
* @param projectTargetPlatform the target platform of the project
* @param sdkStyleProject whether or not a project is SDK-style
*/
createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetPlatform?: string): Promise<vscode.Uri>;
createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetPlatform?: string, sdkStyleProject?: boolean): Promise<vscode.Uri>;
/**
* Gets the project data corresponding to the project file, to be placed in the dashboard container
@@ -131,14 +132,14 @@ declare module 'dataworkspace' {
readonly defaultTargetPlatform?: string;
/**
* Link display value for a link at the end of the project description. linkLocation also needs to be set to use this
* Whether or not sdk style project is an option
*/
readonly linkDisplayValue?: string;
readonly sdkStyleOption?: boolean;
/**
* Location where clicking on the linkDisplayValue will go to
* Location where clicking on the Learn More next to SDK style checkbox will go. sdkStyleOption needs to be set to true to use this
*/
readonly linkLocation?: string
readonly sdkStyleLearnMoreUrl?: string
}
/**

View File

@@ -22,6 +22,7 @@ class NewProjectDialogModel {
name: string = '';
location: string = '';
targetPlatform?: string;
sdkStyleProject?: boolean;
}
export async function openSpecificProjectNewProjectDialog(projectType: IProjectType, workspaceService: WorkspaceService): Promise<vscode.Uri | undefined> {
@@ -35,6 +36,7 @@ export class NewProjectDialog extends DialogBase {
public model: NewProjectDialogModel = new NewProjectDialogModel();
public formBuilder: azdataType.FormBuilder | undefined;
public targetPlatformDropdownFormComponent: azdataType.FormComponent | undefined;
public sdkProjectCheckboxFormComponent: azdataType.FormComponent | undefined;
public newProjectDialogComplete: Deferred<void> | undefined;
public newDialogPromise: Promise<void> = new Promise<void>((resolve, reject) => this.newProjectDialogComplete = { resolve, reject });
public projectUri: vscode.Uri | undefined;
@@ -87,7 +89,7 @@ export class NewProjectDialog extends DialogBase {
.withAdditionalProperties({ projectFileExtension: this.model.projectFileExtension, projectTemplateId: this.model.projectTypeId })
.send();
this.projectUri = await this.workspaceService.createProject(this.model.name, vscode.Uri.file(this.model.location), this.model.projectTypeId, this.model.targetPlatform);
this.projectUri = await this.workspaceService.createProject(this.model.name, vscode.Uri.file(this.model.location), this.model.projectTypeId, this.model.targetPlatform, this.model.sdkStyleProject);
this.newProjectDialogComplete?.resolve();
}
catch (err) {
@@ -122,8 +124,7 @@ export class NewProjectDialog extends DialogBase {
'font-weight': 'bold'
}
}, {
textValue: projectType.description,
linkDisplayValue: projectType.linkDisplayValue
textValue: projectType.description
}
]
};
@@ -138,15 +139,7 @@ export class NewProjectDialog extends DialogBase {
selectedCardId: allProjectTypes.length > 0 ? allProjectTypes[0].id : undefined
}).component();
projectTypeRadioCardGroup.onLinkClick(async (value) => {
for (let projectType of allProjectTypes) {
if (value.cardId === projectType.id) {
void vscode.env.openExternal(vscode.Uri.parse(projectType.linkLocation!));
}
}
});
this.register(projectTypeRadioCardGroup.onSelectionChanged((e) => {
this.register(projectTypeRadioCardGroup.onSelectionChanged(async (e) => {
this.model.projectTypeId = e.cardId;
const selectedProject = allProjectTypes.find(p => p.id === e.cardId);
@@ -155,12 +148,30 @@ export class NewProjectDialog extends DialogBase {
targetPlatformDropdown.values = selectedProject?.targetPlatforms;
targetPlatformDropdown.value = this.getDefaultTargetPlatform(selectedProject);
this.formBuilder?.addFormItem(this.targetPlatformDropdownFormComponent!);
this.formBuilder?.insertFormItem(this.targetPlatformDropdownFormComponent!, 3);
} else {
// remove the target version dropdown if the selected project type didn't provide values for this
this.formBuilder?.removeFormItem(this.targetPlatformDropdownFormComponent!);
this.model.targetPlatform = undefined;
}
if (selectedProject?.sdkStyleOption) {
sdkProjectCheckbox.checked = true;
this.model.sdkStyleProject = true;
if (selectedProject.sdkStyleLearnMoreUrl) {
await sdkLearnMore.updateProperty('url', selectedProject.sdkStyleLearnMoreUrl);
sdkFormComponentGroup.addItem(sdkLearnMore);
} else {
// remove learn more link if the project type didn't provide it
sdkFormComponentGroup.removeItem(sdkLearnMore);
}
this.formBuilder?.addFormItem(this.sdkProjectCheckboxFormComponent!);
} else {
this.model.sdkStyleProject = false;
this.formBuilder?.removeFormItem(this.sdkProjectCheckboxFormComponent!);
}
}));
const projectNameTextBox = view.modelBuilder.inputBox().withProps({
@@ -227,6 +238,34 @@ export class NewProjectDialog extends DialogBase {
component: targetPlatformDropdown
};
const sdkProjectCheckbox = view.modelBuilder.checkBox().withProps({
checked: true,
label: constants.SdkStyleProject
}).component();
this.register(sdkProjectCheckbox.onChanged(() => {
this.model.sdkStyleProject = sdkProjectCheckbox.checked;
}));
const sdkLearnMore = view.modelBuilder.hyperlink().withProps({
label: constants.LearnMore,
url: ''
}).component();
const sdkFormComponentGroup = view.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'row', alignItems: 'baseline' })
.withItems([sdkProjectCheckbox], { CSSStyles: { flex: '0 0 auto', 'margin-right': '10px' } })
.component();
if (allProjectTypes[0].sdkStyleLearnMoreUrl) {
await sdkLearnMore.updateProperty('url', allProjectTypes[0].sdkStyleLearnMoreUrl);
sdkFormComponentGroup.addItem(sdkLearnMore);
}
this.sdkProjectCheckboxFormComponent = {
component: sdkFormComponentGroup,
};
this.formBuilder = view.modelBuilder.formContainer().withFormItems([
{
title: constants.TypeTitle,
@@ -250,6 +289,11 @@ export class NewProjectDialog extends DialogBase {
this.formBuilder.addFormItem(this.targetPlatformDropdownFormComponent);
}
// add sdk style checkbox is the first project has the option
if (allProjectTypes[0].sdkStyleOption) {
this.formBuilder.addFormItem(this.sdkProjectCheckboxFormComponent);
}
await view.initializeModel(this.formBuilder.component());
this.initDialogComplete?.resolve();
}

View File

@@ -19,8 +19,12 @@ export async function createNewProjectWithQuickpick(workspaceService: WorkspaceS
return {
label: projType.displayName,
description: projType.description,
id: projType.id
} as vscode.QuickPickItem & { id: string };
id: projType.id,
targetPlatforms: projType.targetPlatforms,
defaultTargetPlatform: projType.defaultTargetPlatform,
sdkOption: projType.sdkStyleOption,
sdkLearnMoreUrl: projType.sdkStyleLearnMoreUrl
} as vscode.QuickPickItem & { id: string, sdkOption?: boolean, targetPlatforms?: string[], defaultTargetPlatform?: string, sdkLearnMoreUrl?: string };
});
// 1. Prompt for project type
@@ -87,5 +91,79 @@ export async function createNewProjectWithQuickpick(workspaceService: WorkspaceS
continue;
}
await workspaceService.createProject(projectName, vscode.Uri.file(projectLocation), projectType.id, undefined);
let targetPlatform;
if (projectType.targetPlatforms) {
// 4. Target platform of the project
let targetPlatforms: vscode.QuickPickItem[] = projectType.targetPlatforms.map(targetPlatform => { return { label: targetPlatform }; });
if (projectType.defaultTargetPlatform) {
// move the default target platform to be the first one in the list
const defaultIndex = targetPlatforms.findIndex(i => i.label === projectType.defaultTargetPlatform);
if (defaultIndex > -1) {
targetPlatforms.splice(defaultIndex, 1);
}
// add default next to the default target platform
targetPlatforms.unshift({ label: projectType.defaultTargetPlatform, description: constants.Default });
}
const selectedTargetPlatform = await vscode.window.showQuickPick(targetPlatforms, { title: constants.SelectTargetPlatform, ignoreFocusOut: true });
if (!selectedTargetPlatform) {
// User cancelled
return;
}
targetPlatform = selectedTargetPlatform.label;
}
let sdkStyle;
if (projectType.sdkOption) {
// 5. SDK-style project or not
const sdkLearnMoreButton: vscode.QuickInputButton = {
iconPath: new vscode.ThemeIcon('link-external'),
tooltip: constants.LearnMore
};
const quickPick = vscode.window.createQuickPick();
quickPick.items = [{ label: constants.YesRecommended }, { label: constants.No }];
quickPick.title = constants.SdkStyleProject;
quickPick.ignoreFocusOut = true;
const disposables: vscode.Disposable[] = [];
try {
if (projectType.sdkLearnMoreUrl) {
// add button to open sdkLearnMoreUrl if it was provided
quickPick.buttons = [sdkLearnMoreButton];
quickPick.placeholder = constants.SdkLearnMorePlaceholder;
}
let sdkStylePromise = new Promise<boolean | undefined>((resolve) => {
disposables.push(
quickPick.onDidHide(() => {
resolve(undefined);
}),
quickPick.onDidChangeSelection((item) => {
resolve(item[0].label === constants.YesRecommended);
}));
if (projectType.sdkLearnMoreUrl) {
disposables.push(quickPick.onDidTriggerButton(async () => {
await vscode.env.openExternal(vscode.Uri.parse(projectType.sdkLearnMoreUrl!));
}));
}
});
quickPick.show();
sdkStyle = await sdkStylePromise;
quickPick.hide();
} finally {
disposables.forEach(d => d.dispose());
}
if (sdkStyle === undefined) {
// User cancelled
return;
}
}
await workspaceService.createProject(projectName, vscode.Uri.file(projectLocation), projectType.id, targetPlatform, sdkStyle);
}

View File

@@ -169,10 +169,12 @@ export class ProjectDashboard {
.component();
header.addItem(locationLabel, { CSSStyles: { 'padding-left': '34px', 'padding-top': '15px', 'padding-bottom': '50px', 'font-size': '16px' } });
const image = this.projectProvider!.image; // background image added at the bottom right of the header
const backgroundImage = this.projectProvider!.image; // background image added at the bottom right of the header
// Files need to have the vscode-file scheme to be loaded by ADS
const backgroundUri = vscode.Uri.file(backgroundImage!.light.toString()).with({ scheme: 'vscode-file' });
headerContainer.addItem(header, {
CSSStyles: {
'background-image': `url(${vscode.Uri.file(image!.light.toString())})`,
'background-image': `url(${backgroundUri})`,
'background-repeat': 'no-repeat',
'background-position': '85% bottom',
'background-size': '10%',

View File

@@ -197,10 +197,10 @@ export class WorkspaceService implements IWorkspaceService {
return ProjectProviderRegistry.getProviderByProjectExtension(projectType);
}
async createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetVersion?: string): Promise<vscode.Uri> {
async createProject(name: string, location: vscode.Uri, projectTypeId: string, projectTargetVersion?: string, sdkStyleProject?: boolean): Promise<vscode.Uri> {
const provider = ProjectProviderRegistry.getProviderByProjectType(projectTypeId);
if (provider) {
const projectFile = await provider.createProject(name, location, projectTypeId, projectTargetVersion);
const projectFile = await provider.createProject(name, location, projectTypeId, projectTargetVersion, sdkStyleProject);
await this.addProjectsToWorkspace([projectFile]);
this._onDidWorkspaceProjectsChange.fire();
return projectFile;

View File

@@ -50,9 +50,9 @@ delayed-stream@~1.0.0:
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
follow-redirects@^1.14.0:
version "1.14.7"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
form-data@^3.0.0:
version "3.0.0"

View File

@@ -38,10 +38,11 @@ export class DashboardWidget {
}).component();
const header = await this.createHeader(view);
const footerContainer = this.createFooter(view);
const backgroundImageUri = vscode.Uri.file(this.asAbsolutePath('images/background.svg')).with({ scheme: 'vscode-file' });
container.addItem(header, {
CSSStyles: {
'background-image': `
url(${vscode.Uri.file(this.asAbsolutePath('images/background.svg'))}),
url(${backgroundImageUri}),
linear-gradient(0deg, rgba(0,0,0,0.09) 0%, rgba(0,0,0,0) 100%)
`,
'background-repeat': 'no-repeat',
@@ -300,9 +301,11 @@ export class DashboardWidget {
await this._apiWrapper.openExternal(vscode.Uri.parse(linkMetaData.link));
}
});
// Files need to have the vscode-file scheme to be loaded by ADS
const imageUri = vscode.Uri.file(this.asAbsolutePath(linkMetaData.iconPath?.light as string || '')).with({ scheme: 'vscode-file' });
videosContainer.addItem(video1Container, {
CSSStyles: {
'background-image': `url(${vscode.Uri.file(this.asAbsolutePath(linkMetaData.iconPath?.light as string || ''))})`,
'background-image': `url(${imageUri})`,
'background-repeat': 'no-repeat',
'background-position': 'top',
'width': `${maxWidth}px`,

View File

@@ -1,6 +1,6 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "3.0.0-release.204",
"version": "3.0.0-release.214",
"downloadFileNames": {
"Windows_86": "win-x86-net6.0.zip",
"Windows_64": "win-x64-net6.0.zip",

View File

@@ -514,14 +514,14 @@
{
"command": "mssql.designTable",
"when": "connectionProvider == MSSQL && nodeType == Table && config.workbench.enablePreviewFeatures",
"group":"connection@3"
"group": "connection@3"
},
{
"command": "mssql.newTable",
"when": "connectionProvider == MSSQL && nodeType == Folder && nodeLabel == Tables && config.workbench.enablePreviewFeatures",
"group":"connection@1"
"group": "connection@1"
}
],
],
"notebook/toolbar": [
{
"command": "mssql.exportNotebookToSql",
@@ -759,6 +759,9 @@
"connectionProvider": {
"providerId": "MSSQL",
"displayName": "%mssql.provider.displayName%",
"supportedExecutionPlanFileExtensions": [
"sqlplan"
],
"iconPath": [
{
"id": "mssql:cloud",

View File

@@ -1096,7 +1096,7 @@ export namespace InitializeTableDesignerRequest {
}
export namespace ProcessTableDesignerEditRequest {
export const type = new RequestType<TableDesignerEditRequestParams, azdata.designers.DesignerEditResult, void, void>('tabledesigner/processedit');
export const type = new RequestType<TableDesignerEditRequestParams, azdata.designers.DesignerEditResult<azdata.designers.TableDesignerView>, void, void>('tabledesigner/processedit');
}
export namespace PublishTableDesignerChangesRequest {
@@ -1108,9 +1108,22 @@ export namespace TableDesignerGenerateScriptRequest {
}
export namespace TableDesignerGenerateChangePreviewReportRequest {
export const type = new RequestType<azdata.designers.TableInfo, string, void, void>('tabledesigner/generatepreviewreport');
export const type = new RequestType<azdata.designers.TableInfo, azdata.designers.GeneratePreviewReportResult, void, void>('tabledesigner/generatepreviewreport');
}
export namespace DisposeTableDesignerRequest {
export const type = new RequestType<azdata.designers.TableInfo, void, void, void>('tabledesigner/dispose');
}
// ------------------------------- < Table Designer > ------------------------------------
// ------------------------------- < Execution Plan > ------------------------------------
export interface GetExecutionPlanParams {
graphInfo: azdata.executionPlan.ExecutionPlanGraphInfo,
}
export namespace GetExecutionPlanRequest {
export const type = new RequestType<GetExecutionPlanParams, azdata.executionPlan.GetExecutionPlanResult, void, void>('queryexecutionplan/getexecutionplan');
}
// ------------------------------- < Execution Plan > ------------------------------------

View File

@@ -43,16 +43,20 @@ export class SqlCredentialService extends SqlOpsFeature<any> {
protected override registerProvider(options: any): Disposable {
let readCredential = async (credentialId: string): Promise<azdata.Credential> => {
if (Utils.isLinux) {
const password = await this._secretStorage.get(credentialId);
return {
credentialId: credentialId,
password: password
};
}
return this._client.sendRequest(Contracts.ReadCredentialRequest.type, { credentialId, password: undefined });
};
let saveCredential = async (credentialId: string, password: string): Promise<boolean> => {
if (Utils.isLinux) {
/**
* This is only done for linux because this is going to be
* the default credential system for linux in the next release
*/
await this._secretStorage.store(credentialId, password);
return true;
}
return this._client.sendRequest(Contracts.SaveCredentialRequest.type, { credentialId, password });
};
@@ -61,6 +65,7 @@ export class SqlCredentialService extends SqlOpsFeature<any> {
if (Utils.isLinux) {
try {
await this._secretStorage.delete(credentialId);
return true;
} catch (e) {
console.log('credential does not exist in native secret store');
}

View File

@@ -1117,7 +1117,7 @@ export class TableDesignerFeature extends SqlOpsFeature<undefined> {
return Promise.reject(e);
}
};
const processTableEdit = (tableInfo: azdata.designers.TableInfo, tableChangeInfo: azdata.designers.DesignerEdit): Thenable<azdata.designers.DesignerEditResult> => {
const processTableEdit = (tableInfo: azdata.designers.TableInfo, tableChangeInfo: azdata.designers.DesignerEdit): Thenable<azdata.designers.DesignerEditResult<azdata.designers.TableDesignerView>> => {
let params: contracts.TableDesignerEditRequestParams = {
tableInfo: tableInfo,
tableChangeInfo: tableChangeInfo
@@ -1151,7 +1151,7 @@ export class TableDesignerFeature extends SqlOpsFeature<undefined> {
}
};
const generatePreviewReport = (tableInfo: azdata.designers.TableInfo): Thenable<string> => {
const generatePreviewReport = (tableInfo: azdata.designers.TableInfo): Thenable<azdata.designers.GeneratePreviewReportResult> => {
try {
return client.sendRequest(contracts.TableDesignerGenerateChangePreviewReportRequest.type, tableInfo);
}
@@ -1183,3 +1183,48 @@ export class TableDesignerFeature extends SqlOpsFeature<undefined> {
}
}
/**
* Execution Plan Service Feature
* TODO: Move this feature to data protocol client repo once stablized
*/
export class ExecutionPlanServiceFeature extends SqlOpsFeature<undefined> {
private static readonly messagesTypes: RPCMessageType[] = [
contracts.GetExecutionPlanRequest.type,
];
constructor(client: SqlOpsDataClient) {
super(client, ExecutionPlanServiceFeature.messagesTypes);
}
public fillClientCapabilities(capabilities: ClientCapabilities): void {
}
public initialize(capabilities: ServerCapabilities): void {
this.register(this.messages, {
id: UUID.generateUuid(),
registerOptions: undefined
});
}
protected registerProvider(options: undefined): Disposable {
const client = this._client;
const getExecutionPlan = (planFile: azdata.executionPlan.ExecutionPlanGraphInfo): Thenable<azdata.executionPlan.GetExecutionPlanResult> => {
const params: contracts.GetExecutionPlanParams = { graphInfo: planFile };
return client.sendRequest(contracts.GetExecutionPlanRequest.type, params).then(
r => r,
e => {
client.logFailedRequest(contracts.GetExecutionPlanRequest.type, e);
return Promise.reject(e);
}
);
};
return azdata.dataprotocol.registerExecutionPlanProvider({
providerId: client.providerId,
getExecutionPlan
});
}
}

View File

@@ -11,7 +11,7 @@ import * as path from 'path';
import { getCommonLaunchArgsAndCleanupOldLogFiles, getOrDownloadServer } from './utils';
import { Telemetry, LanguageClientErrorHandler } from './telemetry';
import { SqlOpsDataClient, ClientOptions } from 'dataprotocol-client';
import { TelemetryFeature, AgentServicesFeature, SerializationFeature, AccountFeature, SqlAssessmentServicesFeature, ProfilerFeature, TableDesignerFeature } from './features';
import { TelemetryFeature, AgentServicesFeature, SerializationFeature, AccountFeature, SqlAssessmentServicesFeature, ProfilerFeature, TableDesignerFeature, ExecutionPlanServiceFeature } from './features';
import { CredentialStore } from './credentialstore/credentialstore';
import { AzureResourceProvider } from './resourceProvider/resourceProvider';
import { SchemaCompareService } from './schemaCompare/schemaCompareService';
@@ -165,7 +165,8 @@ function getClientOptions(context: AppContext): ClientOptions {
ProfilerFeature,
SqlMigrationService.asFeature(context),
SqlCredentialService.asFeature(context),
TableDesignerFeature
TableDesignerFeature,
ExecutionPlanServiceFeature
],
outputChannel: new CustomOutputChannel()
};

View File

@@ -280,9 +280,9 @@ agent-base@4, agent-base@^4.3.0:
es6-promisify "^5.0.0"
ajv@^6.5.5:
version "6.12.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7"
integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
@@ -694,9 +694,9 @@ extsprintf@^1.2.0:
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
@@ -1899,9 +1899,9 @@ typemoq@^2.1.0:
postinstall-build "^5.0.1"
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"

View File

@@ -329,6 +329,14 @@
"Notebook"
],
"configuration": "./language-configuration.json"
}, {
"id": "dib",
"extensions": [
".dib"
],
"aliases": [
".NET Interactive Notebook"
]
}
],
"menus": {
@@ -703,7 +711,8 @@
"connectionProviderIds": [
"MSSQL"
],
"blockedOnSAW": true
"blockedOnSAW": true,
"supportedLanguages": ["python"]
},
{
"name": "sparkkernel",
@@ -711,6 +720,7 @@
"connectionProviderIds": [
"MSSQL"
],
"supportedLanguages": ["scala"],
"blockedOnSAW": true
},
{
@@ -719,17 +729,20 @@
"connectionProviderIds": [
"MSSQL"
],
"supportedLanguages": ["r"],
"blockedOnSAW": true
},
{
"name": "python3",
"displayName": "Python 3",
"connectionProviderIds": []
"connectionProviderIds": [],
"supportedLanguages": ["python"]
},
{
"name": "powershell",
"displayName": "PowerShell",
"connectionProviderIds": []
"connectionProviderIds": [],
"supportedLanguages": ["powershell"]
}
]
}
@@ -774,7 +787,7 @@
"@microsoft/vscodetestcover": "^1.2.0"
},
"resolutions": {
"url-parse": "^1.5.1"
"url-parse": "^1.5.8"
},
"enableProposedApi": true
}

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { nb } from 'azdata';
import { Kernel, KernelMessage } from '@jupyterlab/services';
@@ -90,7 +91,7 @@ export class JupyterKernel implements nb.IKernel {
requestExecute(content: nb.IExecuteRequest, disposeOnDone?: boolean): nb.IFuture {
content.code = Array.isArray(content.code) ? content.code.join('') : content.code;
content.code = content.code.replace(/\r+\n/gm, '\n'); // Remove \r (if it exists) from newlines
let futureImpl = this.kernelImpl.requestExecute(content as KernelMessage.IExecuteRequest & { cellIndex: number }, disposeOnDone);
let futureImpl = this.kernelImpl.requestExecute(content as KernelMessage.IExecuteRequest & { notebookUri: vscode.Uri, cellUri: vscode.Uri, language: string, cellIndex: number }, disposeOnDone);
return new JupyterFuture(futureImpl);
}

View File

@@ -98,7 +98,10 @@ describe('Jupyter Session', function (): void {
// When I request execute
let future = kernel.requestExecute({
code: code,
cellIndex: 0
cellIndex: 0,
cellUri: undefined,
notebookUri: undefined,
language: ''
}, true);
// Then expect wrapper to be returned

View File

@@ -1798,10 +1798,10 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
url-parse@^1.5.1, url-parse@~1.4.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862"
integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==
url-parse@^1.5.8, url-parse@~1.4.3:
version "1.5.10"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"

View File

@@ -531,9 +531,9 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5:
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
follow-redirects@^1.14.0:
version "1.14.7"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
fs.realpath@^1.0.0:
version "1.0.0"

View File

@@ -898,8 +898,7 @@ export class SchemaCompareMainWindow {
throw new Error(`Unsupported SchemaCompareEndpointType: ${getSchemaCompareEndpointString(this.targetEndpointInfo.endpointType)}`);
}
if (!result || !result.success) {
if (!result || !result.success || result.errorMessage !== '') {
TelemetryReporter.createErrorEvent(TelemetryViews.SchemaCompareMainWindow, 'SchemaCompareApplyFailed', undefined, getTelemetryErrorType(result?.errorMessage))
.withAdditionalProperties({
'operationId': this.comparisonResult.operationId,
@@ -912,6 +911,11 @@ export class SchemaCompareMainWindow {
this.generateScriptButton.title = loc.generateScriptEnabledMessage;
this.applyButton.enabled = true;
this.applyButton.title = loc.applyEnabledMessage;
} else if (this.targetEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Project) {
const workspaceApi = getDataWorkspaceExtensionApi();
workspaceApi.showProjectsView();
void vscode.window.showInformationMessage(loc.applySuccess);
}
TelemetryReporter.createActionEvent(TelemetryViews.SchemaCompareMainWindow, 'SchemaCompareApplyEnded')
@@ -920,13 +924,6 @@ export class SchemaCompareMainWindow {
'operationId': this.comparisonResult.operationId,
'targetType': getSchemaCompareEndpointString(this.targetEndpointInfo.endpointType)
}).send();
if (this.targetEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Project) {
const workspaceApi = getDataWorkspaceExtensionApi();
workspaceApi.showProjectsView();
void vscode.window.showInformationMessage(loc.applySuccess);
}
}
});
}

View File

Before

Width:  |  Height:  |  Size: 847 B

After

Width:  |  Height:  |  Size: 847 B

View File

Before

Width:  |  Height:  |  Size: 852 B

After

Width:  |  Height:  |  Size: 852 B

View File

Before

Width:  |  Height:  |  Size: 339 B

After

Width:  |  Height:  |  Size: 339 B

View File

Before

Width:  |  Height:  |  Size: 338 B

After

Width:  |  Height:  |  Size: 338 B

View File

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

View File

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View File

Before

Width:  |  Height:  |  Size: 247 B

After

Width:  |  Height:  |  Size: 247 B

View File

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 315 B

View File

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -32,32 +32,32 @@
"command": "tempdb.startEvent",
"title": "Start",
"icon": {
"light": "./dist/media/launch.svg",
"dark": "./dist/media/launch_inverse.svg"
"light": "./images/launch.svg",
"dark": "./images/launch_inverse.svg"
}
},
{
"command": "tempdb.stopEvent",
"title": "Stop",
"icon": {
"light": "./dist/media/blocker.svg",
"dark": "./dist/media/blocker_inverse.svg"
"light": "./images/blocker.svg",
"dark": "./images/blocker_inverse.svg"
}
},
{
"command": "tempdb.contention",
"title": "Contention Help for Tempdb",
"icon": {
"light": "./dist/media/documentation.svg",
"dark": "./dist/media/documentation_inverse.svg"
"light": "./images/documentation.svg",
"dark": "./images/documentation_inverse.svg"
}
},
{
"command": "tempdb.pauseEvent",
"title": "Toggle Auto Refresh",
"icon": {
"light": "./dist/media/insights.svg",
"dark": "./dist/media/insights_inverse.svg"
"light": "./images/insights.svg",
"dark": "./images/insights_inverse.svg"
}
}
],
@@ -77,8 +77,8 @@
"id": "server-reports-monitoring",
"title": "Monitor",
"icon": {
"light": "./dist/media/monitor.svg",
"dark": "./dist/media/monitor_inverse.svg"
"light": "./images/monitor.svg",
"dark": "./images/monitor_inverse.svg"
},
"container": {
"server-reports-monitoring-container": {}
@@ -88,8 +88,8 @@
"id": "server-reports-performance",
"title": "Performance",
"icon": {
"light": "./dist/media/performance.svg",
"dark": "./dist/media/performance_inverse.svg"
"light": "./images/performance.svg",
"dark": "./images/performance_inverse.svg"
},
"container": {
"server-reports-performance-container": {}
@@ -104,8 +104,8 @@
"group": "monitoring",
"description": "TempDB reports",
"icon": {
"light": "./dist/media/tempdb.svg",
"dark": "./dist/media/tempdb_inverse.svg"
"light": "./images/tempdb.svg",
"dark": "./images/tempdb_inverse.svg"
},
"container": {
"server-reports-tempdb-container": {}
@@ -125,7 +125,7 @@
"columnsAsLabels": true
}
},
"queryFile": "./dist/sql/all_db_space_used.sql"
"queryFile": "./sql/all_db_space_used.sql"
}
},
{
@@ -140,7 +140,7 @@
"columnsAsLabels": false
}
},
"queryFile": "./dist/sql/cpumetric.sql"
"queryFile": "./sql/cpumetric.sql"
}
},
{
@@ -156,7 +156,7 @@
"columnsAsLabels": false
}
},
"queryFile": "./dist/sql/backup_size_trend.sql"
"queryFile": "./sql/backup_size_trend.sql"
}
},
{
@@ -171,9 +171,9 @@
"columnsAsLabels": true
}
},
"queryFile": "./dist/sql/waits_paul_randal.sql",
"queryFile": "./sql/waits_paul_randal.sql",
"details": {
"queryFile": "./dist/sql/waits_detail_paul_randal.sql",
"queryFile": "./sql/waits_detail_paul_randal.sql",
"label": {
"column": "WaitType",
"state": []
@@ -194,9 +194,9 @@
"columnsAsLabels": true
}
},
"queryFile": "./dist/sql/wait_resources.sql",
"queryFile": "./sql/wait_resources.sql",
"details": {
"queryFile": "./dist/sql/wait_resources.sql",
"queryFile": "./sql/wait_resources.sql",
"label": {
"column": "WaitType",
"state": []
@@ -217,7 +217,7 @@
"columnsAsLabels": true
}
},
"queryFile": "./dist/sql/memorybydb.sql"
"queryFile": "./sql/memorybydb.sql"
}
},
{
@@ -231,7 +231,7 @@
"legendPosition": "none"
}
},
"queryFile": "./dist/sql/typeofContentions.sql",
"queryFile": "./sql/typeofContentions.sql",
"autoRefreshInterval": 0.05
}
},
@@ -247,7 +247,7 @@
"xAxisLabel": "Object Ids for System Tables"
}
},
"queryFile": "./dist/sql/metadataContention.sql",
"queryFile": "./sql/metadataContention.sql",
"autoRefreshInterval": 0.05
}
},
@@ -263,7 +263,7 @@
"xAxisLabel": "Page Types"
}
},
"queryFile": "./dist/sql/allocationContention.sql",
"queryFile": "./sql/allocationContention.sql",
"autoRefreshInterval": 0.05
}
}

View File

@@ -0,0 +1,13 @@
{
"parserOptions": {
"project": "./extensions/sql-bindings/tsconfig.json"
},
"rules": {
"@typescript-eslint/no-floating-promises": [
"error",
{
"ignoreVoid": true
}
]
}
}

1
extensions/sql-bindings/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,21 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
// This task is meant for running the VS Code version of the extension. See VSCODE_DEVELOPMENT.md for more information
{
"type": "extensionHost",
"request": "launch",
"name": "Launch Extension in VS Code",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
}
]
}

View File

@@ -0,0 +1,9 @@
src
out
tsconfig.json
.gitignore
coverage
coverConfig.json
extension.webpack.config.js
*.vsix
yarn.lock

View File

@@ -0,0 +1,29 @@
# Microsoft SQL Bindings for Azure Data Studio and VS Code
## Overview
Microsoft SQL Bindings for Azure Data Studio and VS Code enables users to develop Azure Functions with Azure SQL bindings
### VS Code
This extension is bundled into the `SQL Server (MSSQL)` extension for VS Code and will be installed automatically when that extension is updated or installed.
### Azure Data Studio
This extension is provided as a separate extension in the marketplace.
Please report issues and feature requests [here.](https://github.com/microsoft/azuredatastudio/issues)
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Privacy Statement
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/privacystatement) describes the privacy statement of this software.
## License
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [Source EULA](https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt).

View File

@@ -0,0 +1,11 @@
# VS Code Extension Development
For working on the VS Code version of the package follow these steps for local development/testing.
1. Copy the values from [package.vscode.json](./package.vscode.json) into [package.json](./package.json) (overwriting the properties with the same name there)
2. Compile Azure Data Studio as normal and wait for it to finish
3. Run `code <PathToAzureDataStudioSource>/extensions/sql-bindings` from the command line to open a new VS Code instance at the `sql-bindings` folder
4. Run the `Launch Extension in VS Code` launch target from the `Run and Debug` view
5. This should launch an `Extension Development Host` version of VS Code that is running the extension from sources.
If you have the compilation running as watch then once you make changes you can just reload the window to pick up the latest changes being made.

View File

@@ -0,0 +1,20 @@
{
"enabled": true,
"relativeSourcePath": "..",
"relativeCoverageDir": "../../coverage",
"ignorePatterns": [
"**/node_modules/**",
"**/test/**",
"extension.js"
],
"reports": [
"cobertura",
"lcov",
"json"
],
"verbose": false,
"remapOptions": {
"basePath": "..",
"useAbsolutePaths": true
}
}

View File

@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const withDefaults = require('../shared.webpack.config');
module.exports = withDefaults({
context: __dirname,
entry: {
extension: './src/extension.ts'
}
});

View File

@@ -0,0 +1,82 @@
{
"name": "sql-bindings",
"displayName": "%displayName%",
"description": "%description%",
"version": "0.0.1",
"publisher": "Microsoft",
"preview": true,
"engines": {
"vscode": "^1.30.1",
"azdata": ">=1.35.0"
},
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "",
"aiKey": "AIF-37eefaf0-8022-4671-a3fb-64752724682e",
"activationEvents": [
"onCommand:sqlBindings.addSqlBinding",
"onCommand:sqlBindings.createAzureFunction"
],
"main": "./out/extension",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
},
"extensionDependencies": [
"Microsoft.mssql"
],
"capabilities": {
"virtualWorkspaces": false,
"untrustedWorkspaces": {
"supported": true
}
},
"contributes": {
"commands": [
{
"command": "sqlBindings.addSqlBinding",
"title": "%sqlBindings.addSqlBinding%",
"category": "MS SQL"
},
{
"command": "sqlBindings.createAzureFunction",
"title": "%sqlBindings.createAzureFunction%",
"category": "MS SQL",
"when": "view == objectExplorer && viewItem == Table"
}
],
"menus": {
"commandPalette": [
{
"command": "sqlBindings.addSqlBinding",
"when": "editorLangId == csharp && !azdataAvailable && resourceScheme != untitled"
}
],
"view/item/context": [
{
"command": "sqlBindings.createAzureFunction",
"when": "view == objectExplorer && viewItem == Table",
"group": "zAzure_Function@1"
}
]
}
},
"dependencies": {
"@microsoft/ads-extension-telemetry": "^1.1.5",
"fast-glob": "^3.2.7",
"jsonc-parser": "^2.3.1",
"promisify-child-process": "^3.1.1",
"vscode-nls": "^4.1.2",
"vscode-languageclient": "5.2.1"
},
"devDependencies": {
"@types/node": "^14.14.16",
"tslint": "^5.8.0",
"should": "^13.2.1",
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.0",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7"
}
}

View File

@@ -0,0 +1,6 @@
{
"displayName": "SQL Bindings",
"description": "Enables users to develop and publish Azure Functions with Azure SQL bindings",
"sqlBindings.addSqlBinding": "Add SQL Binding (preview)",
"sqlBindings.createAzureFunction": "Create Azure Function with SQL binding"
}

View File

@@ -0,0 +1,7 @@
{
"name": "sql-bindings-vscode",
"publisher": "ms-mssql",
"extensionDependencies": [
"ms-mssql.mssql"
]
}

View File

@@ -0,0 +1,526 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import * as fs from 'fs';
import * as vscode from 'vscode';
import * as utils from './utils';
import * as constants from './constants';
import { BindingType } from 'sql-bindings';
import * as path from 'path';
import { ConnectionDetails, IConnectionInfo } from 'vscode-mssql';
// https://github.com/microsoft/vscode-azurefunctions/blob/main/src/vscode-azurefunctions.api.d.ts
import { AzureFunctionsExtensionApi } from '../typings/vscode-azurefunctions.api';
// https://github.com/microsoft/vscode-azuretools/blob/main/ui/api.d.ts
import { AzureExtensionApiProvider } from '../typings/vscode-azuretools.api';
/**
* Represents the settings in an Azure function project's locawl.settings.json file
*/
export interface ILocalSettingsJson {
IsEncrypted?: boolean;
Values?: { [key: string]: string };
Host?: { [key: string]: string };
ConnectionStrings?: { [key: string]: string };
}
export interface IFileFunctionObject {
filePromise: Promise<string>;
watcherDisposable: vscode.Disposable;
}
/**
* copied and modified from vscode-azurefunctions extension
* https://github.com/microsoft/vscode-azurefunctions/blob/main/src/funcConfig/local.settings.ts
* @param localSettingsPath full path to local.settings.json
* @returns settings in local.settings.json. If no settings are found, returns default "empty" settings
*/
export async function getLocalSettingsJson(localSettingsPath: string): Promise<ILocalSettingsJson> {
if (fs.existsSync(localSettingsPath)) {
const data: string = (fs.readFileSync(localSettingsPath)).toString();
try {
return JSON.parse(data);
} catch (error) {
console.log(error);
throw new Error(utils.formatString(constants.failedToParse(error.message), constants.azureFunctionLocalSettingsFileName, error.message));
}
}
return {
IsEncrypted: false // Include this by default otherwise the func cli assumes settings are encrypted and fails to run
};
}
/**
* Adds a new setting to a project's local.settings.json file
* modified from setLocalAppSetting code from vscode-azurefunctions extension
* @param projectFolder full path to project folder
* @param key Key of the new setting
* @param value Value of the new setting
* @returns true if successful adding the new setting, false if unsuccessful
*/
export async function setLocalAppSetting(projectFolder: string, key: string, value: string): Promise<boolean> {
const localSettingsPath: string = path.join(projectFolder, constants.azureFunctionLocalSettingsFileName);
const settings: ILocalSettingsJson = await getLocalSettingsJson(localSettingsPath);
settings.Values = settings.Values || {};
if (settings.Values[key] === value) {
// don't do anything if it's the same as the existing value
return true;
} else if (settings.Values[key]) {
const result = await vscode.window.showWarningMessage(constants.settingAlreadyExists(key), { modal: true }, constants.yesString);
if (result !== constants.yesString) {
// key already exists and user doesn't want to overwrite it
return false;
}
}
settings.Values[key] = value;
void fs.promises.writeFile(localSettingsPath, JSON.stringify(settings, undefined, 2));
return true;
}
/**
* Gets the Azure Functions extension API if it is installed
* if it is not installed, prompt the user to install directly, learn more, or do not install
* @returns the Azure Functions extension API if it is installed, prompt if it is not installed
*/
export async function getAzureFunctionsExtensionApi(): Promise<AzureFunctionsExtensionApi | undefined> {
let apiProvider = await vscode.extensions.getExtension(constants.azureFunctionsExtensionName)?.activate() as AzureExtensionApiProvider;
if (!apiProvider) {
const response = await vscode.window.showInformationMessage(constants.azureFunctionsExtensionNotFound,
constants.install, constants.learnMore, constants.doNotInstall);
if (response === constants.install) {
const extensionInstalled = new Promise<void>((resolve, reject) => {
const timeout = setTimeout(async () => {
reject(new Error(constants.timeoutExtensionError));
extensionChange.dispose();
}, 10000);
let extensionChange = vscode.extensions.onDidChange(async () => {
if (vscode.extensions.getExtension(constants.azureFunctionsExtensionName)) {
resolve();
extensionChange.dispose();
clearTimeout(timeout);
}
});
});
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: constants.azureFunctionsExtensionName,
cancellable: false
}, async (_progress, _token) => {
await vscode.commands.executeCommand('workbench.extensions.installExtension', constants.azureFunctionsExtensionName);
}
);
// the extension has not been notified that the azure function extension is installed so wait till it is to then activate it
await extensionInstalled;
apiProvider = await vscode.extensions.getExtension(constants.azureFunctionsExtensionName)?.activate() as AzureExtensionApiProvider;
} else if (response === constants.learnMore) {
await vscode.env.openExternal(vscode.Uri.parse(constants.linkToAzureFunctionExtension));
return undefined;
} else {
return undefined;
}
}
const azureFunctionApi = apiProvider.getApi<AzureFunctionsExtensionApi>('*');
if (azureFunctionApi) {
return azureFunctionApi;
} else {
void vscode.window.showErrorMessage(constants.azureFunctionsExtensionNotInstalled);
return undefined;
}
}
/**
* TODO REMOVE defaultSqlBindingTextLines
* Overwrites the Azure function methods body to work with the binding
* @param filePath is the path for the function file (.cs for C# functions)
*/
export function overwriteAzureFunctionMethodBody(filePath: string): void {
let defaultBindedFunctionText = fs.readFileSync(filePath, 'utf-8');
// Replace default binding text
let newValueLines = defaultBindedFunctionText.split(os.EOL);
const defaultFunctionTextToSkip = new Set(constants.defaultSqlBindingTextLines);
let replacedValueLines = [];
for (let defaultLine of newValueLines) {
// Skipped lines
if (defaultFunctionTextToSkip.has(defaultLine.trimStart())) {
continue;
} else if (defaultLine.trimStart() === constants.defaultBindingResult) { // Result change
replacedValueLines.push(defaultLine.replace(constants.defaultBindingResult, constants.sqlBindingResult));
} else {
// Normal lines to be included
replacedValueLines.push(defaultLine);
}
}
defaultBindedFunctionText = replacedValueLines.join(os.EOL);
fs.writeFileSync(filePath, defaultBindedFunctionText, 'utf-8');
}
/**
* Gets the azure function project for the user to choose from a list of projects files
* If only one project is found that project is used to add the binding to
* if no project is found, user is informed there needs to be a C# Azure Functions project
* @returns the selected project file path
*/
export async function getAzureFunctionProject(): Promise<string | undefined> {
let selectedProjectFile: string | undefined = '';
if (vscode.workspace.workspaceFolders === undefined || vscode.workspace.workspaceFolders.length === 0) {
return selectedProjectFile;
} else {
const projectFiles = await getAzureFunctionProjectFiles();
if (projectFiles !== undefined) {
if (projectFiles.length > 1) {
// select project to add azure function to
selectedProjectFile = (await vscode.window.showQuickPick(projectFiles, {
canPickMany: false,
title: constants.selectProject,
ignoreFocusOut: true
}));
return selectedProjectFile;
} else if (projectFiles.length === 1) {
// only one azure function project found
return projectFiles[0];
}
}
return undefined;
}
}
/**
* Gets the azure function project files based on the host file found in the same folder
* @returns the azure function project files paths
*/
export async function getAzureFunctionProjectFiles(): Promise<string[] | undefined> {
let projFiles: string[] = [];
const hostFiles = await getHostFiles();
if (!hostFiles) {
return undefined;
}
for (let host of hostFiles) {
let projectFile = await vscode.workspace.findFiles(new vscode.RelativePattern(path.dirname(host), '*.csproj'));
projectFile.filter(file => path.dirname(file.fsPath) === path.dirname(host) ? projFiles.push(file?.fsPath) : projFiles);
}
return projFiles.length > 0 ? projFiles : undefined;
}
/**
* Gets the host files from the workspace
* @returns the host file paths
*/
export async function getHostFiles(): Promise<string[] | undefined> {
const hostUris = await vscode.workspace.findFiles('**/host.json');
const hostFiles = hostUris.map(uri => uri.fsPath);
return hostFiles.length > 0 ? hostFiles : undefined;
}
/**
* Gets the local.settings.json file path
* @param projectFile path of the azure function project
* @returns the local.settings.json file path
*/
export async function getSettingsFile(projectFile: string): Promise<string | undefined> {
return path.join(path.dirname(projectFile), 'local.settings.json');
}
/**
* Retrieves the new function file once the file is created and the watcher disposable
* @param projectFile is the path to the project file
* @returns the function file path once created and the watcher disposable
*/
export function waitForNewFunctionFile(projectFile: string): IFileFunctionObject {
const watcher = vscode.workspace.createFileSystemWatcher((
path.dirname(projectFile), '**/*.cs'), false, true, true);
const filePromise = new Promise<string>((resolve, _) => {
watcher.onDidCreate((e) => {
resolve(e.fsPath);
});
});
return {
filePromise,
watcherDisposable: watcher
};
}
/**
* Retrieves the new host project file once it has created and the watcher disposable
* @returns the host file path once created and the watcher disposable
*/
export function waitForNewHostFile(): IFileFunctionObject {
const watcher = vscode.workspace.createFileSystemWatcher('**/host.json', false, true, true);
const filePromise = new Promise<string>((resolve, _) => {
watcher.onDidCreate((e) => {
resolve(e.fsPath);
});
});
return {
filePromise,
watcherDisposable: watcher
};
}
/**
* Adds the required nuget package to the project
* @param selectedProjectFile is the users selected project file path
*/
export async function addNugetReferenceToProjectFile(selectedProjectFile: string): Promise<void> {
await utils.executeCommand(`dotnet add ${selectedProjectFile} package ${constants.sqlExtensionPackageName} --prerelease`);
}
/**
* Adds the Sql Connection String to the local.settings.json
* @param connectionString of the SQL Server connection that was chosen by the user
*/
export async function addConnectionStringToConfig(connectionString: string, projectFile: string): Promise<void> {
const settingsFile = await getSettingsFile(projectFile);
if (settingsFile) {
await setLocalAppSetting(path.dirname(settingsFile), constants.sqlConnectionString, connectionString);
}
}
/**
* Gets the Azure Functions project that contains the given file if the project is open in one of the workspace folders
* @param fileUri file that the containing project needs to be found for
* @returns uri of project or undefined if project couldn't be found
*/
export async function getAFProjectContainingFile(fileUri: vscode.Uri): Promise<vscode.Uri | undefined> {
// get functions csprojs in the workspace
const projectPromises = vscode.workspace.workspaceFolders?.map(f => utils.getAllProjectsInFolder(f.uri, '.csproj')) ?? [];
const functionsProjects = (await Promise.all(projectPromises)).reduce((prev, curr) => prev.concat(curr), []).filter(p => isFunctionProject(path.dirname(p.fsPath)));
// look for project folder containing file if there's more than one
if (functionsProjects.length > 1) {
// TODO: figure out which project contains the file
// the new style csproj doesn't list all the files in the project anymore, unless the file isn't in the same folder
// so we can't rely on using that to check
console.error('need to find which project contains the file ' + fileUri.fsPath);
return undefined;
} else if (functionsProjects.length === 0) {
throw new Error(constants.noAzureFunctionsProjectsInWorkspace);
} else {
return functionsProjects[0];
}
}
// Use 'host.json' as an indicator that this is a functions project
// copied from verifyIsproject.ts in vscode-azurefunctions extension
export async function isFunctionProject(folderPath: string): Promise<boolean> {
return fs.existsSync(path.join(folderPath, constants.hostFileName));
}
/**
* Prompts the user to select type of binding and returns result
*/
export async function promptForBindingType(): Promise<(vscode.QuickPickItem & { type: BindingType }) | undefined> {
const inputOutputItems: (vscode.QuickPickItem & { type: BindingType })[] = [
{
label: constants.input,
type: BindingType.input
},
{
label: constants.output,
type: BindingType.output
}
];
const selectedBinding = (await vscode.window.showQuickPick(inputOutputItems, {
canPickMany: false,
title: constants.selectBindingType,
ignoreFocusOut: true
}));
return selectedBinding;
}
/**
* Prompts the user to enter object name for the SQL query
* @param bindingType Type of SQL Binding
*/
export async function promptForObjectName(bindingType: BindingType): Promise<string | undefined> {
return vscode.window.showInputBox({
prompt: bindingType === BindingType.input ? constants.sqlTableOrViewToQuery : constants.sqlTableToUpsert,
placeHolder: constants.placeHolderObject,
validateInput: input => input ? undefined : constants.nameMustNotBeEmpty,
ignoreFocusOut: true
});
}
/**
* Prompts the user to enter connection setting and updates it from AF project
* @param projectUri Azure Function project uri
*/
export async function promptAndUpdateConnectionStringSetting(projectUri: vscode.Uri | undefined): Promise<string | undefined> {
let connectionStringSettingName: string | undefined;
const vscodeMssqlApi = await utils.getVscodeMssqlApi();
// show the settings from project's local.settings.json if there's an AF functions project
if (projectUri) {
let settings;
try {
settings = await getLocalSettingsJson(path.join(path.dirname(projectUri.fsPath!), constants.azureFunctionLocalSettingsFileName));
} catch (e) {
void vscode.window.showErrorMessage(utils.getErrorMessage(e));
return;
}
let existingSettings: (vscode.QuickPickItem)[] = [];
if (settings?.Values) {
existingSettings = Object.keys(settings.Values).map(setting => {
return {
label: setting
} as vscode.QuickPickItem;
});
}
existingSettings.unshift({ label: constants.createNewLocalAppSettingWithIcon });
let sqlConnectionStringSettingExists = existingSettings.find(s => s.label === constants.sqlConnectionStringSetting);
while (!connectionStringSettingName) {
const selectedSetting = await vscode.window.showQuickPick(existingSettings, {
canPickMany: false,
title: constants.selectSetting,
ignoreFocusOut: true
});
if (!selectedSetting) {
// User cancelled
return;
}
if (selectedSetting.label === constants.createNewLocalAppSettingWithIcon) {
const newConnectionStringSettingName = await vscode.window.showInputBox(
{
title: constants.enterConnectionStringSettingName,
ignoreFocusOut: true,
value: sqlConnectionStringSettingExists ? '' : constants.sqlConnectionStringSetting,
validateInput: input => input ? undefined : constants.nameMustNotBeEmpty
}
) ?? '';
if (!newConnectionStringSettingName) {
// go back to select setting quickpick if user escapes from inputting the setting name in case they changed their mind
continue;
}
// show the connection string methods (user input and connection profile options)
const listOfConnectionStringMethods = [constants.connectionProfile, constants.userConnectionString];
while (true) {
const selectedConnectionStringMethod = await vscode.window.showQuickPick(listOfConnectionStringMethods, {
canPickMany: false,
title: constants.selectConnectionString,
ignoreFocusOut: true
});
if (!selectedConnectionStringMethod) {
// User cancelled
return;
}
let connectionString: string = '';
let includePassword: string | undefined;
let connectionInfo: IConnectionInfo | undefined;
let connectionDetails: ConnectionDetails;
if (selectedConnectionStringMethod === constants.userConnectionString) {
// User chooses to enter connection string manually
connectionString = await vscode.window.showInputBox(
{
title: constants.enterConnectionString,
ignoreFocusOut: true,
value: 'Server=localhost;Initial Catalog={db_name};User ID=sa;Password={your_password};Persist Security Info=False',
validateInput: input => input ? undefined : constants.valueMustNotBeEmpty
}
) ?? '';
} else {
// Let user choose from existing connections to create connection string from
connectionInfo = await vscodeMssqlApi.promptForConnection(true);
if (!connectionInfo) {
// User cancelled return to selectedConnectionStringMethod prompt
continue;
}
connectionDetails = { options: connectionInfo };
try {
// Prompt to include password in connection string if authentication type is SqlLogin and connection has password saved
if (connectionInfo.authenticationType === 'SqlLogin' && connectionInfo.password) {
includePassword = await vscode.window.showQuickPick([constants.yesString, constants.noString], {
title: constants.includePassword,
canPickMany: false,
ignoreFocusOut: true
});
if (includePassword === constants.yesString) {
// set connection string to include password
connectionString = await vscodeMssqlApi.getConnectionString(connectionDetails, true, false);
}
}
// set connection string to not include the password if connection info does not include password, or user chooses to not include password, or authentication type is not sql login
if (includePassword !== constants.yesString) {
connectionString = await vscodeMssqlApi.getConnectionString(connectionDetails, false, false);
}
} catch (e) {
// failed to get connection string for selected connection and will go back to prompt for connection string methods
console.warn(e);
void vscode.window.showErrorMessage(constants.failedToGetConnectionString);
continue;
}
}
if (connectionString) {
try {
const projectFolder: string = path.dirname(projectUri.fsPath);
const localSettingsPath: string = path.join(projectFolder, constants.azureFunctionLocalSettingsFileName);
let userPassword: string | undefined;
// Ask user to enter password if auth type is sql login and password is not saved
if (connectionInfo?.authenticationType === 'SqlLogin' && !connectionInfo?.password) {
userPassword = await vscode.window.showInputBox({
prompt: constants.enterPasswordPrompt,
placeHolder: constants.enterPasswordManually,
ignoreFocusOut: true,
password: true,
validateInput: input => input ? undefined : constants.valueMustNotBeEmpty
});
if (userPassword) {
// if user enters password replace password placeholder with user entered password
connectionString = connectionString.replace(constants.passwordPlaceholder, userPassword);
}
}
if (includePassword !== constants.yesString && !userPassword && connectionInfo?.authenticationType === 'SqlLogin') {
// if user does not want to include password or user does not enter password, show warning message that they will have to enter it manually later in local.settings.json
void vscode.window.showWarningMessage(constants.userPasswordLater, constants.openFile, constants.closeButton).then(async (result) => {
if (result === constants.openFile) {
// open local.settings.json file
void vscode.commands.executeCommand(constants.vscodeOpenCommand, vscode.Uri.file(localSettingsPath));
}
});
}
const success = await setLocalAppSetting(projectFolder, newConnectionStringSettingName, connectionString);
if (success) {
// exit both loops and insert binding
connectionStringSettingName = newConnectionStringSettingName;
break;
} else {
void vscode.window.showErrorMessage(constants.selectConnectionError());
}
} catch (e) {
// display error message and show select setting quickpick again
void vscode.window.showErrorMessage(constants.selectConnectionError(e));
continue;
}
}
}
} else {
// If user cancels out of this or doesn't want to overwrite an existing setting
// just return them to the select setting quickpick in case they changed their mind
connectionStringSettingName = selectedSetting.label;
}
}
// Add sql extension package reference to project. If the reference is already there, it doesn't get added again
await addNugetReferenceToProjectFile(projectUri.fsPath);
} else {
// if no AF project was found or there's more than one AF functions project in the workspace,
// ask for the user to input the setting name
connectionStringSettingName = await vscode.window.showInputBox({
prompt: constants.connectionStringSetting,
placeHolder: constants.connectionStringSettingPlaceholder,
ignoreFocusOut: true
});
}
return connectionStringSettingName;
}

View File

@@ -0,0 +1,90 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vscode-nls';
import * as utils from '../common/utils';
const localize = nls.loadMessageBundle();
// Azure Functions
export const azureFunctionsExtensionName = 'ms-azuretools.vscode-azurefunctions';
export const sqlConnectionString = 'SqlConnectionString';
export const linkToAzureFunctionExtension = 'https://docs.microsoft.com/azure/azure-functions/functions-develop-vs-code';
export const sqlBindingsDoc = 'https://aka.ms/sqlbindings';
export const defaultSqlBindingTextLines =
[
'log.LogInformation(\"C# HTTP trigger function processed a request.\");',
'string name = req.Query[\"name\"];',
'string requestBody = await new StreamReader(req.Body).ReadToEndAsync();',
'dynamic data = JsonConvert.DeserializeObject(requestBody);',
'name = name ?? data?.name;',
'string responseMessage = string.IsNullOrEmpty(name) ? \"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.\" : $\"Hello, {name}. This HTTP triggered function executed successfully.\";'
];
export const defaultBindingResult = 'return new OkObjectResult(responseMessage);';
export const sqlBindingResult = `return new OkObjectResult(result);`;
export const sqlExtensionPackageName = 'Microsoft.Azure.WebJobs.Extensions.Sql';
export const functionNameTitle = localize('functionNameTitle', 'Function Name');
export const selectProject = localize('selectProject', 'Select the Azure Function project for the SQL Binding');
export const azureFunctionsExtensionNotFound = localize('azureFunctionsExtensionNotFound', 'The Azure Functions extension is required to create a new Azure Function with SQL binding but is not installed, install it now?');
export const install = localize('install', 'Install');
export const learnMore = localize('learnMore', 'Learn more');
export const doNotInstall = localize('doNotInstall', 'Do not install');
export const createProject = localize('createProject', 'Create Azure Function Project');
export const selectAzureFunctionProjFolder = localize('selectAzureFunctionProjFolder', 'Select folder for the Azure Function project');
export const timeoutExtensionError = localize('timeoutExtensionError', 'Timed out waiting for extension to install');
export const timeoutAzureFunctionFileError = localize('timeoutAzureFunctionFileError', 'Timed out waiting for Azure Function file to be created');
export const timeoutProjectError = localize('timeoutProjectError', 'Timed out waiting for project to be created');
export const errorNewAzureFunction = localize('errorNewAzureFunction', 'Error creating new Azure Function: {0}');
export const azureFunctionsExtensionNotInstalled = localize('azureFunctionsExtensionNotInstalled', 'Azure Functions extension must be installed in order to use this feature.');
export const azureFunctionsProjectMustBeOpened = localize('azureFunctionsProjectMustBeOpened', 'A C# Azure Functions project must be present in order to create a new Azure Function for this table.');
// Insert SQL binding
export const hostFileName = 'host.json';
export const placeHolderObject = '[dbo].[table1]';
export const sqlBindingsHelpLink = 'https://github.com/Azure/azure-functions-sql-extension/blob/main/README.md';
export const passwordPlaceholder = '******';
export const azureFunctionLocalSettingsFileName = 'local.settings.json';
export const vscodeOpenCommand = 'vscode.open';
export const nameMustNotBeEmpty = localize('nameMustNotBeEmpty', "Name must not be empty");
export const yesString = localize('yesString', "Yes");
export const noString = localize('noString', "No");
export const input = localize('input', "Input");
export const output = localize('output', "Output");
export const selectBindingType = localize('selectBindingType', "Select type of binding");
export const selectAzureFunction = localize('selectAzureFunction', "Select an Azure function in the current file to add SQL binding to");
export const sqlTableOrViewToQuery = localize('sqlTableOrViewToQuery', "SQL table or view to query");
export const sqlTableToUpsert = localize('sqlTableToUpsert', "SQL table to upsert into");
export const connectionStringSetting = localize('connectionStringSetting', "Connection string setting name");
export const selectSetting = localize('selectSetting', "Select SQL connection string setting from local.settings.json");
export const connectionStringSettingPlaceholder = localize('connectionStringSettingPlaceholder', "Connection string setting specified in \"local.settings.json\"");
export const noAzureFunctionsInFile = localize('noAzureFunctionsInFile', "No Azure functions in the current active file");
export const noAzureFunctionsProjectsInWorkspace = localize('noAzureFunctionsProjectsInWorkspace', "No Azure functions projects found in the workspace");
export const addPackage = localize('addPackage', "Add Package");
export const createNewLocalAppSetting = localize('createNewLocalAppSetting', 'Create new local app setting');
export const createNewLocalAppSettingWithIcon = `$(add) ${createNewLocalAppSetting}`;
export const sqlConnectionStringSetting = 'SqlConnectionString';
export const valueMustNotBeEmpty = localize('valueMustNotBeEmpty', "Value must not be empty");
export const enterConnectionStringSettingName = localize('enterConnectionStringSettingName', "Enter connection string setting name");
export const enterConnectionString = localize('enterConnectionString', "Enter connection string");
export const saveChangesInFile = localize('saveChangesInFile', "There are unsaved changes in the current file. Save now?");
export const save = localize('save', "Save");
export function settingAlreadyExists(settingName: string) { return localize('SettingAlreadyExists', 'Local app setting \'{0}\' already exists. Overwrite?', settingName); }
export function failedToParse(errorMessage: string) { return localize('failedToParse', 'Failed to parse "{0}": {1}.', azureFunctionLocalSettingsFileName, errorMessage); }
export function jsonParseError(error: string, line: number, column: number) { return localize('jsonParseError', '{0} near line "{1}", column "{2}"', error, line, column); }
export const moreInformation = localize('moreInformation', "More Information");
export const addPackageReferenceMessage = localize('addPackageReferenceMessage', 'To use SQL bindings, ensure your Azure Functions project has a reference to {0}', sqlExtensionPackageName);
export const addSqlBindingPackageError = localize('addSqlBindingPackageError', 'Error adding Sql Binding extension package to project');
export const failedToGetConnectionString = localize('failedToGetConnectionString', 'An error occurred generating the connection string for the selected connection');
export const connectionProfile = localize('connectionProfile', 'Select a connection profile');
export const userConnectionString = localize('userConnectionString', 'Enter connection string');
export const selectConnectionString = localize('selectConnectionString', 'Select SQL connection string method');
export const selectConnectionError = (err?: any) => err ? localize('selectConnectionError', "Failed to set connection string app setting: {0}", utils.getErrorMessage(err)) : localize('unableToSetConnectionString', "Failed to set connection string app setting");
export const includePassword = localize('includePassword', 'Do you want to include the password from this connection in your local.settings.json file?');
export const enterPasswordPrompt = localize('enterPasswordPrompt', 'Enter the password to be used for the connection string');
export const enterPasswordManually = localize('enterPasswordManually', 'Enter password or press escape to cancel');
export const userPasswordLater = localize('userPasswordLater', 'In order to user the SQL connection string later you will need to manually enter the password in your local.settings.json file.');
export const openFile = localize('openFile', "Open File");
export const closeButton = localize('closeButton', "Close");

View File

@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// copied from vscode-azurefunctions extension
import * as jsonc from 'jsonc-parser';
import * as constants from './constants';
/**
* Parses and returns JSON
* Has extra logic to remove a BOM character if it exists and handle comments
*/
export function parseJson<T extends object>(data: string): T {
if (data.charCodeAt(0) === 0xFEFF) {
data = data.slice(1);
}
const errors: jsonc.ParseError[] = [];
const result: T = <T>jsonc.parse(data, errors, { allowTrailingComma: true });
if (errors.length > 0) {
const [line, column]: [number, number] = getLineAndColumnFromOffset(data, errors[0].offset);
throw new Error(constants.jsonParseError(jsonc.printParseErrorCode(errors[0].error), line, column));
} else {
return result;
}
}
export function getLineAndColumnFromOffset(data: string, offset: number): [number, number] {
const lines: string[] = data.split('\n');
let charCount: number = 0;
let lineCount: number = 0;
let column: number = 0;
for (const line of lines) {
lineCount += 1;
const lineLength: number = line.length + 1;
charCount += lineLength;
if (charCount >= offset) {
column = offset - (charCount - lineLength);
break;
}
}
return [lineCount, column];
}

View File

@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import AdsTelemetryReporter from '@microsoft/ads-extension-telemetry';
import { getPackageInfo } from './utils';
const packageInfo = getPackageInfo()!;
export const TelemetryReporter = new AdsTelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
export enum TelemetryViews {
SqlBindingsQuickPick = 'SqlBindingsQuickPick'
}
export enum TelemetryActions {
startAddSqlBinding = 'startAddSqlBinding',
finishAddSqlBinding = 'finishAddSqlBinding'
}

View File

@@ -0,0 +1,185 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type * as azdataType from 'azdata';
import * as vscode from 'vscode';
import * as vscodeMssql from 'vscode-mssql';
import * as fs from 'fs';
import * as path from 'path';
import * as glob from 'fast-glob';
import * as cp from 'child_process';
export interface ValidationResult {
errorMessage: string;
validated: boolean
}
export interface IPackageInfo {
name: string;
fullName: string;
version: string;
aiKey: string;
}
/**
* Consolidates on the error message string
*/
export function getErrorMessage(error: any): string {
return (error instanceof Error)
? (typeof error.message === 'string' ? error.message : '')
: typeof error === 'string' ? error : `${JSON.stringify(error, undefined, '\t')}`;
}
export async function getAzureFunctionService(): Promise<vscodeMssql.IAzureFunctionsService> {
if (getAzdataApi()) {
// this isn't supported in ADS
throw new Error('Azure Functions service is not supported in Azure Data Studio');
} else {
const api = await getVscodeMssqlApi();
return api.azureFunctions;
}
}
export async function getVscodeMssqlApi(): Promise<vscodeMssql.IExtension> {
const ext = vscode.extensions.getExtension(vscodeMssql.extension.name) as vscode.Extension<vscodeMssql.IExtension>;
return ext.activate();
}
// Try to load the azdata API - but gracefully handle the failure in case we're running
// in a context where the API doesn't exist (such as VS Code)
let azdataApi: typeof azdataType | undefined = undefined;
try {
azdataApi = require('azdata');
if (!azdataApi?.version) {
// webpacking makes the require return an empty object instead of throwing an error so make sure we clear the var
azdataApi = undefined;
}
} catch {
// no-op
}
/**
* Gets the azdata API if it's available in the context this extension is running in.
* @returns The azdata API if it's available
*/
export function getAzdataApi(): typeof azdataType | undefined {
return azdataApi;
}
export async function executeCommand(command: string, cwd?: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
cp.exec(command, { maxBuffer: 500 * 1024, cwd: cwd }, (error: Error | null, stdout: string, stderr: string) => {
if (error) {
reject(error);
return;
}
if (stderr && stderr.length > 0) {
reject(new Error(stderr));
return;
}
resolve(stdout);
});
});
}
/**
* Gets all the projects of the specified extension in the folder
* @param folder
* @param projectExtension project extension to filter on
* @returns array of project uris
*/
export async function getAllProjectsInFolder(folder: vscode.Uri, projectExtension: string): Promise<vscode.Uri[]> {
// path needs to use forward slashes for glob to work
const escapedPath = glob.escapePath(folder.fsPath.replace(/\\/g, '/'));
// filter for projects with the specified project extension
const projFilter = path.posix.join(escapedPath, '**', `*${projectExtension}`);
// glob will return an array of file paths with forward slashes, so they need to be converted back if on windows
return (await glob(projFilter)).map(p => vscode.Uri.file(path.resolve(p)));
}
/**
* Format a string. Behaves like C#'s string.Format() function.
*/
export function formatString(str: string, ...args: any[]): string {
// This is based on code originally from https://github.com/Microsoft/vscode/blob/master/src/vs/nls.js
// License: https://github.com/Microsoft/vscode/blob/master/LICENSE.txt
let result: string;
if (args.length === 0) {
result = str;
} else {
result = str.replace(/\{(\d+)\}/g, (match, rest) => {
let index = rest[0];
return typeof args[index] !== 'undefined' ? args[index] : match;
});
}
return result;
}
/**
* Generates a quoted full name for the object
* @param schema of the object
* @param objectName object chosen by the user
* @returns the quoted and escaped full name of the specified schema and object
*/
export function generateQuotedFullName(schema: string, objectName: string): string {
return `[${escapeClosingBrackets(schema)}].[${escapeClosingBrackets(objectName)}]`;
}
/**
* Returns a promise that will reject after the specified timeout
* @param errorMessage error message to be returned in the rejection
* @param ms timeout in milliseconds. Default is 10 seconds
* @returns a promise that rejects after the specified timeout
*/
export function timeoutPromise(errorMessage: string, ms: number = 10000): Promise<string> {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(errorMessage));
}, ms);
});
}
/**
* Gets a unique file name
* Increment the file name by adding 1 to function name if the file already exists
* Undefined if the filename suffix count becomes greater than 1024
* @param folderPath selected project folder path
* @param fileName base filename to use
* @returns a promise with the unique file name, or undefined
*/
export async function getUniqueFileName(folderPath: string, fileName: string): Promise<string | undefined> {
let count: number = 0;
const maxCount: number = 1024;
let uniqueFileName = fileName;
while (count < maxCount) {
if (!fs.existsSync(path.join(folderPath, uniqueFileName + '.cs'))) {
return uniqueFileName;
}
count += 1;
uniqueFileName = fileName + count.toString();
}
return undefined;
}
export function escapeClosingBrackets(str: string): string {
return str.replace(']', ']]');
}
/**
* Gets the package info for the extension based on where the extension is installed
* @returns the package info object
*/
export function getPackageInfo(): IPackageInfo {
const packageJson = require('../../package.json');
return {
name: packageJson.name,
fullName: `${packageJson.publisher}.${packageJson.name}`,
version: packageJson.version,
aiKey: packageJson.aiKey
};
}

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AddSqlBindingParams, GetAzureFunctionsParams, GetAzureFunctionsResult, ResultStatus } from 'sql-bindings';
import { RequestType } from 'vscode-languageclient';
/**
* Adds a SQL Binding to a specified Azure function in a file
*/
export namespace AddSqlBindingRequest {
export const type = new RequestType<AddSqlBindingParams, ResultStatus, void, void>('azureFunctions/sqlBinding');
}
/**
* Gets the names of the Azure functions in a file
*/
export namespace GetAzureFunctionsRequest {
export const type = new RequestType<GetAzureFunctionsParams, GetAzureFunctionsResult, void, void>('azureFunctions/getAzureFunctions');
}

View File

@@ -0,0 +1,103 @@
/*---------------------------------------------------------------------------------------------
* 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 constants from '../common/constants';
import * as utils from '../common/utils';
import * as azureFunctionsUtils from '../common/azureFunctionsUtils';
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined): Promise<void> {
TelemetryReporter.sendActionEvent(TelemetryViews.SqlBindingsQuickPick, TelemetryActions.startAddSqlBinding);
if (!uri) {
// this command only shows in the command palette when the active editor is a .cs file, so we can safely assume that's the scenario
// when this is called without a uri
uri = vscode.window.activeTextEditor!.document.uri;
if (vscode.window.activeTextEditor!.document.isDirty) {
const result = await vscode.window.showWarningMessage(constants.saveChangesInFile, { modal: true }, constants.save);
if (result !== constants.save) {
return;
}
await vscode.window.activeTextEditor!.document.save();
}
}
// get all the Azure functions in the file
const azureFunctionsService = await utils.getAzureFunctionService();
let getAzureFunctionsResult;
try {
getAzureFunctionsResult = await azureFunctionsService.getAzureFunctions(uri.fsPath);
} catch (e) {
void vscode.window.showErrorMessage(utils.getErrorMessage(e));
return;
}
const azureFunctions = getAzureFunctionsResult.azureFunctions;
if (azureFunctions.length === 0) {
void vscode.window.showErrorMessage(constants.noAzureFunctionsInFile);
return;
}
// 1. select Azure function from the current file
const azureFunctionName = (await vscode.window.showQuickPick(azureFunctions, {
canPickMany: false,
title: constants.selectAzureFunction,
ignoreFocusOut: true
}));
if (!azureFunctionName) {
return;
}
// 2. select input or output binding
const selectedBinding = await azureFunctionsUtils.promptForBindingType();
if (!selectedBinding) {
return;
}
// 3. ask for object name for the binding
const objectName = await azureFunctionsUtils.promptForObjectName(selectedBinding.type);
if (!objectName) {
return;
}
// 4. ask for connection string setting name
let projectUri: vscode.Uri | undefined;
try {
projectUri = await azureFunctionsUtils.getAFProjectContainingFile(uri);
} catch (e) {
// continue even if there's no AF project found. The binding should still be able to be added as long as there was an azure function found in the file earlier
}
let connectionStringSettingName = await azureFunctionsUtils.promptAndUpdateConnectionStringSetting(projectUri);
if (!connectionStringSettingName) {
return;
}
// 5. insert binding
try {
const result = await azureFunctionsService.addSqlBinding(selectedBinding.type, uri.fsPath, azureFunctionName, objectName, connectionStringSettingName);
if (!result.success) {
void vscode.window.showErrorMessage(result.errorMessage);
TelemetryReporter.sendErrorEvent(TelemetryViews.SqlBindingsQuickPick, TelemetryActions.finishAddSqlBinding);
return;
}
TelemetryReporter.createActionEvent(TelemetryViews.SqlBindingsQuickPick, TelemetryActions.finishAddSqlBinding)
.withAdditionalProperties({ bindingType: selectedBinding.label })
.send();
} catch (e) {
void vscode.window.showErrorMessage(utils.getErrorMessage(e));
TelemetryReporter.sendErrorEvent(TelemetryViews.SqlBindingsQuickPick, TelemetryActions.finishAddSqlBinding);
return;
}
}

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