Compare commits

...

212 Commits
1.6.0 ... 1.7.0

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

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

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

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

* replace with space

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

* Fixing variable name and spelling
2019-05-06 15:58:20 -07:00
Aditya Bist
39f9c72390 fixed packaged icons for azure (#5354) 2019-05-03 18:47:45 -07:00
Anthony Dresser
0023714884 Fix menu entry for tasks (#5355)
* fix menu entry for tasks

* change wording for action
2019-05-03 18:20:51 -07:00
kisantia
ec9fdc517f Fix schema compare dialog font sizes (#5353)
* make font sizes consistent

* fix order of source dialog options

* update fontsize to 13

* make fontsize a constant
2019-05-04 10:48:25 +12:00
Anthony Dresser
db387eb770 Fixing the layering in the base folder (#5308)
* removes more builder references

* remove builder from profiler

* formatting

* fix profiler dailog

* remove builder from oatuhdialog

* remove the rest of builder references

* formatting

* add more strict null checks to base

* enable strict tslint rules

* code layering of base

* wip

* working through changes to table data view

* fix tests

* update editabledropdown to not use layout service

* wip

* fix imports

* fix import

* fix compile error

* add more localization

* add comments to changes to import patterns

* add more import comments
2019-05-03 14:49:18 -07:00
kisantia
354ed22706 Fix #5314: schema compare doesn't always open with correct default connection (#5315)
* fix schema compare default connection when there are multiple connections
2019-05-04 09:40:53 +12:00
Aditya Bist
a69f194d8b Fixed CMS connection auth (#5306)
* fixed auth change to reflect in UI

* added comments

* fix bug where cms shows in dropdown

* added parameter to parent call
2019-05-03 13:26:04 -07:00
Aditya Bist
f5d13319a2 Remove CMS from packaged builds (#5349)
* remove cmss from packaged builds

* add repo to package file

* added cms to recommendations
2019-05-03 13:25:47 -07:00
Yurong He
9a0e691635 Change toolbar icon back to black (#5345)
* Change it back to black icon

* Install package icon
2019-05-03 13:11:44 -07:00
kisantia
6c7cb185a1 group source and target components into formcomponentgroups (#5329) 2019-05-04 05:51:40 +12:00
Charles Gagnon
ab22b93ce0 SsmsMin integration clean-up and improvements (#5339)
* SsmsMin integration clean-up and improvements

* Fix tests
2019-05-03 08:44:21 -07:00
Karl Burtram
c7f5278430 Remove 'Try backup or restore task' from task message (#5340) 2019-05-02 18:52:11 -07:00
Anthony Dresser
56ad0dbaf2 revert changes to common file and move icons to specific folder (#5335) 2019-05-02 18:14:13 -07:00
Anthony Dresser
74c92cd460 disable page scrolling in slickgrid (#5333) 2019-05-02 18:13:49 -07:00
Alan Ren
16ebb4322a fix insights dialog issue (#5336) 2019-05-02 18:13:33 -07:00
kisantia
fccd026812 Remove database name from schema compare source/target server field (#5327)
* remove database name from source/target server field
2019-05-03 11:20:28 +12:00
Charles Gagnon
b6e49f2bc0 Fix connections from editor not saving to MRU (#5328) 2019-05-02 16:08:46 -07:00
Karl Burtram
188ccf849d Fix nullref exception in connection profile (#5330)
* Fix nullref exception in connection profile

* Fix condition
2019-05-02 16:04:03 -07:00
Anthony Dresser
1bfdce9642 fix icons for various status; move menu entry to the other panels (#5319) 2019-05-02 14:31:58 -07:00
Karl Burtram
495254b0be Remove package-lock.json from extension sample (#5324) 2019-05-02 13:41:48 -07:00
Charles Gagnon
d209ff7b9a Fix broken CMS test and add to test-extensions-unit scripts (#5301) 2019-05-02 11:13:30 -07:00
Yurong He
98eeb50060 Fixed #4953 provider create file action when file is deleted (#5283)
* Fixed #4953 following query editor behavior provide create file option when file name doesn't exist

* Check active edtior is the correct one before closing

* close editor

* Removed codes not needed

* Check error null
2019-05-02 10:59:46 -07:00
Chris LaFreniere
8a68f0aaf9 Improvements to notebook editor code auto height (#5291) 2019-05-02 10:23:26 -07:00
Anthony Dresser
039859213c Replace observable references with just promises (#5278)
* replace observable references with just promises

* add tests for searching in dataview

* add comments

* work through respecting max matches

* fix tests

* fix strict null checks
2019-05-02 00:06:28 -07:00
Alan Ren
a3c022aebf Update dropdown.ts (#5290)
* Update dropdown.ts

fix the issue that the filtering feature is not working

* format the doc

* comments
2019-05-01 22:55:53 -07:00
Anthony Dresser
3a9b32b6e8 Task item look update (#5299)
* wip

* wip

* wip
2019-05-01 13:25:18 -07:00
Karl Burtram
c1cb9000a9 Various results grid scrolling fixes (#5285) 2019-05-01 12:36:16 -07:00
Kevin Cunnane
104b99ffa0 Fix #4553 Azure account prompt (#5303)
"Are you sure" prompt on removing Azure account does not respect "No"
2019-05-01 12:28:36 -07:00
Charles Gagnon
a89d7f327a Update SsmsMin to 15.0.18120.0 (#5293) 2019-05-01 11:29:36 -07:00
Charles Gagnon
91bc4bde3c Change default timeout value to 30sec to match SSMS (#5289) 2019-05-01 11:19:40 -07:00
Charles Gagnon
80da7ad496 Fix broken CMS commands (#5296) 2019-05-01 10:55:58 -07:00
Charles Gagnon
64bf211a45 Fix failing OE Tests caused by changes in connection API defaults (#5295)
* Fix failing OE Tests caused by changes in connection API defaults

* More spelling fixes
2019-05-01 10:18:23 -07:00
Anthony Dresser
2558a66a48 Merge from vscode 473af338e1bd9ad4d9853933da1cd9d5d9e07dc9 (#5286) 2019-04-30 21:53:52 -07:00
kisantia
df22eab4ec fix diff editor title disappearing after swap (#5280) 2019-05-01 11:30:03 +12:00
Aditya Bist
c2678cf818 Committer work - Agent tests (#5034)
* added couple tests

* added unit tests for agent extension

* added agent test in test script
2019-04-30 16:25:16 -07:00
Yurong He
f9af34b103 Notebook toolbar UI improvement (#5282)
Fixed  #5236
- Change the icon to blue image. Existing icons are not deleted. We will use them when the icons are - - moved as the secondary actions.
- Change the font size to 13px
- Change the height to 21px
- Move Add actions to the left
2019-04-30 16:18:48 -07:00
Charles Gagnon
97cab22e00 Add more SsmsMin interactions (#5267)
* Add support for more SsmsMin property dialogs and the Generate Script Wizard. Also fixed bug with ExtHostObjectExplorerNode getParent function

* Localize package.json entries

* Fix localization tokens

* Address PR comments

* Fix regex and getParent
2019-04-30 16:10:11 -07:00
Kevin Cunnane
64416e05c1 Notebook StdIn support to fix #5231 (#5232)
Fixes #5231 
- Add stdin handling. Has to be at UI level so add plumb through handling
- Add unit tests
- Add new StdIn component.

Testing:
Unit Tests and manual testing of following:
- Prompt for password using `getpass` in python.
   - Password prompt is hidden since "password" is true.
   - Hit enter, it completes
- prompt, stop cell running, StdIn disappears
- prompt, hit escape, stdIn disappears and stdIn request is handled.

Issues: focus isn't always set to the input even though we call focus.
Will investigate this further.
2019-04-30 14:57:27 -07:00
Kevin Cunnane
b21125ff2d Fix markdown security and enable most CSS (#5263)
* Fix markdown security and enable most CSS

Stops using our sanitizer and instead disables HTML in markdown engine
- This was blocking Note because it converted > to >
- It's slightly more strict in that it fully disables HTML unless trusted. Will need to improve handling of Trusted to support this in a future PR

Adds in correct CSS, both from .css file in markdown extension and from built-into all webviews global CSS
- Fix #3765 standard markdown support
- Fix Support of Notes by bringing correct styles
- Fix code block colorization
- Fix link handling so it's not bolded / gets underlined on hover
- Fixes table rendering (for markdown and HTML tables)

* Reduce scope of CSS changes
- Removed some CSS that wasn't needed or caused issues
- Scoped most things under the preview section not the whole component

* Avoid markdown html block by sanitizing after render

* Fix pre node not overflowing
- This was a bug in existing implementation too
2019-04-30 14:21:20 -07:00
Chris LaFreniere
e72d0d03ed Notebooks: More Jupyter Server Hardening (#5264)
* Do not rely on same starting port every time, misc

* put back to 5 seconds for process kill timeout

* extHostNotebook shutdown manager handle
2019-04-30 14:13:04 -07:00
Anthony Dresser
0f12d15020 Refactor connection store (#5024)
* various clean ups

* formatting

* remove linting

* formatting

* IConfigurationService is even better

* messing with connection config tests

* update tests

* formatting

* foramtting

* remove unused code

* add more tests

* working through tests

* formatting

* more factoring of connection store and increase code coverage

* formatting

* fix tests

* change use of state service to storage service

* remove unused files

* fix strict null errors

* formatting
2019-04-30 13:32:32 -07:00
Yurong He
44a2d009c0 Fixed #4169 shows notification when not active code cell is selected when hit F5 (#5259)
* Refine the msg
2019-04-30 13:25:11 -07:00
Anthony Dresser
48682bacde rework panel to not need platform (#5270) 2019-04-30 13:19:21 -07:00
Aditya Bist
f70369c2a6 Fix object explorer session fails (#5256)
* only start session if response successful

* added return type

* fixed OE tests

* format doc
2019-04-30 11:45:52 -07:00
udeeshagautam
f7fc94520a Fixing schema compare object type enum to follow PascalCasing (#5266) 2019-04-30 11:07:46 -07:00
udeeshagautam
77c6f5c9a2 Reverting the checkboxes because of scrollbar issue 5230 (#5271) 2019-04-30 11:07:11 -07:00
kisantia
dffa47301b fix path to dark icon of options button (#5274) 2019-05-01 05:53:55 +12:00
Charles Gagnon
08f47e7e14 Fix "Open File Location" for CSV Export (#5273)
Fix #5177 - File path wasn't being parsed correctly, URI.file should be used for full file paths.
2019-04-30 10:41:19 -07:00
Anthony Dresser
56342af140 Rework editableDropdown to not need platform (#5189)
* rework editableDropdown to not need platform

* rework editable dropdown to not depend on platform

* fix compile

* fix focus bluring
2019-04-30 09:25:04 -07:00
Anthony Dresser
aacc0eca67 Merge from vscode 071a5cf16fc999727acc31c790d78f750fa4b166 (#5261) 2019-04-30 07:54:56 -07:00
Kevin Cunnane
02916aeffa Fix #3440 link in Markdown requires cmd+click (#5239)
- Copied over click handler from VSCode markdown renderer
- Added logic to only support command links if trusted

Now clicking on a link will do an action or open a file.
Created #5238 to track need to support relative links which doesn't work
2019-04-29 19:15:39 -07:00
udeeshagautam
e42bfada9d Feature/schemacompare options (#5143)
* extension now working

* make button messages better

* fix diff editor title disappearing and remove border from source and target name boxes

* redoing a bunch of stuff that disappeared after rebasing

* add images and add to extensions.ts

* moving a few changes to the right place after rebase

* formatting

* Initial schema compare options working code

* Adding description.icon etc.

* Enabling disabling options button

* Name change: SchemaCompareOptions to DeploymentOptions. To reflect SqltoolsService side parameters

* Adding sorting and correct sql tools version

* Adding options button themes

* Formatting fix

* Adding get default options call to get options from tools service

* Exclude/Include changes - first commit

* Adding border to checkboxes

* Taking PR comments

* Updating to latest sqltools with schema compare options
2019-04-29 18:11:48 -07:00
Karl Burtram
72fb114dec Load MSSQL extension first during eager load phase (#5255) 2019-04-29 17:46:30 -07:00
Karl Burtram
9ba1561386 Bump SQL Tools Service to 1.5.0-alpha.91 (#5260) 2019-04-29 17:38:19 -07:00
Aditya Bist
39772c2dbe CMS Extension - 2 (#4908)
* first set of changes to experiment the registration of cms related apis

* Adding cms service entry to workbench

* Adding basic functionality for add remove reg servers and group

* Returning relative path as part of RegServerResult as string

* initial extension

* cleaned building with connecting to server

* get list of registered servers

* progress with registered servers tree

* cms base node with server selection

* removed unused services

* replaced azure stuff with cms

* removed cmsResourceService

* list servers progress

* Removing the cms apis from core. Having mssql extension expose them for cms extension

* create server working fine

* initial expansion and nodes

* Propogating the backend name changes to apis

* initial cms extension working

* cached connection needs change in api

* connect without dashboard in proposed

* Fixing some missing sqlops references

* add registered server bug found

* added refresh context menu option

* added payload

* server description not disabled after reject connection

* added more context actions and action icons

* added empty resource and error when same name server is added

* fixed connection issues with cms and normal connections

* added initial tests

* added cms icons

* removed azure readme

* test script revert

* fix build tests

* added more cms tests

* fixed test script

* fixed silent error when expanding servers

* added more cms tests

* removed cmsdialog from api

* cms dialog without object

* fixed theming issues

* initial connection dialog done

* can make connections

* PM asks for strings and icons

* removed search

* removed unused code and fixed 1 test

* fix connection management tests

* changed icons

* format file

* fixed hygiene

* initial cr comments

* refactored cms connection dialog

* fixed bug when switching dialogs

* localized connection provider options

* fixed cms provider name

* code review comments

* localized options in cms and mssql

* localized more options
2019-04-29 15:16:59 -07:00
David Shiflet
cbf3ca726f Connect opened query editors to the server (#5207)
* Connect opened query editors to the ser

* only show firewall rule error for one file

* remove unused imports

* sync to latest

* add comment

* one more comment
2019-04-29 13:10:19 -04:00
Yurong He
f1e21ebe9d Fix driverlog uri in output (#5212)
* Fixed #4813

* Changed to lowercase for comparision
2019-04-26 20:25:55 -07:00
Yurong He
49c36cc040 Fixed #4947 Increase the size of the notebook command icons and space between icon and button (#5235) 2019-04-26 19:57:40 -07:00
Anthony Dresser
9b90400abd Merge from vscode 63d257f78a36951ab7e821170ba675b11dc06d48 (#5240) 2019-04-26 17:24:54 -07:00
Karl Burtram
8cda364210 Fix product name in error message (#5233)
* Fix product name in error message

* fix typo
2019-04-26 15:32:30 -07:00
Anthony Dresser
ca98ef879d Last of the layering (#5187)
* layer query

* update imports
2019-04-26 15:30:41 -07:00
Chris LaFreniere
bb9c85cd8f Improve Cleanup of Jupyter processes on Notebook and/or ADS Close (#5142)
* Close jupyter and python

* Ensure we stop jupyter correctly on process end

* dont stopServer from clientSession shutdown

* PR comments

* close notebook after each test
2019-04-26 15:28:26 -07:00
Anthony Dresser
91b946bf3d rework listbox to not require platform (#5192) 2019-04-26 15:02:03 -07:00
kisantia
64377000c6 Change default folder in dacpac and schema compare extensions (#5215)
* change default folder in dacpac and schema compare extensions

* move getting rootpath to a method

* change method name
2019-04-27 04:27:03 +12:00
Yurong He
23f4931a1d Fixed #5210 (#5211)
* Fixed #5210

* Added function to check error to ensure get string
2019-04-25 19:45:33 -07:00
Anthony Dresser
3625834028 Merge from vscode 63655183ba5305b70ffaf1327b8a4708f0a79bd9 (#5221) 2019-04-25 19:18:04 -07:00
Alan Ren
705e7b30bc enable 'New Notebook' entry points for PG SQL (#5194)
* enable 'New Notebook' entry points for PG SQL

* fix comment

* permanent fix for context menu entry point
2019-04-25 16:23:01 -07:00
udeeshagautam
6528c0817d quick fix for column name (#5214) 2019-04-25 15:51:54 -07:00
Aditya Bist
f3d7392af3 Localize connection options for mssql (#5209)
* localize connection options for mssql

* added all strings
2019-04-25 15:13:07 -07:00
Yurong He
5d5f44ba11 Fixed #3961 Removed hardcoded value in notebook and use QueryEditor Result RowHight to keep it consistent (#5208) 2019-04-25 12:59:13 -07:00
Anthony Dresser
34457880c7 Merge from vscode 0fde6619172c9f04c41f2e816479e432cc974b8b (#5199) 2019-04-24 22:26:02 -07:00
kisantia
d63f07d29a Schema compare publish (#5127)
* adding publish command
2019-04-25 10:37:40 +12:00
Anthony Dresser
5c2cbc9d29 fix task contribution (#5188) 2019-04-24 15:05:11 -07:00
Karl Burtram
8dbfa10646 Bump npm packages (#5185) 2019-04-24 14:55:36 -07:00
Anthony Dresser
9e804089e0 Move Tasks Panel (#5162)
* moving tasks panel

* fix css styling

* clean up code

* do a bunch of renaming
2019-04-24 13:54:58 -07:00
v-mdriml
51145903aa LOC CHECKIN | Microsoft/azuredatastudio master | 20190424 (#5179) 2019-04-24 13:46:50 -07:00
Anthony Dresser
036c49f398 Modify coverage process to reduce time (#5164)
* modify coverage process to reduce time

* disable coverage on linux
2019-04-24 13:39:30 -07:00
Chris LaFreniere
46b85ebc6b Fix casing on welcome page to be consistent (#5169) 2019-04-24 11:18:33 -07:00
Yurong He
07bc5e2de9 Fixed #3244 (#5166) 2019-04-24 09:04:15 -07:00
Yurong He
e822091907 Only when the connection is connected, then do disconnect. (#5170) 2019-04-23 19:03:49 -07:00
Chris LaFreniere
7d46e77922 Notebooks: Show keyboard shortcut for run cell (#5097)
* Show keyboard shortcut for run cell

* PR comment
2019-04-23 17:33:15 -07:00
Karl Burtram
ad528ad3d5 Update Azure Data Studio to 1.7.0 for May release (#5167) 2019-04-23 17:24:24 -07:00
Yurong He
e8b4c03770 Fixed #4772 create unique connection for each notebook by using noteb… (#5163)
* Fixed #4772 create unique connection for each notebook by using notebook path as uri
Disconnect sqlConnection from SqlKernel to ensure no connection left after the notebook is closed.

* SqlSessionManager is ADS level manager

* Moved path to SqlKernel constructor
2019-04-23 16:42:28 -07:00
Chris LaFreniere
33aacc1798 Improve Notebook Context Menu Casing (#5145) 2019-04-23 11:35:46 -07:00
Anthony Dresser
58959ef35e Enable stricter compile options on extensions (#5044)
* enable stricter compile settings in extensions

* more strict compile

* formatting

* formatting

* revert some changes

* formtting

* formatting
2019-04-23 11:18:00 -07:00
Charles Gagnon
c66b349cec Show correct release notes for command (#5108) 2019-04-23 10:55:09 -07:00
Aditya Bist
5c90df092b Switch on code coverage (#5120)
* testing code coverage for /sql/

* fix test result path

* fixed coverage task:



'

* added coverage to linux and mac as well

* fix script for mac and linux

* bash script cmd

* fixed scripts

* remove warnings from summary

* remove coverage from linux

* added job action tests

* added more tests
2019-04-23 10:47:03 -07:00
Karl Burtram
32374f264f Adjust default fonts (#5146)
* Adjust default fonts

* Adjust default ratio
2019-04-22 17:30:16 -07:00
Anthony Dresser
5e62229f25 Merge from vscode 2b87545500dbc7899a493d69199aa4e061414ea0 (#5148) 2019-04-22 16:57:13 -07:00
Cory Rivera
1b24dff738 Show an Install Skipped message when Python already exists at the specified install location. (#5141)
* Also fixed a bug where future installs would get blocked after doing an install that gets skipped.
2019-04-22 14:28:59 -07:00
Aditya Bist
161135cd90 remove old unused splash screen (#5112) 2019-04-22 13:39:27 -07:00
Aditya Bist
5fb583da06 uncheck desktop icon by default (#5111) 2019-04-22 13:38:51 -07:00
Kevin Cunnane
8b40d20eab Typings reference failing in external extension (#5129)
This fixes an issue where if you copy azdata.proposed.d.ts to
an extension project, it would fail to compile using default
tsconfig.json settings due to missing return type
2019-04-19 16:41:23 -07:00
Chris LaFreniere
432034d2cb Notebooks: Pressing Escape key in markdown cell exits edit mode (#5094)
* Pressing Escape key in markdown exits edit mode

* text + code cells inactive when pressing escape
2019-04-19 16:19:16 -07:00
Alan Ren
0e168e36fc Merge from vscode 12cb89c82e88e035f4ab630f1b9fcebac338dc03 (#5125) 2019-04-19 10:26:20 -07:00
Cory Rivera
f248260584 Add flag to skip python install integration tests. (#5119) 2019-04-18 17:13:19 -07:00
Cory Rivera
880e3e10da Update Python install messages to differentiate between download completion and install completion. (#5114) 2019-04-18 16:52:50 -07:00
Anthony Dresser
f33b95ee82 Use vscode clipboard rather than clipboardy (#5117)
* remove clipboardy and use vscode's clipboard apis instead

* update lock
2019-04-18 16:34:24 -07:00
Anthony Dresser
4a71eb9b90 use vscode open external rather than opener (#5115) 2019-04-18 16:34:12 -07:00
Chris LaFreniere
3372a5ad4b Fix hygiene issues in textCell.css (#5116) 2019-04-18 15:58:27 -07:00
Zbyněk Sailer
8326f05f66 LOC CHECKIN | Microsoft/azuredatastudio master | 20190418 (#5103) 2019-04-18 14:59:25 -07:00
Chris LaFreniere
7ce921d449 Improve tabe markdown css (#5093) 2019-04-18 14:57:26 -07:00
Chris LaFreniere
31f7364f08 Only show nb loading spinner when no cells shown (#5095) 2019-04-18 14:57:11 -07:00
Anthony Dresser
5119d28b9d fix svg references (#5109) 2019-04-18 12:29:18 -07:00
Yurong He
a2a5fe3bee Added more logging for python installation and remove dup test in the other suite (#5106) 2019-04-18 11:24:12 -07:00
Karl Burtram
6222d8c977 Bump agent extension to 0.38.0 (#5104) 2019-04-18 09:48:47 -07:00
Karl Burtram
d3699a261a Update readme for April release (#5063) 2019-04-18 09:25:01 -07:00
Anthony Dresser
9c0e56d640 Layering of everything else but query (#5085)
* layer profiler and edit data

* relayering everything but query

* fix css import

* readd qp

* fix script src

* fix hygiene
2019-04-18 01:28:43 -07:00
Anthony Dresser
ddd89fc52a Renable Strict TSLint (#5018)
* removes more builder references

* remove builder from profiler

* formatting

* fix profiler dailog

* remove builder from oatuhdialog

* remove the rest of builder references

* formatting

* add more strict null checks to base

* enable strict tslint rules

* fix formatting

* fix compile error

* fix the rest of the hygeny issues and add pipeline step

* fix pipeline files
2019-04-18 00:34:53 -07:00
Alan Ren
b852f032d3 Merge from vscode 3a6dcb42008d509900b3a3b2d695564eeb4dbdac (#5098) 2019-04-17 23:38:44 -07:00
Aditya Bist
1fec26c6b3 dont dispose serverTreeView every time hidden (#5092) 2019-04-17 20:12:44 -07:00
kisantia
d3483afaed Schema Compare extension (#4974)
* extension now working

* fix diff editor title disappearing and remove border from source and target name boxes

* redoing a bunch of stuff that disappeared after rebasing

* add images and add to extensions.ts

* moving a few changes to the right place after rebase

* formatting

* update toolbar svgs

* addressing comments

* add return types

* Adding PR comments

* Adding light and dark theme icons

* Fixing the diff editor title for dark theme
2019-04-17 19:14:22 -07:00
Chris LaFreniere
910e4815fa Enable Python Integration Tests For Notebooks (#5090)
* Enable python notebook tests

* change run_python3_test to be string

* Add explicit pyspark check
2019-04-17 16:46:10 -07:00
Karl Burtram
ef118e3351 Update extension recommendation list (#5086) 2019-04-17 16:26:41 -07:00
Chris LaFreniere
2beedb10d4 Add run cells as a command (#5080) 2019-04-17 14:26:31 -07:00
Charles Gagnon
41bf10d989 Fix for build break caused by missing SVG (#5078)
* Fix for build break caused by missing SVG

These files were moved in #5029

* Add a few more missing SVGs
2019-04-17 11:22:42 -07:00
Chris LaFreniere
ac3b6aef27 ADS Welcome Page (#5043)
* ADS Welcome Page

* sample notebook section

* Opens in browser :(

* Remove sample notebooks section

* fix open file in windows

* Change az_data_welcome_page to be under sql/

* fix tslint issue

* Scope table css down
2019-04-17 10:50:43 -07:00
Anthony Dresser
8956b591f7 Merge from vscode 05fc61ffb1aee9fd19173c32113daed079f9b7bd (#5074)
* Merge from vscode 05fc61ffb1aee9fd19173c32113daed079f9b7bd

* fix tests
2019-04-16 22:11:30 -07:00
Anthony Dresser
2f8519cb6b Layer Object Explorer; query plan; task history (#5030)
* relayer query plan, task history, object-explorer

* formatting
2019-04-16 21:12:34 -07:00
Aditya Bist
15a19c044d remove agent from old apis (#5064) 2019-04-16 17:13:02 -07:00
Alan Ren
ec47ff7479 Alanren/fixsmoketest (#5019)
* fix the smoke test

* update readme

* fix the selector for server name input

* add new property to server profile engineType
2019-04-16 16:43:11 -07:00
Aditya Bist
82f707ee89 Fixed agent filter in dark theme (#5048)
* fixed agent filter in dark theme

* added high contrast theme as well
2019-04-16 15:30:16 -07:00
Alan Ren
dfcab8db6a fix the selectbox issue for chart (#5052) 2019-04-16 13:32:52 -07:00
Anthony Dresser
5c10127758 Layer grid code (#5029)
* layer grid

* errors; edit data still not showing up

* fix edit data

* fix tab spaces
2019-04-16 13:30:15 -07:00
Aditya Bist
b376f36733 fix job action context (#5053) 2019-04-16 13:07:22 -07:00
Aditya Bist
96c0f62cf5 Removed duplicate connections code (#5045)
* removed duplicate connections code

* removed old comment

* removed unused code
2019-04-16 11:54:07 -07:00
Zbyněk Sailer
a96f996b59 LOC CHECKIN | Microsoft/azuredatastudio master | 20190411 (#4993) 2019-04-16 10:36:41 -07:00
Anthony Dresser
b75d0b6cb5 Fix bootstrapping around dashboard (#5040) 2019-04-15 23:49:40 -07:00
Anthony Dresser
a5bc65fbfb Merge from vscode 8b5ebbb1b8f6b2127bbbd551ac10cc080482d5b4 (#5041) 2019-04-15 20:37:22 -07:00
Gene Lee
dcdbc95ae7 Fixed bug: CheckboxTreeNode label overflows, and node icon disappears (#5022) 2019-04-15 13:44:49 -07:00
Anthony Dresser
72e7e5e025 relayer connection code; formatting (#5020) 2019-04-15 01:05:23 -07:00
Anthony Dresser
57242a2e13 Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028) 2019-04-14 22:29:14 -07:00
Anthony Dresser
6dbf757385 Remove some vscode differences (#5010)
* remove some vscode differences

* add dates to todo comments
2019-04-12 21:55:07 -07:00
Karl Burtram
c5a32d8373 Show user email address in account picker (#5015)
* Show user email address in account picker

* Fix build break and remove Azure account from sqlops namespace
2019-04-12 17:23:48 -07:00
Charles Gagnon
34288435ec Fix Data Explorer context menu items visibility (#4996)
* Fix Data Explorer context menu items visibility

The when clause was making the menu items show up for all nodes in the Data Explorer - even ones that didn't make sense such as the Databases folders. This change makes it only appear for the Database and Server nodes (which is how the OE tree is set up)
2019-04-12 17:09:53 -07:00
Yurong He
177b48c3f2 Revert #4955 to unblock integration test (#5016) 2019-04-12 14:08:38 -07:00
Anthony Dresser
642f5d4405 replace nulls with undefined (#5014) 2019-04-12 13:08:32 -07:00
Anthony Dresser
92b1c59e48 Strict null check on full "base" code (#4973)
* removes more builder references

* remove builder from profiler

* formatting

* fix profiler dailog

* remove builder from oatuhdialog

* remove the rest of builder references

* formatting

* add more strict null checks to base
2019-04-12 12:59:58 -07:00
Anthony Dresser
cb1682542b remove sql/services (#4991) 2019-04-12 12:48:06 -07:00
Anthony Dresser
9e56187c16 Remove sql/common (#4990)
* remove sql/common/

* formatting

* fix cyclic dependency
2019-04-12 12:47:48 -07:00
Yurong He
51851efda5 Use notebookUtils.getErrorMessage to get the correct msg instead of showing {0} (#5012) 2019-04-12 11:50:44 -07:00
Charles Gagnon
11e4b743e0 Fix wrong release notes being loaded (#5008) 2019-04-11 16:56:55 -07:00
Kevin Cunnane
3349151d4c Touchbar icon support in notebooks (#4998)
* Touchbar icon support in notebooks
- updated shortcut keys to only work if notebook is active
- Added icons
- Now have 1 "add cell" icon that prompts for code/text.
This is useful as there wasn't an icon to differentiate
2019-04-11 16:43:27 -07:00
Kevin Cunnane
c8f6937166 Fix #4500 Untitled notebook reopen doesn't show dirty (#5005)
* Fix 2 notebook issues
- Do not create notebook model twice on start
- Do not cause disposed warnings due to markdown cell deserialization

* Fix notebook dirty on open issue
Before model is resolved we weren't getting dirty events.
Solution is to use backing text model until it's ready.
Must hook to the dirty event & notify to get the dot to appear
2019-04-11 16:39:54 -07:00
Maddy
ad36c1df3d add wrap to the <pre> tag (#5002)
* add wrap to the <pre> tag

* removed styles for browser support
2019-04-11 15:32:52 -07:00
Anthony Dresser
a5b8924e2d restore line height to account list renderer (#4999) 2019-04-11 15:10:38 -07:00
Anthony Dresser
bc898cc2c2 revert data explorer id to connections (#5003) 2019-04-11 15:10:26 -07:00
kisantia
1247b6e8eb bump SQL Tools to 1.5.0-alpha.85 to get invalid dacpac version fix (#5001) 2019-04-11 13:53:45 -07:00
udeeshagautam
2111c3de1a Fix for 4104 : Multiple consecutive spaces in query results cells are condensed into one (#4983)
* preserving spaces in query results - all beginning, trailing and middle spaces will be shown as is

* removing the change through formatting and replacing with css change formatting was leaving special char while removing nbsp
2019-04-11 13:45:10 -07:00
Aditya Bist
bcea1b66be Added some usage details (#4711)
* added some details

* remove unused import

* added new metrics, removed churn

* merged master and code review comments

* code review comments

* normalized days to calendar days/weeks/months

* cleaned up code

* changed comment to start required check for PR

* fix failing test

* fix test

* removed null assignment

* fix null test script
2019-04-11 12:07:20 -07:00
Yurong He
4f8d14ed3e Fix ##3479 ctrl+a select active cell output or preview markdown (#4981)
* Enable ctrl+a to select the output or markdown content when the cell is active

* Moved toggleUserSelect into ngOnChanges

* Resolve PR comments
2019-04-11 11:36:42 -07:00
Chris LaFreniere
442adfbbc3 Add New Notebook from Server Dashboard (#4971) 2019-04-11 10:15:45 -07:00
Aditya Bist
fe12233954 Azure extension changes (#4987)
* removed search box

* removed commented code
2019-04-11 09:44:43 -07:00
Anthony Dresser
c725f6f572 fix html structure of add account dialog (#4988) 2019-04-10 17:41:18 -07:00
Cory Rivera
1870d83081 Add additional error handling to Python installation for Notebooks (#4891)
* Also enabled integration tests for python installation.
2019-04-10 17:09:28 -07:00
Anthony Dresser
8315dacda4 Merge from vscode 31e03b8ffbb218a87e3941f2b63a249f061fe0e4 (#4986) 2019-04-10 16:29:23 -07:00
kisantia
18c54f41bd remove unnecessary message that connection is needed (#4982) 2019-04-10 16:22:18 -07:00
Kevin Cunnane
293f9c22c4 Touchbar support for Run Cell, Run Query, Add Cell (#4972)
* Basic touchbar support

* Touchbar support for Run Cell, Run Query, Add Cell
- Add top 3 notebook commands
- Add top query command

Actions only appear on having active editor of expected type.
In order to make Notebook work as expected, added tabindex to support focusing
and hide outline to ensure it doesn't get weird blue outline on click
Note: does not have icons yet, which would be nice.
However can add in subsequent PR once this comes from UX.
2019-04-10 14:04:36 -07:00
Anthony Dresser
a74510544f Remove rest of builder (#4963)
* removes more builder references

* remove builder from profiler

* formatting

* fix profiler dailog

* remove builder from oatuhdialog

* remove the rest of builder references

* formatting
2019-04-10 13:23:33 -07:00
Aditya Bist
9b053c50c2 Azure - icon change (#4967)
* changed icon and string

* changed add to servers icon
2019-04-10 13:20:43 -07:00
Chris LaFreniere
88712f46bf Fix for relative markdown image paths (#4889)
* Fix for relative markdown image paths

* PR comments
2019-04-10 11:35:06 -07:00
Chris LaFreniere
d6df20b0e8 Notebooks: Potential Fix for "Notebook Provider does not Exist" Error (#4848)
* Fallback to SQL

* Fix providers not found issue

* await whenInstalledExtensionsRegistered

* PR comments
2019-04-10 11:34:46 -07:00
Chris LaFreniere
5dc37f7557 improve assert message (#4968) 2019-04-10 10:14:44 -07:00
Gene Lee
445d306586 Fixed Broken Notebook Preview (#4895) 2019-04-09 18:47:24 -07:00
Chris LaFreniere
d332ae1132 Fix to ensure that we rewrite spark ui links correctly (#4962) 2019-04-09 18:23:21 -07:00
Kevin Cunnane
37f45b10a3 Mitigate (but not fully fix) Run Cell from disconnected notebook (#4960)
This is a partial fix that lays groundwork for full "Prompt to connect" if a kernel needs a connection.
I am waiting on Yurong's refactoring of connection handling before doing any of the prompt work.

- Adds kernel metadata about whether a connection is required.
- For Jupyter, only Spark kernels are listed as requiring a connection
- If this is true and there's no active connection, will show notification and not call execute

In the future, this path will still be used if user is prompted to connect and cancels out.
The future change will be to inject a "connect" handler from notebook.component to the cell callback and use to set connection context
2019-04-09 17:45:05 -07:00
kisantia
d9b6ec0654 Add title for DiffEditor and fix SplitViewContainer (#4961)
* add option to have diff editor title

* fix component being undefined and splitter not showing
2019-04-09 16:41:32 -07:00
kisantia
f98428aea5 Add reverse color option to text diff editor (#4826)
* Add reverse color option to text diff editor
2019-04-09 16:26:41 -07:00
Gene Lee
b3be1d79cd Add support for new endpoint key string 'gateway' (#4954) 2019-04-09 15:19:02 -07:00
Yurong He
ea8f885f05 Call getCurrentGlobalConnection like New Query to get the active connection context (#4955) 2019-04-09 15:15:36 -07:00
Kevin Cunnane
2de47c2a50 Fix #4930 Text cells are referred to as text and markdown in commands (#4956) 2019-04-09 14:20:29 -07:00
Kevin Cunnane
30b8e105f9 Fix #4893 New Notebook Can Open Existing Noteboon (#4959)
Add back check for textDocuments with same name, should've been there anyhow

On rehydration files show as text docs before clicking as only get
changed by customInputConverter code path.
We should look at this long term - ideally we'd update notebookDocuments
with correct values on initial start. #4958 opened to track this.
2019-04-09 14:11:10 -07:00
Kevin Cunnane
2a44fab8ba Fix issue where mac launch often failed to attach (#4957)
- Timeout now matches the windows timeout value
2019-04-09 14:10:56 -07:00
Chris LaFreniere
6a06a99e46 Change pfs.rimraf call in insightsutils test (#4921) 2019-04-09 13:05:36 -07:00
Anthony Dresser
3670dfbebd changes strings for data explorer (#4946) 2019-04-09 12:39:15 -07:00
kisantia
daf929ecc7 add splitViewContainer and diffEditor to ModelBuilder interface (#4950) 2019-04-09 11:45:21 -07:00
Anthony Dresser
f96a17c930 Remove unused code (#4873)
* removes unused features

* remove more unused code; formatting

* lock changes

* fix run issue
2019-04-09 02:00:51 -07:00
Anthony Dresser
2fb06e7f4f Move notebooks to workbench (#4888)
* move notebooks under workbench

* fix style imports
2019-04-09 01:59:55 -07:00
Anthony Dresser
4ece9b0085 remove dispose of button listeners (#4914) 2019-04-09 01:08:56 -07:00
Anthony Dresser
a4bd31e96a Removes Builder references from modal (#4869)
* remove builder from modal

* add more DOM methods
2019-04-09 00:28:52 -07:00
Anthony Dresser
8bdcc3267a Code Layering dashboard (#4883)
* move dashboard to workbench

* revert xlf file changes

* 💄

* 💄

* add back removed functions
2019-04-09 00:26:57 -07:00
Takahito Yamatoya
9e9164c4ee fix the format (#4899) 2019-04-08 19:56:44 -07:00
Alan Ren
5dc6a39652 Update readme.md (#4907) 2019-04-08 16:25:53 -07:00
kisantia
ada0966832 Add toolbar separator (#4890)
* Add option to add toolbar separator after toolbar component
2019-04-08 15:27:18 -07:00
Alan Ren
e6faef27ab Alanren/integration setup (#4871)
* automate the setup and use akv to store values

* update readme.md

* get rid of the save to file part

* update readme

* add more messages

* fix the error

* fix some errors

* fix the readme
2019-04-08 15:11:38 -07:00
Anthony Dresser
acc27d0829 Code Layering Accounts (#4882)
* code layering for accounts

* formatting

* formatting

* formatting
2019-04-08 14:45:30 -07:00
Anthony Dresser
ab54f7bb45 remove builder references from some componnets (#4868) 2019-04-08 14:24:03 -07:00
Yurong He
88161cc37d Fixed cancel connectionDialog from attach to shows dup "select connection" (#4865) 2019-04-08 14:06:46 -07:00
Anthony Dresser
0975e6834e remove builder from taskswidget (#4866) 2019-04-08 13:28:23 -07:00
Anthony Dresser
22ec1d5f0a Strict Null Checks, Builder Removal, Formatting (#4849)
* remove builder; more null checks

* null checks

* formatting

* wip

* fix dropdown themeing

* formatting

* formatting

* fix tests

* update what files are checked

* add code to help refresh bad nodes
2019-04-08 13:27:41 -07:00
udeeshagautam
01784dd186 Adding Diff view and Split view container as Model View Editor Components (#4831)
* intial code for diff view inside model view

* Adding basic Split View Container depending on Flex Layout

* Enabled resizing between top and bottom view

* cleaning up some of the sqlops references

* Adding height as per CR comment
2019-04-08 11:11:14 -07:00
Karl Burtram
02cf91c158 Remove broken VS Code test from merge (#4887) 2019-04-05 15:06:11 -07:00
Karl Burtram
0532346f4f Merge from vscode 591842cc4b71958c81947b254924a215fe3edcbd (#4886) 2019-04-05 14:14:26 -07:00
Chris LaFreniere
657adafb7d always serialize execution count (#4864) 2019-04-05 11:34:10 -07:00
Anthony Dresser
818c0789ea Reduce packaged size of extensions (#4300)
* reduce output of notebooks

* reduce size of azurecore

* update mssql extensions to be webpacked

* formatting

* remove commented code

* fix packaged config

* fix mssql packing
2019-04-05 10:48:00 -07:00
Karl Burtram
cb5bcf2248 Merge from vscode 2b0b9136329c181a9e381463a1f7dc3a2d105a34 (#4880) 2019-04-05 10:09:18 -07:00
2157 changed files with 123450 additions and 84508 deletions

6
.vscode/launch.json vendored
View File

@@ -70,10 +70,12 @@
"timeout": 20000
},
"osx": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh",
"timeout": 20000
},
"linux": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh"
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh",
"timeout": 20000
},
"env": {
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null

14
.vscode/tasks.json vendored
View File

@@ -28,6 +28,20 @@
}
}
},
{
"type": "npm",
"script": "strict-initialization-watch",
"label": "TS - Strict Initialization",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"problemMatcher": {
"base": "$tsc-watch",
"owner": "typescript-strict-initialization",
"applyTo": "allDocuments"
}
},
{
"type": "gulp",
"task": "tslint",

View File

@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron"
target "3.1.6"
target "3.1.8"
runtime "electron"

View File

@@ -1,5 +1,18 @@
# Change Log
## Version 1.6.0
* Release date: April 18, 2019
* Release status: General Availability
## What's new in this version
* Align with latest VS Code editor platform (currently 1.33.1)
* Resolved [bugs and issues](https://github.com/Microsoft/azuredatastudio/milestone/26?closed=1).
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* yamatoya for `fix the format (#4899)`
## Version 1.5.1
* Release date: March 18, 2019
* Release status: General Availability

View File

@@ -9,13 +9,13 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
Platform | Link
-- | --
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2083322
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2083323
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2083324
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2083325
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2083424
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2083326
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2083327
Windows User Installer | https://go.microsoft.com/fwlink/?linkid=2087316
Windows System Installer | https://go.microsoft.com/fwlink/?linkid=2087317
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2087318
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2087170
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2087414
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2087171
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2087415
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
@@ -68,6 +68,7 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
## Contributions and "Thank You"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* yamatoya for `fix the format (#4899)`
* GeoffYoung for `Fix sqlDropColumn description #4422`
* AlexFsmn for `Added context menu for DBs in explorer view to backup & restore db. #2277`
* sadedil for `Missing feature request: Save as XML #3729`

View File

@@ -24,21 +24,15 @@ steps:
- script: |
yarn
displayName: 'Install'
displayName: 'Install'
- script: |
node_modules/.bin/gulp electron
node_modules/.bin/gulp compile --max_old_space_size=4096
displayName: 'Scripts'
yarn gulp electron-x64
displayName: Download Electron
- script: |
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
displayName: 'Tests'
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/test-results.xml'
condition: succeededOrFailed()
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: |
yarn tslint
@@ -47,3 +41,29 @@ steps:
- script: |
yarn strict-null-check
displayName: 'Run Strict Null Check'
- script: |
yarn compile
displayName: 'Compile'
- script: |
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
displayName: 'Tests'
condition: eq(variables['Agent.OS'], 'Linux')
- script: |
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter --coverage
displayName: 'Tests'
condition: ne(variables['Agent.OS'], 'Linux')
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/test-results.xml'
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'cobertura'
summaryFileLocation: $(System.DefaultWorkingDirectory)/.build/coverage/cobertura-coverage.xml
reportDirectory: $(System.DefaultWorkingDirectory)/.build/coverage/lcov-reports
condition: ne(variables['Agent.OS'], 'Linux')

View File

@@ -9,21 +9,12 @@ steps:
displayName: 'Yarn Install'
- script: |
.\node_modules\.bin\gulp electron
yarn gulp electron-x64
displayName: 'Electron'
- script: |
npm run compile
displayName: 'Compile'
- script: |
.\scripts\test.bat --reporter mocha-junit-reporter
displayName: 'Test'
- task: PublishTestResults@2
inputs:
testResultsFiles: 'test-results.xml'
condition: succeededOrFailed()
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: |
yarn tslint
@@ -32,3 +23,22 @@ steps:
- script: |
yarn strict-null-check
displayName: 'Run Strict Null Check'
- script: |
yarn compile
displayName: 'Compile'
- script: |
.\scripts\test.bat --reporter mocha-junit-reporter --coverage
displayName: 'Test'
- task: PublishTestResults@2
inputs:
testResultsFiles: 'test-results.xml'
condition: succeededOrFailed()
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: 'cobertura'
summaryFileLocation: $(System.DefaultWorkingDirectory)\.build\coverage\cobertura-coverage.xml
reportDirectory: $(System.DefaultWorkingDirectory)\.build\coverage\lcov-report

View File

@@ -65,8 +65,7 @@ interface Asset {
platform: string;
type: string;
url: string;
// {{SQL CARBON EDIT}}
mooncakeUrl: string | undefined;
mooncakeUrl?: string;
hash: string;
sha256hash: string;
size: number;
@@ -189,56 +188,18 @@ async function publish(commit: string, quality: string, platform: string, type:
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
// {{SQL CARBON EDIT}}
await assertContainer(blobService, quality);
const blobExists = await doesAssetExist(blobService, quality, blobName);
const promises = [];
if (!blobExists) {
promises.push(uploadBlob(blobService, quality, blobName, file));
}
// {{SQL CARBON EDIT}}
if (process.env['MOONCAKE_STORAGE_ACCESS_KEY']) {
const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
// mooncake is fussy and far away, this is needed!
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
await Promise.all([
assertContainer(blobService, quality),
assertContainer(mooncakeBlobService, quality)
]);
const [blobExists, moooncakeBlobExists] = await Promise.all([
doesAssetExist(blobService, quality, blobName),
doesAssetExist(mooncakeBlobService, quality, blobName)
]);
const promises: Array<Promise<void>> = [];
if (!blobExists) {
promises.push(uploadBlob(blobService, quality, blobName, file));
}
if (!moooncakeBlobExists) {
promises.push(uploadBlob(mooncakeBlobService, quality, blobName, file));
}
} else {
console.log('Skipping Mooncake publishing.');
}
if (promises.length === 0) {
if (blobExists) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return;
}
console.log('Uploading blobs to Azure storage...');
await Promise.all(promises);
await uploadBlob(blobService, quality, blobName, file);
console.log('Blobs successfully uploaded.');
@@ -250,8 +211,6 @@ async function publish(commit: string, quality: string, platform: string, type:
platform: platform,
type: type,
url: `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`,
// {{SQL CARBON EDIT}}
mooncakeUrl: process.env['MOONCAKE_CDN_URL'] ? `${process.env['MOONCAKE_CDN_URL']}/${quality}/${blobName}` : undefined,
hash: sha1hash,
sha256hash,
size

View File

@@ -0,0 +1,176 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as url from 'url';
import * as azure from 'azure-storage';
import * as mime from 'mime';
import { DocumentClient, RetrievedDocument } from 'documentdb';
function log(...args: any[]) {
console.log(...[`[${new Date().toISOString()}]`, ...args]);
}
function error(...args: any[]) {
console.error(...[`[${new Date().toISOString()}]`, ...args]);
}
if (process.argv.length < 3) {
error('Usage: node sync-mooncake.js <quality>');
process.exit(-1);
}
interface Build extends RetrievedDocument {
assets: Asset[];
}
interface Asset {
platform: string;
type: string;
url: string;
mooncakeUrl: string;
hash: string;
sha256hash: string;
size: number;
supportsFastUpdate?: boolean;
}
function updateBuild(commit: string, quality: string, platform: string, type: string, asset: Asset): Promise<void> {
const client = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = 'dbs/builds/colls/' + quality;
const updateQuery = {
query: 'SELECT TOP 1 * FROM c WHERE c.id = @id',
parameters: [{ name: '@id', value: commit }]
};
let updateTries = 0;
function _update(): Promise<void> {
updateTries++;
return new Promise<void>((c, e) => {
client.queryDocuments(collection, updateQuery).toArray((err, results) => {
if (err) { return e(err); }
if (results.length !== 1) { return e(new Error('No documents')); }
const release = results[0];
release.assets = [
...release.assets.filter((a: any) => !(a.platform === platform && a.type === type)),
asset
];
client.replaceDocument(release._self, release, err => {
if (err && err.code === 409 && updateTries < 5) { return c(_update()); }
if (err) { return e(err); }
log('Build successfully updated.');
c();
});
});
});
}
return _update();
}
async function sync(commit: string, quality: string): Promise<void> {
log(`Synchronizing Mooncake assets for ${quality}, ${commit}...`);
const cosmosdb = new DocumentClient(process.env['AZURE_DOCUMENTDB_ENDPOINT']!, { masterKey: process.env['AZURE_DOCUMENTDB_MASTERKEY'] });
const collection = `dbs/builds/colls/${quality}`;
const query = {
query: 'SELECT TOP 1 * FROM c WHERE c.id = @id',
parameters: [{ name: '@id', value: commit }]
};
const build = await new Promise<Build>((c, e) => {
cosmosdb.queryDocuments(collection, query).toArray((err, results) => {
if (err) { return e(err); }
if (results.length !== 1) { return e(new Error('No documents')); }
c(results[0] as Build);
});
});
log(`Found build for ${commit}, with ${build.assets.length} assets`);
const storageAccount = process.env['AZURE_STORAGE_ACCOUNT_2']!;
const blobService = azure.createBlobService(storageAccount, process.env['AZURE_STORAGE_ACCESS_KEY_2']!)
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
const mooncakeBlobService = azure.createBlobService(storageAccount, process.env['MOONCAKE_STORAGE_ACCESS_KEY']!, `${storageAccount}.blob.core.chinacloudapi.cn`)
.withFilter(new azure.ExponentialRetryPolicyFilter(20));
// mooncake is fussy and far away, this is needed!
blobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
for (const asset of build.assets) {
try {
const blobPath = url.parse(asset.url).path;
if (!blobPath) {
throw new Error(`Failed to parse URL: ${asset.url}`);
}
const blobName = blobPath.replace(/^\/\w+\//, '');
log(`Found ${blobName}`);
if (asset.mooncakeUrl) {
log(` Already in Mooncake ✔️`);
continue;
}
const readStream = blobService.createReadStream(quality, blobName, undefined!);
const blobOptions: azure.BlobService.CreateBlockBlobRequestOptions = {
contentSettings: {
contentType: mime.lookup(blobPath),
cacheControl: 'max-age=31536000, public'
}
};
const writeStream = mooncakeBlobService.createWriteStreamToBlockBlob(quality, blobName, blobOptions, undefined);
log(` Uploading to Mooncake...`);
await new Promise((c, e) => readStream.pipe(writeStream).on('finish', c).on('error', e));
log(` Updating build in DB...`);
asset.mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`;
await updateBuild(commit, quality, asset.platform, asset.type, asset);
log(` Done ✔️`);
} catch (err) {
error(err);
}
}
log(`All done ✔️`);
}
function main(): void {
if (process.env['VSCODE_BUILD_SKIP_PUBLISH']) {
error('Skipping publish due to VSCODE_BUILD_SKIP_PUBLISH');
return;
}
const commit = process.env['BUILD_SOURCEVERSION'];
if (!commit) {
error('Skipping publish due to missing BUILD_SOURCEVERSION');
return;
}
const quality = process.argv[2];
sync(commit, quality).catch(err => {
error(err);
process.exit(1);
});
}
main();

View File

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

View File

@@ -18,9 +18,15 @@ steps:
password $(VSCODE_MIXIN_PASSWORD)
EOF
git config user.email "vscode@microsoft.com"
git config user.name "VSCode"
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
git fetch distro
git merge $(node -p "require('./package.json').distro")
yarn
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" yarn gulp -- mixin
yarn gulp -- hygiene
yarn gulp mixin
yarn gulp hygiene
yarn monaco-compile-check
node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js
@@ -30,10 +36,7 @@ steps:
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- vscode-darwin-min
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- upload-vscode-sourcemaps
./build/azure-pipelines/darwin/build.sh
displayName: Build
- script: |
@@ -43,6 +46,11 @@ steps:
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-darwin/$APP_NAME"
displayName: Run unit tests
- script: |
set -e
./scripts/test-integration.sh --build --tfs "Integration Tests"
displayName: Run integration tests
- script: |
set -e
pushd ../VSCode-darwin && zip -r -X -y ../VSCode-darwin.zip * && popd
@@ -69,31 +77,12 @@ steps:
- script: |
set -e
# remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg"
# publish the build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js \
"$(VSCODE_QUALITY)" \
darwin \
archive \
"VSCode-darwin-$(VSCODE_QUALITY).zip" \
$VERSION \
true \
../VSCode-darwin.zip
# publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_MACOS)"
# upload configuration
AZURE_STORAGE_ACCESS_KEY="$(AZURE_STORAGE_ACCESS_KEY)" \
yarn gulp -- upload-vscode-configuration
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
./build/azure-pipelines/darwin/publish.sh
displayName: Publish
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# remove pkg from archive
zip -d ../VSCode-darwin.zip "*.pkg"
# publish the build
PACKAGEJSON=`ls ../VSCode-darwin/*.app/Contents/Resources/app/package.json`
VERSION=`node -p "require(\"$PACKAGEJSON\").version"`
node build/azure-pipelines/common/publish.js \
"$VSCODE_QUALITY" \
darwin \
archive \
"VSCode-darwin-$VSCODE_QUALITY.zip" \
$VERSION \
true \
../VSCode-darwin.zip
# publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_MACOS"
# upload configuration
yarn gulp upload-vscode-configuration

View File

@@ -0,0 +1,30 @@
trigger:
branches:
include: ['master', 'release/*']
pr:
branches:
include: ['master', 'release/*']
steps:
- task: NodeTool@0
inputs:
versionSpec: "10.15.1"
- script: |
set -e
cat << EOF > ~/.netrc
machine github.com
login vscode
password $(VSCODE_MIXIN_PASSWORD)
EOF
git config user.email "vscode@microsoft.com"
git config user.name "VSCode"
git remote add distro "https://github.com/$VSCODE_MIXIN_REPO.git"
git fetch distro
git push distro origin/master:refs/heads/master
git merge $(node -p "require('./package.json').distro")
displayName: Sync & Merge Distro

View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e
yarn gulp "vscode-linux-$VSCODE_ARCH-min"

View File

@@ -22,90 +22,45 @@ steps:
password $(VSCODE_MIXIN_PASSWORD)
EOF
git config user.email "vscode@microsoft.com"
git config user.name "VSCode"
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
git fetch distro
git merge $(node -p "require('./package.json').distro")
CHILD_CONCURRENCY=1 yarn
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- mixin
npm run gulp -- hygiene
npm run monaco-compile-check
yarn gulp mixin
yarn gulp hygiene
yarn monaco-compile-check
node build/azure-pipelines/common/installDistro.js
node build/lib/builtInExtensions.js
displayName: Prepare build
- script: |
set -e
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" npm run gulp -- vscode-linux-$(VSCODE_ARCH)-min
name: build
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
./build/azure-pipelines/linux/build.sh
displayName: Build
- script: |
set -e
npm run gulp -- "electron-$(VSCODE_ARCH)"
yarn gulp "electron-$(VSCODE_ARCH)"
# xvfb seems to be crashing often, let's make sure it's always up
service xvfb start
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests"
# yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-$(VSCODE_ARCH)"
name: test
displayName: Run unit tests
- script: |
set -e
REPO="$(pwd)"
ROOT="$REPO/.."
ARCH="$(VSCODE_ARCH)"
# Publish tarball
PLATFORM_LINUX="linux-$(VSCODE_ARCH)"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(date +%s)"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
# Publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" "$(VSCODE_HOCKEYAPP_ID_LINUX64)"
# Publish DEB
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-deb"
PLATFORM_DEB="linux-deb-$ARCH"
[[ "$ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
# Publish RPM
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-build-rpm"
PLATFORM_RPM="linux-rpm-$ARCH"
[[ "$ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
# Publish Snap
npm run gulp -- "vscode-linux-$(VSCODE_ARCH)-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$(VSCODE_ARCH).tar.gz"
rm -rf $SNAP_TARBALL_PATH
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)
VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)" \
VSCODE_HOCKEYAPP_TOKEN="$(VSCODE_HOCKEYAPP_TOKEN)" \
./build/azure-pipelines/linux/publish.sh
displayName: Publish
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -e
REPO="$(pwd)"
ROOT="$REPO/.."
# Publish tarball
PLATFORM_LINUX="linux-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
BUILDNAME="VSCode-$PLATFORM_LINUX"
BUILD="$ROOT/$BUILDNAME"
BUILD_VERSION="$(date +%s)"
[ -z "$VSCODE_QUALITY" ] && TARBALL_FILENAME="code-$BUILD_VERSION.tar.gz" || TARBALL_FILENAME="code-$VSCODE_QUALITY-$BUILD_VERSION.tar.gz"
TARBALL_PATH="$ROOT/$TARBALL_FILENAME"
PACKAGEJSON="$BUILD/resources/app/package.json"
VERSION=$(node -p "require(\"$PACKAGEJSON\").version")
rm -rf $ROOT/code-*.tar.*
(cd $ROOT && tar -czf $TARBALL_PATH $BUILDNAME)
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_LINUX" archive-unsigned "$TARBALL_FILENAME" "$VERSION" true "$TARBALL_PATH"
# Publish hockeyapp symbols
node build/azure-pipelines/common/symbols.js "$VSCODE_MIXIN_PASSWORD" "$VSCODE_HOCKEYAPP_TOKEN" "$VSCODE_ARCH" "$VSCODE_HOCKEYAPP_ID_LINUX64"
# Publish DEB
yarn gulp "vscode-linux-$VSCODE_ARCH-build-deb"
PLATFORM_DEB="linux-deb-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && DEB_ARCH="i386" || DEB_ARCH="amd64"
DEB_FILENAME="$(ls $REPO/.build/linux/deb/$DEB_ARCH/deb/)"
DEB_PATH="$REPO/.build/linux/deb/$DEB_ARCH/deb/$DEB_FILENAME"
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_DEB" package "$DEB_FILENAME" "$VERSION" true "$DEB_PATH"
# Publish RPM
yarn gulp "vscode-linux-$VSCODE_ARCH-build-rpm"
PLATFORM_RPM="linux-rpm-$VSCODE_ARCH"
[[ "$VSCODE_ARCH" == "ia32" ]] && RPM_ARCH="i386" || RPM_ARCH="x86_64"
RPM_FILENAME="$(ls $REPO/.build/linux/rpm/$RPM_ARCH/ | grep .rpm)"
RPM_PATH="$REPO/.build/linux/rpm/$RPM_ARCH/$RPM_FILENAME"
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "$PLATFORM_RPM" package "$RPM_FILENAME" "$VERSION" true "$RPM_PATH"
# Publish Snap
yarn gulp "vscode-linux-$VSCODE_ARCH-prepare-snap"
# Pack snap tarball artifact, in order to preserve file perms
mkdir -p $REPO/.build/linux/snap-tarball
SNAP_TARBALL_PATH="$REPO/.build/linux/snap-tarball/snap-$VSCODE_ARCH.tar.gz"
rm -rf $SNAP_TARBALL_PATH
(cd .build/linux && tar -czf $SNAP_TARBALL_PATH snap)

View File

@@ -46,5 +46,4 @@ steps:
# Publish snap package
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/publish.js "$VSCODE_QUALITY" "linux-snap-$ARCH" package "$SNAP_FILENAME" "$VERSION" true "$SNAP_PATH"

View File

@@ -62,4 +62,18 @@ jobs:
pool:
vmImage: macOS 10.13
steps:
- template: darwin/product-build-darwin.yml
- template: darwin/product-build-darwin.yml
- job: Mooncake
pool:
vmImage: 'Ubuntu-16.04'
condition: true
dependsOn:
- Windows
- Windows32
- Linux
- LinuxSnap
- Linux32
- macOS
steps:
- template: sync-mooncake.yml

View File

@@ -0,0 +1,18 @@
steps:
- task: NodeTool@0
inputs:
versionSpec: "10.15.1"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.10.1"
- script: |
set -e
(cd build ; yarn)
AZURE_DOCUMENTDB_MASTERKEY="$(AZURE_DOCUMENTDB_MASTERKEY)" \
AZURE_STORAGE_ACCESS_KEY_2="$(AZURE_STORAGE_ACCESS_KEY_2)" \
MOONCAKE_STORAGE_ACCESS_KEY="$(MOONCAKE_STORAGE_ACCESS_KEY)" \
node build/azure-pipelines/common/sync-mooncake.js "$VSCODE_QUALITY"

View File

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

View File

@@ -18,34 +18,47 @@ steps:
"machine monacotools.visualstudio.com`npassword $(VSO_PAT)`nmachine github.com`nlogin vscode`npassword $(VSCODE_MIXIN_PASSWORD)" | Out-File "$env:USERPROFILE\_netrc" -Encoding ASCII
$env:npm_config_arch="$(VSCODE_ARCH)"
$env:CHILD_CONCURRENCY="1"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { git config user.email "vscode@microsoft.com" }
exec { git config user.name "VSCode" }
exec { git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git" }
exec { git fetch distro }
exec { git merge $(node -p "require('./package.json').distro") }
exec { yarn }
exec { npm run gulp -- mixin }
exec { npm run gulp -- hygiene }
exec { npm run monaco-compile-check }
exec { yarn gulp mixin }
exec { yarn gulp hygiene }
exec { yarn monaco-compile-check }
exec { node build/azure-pipelines/common/installDistro.js }
exec { node build/lib/builtInExtensions.js }
displayName: Prepare build
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$env:VSCODE_MIXIN_PASSWORD="$(VSCODE_MIXIN_PASSWORD)"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-min" }
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-inno-updater" }
name: build
.\build\azure-pipelines\win32\build.ps1
displayName: Build
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp -- "electron-$(VSCODE_ARCH)" }
exec { yarn gulp "electron-$(VSCODE_ARCH)" }
exec { .\scripts\test.bat --build --tfs "Unit Tests" }
# yarn smoketest -- --build "$(agent.builddirectory)\VSCode-win32-$(VSCODE_ARCH)"
name: test
displayName: Run unit tests
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { yarn gulp "electron-$(VSCODE_ARCH)" }
exec { .\scripts\test-integration.bat --build --tfs "Integration Tests" }
displayName: Run integration tests
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH)'
FolderPath: '$(agent.builddirectory)/VSCode-win32-$(VSCODE_ARCH),$(agent.builddirectory)/vscode-reh-win32-$(VSCODE_ARCH)'
Pattern: '*.dll,*.exe,*.node'
signConfigType: inlineSignParams
inlineOperation: |
@@ -119,32 +132,11 @@ steps:
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { npm run gulp -- "vscode-win32-$(VSCODE_ARCH)-archive" "vscode-win32-$(VSCODE_ARCH)-system-setup" "vscode-win32-$(VSCODE_ARCH)-user-setup" --sign }
$Repo = "$(pwd)"
$Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$(VSCODE_ARCH)\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$(VSCODE_ARCH)\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$(VSCODE_ARCH)\archive\VSCode-win32-$(VSCODE_ARCH).zip"
$Build = "$Root\VSCode-win32-$(VSCODE_ARCH)"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$env:AZURE_STORAGE_ACCESS_KEY_2 = "$(AZURE_STORAGE_ACCESS_KEY_2)"
$env:MOONCAKE_STORAGE_ACCESS_KEY = "$(MOONCAKE_STORAGE_ACCESS_KEY)"
$env:AZURE_DOCUMENTDB_MASTERKEY = "$(AZURE_DOCUMENTDB_MASTERKEY)"
$assetPlatform = if ("$(VSCODE_ARCH)" -eq "ia32") { "win32" } else { "win32-x64" }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-archive" archive "VSCode-win32-$(VSCODE_ARCH)-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform" setup "VSCodeSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$global:assetPlatform-user" setup "VSCodeUserSetup-$(VSCODE_ARCH)-$Version.exe" $Version true $UserExe }
# publish hockeyapp symbols
$hockeyAppId = if ("$(VSCODE_ARCH)" -eq "ia32") { "$(VSCODE_HOCKEYAPP_ID_WIN32)" } else { "$(VSCODE_HOCKEYAPP_ID_WIN64)" }
exec { node build/azure-pipelines/common/symbols.js "$(VSCODE_MIXIN_PASSWORD)" "$(VSCODE_HOCKEYAPP_TOKEN)" "$(VSCODE_ARCH)" $hockeyAppId }
$env:VSCODE_HOCKEYAPP_TOKEN = "$(VSCODE_HOCKEYAPP_TOKEN)"
.\build\azure-pipelines\win32\publish.ps1
displayName: Publish
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'

View File

@@ -0,0 +1,28 @@
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
$Arch = "$env:VSCODE_ARCH"
exec { yarn gulp "vscode-win32-$Arch-archive" "vscode-win32-$Arch-system-setup" "vscode-win32-$Arch-user-setup" --sign }
$Repo = "$(pwd)"
$Root = "$Repo\.."
$SystemExe = "$Repo\.build\win32-$Arch\system-setup\VSCodeSetup.exe"
$UserExe = "$Repo\.build\win32-$Arch\user-setup\VSCodeSetup.exe"
$Zip = "$Repo\.build\win32-$Arch\archive\VSCode-win32-$Arch.zip"
$Build = "$Root\VSCode-win32-$Arch"
# get version
$PackageJson = Get-Content -Raw -Path "$Build\resources\app\package.json" | ConvertFrom-Json
$Version = $PackageJson.version
$Quality = "$env:VSCODE_QUALITY"
$AssetPlatform = if ("$Arch" -eq "ia32") { "win32" } else { "win32-x64" }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-archive" archive "VSCode-win32-$Arch-$Version.zip" $Version true $Zip }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform" setup "VSCodeSetup-$Arch-$Version.exe" $Version true $SystemExe }
exec { node build/azure-pipelines/common/publish.js $Quality "$AssetPlatform-user" setup "VSCodeUserSetup-$Arch-$Version.exe" $Version true $UserExe }
# publish hockeyapp symbols
$hockeyAppId = if ("$Arch" -eq "ia32") { "$env:VSCODE_HOCKEYAPP_ID_WIN32" } else { "$env:VSCODE_HOCKEYAPP_ID_WIN64" }
exec { node build/azure-pipelines/common/symbols.js "$env:VSCODE_MIXIN_PASSWORD" "$env:VSCODE_HOCKEYAPP_TOKEN" "$Arch" $hockeyAppId }

View File

@@ -87,9 +87,16 @@ const indentationFilter = [
'!build/azure-pipelines/**/*.js',
'!build/azure-pipelines/**/*.config',
'!**/Dockerfile',
'!**/Dockerfile.*',
'!**/*.Dockerfile',
'!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js'
'!extensions/markdown-language-features/media/*.js',
// {{SQL CARBON EDIT}}
'!**/*.xlf',
'!**/*.docx',
'!**/*.sql',
'!extensions/mssql/sqltoolsservice/**',
'!extensions/import/flatfileimportservice/**',
];
const copyrightFilter = [
@@ -118,7 +125,37 @@ const copyrightFilter = [
'!resources/completions/**',
'!extensions/markdown-language-features/media/highlight.css',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*'
'!extensions/*/server/bin/*',
// {{SQL CARBON EDIT}}
'!extensions/notebook/src/intellisense/text.ts',
'!extensions/mssql/src/objectExplorerNodeProvider/webhdfs.ts',
'!src/sql/workbench/parts/notebook/outputs/tableRenderers.ts',
'!src/sql/workbench/parts/notebook/outputs/common/url.ts',
'!src/sql/workbench/parts/notebook/outputs/common/renderMimeInterfaces.ts',
'!src/sql/workbench/parts/notebook/outputs/common/outputProcessor.ts',
'!src/sql/workbench/parts/notebook/outputs/common/mimemodel.ts',
'!src/sql/workbench/parts/notebook/cellViews/media/*.css',
'!src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/rowDetailView.ts',
'!src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts',
'!src/sql/workbench/parts/notebook/outputs/sanitizer.ts',
'!src/sql/workbench/parts/notebook/outputs/renderers.ts',
'!src/sql/workbench/parts/notebook/outputs/registry.ts',
'!src/sql/workbench/parts/notebook/outputs/factories.ts',
'!src/sql/workbench/parts/notebook/models/nbformat.ts',
'!extensions/markdown-language-features/media/tomorrow.css',
'!src/sql/workbench/electron-browser/modelComponents/media/highlight.css',
'!src/sql/parts/modelComponents/highlight.css',
'!extensions/mssql/sqltoolsservice/**',
'!extensions/import/flatfileimportservice/**',
'!extensions/notebook/src/prompts/**',
'!extensions/mssql/src/prompts/**',
'!extensions/notebook/resources/jupyter_config/**',
'!**/*.gif',
'!**/*.xlf'
];
const eslintFilter = [
@@ -164,8 +201,7 @@ gulp.task('eslint', () => {
});
gulp.task('tslint', () => {
// {{SQL CARBON EDIT}}
const options = { emitError: false };
const options = { emitError: true };
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(tslintFilter))
@@ -263,9 +299,8 @@ function hygiene(some) {
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(filter(indentationFilter))
.pipe(indentation)
.pipe(filter(copyrightFilter));
// {{SQL CARBON EDIT}}
// .pipe(copyrights);
.pipe(filter(copyrightFilter))
.pipe(copyrights);
const typescript = result
.pipe(filter(tslintFilter))
@@ -275,15 +310,38 @@ function hygiene(some) {
const javascript = result
.pipe(filter(eslintFilter))
.pipe(gulpeslint('src/.eslintrc'))
.pipe(gulpeslint.formatEach('compact'));
// {{SQL CARBON EDIT}}
// .pipe(gulpeslint.failAfterError());
.pipe(gulpeslint.formatEach('compact'))
.pipe(gulpeslint.failAfterError());
let count = 0;
return es.merge(typescript, javascript)
.pipe(es.through(function (data) {
// {{SQL CARBON EDIT}}
this.emit('end');
count++;
if (process.env['TRAVIS'] && count % 10 === 0) {
process.stdout.write('.');
}
this.emit('data', data);
}, function () {
process.stdout.write('\n');
const tslintResult = tsLinter.getResult();
if (tslintResult.failures.length > 0) {
for (const failure of tslintResult.failures) {
const name = failure.getFileName();
const position = failure.getStartPosition();
const line = position.getLineAndCharacter().line;
const character = position.getLineAndCharacter().character;
console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`);
}
errorCount += tslintResult.failures.length;
}
if (errorCount > 0) {
this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
} else {
this.emit('end');
}
}));
}

View File

@@ -6,21 +6,12 @@
'use strict';
const gulp = require('gulp');
const json = require('gulp-json-editor');
const buffer = require('gulp-buffer');
const filter = require('gulp-filter');
const es = require('event-stream');
const vfs = require('vinyl-fs');
const pkg = require('../package.json');
const cp = require('child_process');
const fancyLog = require('fancy-log');
const ansiColors = require('ansi-colors');
// {{SQL CARBON EDIT}}
const jeditor = require('gulp-json-editor');
gulp.task('mixin', function () {
// {{SQL CARBON EDIT}}
// {{SQL CARBON EDIT}}
const updateUrl = process.env['SQLOPS_UPDATEURL'];
if (!updateUrl) {
console.log('Missing SQLOPS_UPDATEURL, skipping mixin');

View File

@@ -28,7 +28,6 @@ const formatFiles = (some) => {
console.info('ran formatting on file ' + file.path + ' result: ' + result.message);
if (result.error) {
console.error(result.message);
errorCount++;
}
cb(null, file);
@@ -40,7 +39,7 @@ const formatFiles = (some) => {
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(formatting);
}
};
const formatStagedFiles = () => {
const cp = require('child_process');
@@ -81,4 +80,4 @@ const formatStagedFiles = () => {
process.exit(1);
});
});
}
};

View File

@@ -33,12 +33,10 @@ const i18n = require('./lib/i18n');
// {{SQL CARBON EDIT}}
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
const platformInfo = require('service-downloader/out/platform').PlatformInformation;
const glob = require('glob');
// {{SQL CARBON EDIT}} - End
const deps = require('./dependencies');
const getElectronVersion = require('./lib/electron').getElectronVersion;
const createAsar = require('./lib/asar').createAsar;
const minimist = require('minimist');
const { compileBuildTask } = require('./gulpfile.compile');
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
@@ -54,7 +52,7 @@ const nodeModules = [
'rxjs/Observable',
'rxjs/Subject',
'rxjs/Observer',
'ng2-charts/ng2-charts']
'ng2-charts']
.concat(Object.keys(product.dependencies || {}))
.concat(_.uniq(productionDependencies.map(d => d.name)))
.concat(baseModules);
@@ -77,14 +75,16 @@ const vscodeResources = [
'out-build/bootstrap-window.js',
'out-build/paths.js',
'out-build/vs/**/*.{svg,png,cur,html}',
'!out-build/vs/code/browser/**/*.html',
'out-build/vs/base/common/performance.js',
'out-build/vs/base/node/languagePacks.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh}',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/contrib/debug/**/*.json',
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
'out-build/vs/workbench/contrib/webview/electron-browser/webview-pre.js',
'out-build/vs/workbench/contrib/webview/browser/pre/*.js',
'out-build/vs/workbench/contrib/webview/electron-browser/pre/*.js',
'out-build/vs/**/markdown.css',
'out-build/vs/workbench/contrib/tasks/**/*.json',
'out-build/vs/workbench/contrib/welcome/walkThrough/**/*.md',
@@ -102,19 +102,17 @@ const vscodeResources = [
'out-build/sql/parts/admin/**/*.html',
'out-build/sql/parts/connection/connectionDialog/media/*.{gif,png,svg}',
'out-build/sql/parts/common/dblist/**/*.html',
'out-build/sql/parts/dashboard/**/*.html',
'out-build/sql/workbench/parts/dashboard/**/*.html',
'out-build/sql/parts/disasterRecovery/**/*.html',
'out-build/sql/parts/common/modal/media/**',
'out-build/sql/parts/grid/load/lib/**',
'out-build/sql/parts/grid/load/loadJquery.js',
'out-build/sql/parts/grid/media/**',
'out-build/sql/parts/grid/views/**/*.html',
'out-build/sql/workbench/parts/grid/media/**',
'out-build/sql/workbench/parts/grid/views/**/*.html',
'out-build/sql/parts/tasks/**/*.html',
'out-build/sql/parts/taskHistory/viewlet/media/**',
'out-build/sql/parts/jobManagement/common/media/*.svg',
'out-build/sql/media/objectTypes/*.svg',
'out-build/sql/media/icons/*.svg',
'out-build/sql/parts/notebook/media/**/*.svg',
'out-build/sql/workbench/parts/notebook/media/**/*.svg',
'!**/test/**'
];
@@ -359,7 +357,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vscode-nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['build/Release/*.node', '**/*.a']))
// {{SQL CARBON EDIT}} - End
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
.pipe(util.cleanNodeModule('vscode-windows-ca-certs', ['**/*'], ['package.json', '**/*.node']))
@@ -426,14 +424,18 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
result = es.merge(result, gulp.src('resources/win32/bin/code.sh', { base: 'resources/win32' })
.pipe(replace('@@NAME@@', product.nameShort))
.pipe(replace('@@PRODNAME@@', product.nameLong))
.pipe(replace('@@VERSION@@', version))
.pipe(replace('@@COMMIT@@', commit))
.pipe(replace('@@APPNAME@@', product.applicationName))
.pipe(replace('@@QUALITY@@', quality))
.pipe(rename(function (f) { f.basename = product.applicationName; f.extname = ''; })));
result = es.merge(result, gulp.src('resources/win32/VisualElementsManifest.xml', { base: 'resources/win32' })
.pipe(rename(product.nameShort + '.VisualElementsManifest.xml')));
} else if (platform === 'linux') {
result = es.merge(result, gulp.src('resources/linux/bin/code.sh', { base: '.' })
.pipe(replace('@@PRODNAME@@', product.nameLong))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(rename('bin/' + product.applicationName)));
}
@@ -477,8 +479,6 @@ BUILD_TARGETS.forEach(buildTarget => {
minified ? minifyVSCodeTask : optimizeVSCodeTask,
util.rimraf(path.join(buildRoot, destinationFolderName))
),
ext.packageExtensionTask('mssql', platform, arch),
ext.packageExtensionTask('azurecore', platform, arch),
packageTask(platform, arch, sourceFolderName, destinationFolderName, opts)
));
gulp.task(vscodeTask);

View File

@@ -27,7 +27,7 @@ function getDebPackageArch(arch) {
}
function prepareDebPackage(arch) {
// {{SQL CARBON EDIT}}
// {{SQL CARBON EDIT}}
const binaryDir = '../azuredatastudio-linux-' + arch;
const debArch = getDebPackageArch(arch);
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;

View File

@@ -27,7 +27,7 @@ const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`);
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
const issPath = path.join(__dirname, 'win32', 'code.iss');
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
// const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
function packageInnoSetup(iss, options, cb) {
options = options || {};

View File

@@ -237,6 +237,7 @@ exports.fromMarketplace = fromMarketplace;
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
@@ -252,9 +253,10 @@ const sqlBuiltInExtensions = [
'profiler',
'admin-pack',
'big-data-cluster',
'dacpac'
'dacpac',
'schema-compare',
'cms'
];
var azureExtensions = ['azurecore', 'mssql'];
const builtInExtensions = require('../builtInExtensions.json');
/**
* We're doing way too much stuff at once, with webpack et al. So much stuff
@@ -290,8 +292,7 @@ function packageExtensionsStream(optsIn) {
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1);
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));

View File

@@ -283,6 +283,7 @@ interface IPackageExtensionsOptions {
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
// {{SQL CARBON EDIT}}
@@ -299,9 +300,10 @@ const sqlBuiltInExtensions = [
'profiler',
'admin-pack',
'big-data-cluster',
'dacpac'
'dacpac',
'schema-compare',
'cms'
];
var azureExtensions = ['azurecore', 'mssql'];
// {{SQL CARBON EDIT}} - End
interface IBuiltInExtension {
@@ -350,8 +352,7 @@ export function packageExtensionsStream(optsIn?: IPackageExtensionsOptions): Nod
.filter(({ name }) => opts.desiredExtensions ? opts.desiredExtensions.indexOf(name) >= 0 : true)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1)
.filter(({ name }) => azureExtensions.indexOf(name) === -1);
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1);
const localExtensions = () => sequence([...localExtensionDescriptions.map(extension => () => {
return fromLocal(extension.path, opts.sourceMappingURLBase)

View File

@@ -222,10 +222,6 @@
"name": "vs/workbench/services/files",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/files2",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/integrity",
"project": "vscode-workbench"

View File

@@ -24,7 +24,7 @@ function log(message: any, ...rest: any[]): void {
}
export interface Language {
id: string; // laguage id, e.g. zh-tw, de
id: string; // language id, e.g. zh-tw, de
translationId?: string; // language id used in translation tools, e.g zh-hant, de (optional, if not set, the id is used)
folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used)
}
@@ -1378,4 +1378,4 @@ function decodeEntities(value: string): string {
function pseudify(message: string) {
return '\uFF3B' + message.replace(/[aouei]/g, '$&$&') + '\uFF3D';
}
}

View File

@@ -32,7 +32,7 @@ async function _doExecute(task) {
// Always invoke as if it were a callback task
return new Promise((resolve, reject) => {
if (task.length === 1) {
// this is a calback task
// this is a callback task
task((err) => {
if (err) {
return reject(err);

View File

@@ -54,7 +54,7 @@ async function _doExecute(task: Task): Promise<void> {
// Always invoke as if it were a callback task
return new Promise((resolve, reject) => {
if (task.length === 1) {
// this is a calback task
// this is a callback task
task((err) => {
if (err) {
return reject(err);

View File

@@ -1,7 +1,7 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const ts = require("typescript");

View File

@@ -1,6 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as ts from 'typescript';

View File

@@ -74,7 +74,7 @@ function update(options) {
let translationPaths = [];
i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths)
.on('error', (error) => {
console.log(`Error occured while importing translations:`);
console.log(`Error occurred while importing translations:`);
translationPaths = undefined;
if (Array.isArray(error)) {
error.forEach(console.log);
@@ -100,7 +100,7 @@ function update(options) {
gulp.src(path.join(location, languageId, '**', '*.xlf'))
.pipe(i18n.prepareI18nPackFiles(i18n.externalExtensionsWithTranslations, translationPaths, languageId === 'ps'))
.on('error', (error) => {
console.log(`Error occured while importing translations:`);
console.log(`Error occurred while importing translations:`);
translationPaths = undefined;
if (Array.isArray(error)) {
error.forEach(console.log);

View File

@@ -43,7 +43,7 @@
"request": "^2.85.0",
"tslint": "^5.9.1",
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"typescript": "3.3.1",
"typescript": "3.4.5",
"vsce": "1.48.0",
"xml2js": "^0.4.17"
},

View File

@@ -8,7 +8,7 @@
"resolveJsonModule": true,
"experimentalDecorators": true,
// enable JavaScript type checking for the language service
// use the tsconfig.build.json for compiling wich disable JavaScript
// use the tsconfig.build.json for compiling which disable JavaScript
// type checking so that JavaScript file are not transpiled
"allowJs": true,
"checkJs": true,
@@ -22,4 +22,4 @@
"exclude": [
"node_modules/**"
]
}
}

View File

@@ -70,7 +70,7 @@ Type: files; Name: "{app}\resources\app\Credits_45.0.2454.85.html"; Check: IsNot
Type: filesandordirs; Name: "{app}\_"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkedonce; Check: IsNotUpdate
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked;
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
Name: "associatewithfiles"; Description: "{cm:AssociateWithFiles,{#NameLong}}"; GroupDescription: "{cm:Other}"; Flags: unchecked
Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}"

View File

@@ -3201,10 +3201,10 @@ typed-rest-client@^0.9.0:
tunnel "0.0.4"
underscore "1.8.3"
typescript@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.1.tgz#6de14e1db4b8a006ac535e482c8ba018c55f750b"
integrity sha512-cTmIDFW7O0IHbn1DPYjkiebHxwtCMU+eTy30ZtJNBPF9j2O1ITu5XH2YnBeVRKWHqF+3JQwWJv0Q0aUgX8W7IA==
typescript@3.4.5:
version "3.4.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99"
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"

View File

@@ -73,12 +73,12 @@
"git": {
"name": "electron",
"repositoryUrl": "https://github.com/electron/electron",
"commitHash": "73158a6419a3e2da9e4d523e1131052abd28fbbb"
"commitHash": "e84a6860e35e14b4031b88bb9b49841cdb89a305"
}
},
"isOnlyProductionDependency": true,
"license": "MIT",
"version": "3.1.6"
"version": "3.1.8"
},
{
"component": {
@@ -111,11 +111,11 @@
"git": {
"name": "vscode-octicons-font",
"repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font",
"commitHash": "5095860bb929919670646e2dfa0ee47d9b93bcb9"
"commitHash": "4f69de3a233ed501c2098e33047e116ac2fbbf42"
}
},
"license": "MIT",
"version": "1.0.0"
"version": "1.1.0"
},
{
"component": {

View File

@@ -1,61 +1,75 @@
{
"name": "admin-tool-ext-win",
"displayName": "Database Admin Tool Extensions for Windows",
"description": "Adds additional Windows-specific functionality to Azure Data Studio",
"version": "0.0.1",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "^1.30.1",
"sqlops": "*"
},
"activationEvents": [
"*"
],
"main": "./out/main",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
},
"extensionDependencies": [
"Microsoft.mssql"
],
"contributes": {
"commands": [
{
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
"title": "%adminToolExtWin.launchSsmsServerPropertiesDialog%",
"category": "AdminToolExtWin"
}
],
"menus": {
"commandPalette": [
{
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
"when": "false"
}
],
"objectExplorer/item/context": [
{
"command": "adminToolExtWin.launchSsmsServerPropertiesDialog",
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType == Server",
"group": "AdminToolExtWin"
}
]
},
"outputChannels": [
"admin-tool-ext-win"
]
},
"dependencies": {
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "^0.0.15",
"vscode-nls": "^3.2.1"
},
"devDependencies": {
"vscode": "1.0.1"
}
}
"name": "admin-tool-ext-win",
"displayName": "%adminToolExtWin.displayName%",
"description": "%adminToolExtWin.description%",
"version": "0.0.1",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "^1.30.1",
"sqlops": "*"
},
"activationEvents": [
"*"
],
"main": "./out/main",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
},
"extensionDependencies": [
"Microsoft.mssql"
],
"contributes": {
"commands": [
{
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
"title": "%adminToolExtWin.propertiesMenuItem%",
"category": "AdminToolExtWin"
},
{
"command": "adminToolExtWin.launchSsmsMinGswDialog",
"title": "%adminToolExtWin.launchGswMenuItem%",
"category": "AdminToolExtWin"
}
],
"menus": {
"commandPalette": [
{
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
"when": "false"
},
{
"command": "adminToolExtWin.launchSsmsMinGswDialog",
"when": "false"
}
],
"objectExplorer/item/context": [
{
"command": "adminToolExtWin.launchSsmsMinGswDialog",
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType == Database",
"group": "z-AdminToolExt@1"
},
{
"command": "adminToolExtWin.launchSsmsMinPropertiesDialog",
"when": "isWindows && connectionProvider == MSSQL && nodeType && nodeType =~ /^(Server|Database|Table|Column|Index|Statistic|View|ServerLevelLogin|ServerLevelServerRole|ServerLevelCredential|ServerLevelServerAudit|ServerLevelServerAuditSpecification|StoredProcedure|ScalarValuedFunction|TableValuedFunction|AggregateFunction|Synonym|Assembly|UserDefinedDataType|UserDefinedType|UserDefinedTableType|Sequence|User|DatabaseRole|ApplicationRole|Schema|SecurityPolicy|ServerLevelLinkedServer)$/",
"group": "z-AdminToolExt@2"
}
]
},
"outputChannels": [
"admin-tool-ext-win"
]
},
"dependencies": {
"service-downloader": "github:anthonydresser/service-downloader#0.1.5",
"vscode-extension-telemetry": "^0.0.15",
"vscode-nls": "^3.2.1"
},
"devDependencies": {
"vscode": "1.0.1"
}
}

View File

@@ -1,3 +1,6 @@
{
"adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties"
"adminToolExtWin.displayName": "Database Administration Tool Extensions for Windows",
"adminToolExtWin.description": "Adds additional Windows-specific functionality to Azure Data Studio",
"adminToolExtWin.propertiesMenuItem": "Properties",
"adminToolExtWin.launchGswMenuItem": "Generate Scripts..."
}

View File

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

View File

@@ -2,8 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
///
'use strict';
import * as nls from 'vscode-nls';
import * as path from 'path';
@@ -11,15 +9,51 @@ import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { IConfig, ServerProvider } from 'service-downloader';
import { Telemetry } from './telemetry';
import * as utils from './utils';
import { ChildProcess, exec, ExecException } from 'child_process';
import { stringify } from 'querystring';
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes, getConfiguration } from './utils';
import { ChildProcess, exec } from 'child_process';
const baseConfig = require('./config.json');
const localize = nls.loadMessageBundle();
let exePath: string;
let runningProcesses: Map<number, ChildProcess> = new Map<number, ChildProcess>();
interface SmoMapping {
action: string;
urnName: string;
}
const nodeTypeToUrnNameMapping: { [oeNodeType: string]: SmoMapping } = {
'Database': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Database', urnName: 'Database' },
'Server': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Server', urnName: 'Server' },
'ServerLevelServerAudit': { action: 'sqla:AuditProperties', urnName: 'Audit' },
'ServerLevelCredential': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Credential', urnName: 'Credential' },
'ServerLevelServerRole': { action: 'sqla:ManageServerRole', urnName: 'Role' },
'ServerLevelServerAuditSpecification': { action: 'sqla:ServerAuditSpecificationProperties', urnName: 'ServerAuditSpecification' },
'ServerLevelLinkedServer': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.LinkedServer', urnName: 'LinkedServer' },
'Table': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Table', urnName: 'Table' },
'View': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.View', urnName: 'View' },
'Column': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Column', urnName: 'Column' },
'Index': { action: 'sqla:IndexProperties', urnName: 'Index' },
'Statistic': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Statistic', urnName: 'Statistic' },
'StoredProcedure': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.StoredProcedure', urnName: 'StoredProcedure' },
'ScalarValuedFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
'TableValuedFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
'AggregateFunction': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedFunction', urnName: 'UserDefinedFunction' },
'Synonym': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Synonym', urnName: 'Synonym' },
'Assembly': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.SqlAssembly', urnName: 'SqlAssembly' },
'UserDefinedDataType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedDataType', urnName: 'UserDefinedDataType' },
'UserDefinedType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedType', urnName: 'UserDefinedType' },
'UserDefinedTableType': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.UserDefinedTableType', urnName: 'UserDefinedTableType' },
'Sequence': { action: 'sqla:SequenceProperties', urnName: 'Sequence' },
'User': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.User', urnName: 'User' },
'DatabaseRole': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.DatabaseRole', urnName: 'Role' },
'ApplicationRole': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.ApplicationRole', urnName: 'ApplicationRole' },
'Schema': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Schema', urnName: 'Schema' },
'SecurityPolicy': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.SecurityPolicy', urnName: 'SecurityPolicy' },
'ServerLevelLogin': { action: 'sqla:Properties@Microsoft.SqlServer.Management.Smo.Login', urnName: 'Login' },
};
// Params to pass to SsmsMin.exe, only an action and server are required - the rest are optional based on the
// action used. Exported for use in testing.
export interface LaunchSsmsDialogParams {
@@ -27,7 +61,6 @@ export interface LaunchSsmsDialogParams {
server: string;
database?: string;
user?: string;
password?: string;
useAad?: boolean;
urn?: string;
}
@@ -39,8 +72,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
let config: IConfig = JSON.parse(JSON.stringify(baseConfig));
config.installDirectory = path.join(context.extensionPath, config.installDirectory);
config.proxy = utils.getConfiguration('http').get('proxy');
config.strictSSL = utils.getConfiguration('http').get('proxyStrictSSL') || true;
config.proxy = getConfiguration('http').get('proxy');
config.strictSSL = getConfiguration('http').get('proxyStrictSSL') || true;
const serverdownloader = new ServerProvider(config);
const installationStart = Date.now();
@@ -55,9 +88,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
} else {
throw new Error('Could not find SsmsMin.exe after downloading');
}
// Add the command now that we have the exePath to run the tool with
context.subscriptions.push(
vscode.commands.registerCommand('adminToolExtWin.launchSsmsServerPropertiesDialog', handleLaunchSsmsServerPropertiesDialogCommand));
// Register the commands now that we have the exePath to run the tool with
registerCommands(context);
Telemetry.sendTelemetryEvent('startup/ExtensionStarted', {
installationTime: String(installationComplete - installationStart),
@@ -78,16 +111,56 @@ export async function deactivate(): Promise<void> {
runningProcesses.forEach(p => exec('taskkill /pid ' + p.pid + ' /T /F'));
}
/**
* Registers extension commands with command subsystem
* @param context The context used to register the commands
*/
function registerCommands(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.commands.registerCommand('adminToolExtWin.launchSsmsMinPropertiesDialog', handleLaunchSsmsMinPropertiesDialogCommand));
context.subscriptions.push(
vscode.commands.registerCommand('adminToolExtWin.launchSsmsMinGswDialog', handleLaunchSsmsMinGswDialogCommand));
}
/**
* Handler for command to launch SSMS Server Properties dialog
* @param connectionId The connection context from the command
*/
function handleLaunchSsmsServerPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext) {
if (connectionContext && connectionContext.connectionProfile) {
launchSsmsDialog(
/*action*/'sqla:Properties@Microsoft.SqlServer.Management.Smo.Server',
/*connectionProfile*/connectionContext.connectionProfile);
async function handleLaunchSsmsMinPropertiesDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
if (!connectionContext) {
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForProp', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
return;
}
let nodeType: string;
if (connectionContext.isConnectionNode) {
nodeType = 'Server';
}
else if (connectionContext.nodeInfo) {
nodeType = connectionContext.nodeInfo.nodeType;
}
else {
vscode.window.showErrorMessage(localize('adminToolExtWin.noOeNode', 'Could not determine NodeType for handleLaunchSsmsMinPropertiesDialogCommand with context {0}', JSON.stringify(connectionContext)));
return;
}
launchSsmsDialog(
nodeTypeToUrnNameMapping[nodeType].action,
connectionContext);
}
/**
* Handler for command to launch SSMS "Generate Script Wizard" dialog
* @param connectionId The connection context from the command
*/
async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.ObjectExplorerContext): Promise<void> {
if (!connectionContext) {
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', 'No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand'));
}
launchSsmsDialog(
'GenerateScripts',
connectionContext);
}
/**
@@ -96,29 +169,72 @@ function handleLaunchSsmsServerPropertiesDialogCommand(connectionContext?: azdat
* @param params The params used to construct the command
* @param urn The URN to pass to SsmsMin
*/
function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionProfile, urn?: string) {
async function launchSsmsDialog(action: string, connectionContext: azdata.ObjectExplorerContext): Promise<void> {
if (!exePath) {
vscode.window.showErrorMessage(localize('adminToolExtWin.noExeError', 'Unable to find SsmsMin.exe.'));
return;
}
Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
if (!connectionContext.connectionProfile) {
vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionProfile', 'No connectionProfile provided from connectionContext : {0}', JSON.stringify(connectionContext)));
return;
}
// Currently Azure isn't supported by the SSMS server properties dialog
const serverInfo = await azdata.connection.getServerInfo(connectionContext.connectionProfile.id);
if (serverInfo && serverInfo.isCloud) {
vscode.window.showErrorMessage(localize('adminToolExtWin.invalidEngineType', 'This option is not currently available for this engine type.'));
return;
}
// Note - this is a temporary fix for the issue that currently the connection API doesn't allow retrieving credentials for a disconnected
// node. So until that's fixed we'll prevent users from attempting to launch SsmsMin on a disconnected node.
// We also aren't able to hide the menu item on disconnected nodes because we currently don't have a contextKey for the connected status
// of a node.
const activeConnections = await azdata.connection.getActiveConnections();
if (!activeConnections.some(conn => conn.connectionId === connectionContext.connectionProfile.id)) {
vscode.window.showErrorMessage(localize('adminToolExtWin.notConnected', 'This option requires a connected node - please connect and try again.'));
return;
}
let oeNode: azdata.objectexplorer.ObjectExplorerNode;
// Server node is a Connection node and so doesn't have the NodeInfo
if (connectionContext.isConnectionNode) {
oeNode = undefined;
}
else if (connectionContext.nodeInfo && connectionContext.nodeInfo.nodeType && connectionContext.connectionProfile) {
oeNode = await azdata.objectexplorer.getNode(connectionContext.connectionProfile.id, connectionContext.nodeInfo.nodePath);
}
else {
vscode.window.showErrorMessage(localize('adminToolExtWin.noOENode', 'Could not determine Object Explorer node from connectionContext : {0}', JSON.stringify(connectionContext)));
return;
}
let urn: string = await buildUrn(connectionContext.connectionProfile.serverName, oeNode);
let password: string = connectionContext.connectionProfile.password;
if (!password || password === '') {
let creds = await azdata.connection.getCredentials(connectionContext.connectionProfile.id);
password = creds[azdata.ConnectionOptionSpecialType.password];
}
let params: LaunchSsmsDialogParams = {
action: action,
server: connectionProfile.serverName,
database: connectionProfile.databaseName,
password: connectionProfile.password,
user: connectionProfile.userName,
useAad: connectionProfile.authenticationType === 'AzureMFA',
server: connectionContext.connectionProfile.serverName,
database: connectionContext.connectionProfile.databaseName,
user: connectionContext.connectionProfile.userName,
useAad: connectionContext.connectionProfile.authenticationType === 'AzureMFA',
urn: urn
};
let args = buildSsmsMinCommandArgs(params);
Telemetry.sendTelemetryEvent('LaunchSsmsDialog', { 'action': action });
// This will be an async call since we pass in the callback
var proc: ChildProcess = exec(
/*command*/`"${exePath}" ${args}`,
/*options*/undefined,
let proc: ChildProcess = exec(
/*command*/ `"${exePath}" ${args}`,
/*options*/ undefined,
(execException, stdout, stderr) => {
// Process has exited so remove from map of running processes
runningProcesses.delete(proc.pid);
@@ -128,13 +244,15 @@ function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionP
});
let err = stderr.toString();
if (err !== '') {
console.warn(`Error calling SsmsMin with args '${args}' - ${err}`);
vscode.window.showErrorMessage(localize(
'adminToolExtWin.ssmsMinError',
'Error calling SsmsMin with args \'{0}\' - {1}', args, err));
}
});
// If we're not using AAD the tool prompts for a password on stdin
if (params.useAad !== true) {
proc.stdin.end(params.password ? params.password : '');
proc.stdin.end(password ? password : '');
}
// Save the process into our map so we can make sure to stop them if we exit before shutting down
@@ -148,10 +266,34 @@ function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionP
* @param params The params used to build up the command parameter string
*/
export function buildSsmsMinCommandArgs(params: LaunchSsmsDialogParams): string {
return `${params.action ? '-a "' + params.action.replace(/"/g, '\\"') + '"' : ''}\
${params.server ? ' -S "' + params.server.replace(/"/g, '\\"') + '"' : ''}\
${params.database ? ' -D "' + params.database.replace(/"/g, '\\"') + '"' : ''}\
${params.useAad !== true && params.user ? ' -U "' + params.user.replace(/"/g, '\\"') + '"' : ''}\
return `${params.action ? '-a "' + backEscapeDoubleQuotes(params.action) + '"' : ''}\
${params.server ? ' -S "' + backEscapeDoubleQuotes(params.server) + '"' : ''}\
${params.database ? ' -D "' + backEscapeDoubleQuotes(params.database) + '"' : ''}\
${params.useAad !== true && params.user ? ' -U "' + backEscapeDoubleQuotes(params.user) + '"' : ''}\
${params.useAad === true ? ' -G' : ''}\
${params.urn ? ' -u "' + params.urn.replace(/"/g, '\\"') + '"' : ''}`;
${params.urn ? ' -u "' + backEscapeDoubleQuotes(params.urn) + '"' : ''}`;
}
/**
* Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin
* @param serverName The name of the Server to use for the Server segment
* @param node The node to get the URN of
*/
export async function buildUrn(serverName: string, node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
let urnNodes: string[] = [];
while (node) {
// Server is special since it's a connection node - always add it as the root
if (node.nodeType === 'Server') {
break;
}
else if (node.metadata && node.nodeType !== 'Folder') {
// SFC URN expects Name and Schema to be separate properties
let urnSegment = node.metadata.schema && node.metadata.schema !== '' ?
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}' and @Schema='${doubleEscapeSingleQuotes(node.metadata.schema)}']` :
`${nodeTypeToUrnNameMapping[node.nodeType].urnName}[@Name='${doubleEscapeSingleQuotes(node.metadata.name)}']`;
urnNodes = [urnSegment].concat(urnNodes);
}
node = await node.getParent();
}
return [`Server[@Name='${doubleEscapeSingleQuotes(serverName)}']`].concat(urnNodes).join('/');
}

View File

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

View File

@@ -9,20 +9,20 @@ const testRunner = require('vscode/lib/testrunner');
const suite = 'Database Admin Tool Extensions for Windows';
const options: any = {
ui: 'bdd',
useColors: true,
timeout: 600000
ui: 'bdd',
useColors: true,
timeout: 600000
};
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
options.reporter = 'mocha-multi-reporters';
options.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
options.reporter = 'mocha-multi-reporters';
options.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
}
testRunner.configure(options);

View File

@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
/**
* Helper stub class for mocking ExtHostObjectExplorerNode
*/
export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.ObjectExplorerNode {
// Stub properties
private parent: azdata.objectexplorer.ObjectExplorerNode;
// Base properties
public connectionId: string;
public nodePath: string;
public nodeType: string;
public nodeSubType: string;
public nodeStatus: string;
public label: string;
public isLeaf: boolean;
public metadata: azdata.ObjectMetadata;
public errorMessage: string;
constructor(nodeName: string, nodeSchema: string, nodeType, parent: azdata.objectexplorer.ObjectExplorerNode) {
this.parent = parent;
this.nodeType = nodeType;
this.metadata = { metadataType: undefined, metadataTypeName: undefined, name: nodeName, schema: nodeSchema, urn: undefined };
}
isExpanded(): Thenable<boolean> {
throw new Error('Method not implemented');
}
setExpandedState(expandedState: vscode.TreeItemCollapsibleState): Thenable<void> {
throw new Error('Method not implemented');
}
setSelected(selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
throw new Error('Method not implemented');
}
getChildren(): Thenable<azdata.objectexplorer.ObjectExplorerNode[]> {
throw new Error('Method not implemented');
}
getParent(): Thenable<azdata.objectexplorer.ObjectExplorerNode> {
return Promise.resolve(this.parent);
}
refresh(): Thenable<void> {
throw new Error('Method not implemented');
}
/**
*
* @param nodeName Helperfunction to create a node that is a child of this one
* @param nodeSchema The schema to give the child node
* @param nodeType The type of node this should be
*/
createChild(nodeName: string, nodeSchema: string, nodeType: string): ExtHostObjectExplorerNodeStub {
return new ExtHostObjectExplorerNodeStub(nodeName, nodeSchema, nodeType, this);
}
}

View File

@@ -8,60 +8,128 @@
import * as should from 'should';
import 'mocha';
import * as extensionMain from '../main';
import { buildSsmsMinCommandArgs, buildUrn, LaunchSsmsDialogParams } from '../main';
import { doubleEscapeSingleQuotes, backEscapeDoubleQuotes } from '../utils';
import { ExtHostObjectExplorerNodeStub } from './stubs';
describe('buildSsmsMinCommandArgs Method Tests', () => {
it('Should be built correctly with all params and UseAAD as false', function (): void {
let params: extensionMain.LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer',
database: 'myDatabase',
user: 'user',
password: 'password',
useAad: false,
urn: 'Server\\Database\\Table'
};
let args = extensionMain.buildSsmsMinCommandArgs(params);
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
});
it('Should be built correctly with all params and UseAAD as false', function (): void {
const params: LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer',
database: 'myDatabase',
user: 'user',
useAad: false,
urn: 'Server\\Database\\Table'
};
const args = buildSsmsMinCommandArgs(params);
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
});
it('Should be built correctly with all params and UseAAD as true', function (): void {
let params: extensionMain.LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer',
database: 'myDatabase',
user: 'user',
password: 'password',
useAad: true,
urn: 'Server\\Database\\Table'
};
let args = extensionMain.buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
});
it('Should be built correctly with all params and UseAAD as true', function (): void {
const params: LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer',
database: 'myDatabase',
user: 'user',
useAad: true,
urn: 'Server\\Database\\Table'
};
const args = buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
});
it('Should be built correctly and names escaped correctly', function (): void {
let params: extensionMain.LaunchSsmsDialogParams = {
action: 'myAction\'"/\\[]tricky',
server: 'myServer\'"/\\[]tricky',
database: 'myDatabase\'"/\\[]tricky',
user: 'user\'"/\\[]tricky',
password: 'password',
useAad: true,
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
};
let args = extensionMain.buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
});
it('Should be built correctly and names escaped correctly', function (): void {
const params: LaunchSsmsDialogParams = {
action: 'myAction\'"/\\[]tricky',
server: 'myServer\'"/\\[]tricky',
database: 'myDatabase\'"/\\[]tricky',
user: 'user\'"/\\[]tricky',
useAad: true,
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
};
const args = buildSsmsMinCommandArgs(params);
// User is omitted since UseAAD is true
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
});
it('Should be built correctly with only action and server', function (): void {
it('Should be built correctly with only action and server', function (): void {
let params: extensionMain.LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer'
};
let args = extensionMain.buildSsmsMinCommandArgs(params);
should(args).equal('-a "myAction" -S "myServer"');
});
const params: LaunchSsmsDialogParams = {
action: 'myAction',
server: 'myServer'
};
const args = buildSsmsMinCommandArgs(params);
should(args).equal('-a "myAction" -S "myServer"');
});
});
const serverName = 'My\'Server';
const escapedServerName = doubleEscapeSingleQuotes(serverName);
const dbName = 'My\'Db';
const escapedDbName = doubleEscapeSingleQuotes(dbName);
const dbSchema = 'db\'sch';
const escapedDbSchema = doubleEscapeSingleQuotes(dbSchema);
const tableName = 'My\'Table';
const escapedTableName = doubleEscapeSingleQuotes(tableName);
const tableSchema = 'tbl\'sch';
const escapedTableSchema = doubleEscapeSingleQuotes(tableSchema);
describe('buildUrn Method Tests', () => {
it('Urn should be correct with just server', async function (): Promise<void> {
should(await buildUrn(serverName, undefined)).equal(`Server[@Name=\'${escapedServerName}\']`);
});
it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined);
should(await buildUrn(serverName, leafNode)).equal(`Server[@Name='${escapedServerName}']`);
});
it('Urn should be correct with Server and Database node', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database');
should(await buildUrn(serverName, leafNode)).equal(
`Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`);
});
it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> {
const rootNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database')
.createChild('Tables', undefined, 'Folder')
.createChild(tableName, tableSchema, 'Table');
should(await buildUrn(serverName, rootNode)).equal(
`Server[@Name='${escapedServerName}']/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`);
});
});
describe('doubleEscapeSingleQuotes Method Tests', () => {
it('Should return original string if no single quotes', function (): void {
const testString: string = 'MyTestString';
const ret = doubleEscapeSingleQuotes(testString);
should(ret).equal(testString);
});
it('Should return escaped original string if it contains single quotes', function (): void {
const testString: string = 'MyTestString\'\'WithQuotes';
const ret = doubleEscapeSingleQuotes(testString);
should(ret).equal('MyTestString\'\'\'\'WithQuotes');
});
});
describe('backEscapeDoubleQuotes Method Tests', () => {
it('Should return original string if no double quotes', function (): void {
const testString: string = 'MyTestString';
const ret = backEscapeDoubleQuotes(testString);
should(ret).equal(testString);
});
it('Should return escaped original string if it contains double quotes', function (): void {
const testString: string = 'MyTestString\"\"WithQuotes';
const ret = backEscapeDoubleQuotes(testString);
should(ret).equal('MyTestString\\"\\"WithQuotes');
});
});

View File

@@ -7,19 +7,19 @@
import * as vscode from 'vscode';
export interface IPackageInfo {
name: string;
version: string;
aiKey: string;
name: string;
version: string;
aiKey: string;
}
export function getPackageInfo(packageJson: any): IPackageInfo {
if (packageJson) {
return {
name: packageJson.name,
version: packageJson.version,
aiKey: packageJson.aiKey
};
}
if (packageJson) {
return {
name: packageJson.name,
version: packageJson.version,
aiKey: packageJson.aiKey
};
}
}
/**
@@ -28,15 +28,33 @@ export function getPackageInfo(packageJson: any): IPackageInfo {
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
} else if (!resource) {
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
resource = null;
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
} else if (!resource) {
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
resource = null;
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/**
* Escapes all single-quotes (') by prefixing them with another single quote ('')
* ' => ''
* @param value The string to escape
*/
export function doubleEscapeSingleQuotes(value: string): string {
return value.replace(/'/g, '\'\'');
}
/**
* Escape all double-quotes (") by prefixing them with a \
* " => \"
* @param value The string to escape
*/
export function backEscapeDoubleQuotes(value: string): string {
return value.replace(/"/g, '\\"');
}

View File

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

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

File diff suppressed because it is too large Load Diff

View File

@@ -2,14 +2,14 @@
"name": "agent",
"displayName": "SQL Server Agent",
"description": "Manage and troubleshoot SQL Server Agent jobs",
"version": "0.37.0",
"version": "0.39.0",
"publisher": "Microsoft",
"preview": true,
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
"icon": "images/sqlserver.png",
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
"engines": {
"vscode": "0.10.x"
"vscode": "^1.25.0"
},
"activationEvents": [
"*"
@@ -46,7 +46,13 @@
},
"devDependencies": {
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7"
"mocha-multi-reporters": "^1.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^8.10.25",
"mocha": "^5.2.0",
"should": "^13.2.1",
"typemoq": "^2.1.0",
"vscode": "1.1.5"
},
"__metadata": {
"id": "10",

View File

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

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as data from 'azdata';
@@ -12,52 +11,51 @@ import * as data from 'azdata';
* this API from our code
*
* @export
* @class ApiWrapper
*/
export class ApiWrapper {
// Data APIs
// Data APIs
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
return data.dashboard.registerWebviewProvider(widgetId, handler);
}
/**
* Get the configuration for a extensionName
* @param extensionName The string name of the extension to get the configuration for
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/**
* Get the configuration for a extensionName
* @param extensionName The string name of the extension to get the configuration for
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
*/
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
if (typeof resource === 'string') {
try {
resource = this.parseUri(resource);
} catch (e) {
resource = undefined;
}
}
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
}
/**
* Parse uri
*/
public parseUri(uri: string): vscode.Uri {
return vscode.Uri.parse(uri);
}
/**
* Parse uri
*/
public parseUri(uri: string): vscode.Uri {
return vscode.Uri.parse(uri);
}
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
return vscode.window.showOpenDialog(options);
}
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
return vscode.window.showOpenDialog(options);
}
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return vscode.window.showErrorMessage(message, ...items);
}
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
return vscode.window.showErrorMessage(message, ...items);
}
public get workspaceRootPath(): string {
return vscode.workspace.rootPath;
}
public get workspaceRootPath(): string {
return vscode.workspace.rootPath;
}
}

View File

@@ -17,7 +17,7 @@ export class AlertData implements IAgentDialogData {
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
ownerUri: string;
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
@@ -50,7 +50,7 @@ export class AlertData implements IAgentDialogData {
private jobModel: JobData;
constructor(
ownerUri:string,
ownerUri: string,
alertInfo: azdata.AgentAlertInfo,
jobModel?: JobData,
viaJobDialog: boolean = false

View File

@@ -14,7 +14,7 @@ const localize = nls.loadMessageBundle();
export class JobData implements IAgentDialogData {
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
@@ -126,7 +126,7 @@ export class JobData implements IAgentDialogData {
public async save() {
let jobInfo: azdata.AgentJobInfo = this.toAgentJobInfo();
let result = this.dialogMode === AgentDialogMode.CREATE
? await this._agentService.createJob(this.ownerUri, jobInfo)
? await this._agentService.createJob(this.ownerUri, jobInfo)
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
if (!result || !result.success) {
if (this.dialogMode === AgentDialogMode.EDIT) {
@@ -142,7 +142,7 @@ export class JobData implements IAgentDialogData {
localize('jobData.saveSucessMessage', "Job '{0}' updated successfully", jobInfo.name));
} else {
vscode.window.showInformationMessage(
localize('jobData.newJobSuccessMessage',"Job '{0}' created successfully", jobInfo.name));
localize('jobData.newJobSuccessMessage', "Job '{0}' created successfully", jobInfo.name));
}
}

View File

@@ -48,7 +48,7 @@ export class JobStepData implements IAgentDialogData {
private jobModel: JobData;
private viaJobDialog: boolean;
constructor(ownerUri:string, jobModel?: JobData, viaJobDialog: boolean = false) {
constructor(ownerUri: string, jobModel?: JobData, viaJobDialog: boolean = false) {
this.ownerUri = ownerUri;
this.jobName = jobModel.name;
this.jobModel = jobModel;
@@ -102,26 +102,26 @@ export class JobStepData implements IAgentDialogData {
stepData.jobName = jobStepInfo.jobName;
stepData.script = jobStepInfo.script;
stepData.scriptName = jobStepInfo.scriptName,
stepData.stepName = jobStepInfo.stepName,
stepData.subSystem = jobStepInfo.subSystem,
stepData.id = jobStepInfo.id,
stepData.failureAction = jobStepInfo.failureAction,
stepData.successAction = jobStepInfo.successAction,
stepData.failStepId = jobStepInfo.failStepId,
stepData.successStepId = jobStepInfo.successStepId,
stepData.command = jobStepInfo.command,
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
stepData.databaseName = jobStepInfo.databaseName,
stepData.databaseUserName = jobStepInfo.databaseUserName,
stepData.server = jobStepInfo.server,
stepData.outputFileName = jobStepInfo.outputFileName,
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
stepData.retryAttempts = jobStepInfo.retryAttempts,
stepData.retryInterval = jobStepInfo.retryInterval,
stepData.proxyName = jobStepInfo.proxyName;
stepData.stepName = jobStepInfo.stepName,
stepData.subSystem = jobStepInfo.subSystem,
stepData.id = jobStepInfo.id,
stepData.failureAction = jobStepInfo.failureAction,
stepData.successAction = jobStepInfo.successAction,
stepData.failStepId = jobStepInfo.failStepId,
stepData.successStepId = jobStepInfo.successStepId,
stepData.command = jobStepInfo.command,
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
stepData.databaseName = jobStepInfo.databaseName,
stepData.databaseUserName = jobStepInfo.databaseUserName,
stepData.server = jobStepInfo.server,
stepData.outputFileName = jobStepInfo.outputFileName,
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
stepData.retryAttempts = jobStepInfo.retryAttempts,
stepData.retryInterval = jobStepInfo.retryInterval,
stepData.proxyName = jobStepInfo.proxyName;
stepData.dialogMode = AgentDialogMode.EDIT;
stepData.viaJobDialog = true;
return stepData;

View File

@@ -29,7 +29,7 @@ export class OperatorData implements IAgentDialogData {
weekdayPagerStartTime: string;
weekdayPagerEndTime: string;
constructor(ownerUri:string, operatorInfo: azdata.AgentOperatorInfo) {
constructor(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) {
this.ownerUri = ownerUri;
if (operatorInfo) {
this.dialogMode = AgentDialogMode.EDIT;
@@ -58,7 +58,7 @@ export class OperatorData implements IAgentDialogData {
public async save() {
let agentService = await AgentUtils.getAgentService();
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
if (!result || !result.success) {
// TODO handle error here
}

View File

@@ -15,7 +15,7 @@ export class PickScheduleData implements IAgentDialogData {
public selectedSchedule: azdata.AgentJobScheduleInfo;
private jobName: string;
constructor(ownerUri:string, jobName: string) {
constructor(ownerUri: string, jobName: string) {
this.ownerUri = ownerUri;
this.jobName = jobName;
}

View File

@@ -22,7 +22,7 @@ export class ProxyData implements IAgentDialogData {
credentialId: number;
isEnabled: boolean;
constructor(ownerUri:string, proxyInfo: azdata.AgentProxyInfo) {
constructor(ownerUri: string, proxyInfo: azdata.AgentProxyInfo) {
this.ownerUri = ownerUri;
if (proxyInfo) {
@@ -48,7 +48,7 @@ export class ProxyData implements IAgentDialogData {
localize('proxyData.saveSucessMessage', "Proxy '{0}' updated successfully", proxyInfo.accountName));
} else {
vscode.window.showInformationMessage(
localize('proxyData.newJobSuccessMessage',"Proxy '{0}' created successfully", proxyInfo.accountName));
localize('proxyData.newJobSuccessMessage', "Proxy '{0}' created successfully", proxyInfo.accountName));
}
}

View File

@@ -14,7 +14,7 @@ export class ScheduleData implements IAgentDialogData {
public schedules: azdata.AgentJobScheduleInfo[];
public selectedSchedule: azdata.AgentJobScheduleInfo;
constructor(ownerUri:string) {
constructor(ownerUri: string) {
this.ownerUri = ownerUri;
}

View File

@@ -62,14 +62,14 @@ export class AlertDialog extends AgentDialog<AlertData> {
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
private static readonly AlertTypes: string[] = [
private static readonly AlertTypes: string[] = [
AlertData.AlertTypeSqlServerEventString,
// Disabled until next release
// AlertData.AlertTypePerformanceConditionString,
// AlertData.AlertTypeWmiEventString
];
private static readonly AlertSeverities: string[] = [
private static readonly AlertSeverities: string[] = [
AlertDialog.AlertSeverity001Label,
AlertDialog.AlertSeverity002Label,
AlertDialog.AlertSeverity003Label,
@@ -100,21 +100,21 @@ export class AlertDialog extends AgentDialog<AlertData> {
// Response tab strings
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
// Options tab strings
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
// Event Name strings
private readonly NewAlertDialog = 'NewAlertDialogOpen';
@@ -315,7 +315,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
}],
title: AlertDialog.EventAlertText
}
]).withLayout({ width: '100%' }).component();
]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
@@ -332,7 +332,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
if (this.model.severity > 0) {
this.severityRadioButton.checked = true;
this.severityDropDown.value = this.severityDropDown.values[this.model.severity-1];
this.severityDropDown.value = this.severityDropDown.values[this.model.severity - 1];
}
if (this.model.databaseName) {
@@ -356,9 +356,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
.component();
this.executeJobTextBox.enabled = false;
this.newJobButton = view.modelBuilder.button().withProperties({
label: AlertDialog.NewJobButtonLabel,
width: 80
}).component();
label: AlertDialog.NewJobButtonLabel,
width: 80
}).component();
this.newJobButton.enabled = false;
this.newJobButton.onDidClick(() => {
let jobDialog = new JobDialog(this.ownerUri);
@@ -382,7 +382,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
}, {
component: this.newJobButton,
title: AlertDialog.NewJobButtonLabel
}], { componentWidth: '100%'}).component();
}], { componentWidth: '100%' }).component();
let previewTag = view.modelBuilder.text()
.withProperties({
@@ -409,9 +409,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
}).component();
this.newOperatorButton = view.modelBuilder.button().withProperties({
label: AlertDialog.NewOperatorButtonLabel,
width: 80
}).component();
label: AlertDialog.NewOperatorButtonLabel,
width: 80
}).component();
this.operatorsTable.enabled = false;
this.newOperatorButton.enabled = false;
@@ -438,7 +438,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
}, {
component: this.newOperatorButton,
title: ''
}], { componentWidth: '100%'}).component();
}], { componentWidth: '100%' }).component();
let formModel = view.modelBuilder.formContainer()
.withFormItems([{
@@ -548,7 +548,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
} else {
this.model.eventDescriptionKeyword = '';
}
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
this.model.delayBetweenResponses = minutes + seconds;

View File

@@ -70,7 +70,7 @@ export class JobDialog extends AgentDialog<JobData> {
// Event Name strings
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
// UI Components
private generalTab: azdata.window.DialogTab;
@@ -259,9 +259,9 @@ export class JobDialog extends AgentDialog<JobData> {
width: 140
}).component();
this.newStepButton.onDidClick((e)=>{
this.newStepButton.onDidClick((e) => {
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
let stepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, null, true);
stepDialog.onSuccess((step) => {
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
this.steps.push(stepInfo);
@@ -296,7 +296,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.deleteStepButton.enabled = false;
this.moveStepUpButton.onDidClick(() => {
let rowNumber = this.stepsTable.selectedRows[0];
let rowNumber = this.stepsTable.selectedRows[0];
let previousRow = rowNumber - 1;
let previousStep = this.steps[previousRow];
let previousStepId = this.steps[previousRow].id;
@@ -329,7 +329,7 @@ export class JobDialog extends AgentDialog<JobData> {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
let stepData = this.model.jobSteps[rowNumber];
let editStepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
let editStepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, stepData, true);
editStepDialog.onSuccess((step) => {
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
for (let i = 0; i < this.steps.length; i++) {
@@ -349,7 +349,7 @@ export class JobDialog extends AgentDialog<JobData> {
}
});
this.deleteStepButton.onDidClick(async() => {
this.deleteStepButton.onDidClick(async () => {
if (this.stepsTable.selectedRows.length === 1) {
let rowNumber = this.stepsTable.selectedRows[0];
AgentUtils.getAgentService().then(async (agentService) => {
@@ -448,7 +448,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.alerts.push(alertInfo);
this.alertsTable.data = this.convertAlertsToData(this.alerts);
});
this.newAlertButton.onDidClick(()=>{
this.newAlertButton.onDidClick(() => {
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
alertDialog.jobId = this.model.jobId;
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
@@ -491,7 +491,7 @@ export class JobDialog extends AgentDialog<JobData> {
label: 'Remove schedule',
width: 100
}).component();
this.pickScheduleButton.onDidClick(()=>{
this.pickScheduleButton.onDidClick(() => {
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
pickScheduleDialog.onSuccess((dialogModel) => {
let selectedSchedule = dialogModel.selectedSchedule;
@@ -507,8 +507,8 @@ export class JobDialog extends AgentDialog<JobData> {
pickScheduleDialog.showDialog();
});
this.removeScheduleButton.onDidClick(() => {
if (this.schedulesTable.selectedRows.length === 1) {
let selectedRow = this.schedulesTable.selectedRows[0];
if (this.schedulesTable.selectedRows.length === 1) {
let selectedRow = this.schedulesTable.selectedRows[0];
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
for (let i = 0; i < this.schedules.length; i++) {
if (this.schedules[i].name === selectedScheduleName) {
@@ -595,22 +595,23 @@ export class JobDialog extends AgentDialog<JobData> {
let formModel = view.modelBuilder.formContainer().withFormItems([
{
components:
[{
component: emailContainer,
title: ''
},
{
component: pagerContainer,
title: ''
},
{
component: eventLogContainer,
title: ''
},
{
component: deleteJobContainer,
title: ''
}], title: this.NotificationsTabTopLabelString}]).withLayout({ width: '100%' }).component();
[{
component: emailContainer,
title: ''
},
{
component: pagerContainer,
title: ''
},
{
component: eventLogContainer,
title: ''
},
{
component: deleteJobContainer,
title: ''
}], title: this.NotificationsTabTopLabelString
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
@@ -694,7 +695,7 @@ export class JobDialog extends AgentDialog<JobData> {
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
if (!this.model.jobSteps) {
this.model.jobSteps = [];
}

View File

@@ -28,7 +28,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse');
private readonly ParseCommandText: string = localize('jobStepDialog.parse', 'Parse');
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
@@ -124,15 +124,15 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
viaJobDialog: boolean = false
) {
super(ownerUri,
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
this.stepId = jobStepInfo ?
jobStepInfo.id : jobModel.jobSteps ?
jobModel.jobSteps.length + 1 : 1;
jobStepInfo.id : jobModel.jobSteps ?
jobModel.jobSteps.length + 1 : 1;
this.isEdit = jobStepInfo ? true : false;
this.model.dialogMode = this.isEdit ? AgentDialogMode.EDIT : AgentDialogMode.CREATE;
this.jobModel = jobModel;
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
this.server = server;
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
}
@@ -164,7 +164,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
if (this.commandTextBox.value) {
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
if (result && result.parseable) {
this.dialog.message = { text: this.SuccessfulParseText, level: 2};
this.dialog.message = { text: this.SuccessfulParseText, level: 2 };
} else if (result && !result.parseable) {
this.dialog.message = { text: this.FailureParseText };
}
@@ -246,7 +246,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
}).component();
this.typeDropdown.onValueChanged((type) => {
switch (type.selected) {
case(this.TSQLScript):
case (this.TSQLScript):
this.runAsDropdown.value = '';
this.runAsDropdown.values = [''];
this.runAsDropdown.enabled = false;
@@ -256,7 +256,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false;
break;
case(this.Powershell):
case (this.Powershell):
this.runAsDropdown.value = this.AgentServiceAccount;
this.runAsDropdown.values = [this.runAsDropdown.value];
this.runAsDropdown.enabled = true;
@@ -266,7 +266,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
this.processExitCodeBox.value = '';
this.processExitCodeBox.enabled = false;
break;
case(this.CmdExec):
case (this.CmdExec):
this.databaseDropdown.enabled = false;
this.databaseDropdown.values = [''];
this.databaseDropdown.value = '';
@@ -397,13 +397,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
let retryAttemptsContainer = view.modelBuilder.formContainer()
.withFormItems(
[{
component: this.retryAttemptsBox,
title: this.RetryAttemptsLabel
}], {
horizontal: false,
componentWidth: '100%'
})
[{
component: this.retryAttemptsBox,
title: this.RetryAttemptsLabel
}], {
horizontal: false,
componentWidth: '100%'
})
.component();
let retryIntervalContainer = view.modelBuilder.formContainer()
@@ -411,7 +411,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
[{
component: this.retryIntervalBox,
title: this.RetryIntervalLabel
}], {
}], {
horizontal: false
})
.component();
@@ -427,13 +427,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
this.fileBrowserDialog = azdata.window.createModelViewDialog(fileBrowserTitle);
let fileBrowserTab = azdata.window.createTab('File Browser');
this.fileBrowserDialog.content = [fileBrowserTab];
this.fileBrowserDialog.content = [fileBrowserTab];
fileBrowserTab.registerContent(async (view) => {
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
.component();
this.selectedPathTextBox = view.modelBuilder.inputBox()
.withProperties({ inputType: 'text'})
.withProperties({ inputType: 'text' })
.component();
this.fileBrowserTree.onDidChange((args) => {
this.selectedPathTextBox.value = args.fullPath;
@@ -462,7 +462,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
component: this.fileBrowserNameBox,
title: this.FileNameLabelString
}
]).component();
]).component();
view.initializeModel(fileBrowserContainer);
});
this.fileBrowserDialog.okButton.onClick(() => {

View File

@@ -135,7 +135,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
this.pagerTuesdayCheckBox.onChanged(() => {
if (this.pagerTuesdayCheckBox .checked) {
if (this.pagerTuesdayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
@@ -153,7 +153,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
}).component();
this.pagerWednesdayCheckBox.onChanged(() => {
if (this.pagerWednesdayCheckBox .checked) {
if (this.pagerWednesdayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
@@ -171,7 +171,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
}).component();
this.pagerThursdayCheckBox.onChanged(() => {
if (this.pagerThursdayCheckBox .checked) {
if (this.pagerThursdayCheckBox.checked) {
this.weekdayPagerStartTimeInput.enabled = true;
this.weekdayPagerEndTimeInput.enabled = true;
} else {
@@ -362,7 +362,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
}, {
component: pagerSundayCheckboxContainer,
title: ''
}] ,
}],
title: OperatorDialog.PagerDutyScheduleLabel
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
'use strict';
import * as nls from 'vscode-nls';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
@@ -20,8 +20,8 @@ export class PickScheduleDialog {
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
private readonly SchedulesLabelText: string = localize('pickSchedule.availableSchedules', 'Available Schedules:');
public static readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Name');
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID','ID');
public static readonly ScheduleDescription: string = localize('pickSchedule.description','Description');
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID', 'ID');
public static readonly ScheduleDescription: string = localize('pickSchedule.description', 'Description');
// UI Components
@@ -74,7 +74,7 @@ export class PickScheduleDialog {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [ schedule.id, schedule.name, schedule.description ];
data[i] = [schedule.id, schedule.name, schedule.description];
}
this.schedulesTable.data = data;
}

View File

@@ -84,7 +84,7 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
this.generalTab.registerContent(async view => {
this.proxyNameTextBox = view.modelBuilder.inputBox()
.withProperties({width: 420})
.withProperties({ width: 420 })
.component();
this.credentialNameDropDown = view.modelBuilder.dropDown()

View File

@@ -69,7 +69,7 @@ export class ScheduleDialog {
let data: any[][] = [];
for (let i = 0; i < this.model.schedules.length; ++i) {
let schedule = this.model.schedules[i];
data[i] = [ schedule.name ];
data[i] = [schedule.name];
}
this.schedulesTable.data = data;
}

View File

@@ -22,57 +22,57 @@ const localize = nls.loadMessageBundle();
* The main controller class that initializes the extension
*/
export class MainController {
protected _context: vscode.ExtensionContext;
protected _context: vscode.ExtensionContext;
// PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext) {
this._context = context;
}
// PUBLIC METHODS //////////////////////////////////////////////////////
public constructor(context: vscode.ExtensionContext) {
this._context = context;
}
public static showNotYetImplemented(): void {
vscode.window.showInformationMessage(
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
}
public static showNotYetImplemented(): void {
vscode.window.showInformationMessage(
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
}
/**
* Activates the extension
*/
public activate(): void {
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
let dialog = new JobDialog(ownerUri, jobInfo);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
AgentUtils.getAgentService().then(async(agentService) => {
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
});
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
let dialog = new PickScheduleDialog(ownerUri, jobName);
await dialog.showDialog();
});
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
AgentUtils.getAgentService().then(async (agentService) => {
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
});
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
let dialog = new OperatorDialog(ownerUri, operatorInfo);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
}
/**
* Activates the extension
*/
public activate(): void {
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
let dialog = new JobDialog(ownerUri, jobInfo);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
AgentUtils.getAgentService().then(async (agentService) => {
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
});
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
let dialog = new PickScheduleDialog(ownerUri, jobName);
await dialog.showDialog();
});
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
AgentUtils.getAgentService().then(async (agentService) => {
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
});
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
let dialog = new OperatorDialog(ownerUri, operatorInfo);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
});
}
/**
* Deactivates the extension
*/
public deactivate(): void {
}
/**
* Deactivates the extension
*/
public deactivate(): void {
}
}

View File

@@ -1,21 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import 'mocha';
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import { JobData } from '../data/jobData';
import { TestAgentService } from './testAgentService';
const testOwnerUri = 'agent://testuri';
suite('Agent extension', () => {
test('Create Job Data', async () => {
let testAgentService = new TestAgentService();
let data = new JobData(testOwnerUri, undefined, testAgentService);
data.save();
});
});

View File

@@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as should from 'should';
import * as TypeMoq from 'typemoq';
import 'mocha';
import * as azdata from 'azdata';
import { JobData } from '../../data/jobData';
const testOwnerUri = 'agent://testuri';
let mockJobData: TypeMoq.IMock<JobData>;
let mockAgentService: TypeMoq.IMock<azdata.AgentServicesProvider>;
describe('Agent extension create job objects', function (): void {
beforeEach(() => {
mockAgentService = TypeMoq.Mock.ofType<azdata.AgentServicesProvider>();
mockAgentService.setup(s => s.createJob(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createJob(undefined, TypeMoq.It.isAny())).returns(() => undefined);
mockAgentService.setup(s => s.createAlert(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createAlert(undefined, TypeMoq.It.isAny())).returns(() => undefined);
mockAgentService.setup(s => s.createJobSchedule(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createJobSchedule(undefined, TypeMoq.It.isAny())).returns(() => undefined);
mockAgentService.setup(s => s.createJobStep(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createJobStep(undefined, TypeMoq.It.isAny())).returns(() => undefined);
mockAgentService.setup(s => s.createOperator(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createOperator(undefined, TypeMoq.It.isAny())).returns(() => undefined);
mockAgentService.setup(s => s.createProxy(TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(() => TypeMoq.It.isAny());
mockAgentService.setup(s => s.createProxy(undefined, TypeMoq.It.isAny())).returns(() => undefined);
});
it('Create Job Data', async () => {
// should fail when ownerUri is null
let createJobResult = mockAgentService.object.createJob(null, TypeMoq.It.isAny());
should.strictEqual(createJobResult, undefined);
createJobResult = mockAgentService.object.createJob(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createJobResult, undefined);
mockJobData = TypeMoq.Mock.ofType<JobData>(JobData, TypeMoq.MockBehavior.Loose, false, [TypeMoq.It.isAnyString(), undefined, mockAgentService]);
});
it('Create Alert Data', async () => {
// should fail when ownerUri is null
let createAlertResult = mockAgentService.object.createAlert(null, TypeMoq.It.isAny());
should.strictEqual(createAlertResult, undefined);
createAlertResult = mockAgentService.object.createAlert(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createAlertResult, undefined);
});
it('Create Job Schedule Data', async () => {
// should fail when ownerUri is null
let createJobScheduleResult = mockAgentService.object.createJobSchedule(null, TypeMoq.It.isAny());
should.strictEqual(createJobScheduleResult, undefined);
createJobScheduleResult = mockAgentService.object.createJobSchedule(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createJobScheduleResult, undefined);
});
it('Create Job Step Data', async () => {
// should fail when ownerUri is null
let createJobStepResult = mockAgentService.object.createJobStep(null, TypeMoq.It.isAny());
should.strictEqual(createJobStepResult, undefined);
createJobStepResult = mockAgentService.object.createJobStep(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createJobStepResult, undefined);
});
it('Create Operator Data', async () => {
// should fail when ownerUri is null
let createOperatorResult = mockAgentService.object.createOperator(null, TypeMoq.It.isAny());
should.strictEqual(createOperatorResult, undefined);
createOperatorResult = mockAgentService.object.createOperator(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createOperatorResult, undefined);
});
it('Create Proxy Data', async () => {
// should fail when ownerUri is null
let createProxyResult = mockAgentService.object.createProxy(null, TypeMoq.It.isAny());
should.strictEqual(createProxyResult, undefined);
createProxyResult = mockAgentService.object.createProxy(testOwnerUri, TypeMoq.It.isAny());
should.notEqual(createProxyResult, undefined);
});
});

View File

@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path = require('path');
const testRunner = require('vscode/lib/testrunner');
const suite = 'Agent Tests';
const options: any = {
ui: 'bdd',
useColors: true,
timeout: 600000
};
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
options.reporter = 'mocha-multi-reporters';
options.reporterOptions = {
reporterEnabled: 'spec, mocha-junit-reporter',
mochaJunitReporterReporterOptions: {
testsuitesTitle: `${suite} ${process.platform}`,
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
}
};
}
testRunner.configure(options);
export = testRunner;

View File

@@ -1,110 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
export class TestAgentService implements azdata.AgentServicesProvider {
handle?: number;
readonly providerId: string = 'Test Provider';
// Job management methods
getJobs(ownerUri: string): Thenable<azdata.AgentJobsResult> {
return undefined;
}
getJobHistory(ownerUri: string, jobId: string, jobName: string): Thenable<azdata.AgentJobHistoryResult> {
return undefined;
}
jobAction(ownerUri: string, jobName: string, action: string): Thenable<azdata.ResultStatus> {
return undefined;
}
createJob(ownerUri: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.CreateAgentJobResult> {
return undefined;
}
updateJob(ownerUri: string, originalJobName: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.UpdateAgentJobResult> {
return undefined;
}
deleteJob(ownerUri: string, jobInfo: azdata.AgentJobInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
getJobDefaults(ownerUri: string): Thenable<azdata.AgentJobDefaultsResult> {
return undefined;
}
// Job Step management methods
createJobStep(ownerUri: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.CreateAgentJobStepResult> {
return undefined;
}
updateJobStep(ownerUri: string, originalJobStepName: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.UpdateAgentJobStepResult> {
return undefined;
}
deleteJobStep(ownerUri: string, jobInfo: azdata.AgentJobStepInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
// Alert management methods
getAlerts(ownerUri: string): Thenable<azdata.AgentAlertsResult> {
return undefined;
}
createAlert(ownerUri: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.CreateAgentAlertResult> {
return undefined;
}
updateAlert(ownerUri: string, originalAlertName: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.UpdateAgentAlertResult> {
return undefined;
}
deleteAlert(ownerUri: string, alertInfo: azdata.AgentAlertInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
// Operator management methods
getOperators(ownerUri: string): Thenable<azdata.AgentOperatorsResult> {
return undefined;
}
createOperator(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.CreateAgentOperatorResult> {
return undefined;
}
updateOperator(ownerUri: string, originalOperatorName: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.UpdateAgentOperatorResult> {
return undefined;
}
deleteOperator(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
// Proxy management methods
getProxies(ownerUri: string): Thenable<azdata.AgentProxiesResult> {
return undefined;
}
createProxy(ownerUri: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.CreateAgentOperatorResult> {
return undefined;
}
updateProxy(ownerUri: string, originalProxyName: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.UpdateAgentOperatorResult> {
return undefined;
}
deleteProxy(ownerUri: string, proxyInfo: azdata.AgentProxyInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
// Agent Credential method
getCredentials(ownerUri: string): Thenable<azdata.GetCredentialsResult> {
return undefined;
}
// Job Schedule management methods
getJobSchedules(ownerUri: string): Thenable<azdata.AgentJobSchedulesResult> {
return undefined;
}
createJobSchedule(ownerUri: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.CreateAgentJobScheduleResult> {
return undefined;
}
updateJobSchedule(ownerUri: string, originalScheduleName: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.UpdateAgentJobScheduleResult> {
return undefined;
}
deleteJobSchedule(ownerUri: string, scheduleInfo: azdata.AgentJobScheduleInfo): Thenable<azdata.ResultStatus> {
return undefined;
}
registerOnUpdated(handler: () => any): void {
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
src/**
out/**
tsconfig.json
extension.webpack.config.js
yarn.lock

View File

@@ -3,16 +3,19 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// localizable strings
//@ts-check
export const InvalidProvider = 'Provider is invalid';
'use strict';
/**
* Feature names
*/
export const RestoreFeatureName = 'restore';
export const BackupFeatureName = 'backup';
export const MssqlProviderId = 'MSSQL';
export const notebookModeId = 'notebook';
const withDefaults = require('../shared.webpack.config');
module.exports = withDefaults({
context: __dirname,
entry: {
extension: './src/extension.ts'
},
externals: {
'ms-rest': 'commonjs ms-rest',
'request': 'commonjs request'
}
});

View File

@@ -42,15 +42,15 @@
{
"id": "microsoft",
"icon": {
"light": "./out/account-provider/media/microsoft_account_light.svg",
"dark": "./out/account-provider/media/microsoft_account_dark.svg"
"light": "./resources/light/microsoft_account_light.svg",
"dark": "./resources/dark/microsoft_account_dark.svg"
}
},
{
"id": "work_school",
"icon": {
"light": "./out/account-provider/media/work_school_account_light.svg",
"dark": "./out/account-provider/media/work_school_account_dark.svg"
"light": "./resources/light/work_school_account_light.svg",
"dark": "./resources/dark/work_school_account_dark.svg"
}
}
],
@@ -104,8 +104,8 @@
"command": "azure.resource.connectsqldb",
"title": "%azure.resource.connectsqldb.title%",
"icon": {
"dark": "resources/dark/connect_to_inverse.svg",
"light": "resources/light/connect_to.svg"
"dark": "resources/dark/add_to_server_list_inverse.svg",
"light": "resources/light/add_to_server_list.svg"
}
}
],
@@ -156,17 +156,19 @@
"hasAzureResourceProviders": true
},
"dependencies": {
"adal-node": "^0.1.28",
"azure-arm-resource": "^7.0.0",
"azure-arm-sql": "^5.0.1",
"ms-rest": "^2.5.0",
"request": "2.88.0",
"vscode-nls": "^4.0.0"
},
"devDependencies": {
"@types/mocha": "^5.2.5",
"@types/node": "^8.0.24",
"@types/node": "^10.12.12",
"@types/request": "^2.48.1",
"mocha": "^5.2.0",
"should": "^13.2.1",
"typemoq": "^2.1.0",
"vscode": "^1.1.26"
"typemoq": "^2.1.0"
}
}

View File

@@ -10,8 +10,8 @@
"azure.resource.refresh.title": "Refresh",
"azure.resource.signin.title": "Sign In",
"azure.resource.selectsubscriptions.title": "Select Subscriptions",
"azure.resource.connectsqlserver.title": "Add to Servers",
"azure.resource.connectsqldb.title": "Connect",
"azure.resource.connectsqlserver.title": "Connect",
"azure.resource.connectsqldb.title": "Add to Servers",
"accounts.clearTokenCache": "Clear Azure Account Token Cache",

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 12H16V13H13V16H12V13H9V12H12V9H13V12ZM1 6V5H2V6H1ZM15 5V6H4V5H15ZM1 3V2H2V3H1ZM15 2V3H4V2H15Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 226 B

View File

@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1,.cls-2{clip-rule:evenodd;}.cls-2,.cls-5,.cls-7{fill:#fff;}.cls-3,.cls-5{fill-rule:evenodd;}.cls-4{clip-path:url(#clip-path);}.cls-6{clip-path:url(#clip-path-2);}</style><clipPath id="clip-path"><path class="cls-1" d="M11.5-15.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5-9v6h-1V-9a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1,2.53,2.53,0,0,0,.53.8,2.53,2.53,0,0,0,.8.53,2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath><clipPath id="clip-path-2"><path class="cls-2" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath></defs><title>connect_to_inverse</title><path class="cls-3" d="M11.5-15.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5-9v6h-1V-9a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1,2.53,2.53,0,0,0,.53.8,2.53,2.53,0,0,0,.8.53,2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-4"><rect x="-0.5" y="-23.92" width="17" height="26"/></g><path class="cls-5" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-6"><rect class="cls-7" x="-0.5" y="-5" width="17" height="26"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 12H16V13H13V16H12V13H9V12H12V9H13V12ZM1 6V5H2V6H1ZM15 5V6H4V5H15ZM1 3V2H2V3H1ZM15 2V3H4V2H15Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 228 B

View File

@@ -1 +0,0 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1,.cls-2{clip-rule:evenodd;}.cls-2,.cls-5,.cls-7{fill:#fff;}.cls-3,.cls-5{fill-rule:evenodd;}.cls-4{clip-path:url(#clip-path);}.cls-6{clip-path:url(#clip-path-2);}</style><clipPath id="clip-path"><path class="cls-1" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath><clipPath id="clip-path-2"><path class="cls-2" d="M11.5,21.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77,3.43,3.43,0,0,1-1.19.4v6h-1v-6a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,27.72a2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/></clipPath></defs><title>connect_to</title><path class="cls-3" d="M11.5,3V6.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77A3.43,3.43,0,0,1,8.5,10v6h-1V10a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05A3.4,3.4,0,0,1,4.5,6.5V3h1V0h1V3h3V0h1V3Zm-1,1h-5V6.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,8.8,2.45,2.45,0,0,0,8,9a2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-4"><rect x="-0.5" y="-5" width="17" height="26"/></g><path class="cls-5" d="M11.5,21.92v3.5a3.4,3.4,0,0,1-.23,1.24,3.48,3.48,0,0,1-.63,1.05,3.57,3.57,0,0,1-1,.77,3.43,3.43,0,0,1-1.19.4v6h-1v-6a3.39,3.39,0,0,1-1.2-.4,3.59,3.59,0,0,1-.95-.77,3.48,3.48,0,0,1-.63-1.05,3.4,3.4,0,0,1-.23-1.24v-3.5h1v-3h1v3h3v-3h1v3Zm-1,1h-5v2.5a2.45,2.45,0,0,0,.2,1A2.49,2.49,0,0,0,7,27.72a2.45,2.45,0,0,0,1,.2,2.42,2.42,0,0,0,1-.2,2.53,2.53,0,0,0,.79-.53,2.59,2.59,0,0,0,.54-.8,2.41,2.41,0,0,0,.2-1Z"/><g class="cls-6"><rect class="cls-7" x="-0.5" y="13.92" width="17" height="26"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as adal from 'adal-node';
import * as azdata from 'azdata';
import * as request from 'request';
@@ -12,7 +10,6 @@ import * as nls from 'vscode-nls';
import * as vscode from 'vscode';
import * as url from 'url';
import {
Arguments,
AzureAccount,
AzureAccountProviderMetadata,
AzureAccountSecurityTokenCollection,
@@ -29,17 +26,12 @@ export class AzureAccountProvider implements azdata.AccountProvider {
private static AadCommonTenant: string = 'common';
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _args: Arguments;
private _autoOAuthCancelled: boolean;
private _commonAuthorityUrl: string;
private _inProgressAutoOAuth: InProgressAutoOAuth;
private _isInitialized: boolean;
constructor(private _metadata: AzureAccountProviderMetadata, private _tokenCache: TokenCache) {
this._args = {
host: this._metadata.settings.host,
clientId: this._metadata.settings.clientId
};
this._autoOAuthCancelled = false;
this._inProgressAutoOAuth = null;
this._isInitialized = false;
@@ -54,8 +46,8 @@ export class AzureAccountProvider implements azdata.AccountProvider {
/**
* Clears all tokens that belong to the given account from the token cache
* @param {"data".AccountKey} accountKey Key identifying the account to delete tokens for
* @returns {Thenable<void>} Promise to clear requested tokens from the token cache
* @param accountKey Key identifying the account to delete tokens for
* @returns Promise to clear requested tokens from the token cache
*/
public clear(accountKey: azdata.AccountKey): Thenable<void> {
return this.doIfInitialized(() => this.clearAccountTokens(accountKey));
@@ -63,7 +55,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
/**
* Clears the entire token cache. Invoked by command palette action.
* @returns {Thenable<void>} Promise to clear the token cache
* @returns Promise to clear the token cache
*/
public clearTokenCache(): Thenable<void> {
return this._tokenCache.clear();
@@ -92,13 +84,13 @@ export class AzureAccountProvider implements azdata.AccountProvider {
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
let task = this.getAccessTokens(account, azdata.AzureResource.ResourceManagement)
.then(
() => {
return account;
},
() => {
account.isStale = true;
return account;
}
() => {
return account;
},
() => {
account.isStale = true;
return account;
}
);
rehydrationTasks.push(task);
}
@@ -321,10 +313,10 @@ export class AzureAccountProvider implements azdata.AccountProvider {
* Retrieves a token for the given user ID for the specific tenant ID. If the token can, it
* will be retrieved from the cache as per the ADAL API. AFAIK, the ADAL API will also utilize
* the refresh token if there aren't any unexpired tokens to use.
* @param {string} userId ID of the user to get a token for
* @param {string} tenantId Tenant to get the token for
* @param {string} resourceId ID of the resource the token will be good for
* @returns {Thenable<TokenResponse>} Promise to return a token. Rejected if retrieving the token fails.
* @param userId ID of the user to get a token for
* @param tenantId Tenant to get the token for
* @param resourceId ID of the resource the token will be good for
* @returns Promise to return a token. Rejected if retrieving the token fails.
*/
private getToken(userId: string, tenantId: string, resourceId: string): Thenable<adal.TokenResponse> {
let self = this;
@@ -346,9 +338,9 @@ export class AzureAccountProvider implements azdata.AccountProvider {
/**
* Performs a web request using the provided bearer token
* @param {TokenResponse} accessToken Bearer token for accessing the provided URI
* @param {string} uri URI to access
* @returns {Thenable<any>} Promise to return the deserialized body of the request. Rejected if error occurred.
* @param accessToken Bearer token for accessing the provided URI
* @param uri URI to access
* @returns Promise to return the deserialized body of the request. Rejected if error occurred.
*/
private makeWebRequest(accessToken: adal.TokenResponse, uri: string): Thenable<any> {
return new Promise<any>((resolve, reject) => {
@@ -363,7 +355,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
};
// Setup the callback to resolve/reject this promise
let callback = (error, response, body: { error: any; value: any; }) => {
const callback: request.RequestCallback = (error, response, body: { error: any; value: any; }) => {
if (error || body.error) {
reject(error || JSON.stringify(body.error));
} else {
@@ -433,6 +425,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
name: tokenResponse.userId,
displayInfo: {
accountType: accountType,
userId: tokenResponse.userId,
contextualDisplayName: contextualDisplayName,
displayName: displayName
},

View File

@@ -77,14 +77,14 @@ export class AzureAccountProviderService implements vscode.Disposable {
return Promise.all(promises)
.then(
() => {
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
},
err => {
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
});
() => {
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
},
err => {
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
});
}
private onDidChangeConfiguration(): void {

View File

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

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as adal from 'adal-node';
import * as azdata from 'azdata';
import * as crypto from 'crypto';
@@ -34,8 +32,8 @@ export default class TokenCache implements adal.TokenCache {
.then(cache => self.addToCache(cache, entries))
.then(updatedCache => self.writeCache(updatedCache))
.then(
() => callback(null, false),
(err) => callback(err, true)
() => callback(null, false),
(err) => callback(err, true)
);
});
}
@@ -70,8 +68,8 @@ export default class TokenCache implements adal.TokenCache {
);
})
.then(
results => callback(null, results),
(err) => callback(err, null)
results => callback(null, results),
(err) => callback(err, null)
);
});
}
@@ -79,7 +77,7 @@ export default class TokenCache implements adal.TokenCache {
/**
* Wrapper to make callback-based find method into a thenable method
* @param query Partial object to use to look up tokens. Ideally should be partial of adal.TokenResponse
* @returns {Thenable<any[]>} Promise to return the matching adal.TokenResponse objects.
* @returns Promise to return the matching adal.TokenResponse objects.
* Rejected if an error was sent in the callback
*/
public findThenable(query: any): Thenable<any[]> {
@@ -104,16 +102,16 @@ export default class TokenCache implements adal.TokenCache {
.then(cache => self.removeFromCache(cache, entries))
.then(updatedCache => self.writeCache(updatedCache))
.then(
() => callback(null, null),
(err) => callback(err, null)
() => callback(null, null),
(err) => callback(err, null)
);
});
}
/**
* Wrapper to make callback-based remove method into a thenable method
* @param {TokenResponse[]} entries Array of entries to remove from the token cache
* @returns {Thenable<void>} Promise to remove the given tokens from the token cache
* @param entries Array of entries to remove from the token cache
* @returns Promise to remove the given tokens from the token cache
* Rejected if an error was sent in the callback
*/
public removeThenable(entries: adal.TokenResponse[]): Thenable<void> {
@@ -138,7 +136,7 @@ export default class TokenCache implements adal.TokenCache {
&& entry1.resource === entry2.resource;
}
private static findByPartial(entry: adal.TokenResponse, query: object): boolean {
private static findByPartial(entry: adal.TokenResponse, query: { [key: string]: any }): boolean {
for (let key in query) {
if (entry[key] === undefined || entry[key] !== query[key]) {
return false;
@@ -186,8 +184,8 @@ export default class TokenCache implements adal.TokenCache {
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
try {
return <EncryptionParams>{
key: new Buffer(splitValues[0], 'hex'),
initializationVector: new Buffer(splitValues[1], 'hex')
key: Buffer.from(splitValues[0], 'hex'),
initializationVector: Buffer.from(splitValues[1], 'hex')
};
} catch (e) {
// Swallow the error and fall through to generate new params

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as azdata from 'azdata';
@@ -15,7 +13,6 @@ import * as constants from './constants';
* this API from our code
*
* @export
* @class ApiWrapper
*/
export class ApiWrapper {
// Data APIs
@@ -156,12 +153,6 @@ export class ApiWrapper {
return vscode.window.showSaveDialog(options);
}
public openTextDocument(uri: vscode.Uri): Thenable<vscode.TextDocument>;
public openTextDocument(options: { language?: string; content?: string; }): Thenable<vscode.TextDocument>;
public openTextDocument(uriOrOptions): Thenable<vscode.TextDocument> {
return vscode.workspace.openTextDocument(uriOrOptions);
}
public showTextDocument(document: vscode.TextDocument, column?: vscode.ViewColumn, preserveFocus?: boolean, preview?: boolean): Thenable<vscode.TextEditor> {
let options: vscode.TextDocumentShowOptions = {
viewColumn: column,
@@ -212,7 +203,7 @@ export class ApiWrapper {
return azdata.accounts.getAllAccounts();
}
public getSecurityToken(account: azdata.Account, resource: azdata.AzureResource): Thenable<{}> {
public getSecurityToken(account: azdata.Account, resource: azdata.AzureResource): Thenable<{ [key: string]: any }> {
return azdata.accounts.getSecurityToken(account, resource);
}

View File

@@ -3,8 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import { ApiWrapper } from './apiWrapper';

View File

@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
export function registerAzureResourceDatabaseCommands(appContext: AppContext): void {
appContext.apiWrapper.registerCommand('azure.resource.connectsqldb', async (node?: TreeNode) => {
if (!node)
{
if (!node) {
return;
}

View File

@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
export function registerAzureResourceDatabaseServerCommands(appContext: AppContext): void {
appContext.apiWrapper.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
if (!node)
{
if (!node) {
return;
}

View File

@@ -21,9 +21,9 @@ export class AzureResourceDatabaseServerService implements IAzureResourceDatabas
svrs.forEach((svr) => databaseServers.push({
name: svr.name,
fullName: svr.fullyQualifiedDomainName,
loginName: svr.administratorLogin,
defaultDatabaseName: 'master'
fullName: svr.fullyQualifiedDomainName,
loginName: svr.administratorLogin,
defaultDatabaseName: 'master'
}));
return databaseServers;

View File

@@ -5,7 +5,7 @@
'use strict';
import { ServiceClientCredentials } from 'ms-rest';
import { ServiceClientCredentials } from 'ms-rest';
import { azureResource } from '../../azure-resource';
import { AzureResourceDatabaseServer } from './models';

View File

@@ -17,10 +17,10 @@ export class AzureResourceCacheService implements IAzureResourceCacheService {
}
public generateKey(id: string): string {
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
}
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
}
public get<T>(key: string): T | undefined {
public get<T>(key: string): T | undefined {
return this._context.workspaceState.get(key);
}

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