mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 18:46:43 -05:00
Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1467cdd72 | |||
|
|
aaa9c4a744 | ||
|
|
989193645c | ||
|
|
5e04523635 | ||
|
|
eb3598f1a7 | ||
|
|
52bbb60def | ||
|
|
ab0ea5db62 | ||
|
|
ff042613d1 | ||
|
|
f70ff23ca5 | ||
|
|
32fa73f524 | ||
|
|
d3dd7d812f | ||
|
|
8b3ef369af | ||
|
|
f25b0530b9 | ||
|
|
e1694e5a30 | ||
|
|
587d31ab2c | ||
|
|
62959d565c | ||
|
|
63a78e62aa | ||
|
|
a3041f25b2 | ||
|
|
05b6593f58 | ||
|
|
8f232ae3e8 | ||
|
|
186f8d3771 | ||
|
|
c641865891 | ||
|
|
5ed263ecd2 | ||
|
|
cc148930c7 | ||
|
|
8a6f61c78d | ||
|
|
549464dab1 | ||
|
|
405122daeb | ||
|
|
86d0779c87 | ||
|
|
cc84a5e709 | ||
|
|
b54d12b2be | ||
|
|
b07fee5a5f | ||
|
|
883d5714cc | ||
|
|
94cdaf9d57 | ||
|
|
731dc6318f | ||
|
|
25cdb558a7 | ||
|
|
696cdc3200 | ||
|
|
c5e8ecd24b | ||
|
|
12da714803 | ||
|
|
131c288ab4 | ||
|
|
646b001160 | ||
|
|
9a1d823c69 | ||
|
|
efcf52f62c | ||
|
|
dce130c5af | ||
|
|
306eb42ae7 | ||
|
|
a612781638 | ||
|
|
a1f7bddb3a | ||
|
|
f7f5ee780a | ||
|
|
b79381d88e | ||
|
|
711db9cadc | ||
|
|
75deb08a2c | ||
|
|
ba3d16b63b | ||
|
|
64337310ae | ||
|
|
e5e535475a | ||
|
|
a63463e35b | ||
|
|
131b818450 | ||
|
|
b0ff2ef08e | ||
|
|
ebc7ef5a43 | ||
|
|
0bd0e14f71 | ||
|
|
abf11c36af | ||
|
|
86b3eaee5a | ||
|
|
f938b436b6 | ||
|
|
0d13bc4ed8 | ||
|
|
fda050e667 | ||
|
|
a73929e5e7 | ||
|
|
9c5ec7dcbc | ||
|
|
600f59eae6 | ||
|
|
7e39174f63 | ||
|
|
e0592c10d9 | ||
|
|
e6e6085d0d | ||
|
|
0513282081 | ||
|
|
b1bc59095b | ||
|
|
b6a67cfde7 | ||
|
|
a7b64c347a | ||
|
|
183c743537 | ||
|
|
e1f142b619 | ||
|
|
523dd8ad4b | ||
|
|
d9b5d71148 | ||
|
|
f7ac504a6c | ||
|
|
51ea238b49 | ||
|
|
c3b8c97b9d | ||
|
|
08ded51e75 | ||
|
|
4f155423dc | ||
|
|
df481311ed | ||
|
|
7e401bfa1a | ||
|
|
96c4257d25 | ||
|
|
75c59f8b41 | ||
|
|
41e7569fde | ||
|
|
89e41572a8 |
2
.github/respond-to-issue-based-on-label.yml
vendored
2
.github/respond-to-issue-based-on-label.yml
vendored
@@ -23,7 +23,7 @@ Needs Logs:
|
||||
# actions for Needs Logs - Azure label
|
||||
Needs Logs - Azure:
|
||||
comment: |
|
||||
We need more info to debug your Azure Active Directory issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
|
||||
We need more info to debug your Microsoft Entra ID issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
|
||||
|
||||
- In the settings menu, find the setting titled `Azure: Logging Level` and select the `Verbose` option
|
||||
- Restart Azure Data Studio
|
||||
|
||||
2
.github/workflows/bad-tag.yml
vendored
2
.github/workflows/bad-tag.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
if: github.event.ref == '1.999.0'
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: "microsoft/vscode-github-triage-actions"
|
||||
ref: stable
|
||||
|
||||
6
.github/workflows/basic.yml
vendored
6
.github/workflows/basic.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# TODO: rename azure-pipelines/linux/xvfb.init to github-actions
|
||||
- name: Setup Build Environment
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: actions/checkout@v4
|
||||
|
||||
# - uses: actions/setup-node@v3
|
||||
# with:
|
||||
|
||||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
CHILD_CONCURRENCY: "1"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# TODO: rename azure-pipelines/linux/xvfb.init to github-actions
|
||||
- name: Setup Build Environment
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
- name: Combine code coverage files
|
||||
run: node test/combineCoverage
|
||||
- name: Upload Code Coverage
|
||||
uses: coverallsapp/github-action@v2.2.1
|
||||
uses: coverallsapp/github-action@v2.2.3
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: "test/coverage/lcov.info"
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
@@ -236,7 +236,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/on-label.yml
vendored
2
.github/workflows/on-label.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
name: Process Label Action
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Process Label Action
|
||||
uses: hramos/label-actions@v2
|
||||
with:
|
||||
|
||||
2
.github/workflows/on-pr-open.yml
vendored
2
.github/workflows/on-pr-open.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'microsoft/azuredatastudio'
|
||||
ref: main
|
||||
|
||||
2
.github/workflows/telemetry.yml
vendored
2
.github/workflows/telemetry.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
steps:
|
||||
- uses: 'actions/checkout@v3'
|
||||
- uses: 'actions/checkout@v4'
|
||||
|
||||
- uses: 'actions/setup-node@v3'
|
||||
with:
|
||||
|
||||
2
.yarnrc
2
.yarnrc
@@ -1,4 +1,4 @@
|
||||
disturl "https://electronjs.org/headers"
|
||||
target "22.3.14"
|
||||
target "22.3.25"
|
||||
runtime "electron"
|
||||
build_from_source "true"
|
||||
|
||||
85
CHANGELOG.md
85
CHANGELOG.md
@@ -1,5 +1,88 @@
|
||||
# Change Log
|
||||
|
||||
## September 2023 (Hotfix 1)
|
||||
|
||||
Azure Data Studio 1.46.1 is the latest general availability (GA) release.
|
||||
|
||||
- Release number: 1.46.1
|
||||
- Release date: October 3, 2023
|
||||
|
||||
### Bug fixes in 1.46.1
|
||||
|
||||
| New Item | Details |
|
||||
| --- | --- |
|
||||
| Security | Update to Electron v22.3.25 with patch for [CVE-2023-5217](https://github.com/advisories/GHSA-qqvq-6xgj-jw8g) |
|
||||
|
||||
For details about the issue addressed in the September 2023 hotfix release, visit the [September 2023 Hotfix Release on GitHub](https://github.com/microsoft/azuredatastudio/milestone/106?closed=1).
|
||||
|
||||
For a list of the current known issues, visit the [issues list on GitHub](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue).
|
||||
|
||||
## September 2023
|
||||
|
||||
Azure Data Studio 1.46.0 is the latest general availability (GA) release.
|
||||
|
||||
- Release number: 1.46.0
|
||||
- Release date: September 20, 2023
|
||||
|
||||
### What's new in 1.46.0
|
||||
|
||||
| New Item | Details |
|
||||
| --- | --- |
|
||||
| Attach/Detach Database | Introduced support for attaching and detaching databases (Preview) |
|
||||
| Connection | Introduced support for custom cloud providers, see ([Azure Data Studio - Azure Connectivity](https://learn.microsoft.com/sql/azure-data-studio/azure-connectivity?#configuring-custom-cloud-endpoints)) for configuration information |
|
||||
| Connection | Enabled Connection Pooling as default behavior |
|
||||
| Connection | Introduced command `SQL Server: Clear Pooled Connections` to clear inactive pooled connections |
|
||||
| Database Properties | Introduced support for viewing database properties (Preview) |
|
||||
| General | Added support for Server and Database properties (Preview) |
|
||||
| Result Set | Updated copy notification to automatically close after three (3) seconds, and included an option to disable notifications |
|
||||
| Result Set | Added a prompt to open the file location after saving result to Excel |
|
||||
| Profiler Extension | Introduced a progress dialog when opening an XEL file |
|
||||
| Server Properties | Introduced support for viewing server properties (Preview) |
|
||||
| SQL Database Projects Extension | Released version 1.3.1 |
|
||||
| SQL Database Projects Extension | Added support for "Azure Synapse Serverless SQL Pool” target platform |
|
||||
| SQL Database Projects Extension | Added support for “Synapse Data Warehouse in Microsoft Fabric” target platform |
|
||||
| SQL Database Projects Extension | Updated to Microsoft.Build.Sql SDK version to 0.1.12-preview |
|
||||
|
||||
### Bug fixes in 1.46.0
|
||||
|
||||
| New Item | Details |
|
||||
| --- | --- |
|
||||
| Accessibility | Improved screen reader prompts for SQL Database Projects extension, Database Migration Assessment for Oracle extension, SQL Agent extension, and when installing a new extension |
|
||||
| Accessibility | Addressed issues with install button tool tip, new connection button, and new server group buttons |
|
||||
| Accessibility | Fixed color contrast for creating connections and notebooks, running queries, and deploying a server |
|
||||
| Connection | Added refresh prompt for Azure accounts when error AADSTS700082 occurs |
|
||||
| Connection | Introduced notification when a duplicate connection exists upon dragging a connection to a different group |
|
||||
| Connection | Fixed issue to prevent Dashboard server name from being replaced with profile name |
|
||||
| Connection | Added retry logic to wait for resume when establishing connection to a serverless Azure database |
|
||||
| Connection | Fixed issue where tab color did not align with server group color |
|
||||
| Connection | Updated Cluster Server connection property to have the correct Boolean value for Cosmos DB |
|
||||
| Connection | Fixed issue with advanced connection options not correctly transferred to change password dialog |
|
||||
| Connection | Addressed incorrect label for first connection in the Recent connections list |
|
||||
| Connection | Improved account selection experience after enabling cloud settings |
|
||||
| General | Fixed issue with incorrect cell colors when editing data |
|
||||
| General | Addressed problem with invalid data for a column's data type when editing data |
|
||||
| General | Re-enabled full screen toggle behavior for the F11 key binding |
|
||||
| Notebooks | Addressed issue where kernel failed to change correctly when switching to Python |
|
||||
| Query Editor | Fixed Intellisense refresh behavior |
|
||||
| Query Editor | Improved query execution performance |
|
||||
| Query Editor | Improved read performance for large data sets |
|
||||
| Query Editor | Addressed issue where selecting Cancel would not immediately cancel a query that was executing |
|
||||
| Query Editor | Resolved problem of queries hanging when executing against Synapse Dedicated Pool |
|
||||
| Query Plan Viewer | Fixed issue where missing index definition recommendation included incorrect column |
|
||||
| Query Plan Viewer | Addressed issue with query plan XML having the incorrect format |
|
||||
| Result Set | Corrected XML formatting when opening a column from the result set |
|
||||
| Result Set | Fixed issue where copying results to clipboard did not work |
|
||||
| Schema Compare | Added support to automatically resize the split view when the window changes size |
|
||||
| Schema Compare | Addressed error “StartIndex cannot be less than zero” which occurred when applying change using Schema Compare |
|
||||
| Schema Compare | Display 'Yes' button to re-compare after changing options in Schema Compare |
|
||||
| SQL Database Projects | Fixed issue where databases were not populated if a project was created from the server instead of a database |
|
||||
| SQL Database Projects | Addressed error 'Could not run the "SqlModelResolutionTask" task because MSBuild could not create or connect to a task host with runtime "NET" and architecture "arm64"' resulting in build failure on arm64 with SDK-style and legacy style projects |
|
||||
| Welcome Page | Improved display of Install button under the extension list on Welcome Page |
|
||||
|
||||
For a full list of bug fixes addressed for the September 2023 hotfix release, visit the [September 2023 Release on GitHub](https://github.com/microsoft/azuredatastudio/milestone/102?closed=1).
|
||||
|
||||
For a list of the current known issues, visit the [issues list on GitHub](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue).
|
||||
|
||||
## July 2023 (Hotfix)
|
||||
|
||||
Azure Data Studio 1.45.1 is the latest general availability (GA) release.
|
||||
@@ -27,8 +110,6 @@ For a full list of bug fixes addressed for the July 2023 hotfix release, visit t
|
||||
| --- | --- | --- |
|
||||
| Installation | Azure Data Studio installation fails on RHEL 8 | Use RHEL 9, or manually install glibc-2.29 and add it to the Library Path and then re-install ADS |
|
||||
|
||||
For a list of the current known issues, visit the [issues list on GitHub](https://github.com/microsoft/azuredatastudio/issues?q=is%3Aissue).
|
||||
|
||||
## July 2023
|
||||
|
||||
Azure Data Studio 1.45.0 is the latest general availability (GA) release.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[](https://dev.azure.com/ms/azuredatastudio/_build/latest?definitionId=453&branchName=main)
|
||||
[](https://twitter.com/azuredatastudio)
|
||||
|
||||
Azure Data Studio is a data management and development tool with connectivity to popular cloud and on-premises databases. Azure Data Studio supports Windows, macOS, and Linux, with immediate capability to connect to Azure SQL and SQL Server. Browse the [extension library](wiki/List-of-Extensions) for additional database support options including MySQL, PostgreSQL, and MongoDB.
|
||||
Azure Data Studio is a data management and development tool with connectivity to popular cloud and on-premises databases. Azure Data Studio supports Windows, macOS, and Linux, with immediate capability to connect to Azure SQL and SQL Server. Browse the [extension library](https://github.com/microsoft/azuredatastudio/wiki/List-of-Extensions) for additional database support options including MySQL, PostgreSQL, and MongoDB.
|
||||
|
||||
## **Download the latest Azure Data Studio release**
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
{
|
||||
"codebaseName": "devdiv_vscode-client",
|
||||
"codebaseName": "Azure Data Studio",
|
||||
"ppe": false,
|
||||
"notificationAliases": [
|
||||
"sbatten@microsoft.com"
|
||||
"kvhdir@microsoft.com",
|
||||
"sakshis@microsoft.com"
|
||||
],
|
||||
"codebaseAdmins": [
|
||||
"REDMOND\\stbatt",
|
||||
"REDMOND\\monacotools"
|
||||
"REDMOND\\karlb",
|
||||
"REDMOND\\chgagnon",
|
||||
"REDMOND\\kisantia",
|
||||
"REDMOND\\sakshis"
|
||||
],
|
||||
"instanceUrl": "https://devdiv.visualstudio.com/defaultcollection",
|
||||
"projectName": "DevDiv",
|
||||
"areaPath": "DevDiv\\VS Code (compliance tracking only)\\Visual Studio Code Client",
|
||||
"instanceUrl": "https://msdata.visualstudio.com",
|
||||
"projectName": "Database Systems",
|
||||
"areaPath": "Database Systems\\SQL Tools\\Azure Data Studio",
|
||||
"notifyAlways": true,
|
||||
"template": "TFSDEVDIV",
|
||||
"tools": [
|
||||
|
||||
@@ -25,6 +25,8 @@ steps:
|
||||
- script: |
|
||||
set -e
|
||||
tar -xzf $(Pipeline.Workspace)/compilation.tar.gz
|
||||
# delete tar.gz after it's been extracted to clear up the space
|
||||
rm $(Pipeline.Workspace)/compilation.tar.gz
|
||||
displayName: Extract compilation output
|
||||
|
||||
- script: |
|
||||
|
||||
@@ -9,7 +9,7 @@ steps:
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '3.x'
|
||||
versionSpec: '3.11.x'
|
||||
addToPath: true
|
||||
|
||||
- task: AzureKeyVault@1
|
||||
@@ -41,12 +41,23 @@ steps:
|
||||
exec { git config --global https.postBuffer 524288000 }
|
||||
displayName: Prepare tooling
|
||||
|
||||
- task: CodeQL3000Init@0
|
||||
displayName: CodeQL Initialize
|
||||
condition: eq(variables['Codeql.enabled'], 'True')
|
||||
|
||||
- powershell: |
|
||||
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||
git fetch distro
|
||||
git merge $(node -p "require('./package.json').distro")
|
||||
displayName: Merge distro
|
||||
|
||||
- powershell: |
|
||||
git remote add distro "https://github.com/$(VSCODE_MIXIN_REPO).git"
|
||||
git fetch distro
|
||||
git merge ab87de2203e5a9d8377a74725dc6e2258de6da79
|
||||
condition: eq(variables['VSCODE_QUALITY'], 'agc')
|
||||
displayName: Merge AGC endpoints
|
||||
|
||||
- powershell: |
|
||||
. build/azure-pipelines/win32/exec.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -135,6 +146,19 @@ steps:
|
||||
displayName: Install SAW Extensions
|
||||
condition: and(succeeded(), eq(variables['VSCODE_QUALITY'], 'saw'), ne(variables['VSCODE_ARCH'], 'arm64'))
|
||||
|
||||
- powershell: |
|
||||
# Install AGC specific extensions
|
||||
$ErrorActionPreference = "Stop"
|
||||
$tempFilePath = (New-TemporaryFile).FullName
|
||||
$zipFilePath = $tempFilePath + ".zip"
|
||||
$extensionUri = "$(agc-extensions-uri)"
|
||||
$adsExtensionPath = "$(agent.builddirectory)\azuredatastudio-win32-x64\resources\app\extensions"
|
||||
Invoke-WebRequest -Uri $extensionUri -OutFile $tempFilePath
|
||||
Move-Item $tempFilePath $zipFilePath
|
||||
Expand-Archive $zipFilePath -DestinationPath $adsExtensionPath
|
||||
displayName: Install AGC Extensions
|
||||
condition: and(succeeded(), eq(variables['VSCODE_QUALITY'], 'agc'), ne(variables['VSCODE_ARCH'], 'arm64'))
|
||||
|
||||
# - powershell: | @anthonydresser unit tests timeout never existing the node process
|
||||
# . build/azure-pipelines/win32/exec.ps1
|
||||
# $ErrorActionPreference = "Stop"
|
||||
@@ -344,6 +368,10 @@ steps:
|
||||
continueOnError: true
|
||||
condition: and(succeededOrFailed(), eq(variables['RUN_UNSTABLE_TESTS'], 'true'))
|
||||
|
||||
- task: CodeQL3000Finalize@0
|
||||
displayName: CodeQL Finalize
|
||||
condition: eq(variables['Codeql.enabled'], 'True')
|
||||
|
||||
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
|
||||
displayName: 'Component Detection'
|
||||
inputs:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -92,21 +92,24 @@ async function main(buildDir?: string): Promise<void> {
|
||||
'-insert',
|
||||
'NSAppleEventsUsageDescription',
|
||||
'-string',
|
||||
'An application in Visual Studio Code wants to use AppleScript.',
|
||||
// ${{SQL CARBON EDIT}} Update application name to Azure Data Studio
|
||||
'An application in Azure Data Studio wants to use AppleScript.',
|
||||
`${infoPlistPath}`
|
||||
]);
|
||||
await spawn('plutil', [
|
||||
'-replace',
|
||||
'NSMicrophoneUsageDescription',
|
||||
'-string',
|
||||
'An application in Visual Studio Code wants to use the Microphone.',
|
||||
// ${{SQL CARBON EDIT}} Update application name to Azure Data Studio
|
||||
'An application in Azure Data Studio wants to use the Microphone.',
|
||||
`${infoPlistPath}`
|
||||
]);
|
||||
await spawn('plutil', [
|
||||
'-replace',
|
||||
'NSCameraUsageDescription',
|
||||
'-string',
|
||||
'An application in Visual Studio Code wants to use the Camera.',
|
||||
// ${{SQL CARBON EDIT}} Update application name to Azure Data Studio
|
||||
'An application in Azure Data Studio wants to use the Camera.',
|
||||
`${infoPlistPath}`
|
||||
]);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -16,6 +16,7 @@ import * as fancyLog from 'fancy-log';
|
||||
import * as ansiColors from 'ansi-colors';
|
||||
import * as iconv from '@vscode/iconv-lite-umd';
|
||||
import { l10nJsonFormat, getL10nXlf, l10nJsonDetails, getL10nFilesFromXlf, getL10nJson } from '@vscode/l10n-dev';
|
||||
import { aliasStrings } from './vscodeLocStringAlias'; // {{SQL CARBON EDIT}} - Needed to store aliased strings.
|
||||
|
||||
function log(message: any, ...rest: any[]): void {
|
||||
fancyLog(ansiColors.green('[i18n]'), message, ...rest);
|
||||
@@ -904,6 +905,28 @@ export function createI18nFile(name: string, messages: any): File { // {{SQL CAR
|
||||
'Do not edit this file. It is machine generated.'
|
||||
];
|
||||
for (const key of Object.keys(messages)) {
|
||||
// {{SQL CARBON EDIT}} - Temporarily used to handle aliased ids from vscode-translations-export - https://github.com/microsoft/azuredatastudio/issues/24411
|
||||
let areaList = messages['contents'];
|
||||
if (name.startsWith('extensions/') && key.startsWith('contents') && areaList) {
|
||||
for (const areaKey of Object.keys(areaList)) {
|
||||
let stringList = messages['contents'][areaKey];
|
||||
for (const stringKey of Object.keys(stringList)) {
|
||||
let shortName = name.substring(11); //remove 'extensions/' (size 11) from name to get extension name by itself.
|
||||
let keyAlias = aliasStrings as StringMap<StringMap<string>>
|
||||
// '++CODE++' comes from @vscode/l10n-dev/dist/main.js#L358 which replaces any id that is the same as the string message.
|
||||
if (stringKey.startsWith('++CODE++') && keyAlias[shortName]) {
|
||||
let shortBundleKey = stringKey.substring(8); //remove '++CODE++' (size 8) and only use hash to lookup.
|
||||
let aliasKey = keyAlias[shortName][shortBundleKey];
|
||||
if (aliasKey) {
|
||||
let originalMessage = messages['contents'][areaKey][stringKey];
|
||||
messages['contents'][areaKey][stringKey] = undefined;
|
||||
messages['contents'][areaKey][aliasKey] = originalMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// {{SQL CARBON EDIT}} - End
|
||||
result[key] = messages[key];
|
||||
}
|
||||
|
||||
|
||||
324
build/lib/vscodeLocStringAlias.js
Normal file
324
build/lib/vscodeLocStringAlias.js
Normal file
File diff suppressed because one or more lines are too long
321
build/lib/vscodeLocStringAlias.ts
Normal file
321
build/lib/vscodeLocStringAlias.ts
Normal file
@@ -0,0 +1,321 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const aliasStrings = {
|
||||
"Microsoft.data-workspace": {
|
||||
'60dc6b3745804caa2d48a35dbb7306bb3f4f05286e7f9de259423f6abe87ec8f': "SelectProjectFileAction"
|
||||
},
|
||||
"Microsoft.query-store": {
|
||||
'9cb725c039170871de7978892c2fdf0f763f58359bd66bd0b1a06b0bdf3f6b38': "DOPLabel",
|
||||
'17bc05152f339d6dc2fb2844595760e9009662c4315fa1ac0d61c7e47dfbdbb3': "UTC"
|
||||
},
|
||||
"Microsoft.sql-database-projects": {
|
||||
'99c40ab405926cb5ad1def9cff4d7ce624f8f8abfff4e85f655347fcb949d08e': "Date",
|
||||
'031a8f0f659df890dfd53c92e45295b0f14c997185bae46e168831e403b273f7': "Failed",
|
||||
'6ecc3df6bffdd06c58cd4f6e276929e119c8f653c53f5a6a5a5e66dfa1c3fc93': "Move",
|
||||
'920e413c7d411b61ef3e8c63b1cb6ad058d5f95f8b481dbafe60248387d8c355': "Status",
|
||||
'c88a0b907419a70c27ab7c1f8e5fb54441a4d9c3567e4c928fa7b2091194aecf': "Success",
|
||||
'33b93476cf597a3330653b66a658983d892ac264b5d6029a2dc642b9b1f30870': "Time",
|
||||
'b1d6b91b67c2afa5e322988d9462638d354ddf8a1ef79dba987f815c22b4baee': "at",
|
||||
'37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f': "default",
|
||||
'3f3427aca58e7fc32ec5cbdb6672708a22cf47187860405366a7c07144c668d9': "fileObject",
|
||||
'eb0cc5d4abfad6f62ea7a9c502352824ac2f6a263ef9c8b96b795df59f8f6870': "folderObject",
|
||||
'1b52f3a2e15148731314bf167145c54565ed2385a862b5eb7771eaf719e4f82e': "hr",
|
||||
'1f6fa6f69d185e6086d04e7330361bf9001a3b8d0ce511171055dc34eb90c1c5': "min",
|
||||
'b2c1822878838eb52770e9845b4582d503d975b484897b83048ea841e0c5c6b6': "msec",
|
||||
'add93534eeb463800fe0ed0946048d33636dd2a014fab92e8a37f77ce98c740b': "sec"
|
||||
},
|
||||
"vscode.git": {
|
||||
'a93447605ef4b2cc8eda934a1e9af7ad57f8d2d2e5dc1defbaa121ed13550e57': "$(info) Remote \"{0}\" has no tags.",
|
||||
'd33636398d4d33c00d489b6b7a46b224e0b779fcf33fd6c3e3d6e40c2933373a': "$(info) This repository has no tags.",
|
||||
'96ab5dc0020f2126bcb175ec9f0fe83b01c1b357fd2a9f0a3afc3d1f2860ee85': "\"{0}\" has fingerprint \"{1}\"",
|
||||
'59dacc1ec703cf2cd4c3f087ed4ff2d7da089b9634de61200779a5007bac6af0': "A branch named \"{0}\" already exists",
|
||||
'621321bc491d0f5f5702b38ee93f4b2f0b07bb9f72e3c1ad3ce06ce6b0f06219': "A git repository was found in the parent folders of the workspace or the open file(s). Would you like to open the repository?",
|
||||
'1da1a00fd75ac0a5f8e6d1c1649dec3b58f5c987faaffe73078f7296a636312f': "Absolute paths not supported in \"git.scanRepositories\" setting.",
|
||||
'6fa5252bce4290bcd9ff56fe10025f8bdfc5d4e24691f6fa68f27ed431c063a2': "Add Remote",
|
||||
'060c966a30504cab8cdc4cd05de72451e3a644e0bfe14080fc49722e00e93f75': "Add a new remote...",
|
||||
'd5eca92389f946b04241308e4a3b9b92fc39429ee9348a6c24448dc1a4b24c6f': "Add remote from URL",
|
||||
'd6641e7833cbdcd1456edcd6d584a99f9d005f5cd0b4c8bbcbf18099e680f089': "Add remote from {0}",
|
||||
'de161ac4087726413ce474f53279a95dc36167a2274bb58721f8720b87bfd611': "Add to Workspace",
|
||||
'b9f653e0e3af44de571212f85ec3f499df207e29bd1f28ab02cb527899690926': "All Repositories",
|
||||
'de9f057a471cdb8d3b082719bdc7ad2031788d042947349723fa83c9d13a517a': "Always",
|
||||
'2c707611079d56814a3db49f113e4b83c4825cc85ed4a25ec42c3d93196a4b0b': "Always Pull",
|
||||
'4d9f6cfd4b0c13b17c73c16f9ad939310ef950e9e6d5a20ecf0a24663669d8be': "Are you sure you want to DELETE {0} files?\\nThis is IRREVERSIBLE!\\nThese files will be FOREVER LOST if you proceed.",
|
||||
'405467178639c4f62d3a56a1ae70edb4b6a2526bcc4f3dbc8ee8b34e5f49e6c0': "Are you sure you want to DELETE {0}?\\nThis is IRREVERSIBLE!\\nThis file will be FOREVER LOST if you proceed.",
|
||||
'46d379e48de8077187857870eaed5866f00e7d88fee7d4f6ab609ca34912c244': "Are you sure you want to continue connecting?",
|
||||
'ffb8582a7ae040adfcc7adbee5a8207a55754268d09fa3b06b21a86c0893b609': "Are you sure you want to create an empty commit?",
|
||||
'ec1000557d338870dea0e872589afc8fd1758ab4bf53a9fa2721bc8ec9a3261e': "Are you sure you want to discard ALL changes in {0} files?\\nThis is IRREVERSIBLE!\\nYour current working set will be FOREVER LOST if you proceed.",
|
||||
'2169b04f53a8d7b7c06071bc23579d940de5187c1f3e3df2dd4bbf9724f1e4e3': "Are you sure you want to discard changes in {0} files?",
|
||||
'f8a5199a5d46ea80a9e9b2626e8181906ca21c5a37e2425379945161e76f6a6f': "Are you sure you want to discard changes in {0}?",
|
||||
'6f875b4f8d4f7d28e6dc570891696be992d21c501c1d04ae0a91adb407418b9d': "Are you sure you want to drop ALL stashes? There are {0} stashes that will be subject to pruning, and MAY BE IMPOSSIBLE TO RECOVER.",
|
||||
'24ab570db1c20d8c4ec76c5a64104f95d1ddff931a4194f0c0f975a22a5df50d': "Are you sure you want to drop ALL stashes? There is 1 stash that will be subject to pruning, and MAY BE IMPOSSIBLE TO RECOVER.",
|
||||
'76f1fe23e2bbf8ac3061a3fdd5bd60802fcf476e1b2ee914f93825bd1b0faf70': "Are you sure you want to drop the stash: {0}?",
|
||||
'32961fc63b06971d43dae40be139f80907bbbff6767b9b2f49269adc85416813': "Are you sure you want to restore {0} files?",
|
||||
'c88929a2d06f38f89607f487372203d45323cf7b8af3ccaedcb18de0e25f4e1a': "Are you sure you want to restore {0}?",
|
||||
'329f9a037f3c5a986261e6a6e542e87bfa0ee72b98c08c0345a67fbe360f935c': "Are you sure you want to stage {0} files with merge conflicts?",
|
||||
'd0d9c64e1041439f769f99f8c2e321f3c0448095a9d175f2dbb9a422e0de437f': "Are you sure you want to stage {0} with merge conflicts?",
|
||||
'fca24e51f77ed30ee8b875dba3000717e817f65dacb9130a9b1f1dffe8fdc679': "Ask Me Later",
|
||||
'06f6bb7108ffdb5caf844b4538b5ec8f44cc1b3bc6b577624d32fc57eff9fe3f': "Branch name",
|
||||
'69c5b417453bbe27e9b739db7bbb93c3ee3b7a3698a808d28fa6115e685c36f7': "Branch name needs to match regex: {0}",
|
||||
'fc84c23a4b9614dda0c2bff6659a5b1fdd3d211de84fe26b42e79efc1d95dcef': "Can\\'t push refs to remote. Try running \"Pull\" first to integrate your changes.",
|
||||
'9409f5afddffd4a93106de025d9682aecf16664dea804f2e6401b8464a5584dc': "Can\\'t undo because HEAD doesn\\'t point to any commit.",
|
||||
'bbd4b6a86bc65b6ac8e79e97afc61499158edb40f7bb404c70637b46d80a7ad2': "Changes",
|
||||
'c393643a0d2b8afb59b5368249e1aa94ac44dbd6aab25347a4c8788acf7065a1': "Checking Out Branch/Tag...",
|
||||
'06c1c85316f574170dfd57c5f7fde4af263c41616826fe806c2e032cc4ffed0a': "Checking Out Changes...",
|
||||
'870cef993507d1e51e03f108fccd4ba158542d9d3617e0d6065fa9ff2957fea8': "Checkout Branch/Tag...",
|
||||
'3de23bd5c86856018b0b9b70b96e257b66c8efce795c7864e6a68c779464b25e': "Checkout detached...",
|
||||
'ef12959262a90a02838d73d524e3dae6a0271a013f2017051508ce526016175d': "Choose Folder...",
|
||||
'339efbb5f4e6a1cb79b21d625f068b11022acd5e37857d396d4d2a5fa5fce451': "Choose a folder to clone {0} into",
|
||||
'61cc7bd271a5a5b8784320285c1920a502420a5bef95f8a159323ddd4064a820': "Choose a repository",
|
||||
'f0b79e95174d85877c16dd82f0c4d4d6f36a31c31c4b47419039da94dbd22ddd': "Choose which repository to clone",
|
||||
'd425c4cb46b4dbd6b73ee7bc369b63795cefbe0702c041f581fc0be71739c4b5': "Clone from URL",
|
||||
'58987b3663ca5a076846d352605196819f81c5e118d93937d9480b26520120d7': "Clone from {0}",
|
||||
'dc4a4db67704a975c2d0d65338d136d6f9ad7336dec08ffe2dac1e42b42f21d0': "Cloning git repository \"{0}\"...",
|
||||
'82a9c46ffa4789945d9f2359d75891558ef6faa8dee09e4b25e4e0597704f5bd': "Commit",
|
||||
'd0018212c7ec56f7dec88df64cea48c03cd22fb7294f5a731061fb6fe037c171': "Commit & Push Changes",
|
||||
'8ee870c3b9de2b0f27c0b858a94a0d8b6e605caf6c1a481c5ee1fe1cafd73cd5': "Commit & Sync Changes",
|
||||
'6ead59e71e458fb4011c59193f4aca9b0c9aa84ae5be108386fbbf1527973788': "Commit Anyway",
|
||||
'749e00cf6618bc6ef3d0fbe34d822881466a634f5c7b85d166df2fb1460f0056': "Commit Changes",
|
||||
'f1902e6bba725c6d3fcf51683aabc4686fb2a0f0dd682e1d6a9adf32fa0441d9': "Commit Changes on \"{0}\"",
|
||||
'2a8cf21232f60e18a2463520f642e8744cbb02e52bf28da24679207e4302b447': "Commit Changes to New Branch",
|
||||
'cb039e43bfd1824728db88aee47282a1362819ca8ccbfec5b311ee5af0e89760': "Commit Hash",
|
||||
'ed1fdf6e6ca057297a99375eca0f051f9ffbec49a1767e2126918b24e1350dff': "Commit Staged Changes",
|
||||
'26306d203c4a6f1a77f32cd065d7d11593ba0c7a9b5c52c188b98f22b620941f': "Commit message",
|
||||
'853333402637451d6aa3b25ece807151fc432e65654ef1a92683c08d2f469a08': "Commit operation was cancelled due to empty commit message.",
|
||||
'c561966032532f5cb4e661520907ce9195227eab5a7a8502ed432c65d2cec33c': "Commit to New Branch & Push Changes",
|
||||
'3807b76456b337798395543fd7f71add47058cc837ec3ce97557869b96a5a178': "Commit to New Branch & Synchronize Changes",
|
||||
'c5803c644368982b5ba18930ba87da76d777035a01c0404d0a738689513da3c1': "Commit to a New Branch",
|
||||
'd713d959ee6b9ef81c29bf51aa9a1e02cd00557b1d256630a191495aef81788b': "Commits without verification are not allowed, please enable them with the \"git.allowNoVerifyCommit\" setting.",
|
||||
'222889674324947cdb3d7362d9c932658d6035ca96fa1b2d03e8243c2a494ebe': "Committing & Pushing Changes...",
|
||||
'0670568e2bce6ac7ba3dd75805187f7e4b7bf4660f663ce69edc04bcddaa6b79': "Committing & Synchronizing Changes...",
|
||||
'094f485ef9934983ca0d9a7980a869fbf0b1cdc609a840d1eb2f0a13dacd8c11': "Committing Changes to New Branch...",
|
||||
'e00dcd402be4da03cd33575153acf4ae2f39273fecefe7c78f13b743f4ca887a': "Committing Changes...",
|
||||
'7e9af1cefa5907c0ad11ae3d77a1116494026ffc9419dc3f9d51eee1e5c0f87c': "Committing to New Branch & Pushing Changes...",
|
||||
'c1de8d4fc91a72a414f95fb6e7ddaa42e846c3862560e6ad81ec2508c9c95542': "Committing to New Branch & Synchronizing Changes...",
|
||||
'26727a77b60784d2907788f4dcd2c528470f39420c7d89cf6b2fb7017bd0d973': "Conflict: Added By Them",
|
||||
'e60a6686b1c40266a21a7fb54613a90683e298c8373488c8c9b09b9b696e7dc6': "Conflict: Added By Us",
|
||||
'cf655e271c68cfa38a63d55a83b3f244fdf668f6102a8b2f7dedb774e1a53fcd': "Conflict: Both Added",
|
||||
'90a447188c3e8f03122432f6eadb32a86a3d3f2a7bfe47973c5268a43cfa482b': "Conflict: Both Deleted",
|
||||
'9b10e40394e51ee85ee978d10dcd4e39508bc7b7dbfaca0ff1c0fb1d34a4f48b': "Conflict: Both Modified",
|
||||
'a7f3173b4ff7b9d91eeae6f949c39727b52e7620a66d6f4335335fc762506332': "Conflict: Deleted By Them",
|
||||
'313cc973de4d5d23fd082327d53acce5fc69559e3a717dbac4fde62c7033f1bf': "Conflict: Deleted By Us",
|
||||
'c38d012d028807fe8d3ac2fbc2fc2458388aeae57372a45be95c4357f48d3c34': "Continue Rebase",
|
||||
'416df53dc1046300db7c7db89015858f86d148ea5e66f0152592e046c04a100d': "Continuing Rebase...",
|
||||
'c5422e509267a427656ce69d6d0aed53ffcfe5eb313def9a960db7cb5b8c9c4d': "Could not clone your repository as Git is not installed.",
|
||||
'978fa11dc34a758c8d99fce0d36a97740cb8abe19bd39a1be049b57bb9a98e57': "Create Empty Commit",
|
||||
'fb35e61360cb5fe2fbdef3c15a4ac4ae3edd46fc19913a84305f8e128b441c3d': "Create new branch from...",
|
||||
'3c198f713861e91b8d3bf53ff23b4fd65849b602ba85b3e2397b09aa65597b61': "Create new branch...",
|
||||
'e0d1b68224bf0b31ef16b206c65b5f8f6b89d18161f4a7cdcb8d0ac8d952549a': "Current",
|
||||
'd2c753607fd4607a83f71c14f48c474f08562ccb59c23e8799cfebaa2d15c655': "Current commit message only contains whitespace characters",
|
||||
'06da38448937c5ca3cf8a9a4e91edb8a50fcfb20885e7d93d5019bf591fdc5c0': "Delete Branch",
|
||||
'e1e5fe2043bd3003147a785a42a5edddccbf57d465ca32ad0f033cf7b64f04c8': "Delete File",
|
||||
'93617a8503951c38871d9a8a3152d84ff1671eb5dfe9c240595b24ec55c4492e': "Delete Files",
|
||||
'28e18dc9db382d81d5c2e056abe2655575404a55828822b0757419101a346de2': "Delete file",
|
||||
'b48ff39c2e0f5451b9b29b09c2a74d2760db230749ffd48a6e901cc91fef9a8d': "Deleted",
|
||||
'ecf1d885169c7d720890312e456270950a4fb8436c6c29132559f44398a81641': "Discard 1 File",
|
||||
'92cbd25a58021e00fde8fe8247b6a62746304c19327ce600b1e3408922d43c10': "Discard 1 Tracked File",
|
||||
'da0cd4de5d64172a4fffefb1068f8644fb1c91e7247d3ad433f2d6b98a2d1a90': "Discard All {0} Files",
|
||||
'e07e053c2e10b3f1b6aef657d937cd91d45df4e40242788d7d621faea3380c27': "Discard Changes",
|
||||
'0208f13819883488a07422dacea98808be6cea4cc2e67d5e52b6c3ca33a95113': "Discard {0} Tracked Files",
|
||||
'ff334811c3daeb430bf1fc25d912064178fbd14eab61e156e8c1c08bc8e7d8ce': "Don\\'t Pull",
|
||||
'acfa223353d8377425be54cf045adeac692b65ffd91850a365d508179cb64ac5': "Don\\'t Show Again",
|
||||
'64488bcdbc42e52d74ab9bb817297e8e3c66c04011677d381ca0428664bb5f03': "Download Git",
|
||||
'969ccbd3cf6300ecd5c880459d81ae9027df7517563184a1b8b15282db230621': "Email",
|
||||
'f9e38e00f92b08ea1873eb83b3a80656bca1da49a4b862e70d1a34d654a052dd': "Failed to authenticate to git remote.",
|
||||
'f4154fae85d6442f7aa7a5d154396ecb33eedeb2a5b2b66927e0e5caf5d208fb': "Failed to authenticate to git remote:\\n\\n{0}",
|
||||
'6a66e0c4a1187c2d6f73bfdcb24f18ae955a7605966123ca96e3de6867ab2630': "File \"{0}\" was deleted by them and modified by us.\\n\\nWhat would you like to do?",
|
||||
'46d6d9362c923eaebd6cee4e18bd246f1da95871cf454e96d99d989d2be68cca': "File \"{0}\" was deleted by us and modified by them.\\n\\nWhat would you like to do?",
|
||||
'c801735bdcbaef47f4f9fdc4e6db3ef65f65738dd91850477f7a4c89d4b5b60b': "Force Checkout",
|
||||
'dea241f37f7b03284af862a9376f0b02d561af0bcaa05f80bec1226bc26c8bca': "Force push is not allowed, please enable it with the \"git.allowForcePush\" setting.",
|
||||
'a39de9d1a73052f9e82004d14cd2ac6cf1a4da3f959a50b5f5a7a9507c094ef8': "Git History",
|
||||
'6030c83165fb700fcca51c74a9940aeefaf8084c612f5b57eea3723737c5f57d': "Git error",
|
||||
'0b6123eb22cd4cf46d32366cda6edad66e902cb5f5865aa4c2a93697a497ca11': "Git local working changes",
|
||||
'6a29332d3557881b20eb99f45dcbce35edccdb3f47128fbf67b1795e1b8c75c9': "Git repositories were found in the parent folders of the workspace or the open file(s). Would you like to open the repositories?",
|
||||
'854b5b2f0c2de71cd9efe57794a6f669b49e3d554ba7c7c175d78154d2bd28c9': "Git: {0}",
|
||||
'0c3b2f01bfd0bbe594a1e89ebf29c9ba17e93abd909f66330bf0ab7320d2b482': "HEAD version of \"{0}\" is not available.",
|
||||
'7d648f5b47f34afb32946011a07e32176ad966f44ad9efff8380c73dfc5c5b87': "Ignored",
|
||||
'e301820ac83931005088b32674481b184df58276cd0e79f0c8c8f7615dc023a6': "Incoming",
|
||||
'4bc49b7e3107933d6c3033c90e34518e26bf9af94ce830042b13eee60f0134d6': "Index Added",
|
||||
'39520d0f752236ebe985a9ab539075bb3961e0b2b3d54494689e724aa460dbc7': "Index Copied",
|
||||
'606a5aedaa4178761d620b63ca8f7ddabd6cc481415cdbf64bc952f6a3d6fc8b': "Index Deleted",
|
||||
'26f13b9c8050f9ac86037d900a1aa7e429efa319836c75edcb5eb0857a1da984': "Index Modified",
|
||||
'0fab3d719bfe30418fa5b3301a3d2ea05178de4451bfe358cad5fc22ebdad0e6': "Index Renamed",
|
||||
'905dd9958f630cdc089ae37a56c186841863cb5192c59c886dede1fa4eba71ed': "Initialize Repository",
|
||||
'da5494fdeba5f3b5e1dd5b73c79aeab8c5d28830990fa85d01210710cfc805d5': "Intent to Add",
|
||||
'93c86a252e562f412c0322b6348bae591b3c1fe7f09460fb40083f9ec8011981': "Intent to Rename",
|
||||
'96fb1f951270c90a70612cc71ad71290be1afd46011b51131a4954b898d66dcf': "Invalid branch name",
|
||||
'cd20f59f1dd9f869d17a79e25727c8fb29fa0fb4514d93857985bde8ea3d0c8a': "It looks like the current branch \"{0}\" might have been rebased. Are you sure you still want to pull into it?",
|
||||
'5d5cabe4050fdd7a47b6188df4bb4137acc7d06474495edcfa62d7a8fc4aad70': "It looks like the current branch might have been rebased. Are you sure you still want to pull into it?",
|
||||
'59666b50ef3b41a833f9d754d1880bfcdc934fe14df5930556c87663f39d7de9': "It\\'s not possible to change the commit message in the middle of a rebase. Please complete the rebase operation and use interactive rebase instead.",
|
||||
'60c138e94a1d502e1392e9ca62e5393e93e280a7f28e4f5a3ff4a575d56c388b': "Keep Our Version",
|
||||
'e9f8f78f902c9e4bbe0a5c91eb57172bbc53f6698bb4521006df79aa6b280dbe': "Keep Their Version",
|
||||
'8d8cd546b58d91c300d3149ef40b8d98d3061dc38f15ea937d2ed785a3f25771': "Learn More",
|
||||
'e3e4bd64cdeb80cce6901d2b155f16e51b36db5d01952c893be3e7fa3eb1b094': "Log level: {0}",
|
||||
'fa0f601f537c892e522505a224c5996f94857505214c507f5745273c327b3333': "Make sure you configure your \"user.name\" and \"user.email\" in git.",
|
||||
'4eaae38d7115a0c0cb42e2c87cc2043f6897eab74e688450588c109cbb2496ed': "Manage Unsafe Repositories",
|
||||
'c08f87c6bf2a44ca177005eb990385dde9b14cc5289bc4420a45c199ec474e90': "Merge Changes",
|
||||
'2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91': "Message",
|
||||
'ad33f83890a4c1ba0086d4d728279e8e61d185c14352ea3d6663449460aad18d': "Message (commit on \"{0}\")",
|
||||
'2ee8b430941cdf1bf2209d255c8463471ba4c3de2d94129c257ab035a1d42a8e': "Message ({0} to commit on \"{1}\")",
|
||||
'f0f141c12a17f52bcd64321cf6969ffbc81f015b584641cd783d89904c1f72ea': "Message ({0} to commit)",
|
||||
'd45c9f6ecdd755947ace0120f734f99da7328ecb87b04c3b10d780117a94c2ed': "Migrate Changes",
|
||||
'e8ce5dcaf408935ff76747226d2e8bee4319a2f593c1d7a838115e56183d1f37': "Modified",
|
||||
'6300ef800bb884295b0b4b35682b75cecd7cc550d202db56d04a0643b8fb873f': "Never",
|
||||
'1ea442a134b2a184bd5d40104401f2a37fbc09ccf3f4bc9da161c6099be3691d': "No",
|
||||
'440633c6285d225a6e3849eb5e17f33c608ad0285fdf7acc14f7e4d912516ed9': "No rebase in progress.",
|
||||
'565339bc4d33d72817b583024112eb7f5cdf3e5eef0252d6ec1b9c9a94e12bb3': "OK",
|
||||
'e78008c3f3637c142067bbec565bb0d623b5a2113699795765c09e4f95cb7bd0': "OK, Don\\'t Ask Again",
|
||||
'a863d11492e395445acc633ced9be38f332c9aa0d0607dc83b5ab3b60a6d9fbd': "OK, Don\\'t Show Again",
|
||||
'ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942': "Open",
|
||||
'd77d0470fcb6e709dbc646f6ae4b68a4db64162b769b2914a3a760a1bbadb4df': "Open Comparison",
|
||||
'893fcb727fc6ee5a7516324e78ec23f7c12b62546a74b0b37f86d7e30d205547': "Open Git Log",
|
||||
'6fba1de2739c8e7ee835016e3340ef0b6c11d1b7cb2123af7ee23abf7f124682': "Open Merge",
|
||||
'f10c3c817a26227242cc20133608ec65402399011cff683c49aed7ea3b4e5436': "Open Repositories In Parent Folders",
|
||||
'2466923190a5c2d42540382922f01b6091b99ac2253c9eac5a066ccc129fac1d': "Open Repository",
|
||||
'e8e0ccba8b0da9ab15259028d04ab1bb9e9ae240bae643e8e07c87dae591120b': "Open in New Window",
|
||||
'4085b549321e7af912c77c7eaf2313790ad7d283eb11d32780764b816c2a3c34': "Optionally provide a stash message",
|
||||
'e7611f0537df5fc5d0177da520628219fccf065a1d4176cfbde2f75d824821f4': "Passphrase",
|
||||
'93abc930718bf1254198727dd8023b30499c5f833319550cdf7a20490a5ee744': "Pick a branch to pull from",
|
||||
'23a1e19a9fdf977e37f940b03ad56faab51a9a907bba6a975e35a707e5469c50': "Pick a provider to publish the branch \"{0}\" to:",
|
||||
'3e7c9d7d3ffce6d2931f8f2ec3cb30afce7f4786401f1391b97866c4f8739ccf': "Pick a remote to publish the branch \"{0}\" to:",
|
||||
'9b097971a9f0ce4309cddca492d9689f9e39b5b37cb374442960925f227c0776': "Pick a remote to pull the branch from",
|
||||
'e60dcf7dfc306478e6b869345c50ad6ac41a4b2697c8c449ab03e2b74ed81754': "Pick a remote to remove",
|
||||
'1db2709f2fc57a3e38685eeb075e00235bad5ee2538a98973dc2f5cb6b09c4ec': "Pick a repository to mark as safe and open",
|
||||
'6e2c8ec7bb53a72cb08507098e1cd6685bb5b0defbf4bb4751a91f73fd4ab061': "Pick a repository to open",
|
||||
'4409fc12fb9667fbb6713fe6c40de5a69128fafb717e7f925f9829d842769a66': "Pick a stash to apply",
|
||||
'8c4d9b659312323368fa1e554a7aaf11f36cb27249a24c81435d66ffb3633e36': "Pick a stash to drop",
|
||||
'e7ae4efa4b2f3d2f0dfc06be57bd0d9b4a693241f232b00f301497beb274a7eb': "Pick a stash to pop",
|
||||
'75fba89ae3e3799730e92c23de5c58ee0ea959aa5da12542326144c238174630': "Pick workspace folder to initialize git repo in",
|
||||
'3fa8ce1777f7ddc400c486a158fcb785fe326b88693300df8417d8cb7747cc52': "Please check out a branch to push to a remote.",
|
||||
'afd39827f783ddaf8c31a86ba2a80713ab112800005041f8819c14f5a121d6e1': "Please clean your repository working tree before checkout.",
|
||||
'ec5aa3af193303194748ccfa4adc86db1954ea441cb3ca754747829c73082e55': "Please provide a commit message",
|
||||
'e1ac5b25ecf9376124ae3505bdd6ffea60e96fb3744db2d6b08b9ec5dbbabd72': "Please provide a message to annotate the tag",
|
||||
'90aebb5a363734633e81d596dbc87a7083af97c15029ec4ed00ed85d3018c20e': "Please provide a new branch name",
|
||||
'a0d728e7c6fd83c9267a9b4bf25b543be6cded7d82d72c9d958ea552ddcaf1c7': "Please provide a remote name",
|
||||
'fc2a1795716d5b38e136f05edebeea54359088832fc36dcf048a92deba47971d': "Please provide a tag name",
|
||||
'00b3526ea21a69a7bbd09c6f006cce721c78be5995e2eb6c3cb8f0c2ede22879': "Please provide the commit hash",
|
||||
'fe4e7d8ab1a693b8d287c28b1fe5b6f772a2afbaa5063ebbd0766c52e54f161a': "Publish Branch",
|
||||
'c293a1d51314232c4ec79dce0e0ba928b4fc287124feb00c8c5cd98914a0f9ab': "Publish Branch/{Locked=\"Branch\"}Do not translate \"Branch\" as it is a git term",
|
||||
'7b7fce492a49fe2194302f4d5f2d1b1d22fe41602d876524174f6c819d9d05da': "Publish Branch \"{0}\"/{Locked=\"Branch\"}Do not translate \"Branch\" as it is a git term",
|
||||
'260304d6c22e64ea2f796f4f4a3ff96dcf866e99b747e759b12bcd31e8b52c0a': "Publish to {0}",
|
||||
'095bbfcf66c550a934f58c2bf959ecdcde72853a70196b86e619503c41b3dbdc': "Publish to...",
|
||||
'0dd87f831d7eff59524e2c4567b7ef14f691d2956d887315793bd818f29cfca0': "Publishing Branch \"{0}\".../{Locked=\"Branch\"}Do not translate \"Branch\" as it is a git term",
|
||||
'f401b998c2c5d9bcffc048b2e4ab1484559b14e6d232742a05671ca3e75cf311': "Publishing Branch.../{Locked=\"Branch\"}Do not translate \"Branch\" as it is a git term",
|
||||
'b66d044181a0e29642a958723512a8706ae494ccf63552c08cddca418d1cf097': "Pull",
|
||||
'2fa67ee4b98c8e901e1c778121ae4ffded7b1b732bbea170aa7f751847aa399f': "Pull {0} and push {1} commits between {2}/{3}",
|
||||
'02f3c611e65bc29302de5c9875f7ff07a7ce87d0d0452f9daa175b8fdcc8ad5f': "Pull {0} commits from {1}/{2}",
|
||||
'591937c4982b465f47118b1e37d9e2eac87a8d8d43125721e347585ec544f12a': "Push {0} commits to {1}/{2}",
|
||||
'276cd31a44092264bf1967b71011e0bf264668edf0e6872bf767b75cf60ec3a0': "Rebasing",
|
||||
'c780499abfa9079473c8de8595fd16c2f601d0695e95f691a5abe35286604b1d': "Remote \"{0}\" already exists.",
|
||||
'bd5bc169c6e722863058ba5e309b4a9a775d3419563c2a06a6c147291a81055d': "Remote branch at {0}",
|
||||
'96c1a5aafd493223d4edf01cfcd541cfbb69b57c438ed03db51bc3ee2510a377': "Remote name",
|
||||
'2e141cb8b2a2a6376c496e0068e12538b13e4b1e7a12386b9e9907699866cf45': "Remote name format invalid",
|
||||
'25202086021659225a6b0065ed7ea55875f99c94859e62037b4e00bf1aead47b': "Replace Local Tag(s)",
|
||||
'79b6a575a54e574a842c9e02e87858cb7596b721ae632a41755f20726c9aa23f': "Restore file",
|
||||
'7e420ff8a2ebf63aa024db900f0707a6d4f457c8048f6cc72523b2f709e8e0f1': "Restore files",
|
||||
'e98f3fe796a6bb3a6a887b34998889dc6aad09782c4abf35f15e75aa0a1c32d5': "Save All & Commit",
|
||||
'73bd1493a71408520de7d84d0c500708f92ae677a49fe1cec7350d5363f1088e': "Save All & Stash",
|
||||
'037c1c212912fcec15b3d4126ce0e79c0593c0f74cf8668451ca698b7bc52475': "Select a branch or tag to checkout",
|
||||
'be8e59066232b90b3820f1ad5bafd5d609e5d3ab42d30fb11a27c7e6cd8e2448': "Select a branch to checkout in detached mode",
|
||||
'5410dd4e0d2b06155ae6bd36e52b58b7358ce288ef781b45e9852016e2394b7a': "Select a branch to delete",
|
||||
'92529e041289d83949ecddfbff14a45431a230e115bea765a0b8757bba4a8d9b': "Select a branch to merge from",
|
||||
'6f8226b637c0f77b71ff88c5ec433a57f3ce11bbe7053bc43d1aa8a6589e75a2': "Select a branch to rebase onto",
|
||||
'34412b9ae0d9a8f1243ae6c065eacf2f2d3febce0e38f5df0b6e8d8cdbed0c20': "Select a ref to create the branch from",
|
||||
'9fd471b3f11fb4a7e5f87c9f2a87aee1c38c65ff43a596cb75a23f605bc43b17': "Select a remote to delete a tag from",
|
||||
'f549e4b0d6b56de82dafefee73dd06920cc27a791ad66fa19d99017abae64158': "Select a remote to fetch",
|
||||
'28c2080e378f1d291ab790609682492e0a165b461868f8546b32bc1aa497c3da': "Select a tag to delete",
|
||||
'a2f33e4d476de1d0148d5cdc59a5d6d85769b8980e454594cb34dde1372ab35c': "Select as Repository Destination",
|
||||
'edd969c69f64aff645b3027bab51746e3b4b8bbafdc573981df42125e9e85dbe': "Show Changes",
|
||||
'6b6f44c50d93c59d9c56dce2d44335706fc24ecf4e926d7eabbb6e34c226ae47': "Show Command Output",
|
||||
'3b9a10ffe5b4930c1891d29191418182fd5334195fedd2ce60dfd04c721d3b69': "Skipped found git in: \"{0}\"",
|
||||
'b5ff1947b664c6719dfbb25602ff832dd7fcfc5068944fa750a36fad11a9f7e6': "Staged Changes",
|
||||
'1b0a609aede05f4f39c423b8a4b57d004741211ef76980e4a37179df32d731a5': "Stash & Checkout",
|
||||
'9af34d9f6e18cfc2c71f9bfa484d075cda9121682aba174a6fca7a915f403ff1': "Stash Anyway",
|
||||
'ec8df3d159f741b74f7099bbd10d817aa40b3df5b7ae075629351f950cd462ff': "Stash message",
|
||||
'3601420ab6a0cf864306d9d83b2714b1b2c7976e1affe639d813d280267aa3e2': "Stashed Changes",
|
||||
'376ab71f351b85d3afac0fcbd859636e97909a7fe85d5c049dff55139600db27': "Successfully pushed.",
|
||||
'e8cd388771e552260257ad74ec3080faa98ffa7598b8e782b2a8c08ae1f8107a': "Synchronize Changes",
|
||||
'720bccb504d6429a9e4ec1f87fae45a608701f32f298c17a874e884064b0b9cc': "Synchronizing Changes...",
|
||||
'c620cca03e560f7ed57a468dddc1935ece81ff2095dda0f98d987226857b60cc': "Syncing. Cancelling may cause serious damages to the repository",
|
||||
'44b333daa4f9e6decfc3260fee4c03285e7b4d9c5315de608d5710283e49e54a': "Tag at {0}",
|
||||
'1ace926bc7cdee5323e297d439d2d268286749252b1c7f5e332d5003681d092d': "Tag name",
|
||||
'3bb614b0a444e925eb3e24b58dda2d4cc23de94c0968d0db2340b60acefdeab2': "The \"{0}\" repository has {1} submodules which won\\'t be opened automatically. You can still open each one individually by opening a file within.",
|
||||
'a19a357466e3cc3926579645f74ec7860df52578196b7b4147b221046f946d8d': "The branch \"{0}\" has no remote branch. Would you like to publish this branch?",
|
||||
'a213b755cc8239f62a4220d72ca8756a1ef91aec1ca885d2ddec7604f9718675': "The branch \"{0}\" is not fully merged. Delete anyway?",
|
||||
'96bbc2b6d0b5fa5726a6c8930a2bbcd4cfb8a4b95edd9f2a6666260ec402564d': "The current branch is not published to the remote. Would you like to publish it to access your changes elsewhere?",
|
||||
'31ac359d3ec1d704b0100940cf5eea360a13749b909afeff6fd6afac9944de77': "The following file has unsaved changes which won\\'t be included in the commit if you proceed: {0}.\\n\\nWould you like to save it before committing?",
|
||||
'a04370991d0a37372ec445bf861013866402b3caf1379a06445405c80a53712c': "The following file has unsaved changes which won\\'t be included in the stash if you proceed: {0}.\\n\\nWould you like to save it before stashing?",
|
||||
'23ba98146c9e50555dba1090bfd5e783e2ed2dd0823bb47fbe5f67ce258a9eb5': "The following untracked file will be DELETED FROM DISK if discarded: {0}.",
|
||||
'e109d755dd32053afa001e1e366b7a51561c73d2fcea81e79cdb7a46dc7fc47a': "The git repositories in the current folder are potentially unsafe as the folders are owned by someone other than the current user.",
|
||||
'02c2cdd6b3ac71010ce7c47a400c9719fead4aa3269d72b8f462ff61a45d4ab3': "The git repository at \"{0}\" has too many active changes, only a subset of Git features will be enabled.",
|
||||
'8d01c87529131c0fe41305b68799b99052dc4a274a4affcc1cea877cc14346d7': "The git repository in the current folder is potentially unsafe as the folder is owned by someone other than the current user.",
|
||||
'5fd10738fc1c6f99d48f2d972e7a4c4fa0ffa39ff4f89ae5cba4055c08eb98d4': "The last commit was a merge commit. Are you sure you want to undo it?",
|
||||
'b45f0ffa9a6ab73edb905b626d6fe3ed00854ca7abf7303b919cf686315b9f99': "The new branch will be \"{0}\"",
|
||||
'4360153c542717595a316b4979c6bba0e30dd9ccd312e1c4c852a00bdd6366d6': "The repository does not have any commits. Please make an initial commit before creating a stash.",
|
||||
'27ee389973941a5e4c33938ada96f71810852631100b4c853fde3b8ff00a4b5c': "The selection range does not contain any changes.",
|
||||
'abbd48f372807f93e0988532fd3acb1f1eb758ec9a414c4a0bbde208ca64ea73': "There are merge conflicts. Resolve them before committing.",
|
||||
'4a9bc15b4ed0cf72587423bf0e2d14780f2050bfbb59d187cf98cc081e0d1d1b': "There are no available repositories",
|
||||
'ae1a589b1c95953ed140c40811e495dcbaea430a742c8f895231e3c270e852ef': "There are no changes to commit.",
|
||||
'1817660c6b621c7c863521e96a45227469758a3f51d690448de5d1b50c46bc2d': "There are no changes to stash.",
|
||||
'0eb60d4befa938a3a146ef5031aaffff7f5c3b290ca2524472b36a3ef99259da': "There are no staged changes to commit.\\n\\nWould you like to stage all your changes and commit them directly?",
|
||||
'0a6f7df2d272dbe9feb4bf0dd43c6a93144be7e5192b330ca7a1b191666c5b93': "There are no staged changes to stash.",
|
||||
'46031808b597269632b77fb15757e8f4e0f56b9028ddf7b5889e68f5753668c9': "There are no stashes in the repository.",
|
||||
'be81fa311df402c9d32e9f0d31240455ba7bd8c5a968fd9c4261854469666a80': "There are {0} unsaved files.\\n\\nWould you like to save them before committing?",
|
||||
'bd3d54b7b5279debc1b7120498741a9123d3247573fb0b03ee2b356e799ec807': "There are {0} unsaved files.\\n\\nWould you like to save them before stashing?",
|
||||
'17a302d9654f49beddb9c262df6083f2295f88a618de2130cd94a71c13c9a815': "There are {0} untracked files which will be DELETED FROM DISK if discarded.",
|
||||
'1547ede309e6d1f85da487e614b5c06ecb8be8280e4d7edc5431a29025a0cf49': "There were merge conflicts while applying the stash.",
|
||||
'4e5370c14c2e52f7bc248222f1d743cfeecaef3f484f987facbf4604af7d7bdd': "This action will pull and push commits from and to \"{0}/{1}\".",
|
||||
'a3bfed7d5da3d9d87e3ffe75f75ecb1c47b3d635177a918a421dbc3da4789012': "This repository has no remotes configured to fetch from.",
|
||||
'946fda221b3c1389605a25d3c1836cbe2931594e7f17b1d406c6794e16bf7060': "This will DELETE {0} untracked files!\\nThis is IRREVERSIBLE!\\nThese files will be FOREVER LOST.",
|
||||
'8a31a9a33b1daab0d79eae0dc86548abb75d8210f058d99a3ef4b6f3ece60162': "This will create a Git repository in \"{0}\". Are you sure you want to continue?",
|
||||
'05f7892749ae2c9768ce4044a9df51b9f9bb38485c7c42049a15b1b99b9535d9': "Too many changes were detected. Only the first {0} changes will be shown below.",
|
||||
'4460d1b1316e9beeda90bd568c3e9d13b47a3710674433fd1022371f8e1d3108': "Unable to pull from remote repository due to conflicting tag(s): {0}. Would you like to resolve the conflict by replacing the local tag(s)?",
|
||||
'0d0b4290628654ca57e79767b0c2c66ab30fd9b41dfe4eb48495003a199bf27f': "Uncommitted Changes",
|
||||
'35a96c53b643b0cfb6501a078cb24a26c2158f732df4e497c68292ab9b2fb387': "Undo merge commit",
|
||||
'c7ba5477e19cf0bb25460d840cc2e67341e81e1c2d274d00b3054c73898d4d27': "Untracked",
|
||||
'd9dbf89a0df1e2e894271aa0784f5a497aa621698eca5da8c125870ead7b718e': "Untracked Changes",
|
||||
'eda6b0f61d9c085625dc90eb871b839a26cdbd818b39a6198eb4cc9a8fcc4ea5': "Using git \"{0}\" from \"{1}\"",
|
||||
'e7fde14b366ecaa13e8419d872a4b9f4008fa1e14c03f17d947b76c8e2130d91': "Validating found git in: \"{0}\"",
|
||||
'7f1d79b89e7e2a73fb77da103a8f48ff6a1d82d197245b96a00bd0bb1b807301': "Would you like to add \"{0}\" to .gitignore?",
|
||||
'a9b2a56ef24209b80c6e9e0508fae6e0cd8dde12582670f4867730d234fa660f': "Would you like to open the cloned repository, or add it to the current workspace?",
|
||||
'8e3e2fa1eac65813d54533388a9394094f68b3af6c8408dde1e4a3d4e57d91d7': "Would you like to open the cloned repository?",
|
||||
'2f583a9a7e36a2087285836c950f99f22099e18fd2565543ba73d4b175fdd72f': "Would you like to open the initialized repository, or add it to the current workspace?",
|
||||
'01cedefc7a6bda340489ba5bce02d9cf13cf3344b44ff23845566a379edf01a5': "Would you like to open the initialized repository?",
|
||||
'0d956bc1273b2c3663c075e95965229e067e6aa8baf635905a73feec866b0ce6': "Would you like {0} to [periodically run \"git fetch\"]({1})?",
|
||||
'85a39ab345d672ff8ca9b9c6876f3adcacf45ee7c1e2dbd2408fd338bd55e07e': "Yes",
|
||||
'568b3eef26e3360a32fba05157ba2b75657ca22b5929211279821ff88bd2fa3d': "Yes, Don\\'t Show Again",
|
||||
'08b041935798fbf6fd6ff51099ffedb140a475889986d14f5559ff8e7fc571dd': "You",
|
||||
'30757342a07b54b8546d73b091103bc1ec0e1d5b015265bb6a21b5f4716b0d53': "You are about to commit your changes without verification, this skips pre-commit hooks and can be undesirable.\\n\\nAre you sure to continue?",
|
||||
'0907e6f3642577f3302552d8e71bbc82073e9de0fe7c04c02c095e7ad6176750': "You are about to force push your changes, this can be destructive and could inadvertently overwrite changes made by others.\\n\\nAre you sure to continue?",
|
||||
'fe2df0f8d1bf9e45d9afaf5ca1a24523803f19221bec807bfc00f13cc519aa77': "You are trying to commit to a protected branch and you might not have permission to push your commits to the remote.\\n\\nHow would you like to proceed?",
|
||||
'802759f1e5e53993fd0ea369ce7f0ae28138651ca90cffb363771432692e5630': "Your local changes would be overwritten by checkout.",
|
||||
'4006ee78c8bf7a85704c33264a1bdfcce6e88144b698cccdfc9b73d259294da3': "Your repository has no remotes configured to publish to.",
|
||||
'b85f634ce5d7b0c897cffccadc3bd1827a2b7d3022f77288e460892af9e561a2': "Your repository has no remotes configured to pull from.",
|
||||
'b2cfea1b73b4855e2c9788d34218761d0345b040ca237bdc9d0d4fc2577e6be5': "Your repository has no remotes configured to push to.",
|
||||
'390f001b0ad6b35e9d11767949fbe88481014bff0abcdb95925ca74bcee7cd90': "Your repository has no remotes.",
|
||||
'9390298f3fb0c5b160498935d79cb139aef28e1c47358b4bbba61862b9c26e59': "no",
|
||||
'8a798890fe93817163b10b5f7bd2ca4d25d84c52739a645a889c173eee7d9d3d': "yes",
|
||||
'87bd11c53118b1c7e013a7abab752a62a22b8ab546323fa0daa6ceae4474fadb': "{0} (Deleted)",
|
||||
'2902a2172b4cd18aff8b58fe9754a4d14b8f14caf5faee5f32b52092ecafbf05': "{0} (Index)",
|
||||
'd6bd8cfa8b318f8c3845ea4c575f6dfc48f3db10ebec956199cb5afe75ced8f7': "{0} (Intent to add)",
|
||||
'aac7b4cbb9b0b84aa84433090d5b052e903003ebbe61d74bff4b1609e302f98f': "{0} (Ours)",
|
||||
'84d560d3629f1574ce6136b005e80785cc48e18319cdaf6e8736dfdc9d5bf899': "{0} (Theirs)",
|
||||
'236384de21336e110098c378d5fbdee9628af5281f36a15d98daa43702757ff0': "{0} (Untracked)",
|
||||
'da0616325ba5bc9c1849caff89e19cc03b34b23ed3bc73ddfc6ac06a2db891d7': "{0} (Working Tree)",
|
||||
'fa1e7180cf6c8ea611aeffecae3ff04d94f9558bbd8f2c69960ac883c1f31595': "{0} ({1})",
|
||||
'10e858c003479d92e7f97dcfac77c7ac8950cc2017a2edacb99f84eceacc5e3b': "{0} ({1}) ↔ {0} ({2})",
|
||||
'82a451fe75f2a900d68020e00d21556defd511eccbd8b2e5743ac8ec3168c9fa': "{0} Commit",
|
||||
'ba938268068ea08ae956bde42d00e5794a9213cfe5766936cacb2f3758b72dc0': "{0} Commit & Push",
|
||||
'9e5f10ce1f838d861901ebb2c83f8824296843cff8472960cfafc0098182383c': "{0} Commit & Sync",
|
||||
'5ea8624f43aa58ee102eae1842f3ba8a08c5bc1e1541440e5fcf3d9c91f78463': "{0} Continue",
|
||||
'22b70b7e3d265ec2795798f823257aae227228dc4191a3cc85fd00bd2f368f3a': "{0} Fetch all remotes",
|
||||
'81ad1e4c7e769dcad02d582dd25ee2810c51cc4989b92b5d32a2f1e5467d9927': "{0} Publish Branch/{Locked=\"Branch\"}Do not translate \"Branch\" as it is a git term",
|
||||
'da089f5ddfe606c3dc6f961bcb1316e41e11cf382afe908f8371b88e97b89225': "{0} Sync Changes{1}{2}",
|
||||
'24cf0fac66cc6a565ec23f5b2b9d58f2c8606cb7313b2591836da1f8d0a53993': "{0} characters left in current line",
|
||||
'8de94f809d2ce26a9db6bd5c9e3fe247254b40c6888ad3044050a147374dbd91': "{0} characters over {1} in current line",
|
||||
'93264f176451ecdd4985efc6ce3e65eb7759381031de21dcdf8809bc3e90e810': "{0} ↔ {1}",
|
||||
'86b933c7292229ebcd6fc4977d94683a09568745f08b5eff0ddf6249ca56a11d': "{0}\\n\\nThis is IRREVERSIBLE, your current working set will be FOREVER LOST."
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@
|
||||
"@actions/core": "1.9.1",
|
||||
"@actions/github": "2.1.1",
|
||||
"@azure/cosmos": "^3.17.3",
|
||||
"@azure/identity": "^2.1.0",
|
||||
"@azure/storage-blob": "^12.13.0",
|
||||
"@azure/identity": "^3.3.0",
|
||||
"@azure/storage-blob": "^12.16.0",
|
||||
"@electron/get": "^1.12.4",
|
||||
"@types/ansi-colors": "^3.2.0",
|
||||
"@types/azure": "0.9.19",
|
||||
"@types/azure": "0.9.20",
|
||||
"@types/byline": "^4.2.32",
|
||||
"@types/cssnano": "^4.0.0",
|
||||
"@types/debounce": "^1.0.0",
|
||||
|
||||
@@ -53,6 +53,15 @@
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/core-auth@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44"
|
||||
integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
"@azure/core-util" "^1.1.0"
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/core-client@^1.4.0":
|
||||
version "1.6.1"
|
||||
resolved "https://registry.npmjs.org/@azure/core-client/-/core-client-1.6.1.tgz"
|
||||
@@ -140,6 +149,14 @@
|
||||
dependencies:
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/core-util@^1.1.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.5.0.tgz#ffe49c3e867044da67daeb8122143fa065e1eb0e"
|
||||
integrity sha512-GZBpVFDtQ/15hW1OgBcRdT4Bl7AEpcEZqLfbAvOtm1CQUncKWiYapFHVD588hmlV27NbOOtSm3cnLF3lvoHi4g==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/core-util@^1.1.1":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.3.0.tgz#ea736a0cb0437ac0d049d57ff627c240b41479ec"
|
||||
@@ -167,21 +184,21 @@
|
||||
universal-user-agent "^6.0.0"
|
||||
uuid "^8.3.0"
|
||||
|
||||
"@azure/identity@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-2.1.0.tgz#89f0bfc1d1264dfd3d0cb19837c33a9c6706d548"
|
||||
integrity sha512-BPDz1sK7Ul9t0l9YKLEa8PHqWU4iCfhGJ+ELJl6c8CP3TpJt2urNCbm0ZHsthmxRsYoMPbz2Dvzj30zXZVmAFw==
|
||||
"@azure/identity@^3.3.0":
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.3.0.tgz#0166cfdfa892d73eeb69c390dac91796c6f85f79"
|
||||
integrity sha512-gISa/dAAxrWt6F2WiDXZY0y2xY4MLlN2wkNW4cPuq5OgPQKLSkxLc4I2WR04puTfZyQZnpXbAapAMEj1b96fgg==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
"@azure/core-auth" "^1.3.0"
|
||||
"@azure/core-auth" "^1.5.0"
|
||||
"@azure/core-client" "^1.4.0"
|
||||
"@azure/core-rest-pipeline" "^1.1.0"
|
||||
"@azure/core-tracing" "^1.0.0"
|
||||
"@azure/core-util" "^1.0.0"
|
||||
"@azure/logger" "^1.0.0"
|
||||
"@azure/msal-browser" "^2.26.0"
|
||||
"@azure/msal-common" "^7.0.0"
|
||||
"@azure/msal-node" "^1.10.0"
|
||||
"@azure/msal-browser" "^2.37.1"
|
||||
"@azure/msal-common" "^13.1.0"
|
||||
"@azure/msal-node" "^1.17.3"
|
||||
events "^3.0.0"
|
||||
jws "^4.0.0"
|
||||
open "^8.0.0"
|
||||
@@ -196,36 +213,31 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@azure/msal-browser@^2.26.0":
|
||||
version "2.37.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.37.0.tgz#32d7af74eef53f2692f8a9d6bd6818c78faf4c1b"
|
||||
integrity sha512-YNGD/W/tw/5wDWlXOfmrVILaxVsorVLxYU2ovmL1PDvxkdudbQRyGk/76l4emqgDAl/kPQeqyivxjOU6w1YfvQ==
|
||||
"@azure/msal-browser@^2.37.1":
|
||||
version "2.38.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.38.2.tgz#707725c892258fe6b3af4dd410e1daff608521b5"
|
||||
integrity sha512-71BeIn2we6LIgMplwCSaMq5zAwmalyJR3jFcVOZxNVfQ1saBRwOD+P77nLs5vrRCedVKTq8RMFhIOdpMLNno0A==
|
||||
dependencies:
|
||||
"@azure/msal-common" "13.0.0"
|
||||
"@azure/msal-common" "13.3.0"
|
||||
|
||||
"@azure/msal-common@13.0.0":
|
||||
version "13.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-13.0.0.tgz#9c39184903b5d0fd6e643ccc12193fae220e912b"
|
||||
integrity sha512-GqCOg5H5bouvLij9NFXFkh+asRRxsPBRwnTDsfK7o0KcxYHJbuidKw8/VXpycahGXNxgtuhqtK/n5he+5NhyEA==
|
||||
"@azure/msal-common@13.3.0", "@azure/msal-common@^13.1.0":
|
||||
version "13.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-13.3.0.tgz#dfa39810e0fbce6e07ca85a2cf305da58d30b7c9"
|
||||
integrity sha512-/VFWTicjcJbrGp3yQP7A24xU95NiDMe23vxIU1U6qdRPFsprMDNUohMudclnd+WSHE4/McqkZs/nUU3sAKkVjg==
|
||||
|
||||
"@azure/msal-common@^7.0.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-7.6.0.tgz#b52e97ef540275f72611cff57937dfa0b34cdcca"
|
||||
integrity sha512-XqfbglUTVLdkHQ8F9UQJtKseRr3sSnr9ysboxtoswvaMVaEfvyLtMoHv9XdKUfOc0qKGzNgRFd9yRjIWVepl6Q==
|
||||
|
||||
"@azure/msal-node@^1.10.0":
|
||||
version "1.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.17.2.tgz#42566443e0cdf476bcb43854c9fe47a2def40baf"
|
||||
integrity sha512-l8edYnA2LQj4ue3pjxVz1Qy4HuU5xbcoebfe2bGTRvBL9Q6n2Df47aGftkLIyimD1HxHuA4ZZOe23a/HshoYXw==
|
||||
"@azure/msal-node@^1.17.3":
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.18.3.tgz#e265556d4db0340590eeab5341469fb6740251d0"
|
||||
integrity sha512-lI1OsxNbS/gxRD4548Wyj22Dk8kS7eGMwD9GlBZvQmFV8FJUXoXySL1BiNzDsHUE96/DS/DHmA+F73p1Dkcktg==
|
||||
dependencies:
|
||||
"@azure/msal-common" "13.0.0"
|
||||
"@azure/msal-common" "13.3.0"
|
||||
jsonwebtoken "^9.0.0"
|
||||
uuid "^8.3.0"
|
||||
|
||||
"@azure/storage-blob@^12.13.0":
|
||||
version "12.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.14.0.tgz#32d3e5fa3bb2a12d5d44b186aed11c8e78f00178"
|
||||
integrity sha512-g8GNUDpMisGXzBeD+sKphhH5yLwesB4JkHr1U6be/X3F+cAMcyGLPD1P89g2M7wbEtUJWoikry1rlr83nNRBzg==
|
||||
"@azure/storage-blob@^12.16.0":
|
||||
version "12.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.16.0.tgz#c41fb1e538d6f6e2a6756bfcc69382eededf4fa1"
|
||||
integrity sha512-jz33rUSUGUB65FgYrTRgRDjG6hdPHwfvHe+g/UrwVG8MsyLqSxg9TaW7Yuhjxu1v1OZ5xam2NU6+IpCN0xJO8Q==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
"@azure/core-http" "^3.0.0"
|
||||
@@ -540,10 +552,10 @@
|
||||
resolved "https://registry.npmjs.org/@types/ansi-colors/-/ansi-colors-3.2.0.tgz"
|
||||
integrity sha512-0caWAhXht9N2lOdMzJLXybsSkYCx1QOdxx6pae48tswI9QV3DFX26AoOpy0JxwhCb+zISTqmd6H8t9Zby9BoZg==
|
||||
|
||||
"@types/azure@0.9.19":
|
||||
version "0.9.19"
|
||||
resolved "https://registry.npmjs.org/@types/azure/-/azure-0.9.19.tgz"
|
||||
integrity sha1-Gmqb2Fa0N93s8/n8hAemg8hpugI=
|
||||
"@types/azure@0.9.20":
|
||||
version "0.9.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/azure/-/azure-0.9.20.tgz#ce00ed2546c5dc5c63489162c804a2f773b95cfa"
|
||||
integrity sha512-5+YeTSAruOEjCtmRJlqnhUTJtA4+kjPhOwUUT6Eo4O3MDQIlGzGwJw70umHgaSw0hZoWIB2g/iCRXtmesn9F2w==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
@@ -2627,14 +2639,14 @@ mimic-response@^3.1.0:
|
||||
resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz"
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^3.0.3, minimatch@^3.1.1:
|
||||
minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
|
||||
@@ -1213,7 +1213,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1227,6 +1227,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -1151,7 +1151,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1165,6 +1165,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -1214,7 +1214,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1228,6 +1228,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -1467,7 +1467,7 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
dependencies:
|
||||
mime-db "1.44.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1481,6 +1481,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -520,12 +520,13 @@
|
||||
"hasAzureResourceProviders": true
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/arm-resourcegraph": "^4.0.0",
|
||||
"@azure/arm-resourcegraph": "^4.2.1",
|
||||
"@azure/arm-subscriptions": "^3.0.0",
|
||||
"@azure/msal-common": "^11.0.0",
|
||||
"@azure/msal-node": "^1.16.0",
|
||||
"@azure/msal-common": "^13.3.0",
|
||||
"@azure/msal-node": "^1.18.3",
|
||||
"@azure/ms-rest-js": "^2.2.0",
|
||||
"@azure/storage-blob": "^12.13.0",
|
||||
"axios": "^0.27.2",
|
||||
"axios": "^1.5.0",
|
||||
"lockfile": "1.0.4",
|
||||
"@microsoft/ads-extension-telemetry": "^3.0.1",
|
||||
"node-fetch": "^2.6.7",
|
||||
|
||||
@@ -22,8 +22,7 @@ import { MemoryDatabase } from '../utils/memoryDatabase';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { AzureAuthError } from './azureAuthError';
|
||||
import { AccountInfo, AuthError, AuthenticationResult, InteractionRequiredAuthError, PublicClientApplication } from '@azure/msal-node';
|
||||
import { HttpClient } from './httpClient';
|
||||
import { getProxyEnabledHttpClient, getTenantIgnoreList, updateTenantIgnoreList } from '../../utils';
|
||||
import { getTenantIgnoreList, updateTenantIgnoreList } from '../../utils';
|
||||
import { errorToPromptFailedResult } from './networkUtils';
|
||||
import { MsalCachePluginProvider } from '../utils/msalCachePlugin';
|
||||
import { isErrorResponseBodyWithError } from '../../azureResource/utils';
|
||||
@@ -32,6 +31,7 @@ const localize = nls.loadMessageBundle();
|
||||
|
||||
export type GetTenantsResponseData = {
|
||||
value: TenantResponse[];
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export abstract class AzureAuth implements vscode.Disposable {
|
||||
@@ -44,7 +44,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
protected readonly scopesString: string;
|
||||
protected readonly clientId: string;
|
||||
protected readonly resources: Resource[];
|
||||
protected readonly httpClient: HttpClient;
|
||||
private readonly _disposableStore: vscode.Disposable[];
|
||||
|
||||
constructor(
|
||||
protected readonly metadata: AzureAccountProviderMetadata,
|
||||
@@ -55,7 +55,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
protected readonly authType: AzureAuthType,
|
||||
public readonly userFriendlyName: string
|
||||
) {
|
||||
|
||||
this._disposableStore = [];
|
||||
this.loginEndpointUrl = this.metadata.settings.host;
|
||||
this.commonTenant = {
|
||||
id: 'common',
|
||||
@@ -68,8 +68,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
this.redirectUri = this.metadata.settings.redirectUri;
|
||||
this.clientId = this.metadata.settings.clientId;
|
||||
this.resources = [
|
||||
this.metadata.settings.armResource,
|
||||
this.metadata.settings.graphResource,
|
||||
this.metadata.settings.armResource
|
||||
];
|
||||
if (this.metadata.settings.sqlResource) {
|
||||
this.resources.push(this.metadata.settings.sqlResource);
|
||||
@@ -99,7 +98,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
|
||||
this.scopes = [...this.metadata.settings.scopes];
|
||||
this.scopesString = this.scopes.join(' ');
|
||||
this.httpClient = getProxyEnabledHttpClient();
|
||||
this._disposableStore.push(this.uriEventEmitter);
|
||||
}
|
||||
|
||||
public async startLogin(): Promise<AzureAccount | azdata.PromptFailedResult> {
|
||||
@@ -310,6 +309,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
|| error.errorMessage.includes(Constants.AADSTS50078)
|
||||
|| error.errorMessage.includes(Constants.AADSTS50085)
|
||||
|| error.errorMessage.includes(Constants.AADSTS50089)
|
||||
|| error.errorMessage.includes(Constants.AADSTS700082)
|
||||
|| error.errorMessage.includes(Constants.AADSTS700084);
|
||||
}
|
||||
|
||||
@@ -510,8 +510,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
this.clientApplication.clearCache();
|
||||
|
||||
// unlink both cache files
|
||||
await this.msalCacheProvider.unlinkMsalCache();
|
||||
await this.msalCacheProvider.unlinkLocalCache();
|
||||
await this.msalCacheProvider.unlinkCacheFiles();
|
||||
|
||||
// Delete Encryption Keys
|
||||
await this.msalCacheProvider.clearCacheEncryptionKeys();
|
||||
@@ -541,7 +540,9 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
await this.msalCacheProvider.clearAccountFromLocalCache(accountKey.accountId);
|
||||
}
|
||||
|
||||
public async dispose() { }
|
||||
public async dispose() {
|
||||
this._disposableStore.forEach(d => d.dispose());
|
||||
}
|
||||
|
||||
public async autoOAuthCancelled(): Promise<void> { }
|
||||
|
||||
@@ -624,7 +625,7 @@ export interface TokenClaims { // https://docs.microsoft.com/en-us/azure/active-
|
||||
aud: string;
|
||||
/**
|
||||
* Identifies the issuer, or "authorization server" that constructs and
|
||||
* returns the token. It also identifies the Azure AD tenant for which
|
||||
* returns the token. It also identifies the Microsoft Entra tenant for which
|
||||
* the user was authenticated. If the token was issued by the v2.0 endpoint,
|
||||
* the URI will end in /v2.0. The GUID that indicates that the user is a consumer
|
||||
* user from a Microsoft account is 9188040d-6c67-4c5b-b112-36a304b66dad.
|
||||
@@ -642,7 +643,7 @@ export interface TokenClaims { // https://docs.microsoft.com/en-us/azure/active-
|
||||
* account not in the same tenant as the issuer - guests, for instance.
|
||||
* If the claim isn't present, it means that the value of iss can be used instead.
|
||||
* For personal accounts being used in an organizational context (for instance,
|
||||
* a personal account invited to an Azure AD tenant), the idp claim may be
|
||||
* a personal account invited to a Microsoft Entra tenant), the idp claim may be
|
||||
* 'live.com' or an STS URI containing the Microsoft account tenant
|
||||
* 9188040d-6c67-4c5b-b112-36a304b66dad.
|
||||
*/
|
||||
@@ -675,7 +676,7 @@ export interface TokenClaims { // https://docs.microsoft.com/en-us/azure/active-
|
||||
*/
|
||||
at_hash: string;
|
||||
/**
|
||||
* An internal claim used by Azure AD to record data for token reuse. Should be ignored.
|
||||
* An internal claim used by Microsoft Entra ID to record data for token reuse. Should be ignored.
|
||||
*/
|
||||
aio: string;
|
||||
/**
|
||||
|
||||
@@ -1,413 +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 { AzureNetworkResponse } from 'azurecore';
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import { TextEncoder } from 'util';
|
||||
import { NetworkRequestOptions, urlToHttpOptions } from './networkUtils';
|
||||
|
||||
/**
|
||||
* http methods
|
||||
*/
|
||||
export enum HttpMethod {
|
||||
GET = 'get',
|
||||
POST = 'post',
|
||||
PUT = 'put',
|
||||
DELETE = 'delete',
|
||||
PATCH = 'patch'
|
||||
}
|
||||
|
||||
export enum HttpStatus {
|
||||
SUCCESS_RANGE_START = 200,
|
||||
SUCCESS_RANGE_END = 299,
|
||||
REDIRECT = 302,
|
||||
CLIENT_ERROR_RANGE_START = 400,
|
||||
CLIENT_ERROR_RANGE_END = 499,
|
||||
SERVER_ERROR_RANGE_START = 500,
|
||||
SERVER_ERROR_RANGE_END = 599
|
||||
}
|
||||
|
||||
export enum ProxyStatus {
|
||||
SUCCESS_RANGE_START = 200,
|
||||
SUCCESS_RANGE_END = 299,
|
||||
SERVER_ERROR = 500
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements the API for network requests.
|
||||
*/
|
||||
export class HttpClient {
|
||||
private proxyUrl: string;
|
||||
private customAgentOptions: http.AgentOptions | https.AgentOptions;
|
||||
static readonly AUTHORIZATION_PENDING: string = 'authorization_pending';
|
||||
|
||||
constructor(
|
||||
proxyUrl?: string,
|
||||
customAgentOptions?: http.AgentOptions | https.AgentOptions
|
||||
) {
|
||||
this.proxyUrl = proxyUrl || '';
|
||||
this.customAgentOptions = customAgentOptions || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Http Get request
|
||||
* @param url
|
||||
* @param options
|
||||
*/
|
||||
async sendGetRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions,
|
||||
cancellationToken?: number | undefined
|
||||
): Promise<AzureNetworkResponse<T>> {
|
||||
if (this.proxyUrl) {
|
||||
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.GET, options, this.customAgentOptions as http.AgentOptions, cancellationToken);
|
||||
} else {
|
||||
return networkRequestViaHttps(url, HttpMethod.GET, options, this.customAgentOptions as https.AgentOptions, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Http Post request
|
||||
* @param url
|
||||
* @param options
|
||||
*/
|
||||
async sendPostRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions,
|
||||
cancellationToken?: number
|
||||
): Promise<AzureNetworkResponse<T>> {
|
||||
if (this.proxyUrl) {
|
||||
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.POST, options, this.customAgentOptions as http.AgentOptions, cancellationToken);
|
||||
} else {
|
||||
return networkRequestViaHttps(url, HttpMethod.POST, options, this.customAgentOptions as https.AgentOptions, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Http Put request
|
||||
* @param url
|
||||
* @param options
|
||||
*/
|
||||
async sendPutRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions,
|
||||
cancellationToken?: number
|
||||
): Promise<AzureNetworkResponse<T>> {
|
||||
if (this.proxyUrl) {
|
||||
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.PUT, options, this.customAgentOptions as http.AgentOptions, cancellationToken);
|
||||
} else {
|
||||
return networkRequestViaHttps(url, HttpMethod.PUT, options, this.customAgentOptions as https.AgentOptions, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Http Delete request
|
||||
* @param url
|
||||
* @param options
|
||||
*/
|
||||
async sendDeleteRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions
|
||||
): Promise<AzureNetworkResponse<T>> {
|
||||
if (this.proxyUrl) {
|
||||
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.DELETE, options, this.customAgentOptions as http.AgentOptions);
|
||||
} else {
|
||||
return networkRequestViaHttps(url, HttpMethod.DELETE, options, this.customAgentOptions as https.AgentOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Http Patch request
|
||||
* @param url
|
||||
* @param options
|
||||
*/
|
||||
async sendPatchRequestAsync<T>(
|
||||
url: string,
|
||||
options?: NetworkRequestOptions,
|
||||
cancellationToken?: number
|
||||
): Promise<AzureNetworkResponse<T>> {
|
||||
if (this.proxyUrl) {
|
||||
return networkRequestViaProxy(url, this.proxyUrl, HttpMethod.PATCH, options, this.customAgentOptions as http.AgentOptions, cancellationToken);
|
||||
} else {
|
||||
return networkRequestViaHttps(url, HttpMethod.PATCH, options, this.customAgentOptions as https.AgentOptions, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const networkRequestViaProxy = <T>(
|
||||
destinationUrlString: string,
|
||||
proxyUrlString: string,
|
||||
httpMethod: string,
|
||||
options?: NetworkRequestOptions,
|
||||
agentOptions?: http.AgentOptions,
|
||||
timeout?: number
|
||||
): Promise<AzureNetworkResponse<T>> => {
|
||||
const destinationUrl = new URL(destinationUrlString);
|
||||
const proxyUrl = new URL(proxyUrlString);
|
||||
|
||||
// 'method: connect' must be used to establish a connection to the proxy
|
||||
const headers = options?.headers || {} as Record<string, string>;
|
||||
const tunnelRequestOptions: https.RequestOptions = {
|
||||
host: proxyUrl.hostname,
|
||||
port: proxyUrl.port,
|
||||
method: 'CONNECT',
|
||||
path: destinationUrl.hostname,
|
||||
headers: headers
|
||||
};
|
||||
|
||||
if (timeout) {
|
||||
tunnelRequestOptions.timeout = timeout;
|
||||
}
|
||||
|
||||
if (agentOptions && Object.keys(agentOptions).length) {
|
||||
tunnelRequestOptions.agent = new http.Agent(agentOptions);
|
||||
}
|
||||
|
||||
// compose a request string for the socket
|
||||
let postRequestStringContent: string = '';
|
||||
if (httpMethod === HttpMethod.POST || httpMethod === HttpMethod.PUT) {
|
||||
// Note: Text Encoder is necessary here because otherwise it was not able to handle Chinese characters in table names.
|
||||
const body = (new TextEncoder()).encode(JSON.stringify(options?.body || ''));
|
||||
postRequestStringContent =
|
||||
'Content-Type: application/json\r\n' +
|
||||
`Content-Length: ${body.length}\r\n` +
|
||||
`\r\n${body}`;
|
||||
}
|
||||
const outgoingRequestString = `${httpMethod.toUpperCase()} ${destinationUrl.href} HTTP/1.1\r\n` +
|
||||
`Host: ${destinationUrl.host}\r\n` +
|
||||
'Connection: close\r\n' +
|
||||
postRequestStringContent +
|
||||
'\r\n';
|
||||
|
||||
return new Promise<AzureNetworkResponse<T>>(((resolve, reject) => {
|
||||
const request = http.request(tunnelRequestOptions);
|
||||
|
||||
if (tunnelRequestOptions.timeout) {
|
||||
request.on('timeout', () => {
|
||||
request.destroy();
|
||||
reject(new Error('Request time out'));
|
||||
});
|
||||
}
|
||||
|
||||
request.end();
|
||||
|
||||
// establish connection to the proxy
|
||||
request.on('connect', (response, socket) => {
|
||||
const proxyStatusCode = response?.statusCode || ProxyStatus.SERVER_ERROR;
|
||||
if ((proxyStatusCode < ProxyStatus.SUCCESS_RANGE_START) || (proxyStatusCode > ProxyStatus.SUCCESS_RANGE_END)) {
|
||||
request.destroy();
|
||||
socket.destroy();
|
||||
reject(new Error(`Error connecting to proxy. Http status code: ${response.statusCode}. Http status message: ${response?.statusMessage || 'Unknown'}`));
|
||||
}
|
||||
if (tunnelRequestOptions.timeout) {
|
||||
socket.setTimeout(tunnelRequestOptions.timeout);
|
||||
socket.on('timeout', () => {
|
||||
request.destroy();
|
||||
socket.destroy();
|
||||
reject(new Error('Request time out'));
|
||||
});
|
||||
}
|
||||
|
||||
// make a request over an HTTP tunnel
|
||||
socket.write(outgoingRequestString);
|
||||
|
||||
const data: Buffer[] = [];
|
||||
socket.on('data', (chunk) => {
|
||||
data.push(chunk);
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
// combine all received buffer streams into one buffer, and then into a string
|
||||
const dataString = Buffer.concat([...data]).toString();
|
||||
|
||||
// separate each line into it's own entry in an arry
|
||||
const dataStringArray = dataString.split('\r\n');
|
||||
// the first entry will contain the statusCode and statusMessage
|
||||
const httpStatusCode = parseInt(dataStringArray[0].split(' ')[1], undefined);
|
||||
// remove 'HTTP/1.1' and the status code to get the status message
|
||||
const statusMessage = dataStringArray[0].split(' ').slice(2).join(' ');
|
||||
// the last entry will contain the body
|
||||
const body = dataStringArray[dataStringArray.length - 1];
|
||||
|
||||
// everything in between the first and last entries are the headers
|
||||
const headersArray = dataStringArray.slice(1, dataStringArray.length - 2);
|
||||
|
||||
// build an object out of all the headers
|
||||
const entries = new Map();
|
||||
headersArray.forEach((header) => {
|
||||
/**
|
||||
* the header might look like 'Content-Length: 1531', but that is just a string
|
||||
* it needs to be converted to a key/value pair
|
||||
* split the string at the first instance of ':'
|
||||
* there may be more than one ':' if the value of the header is supposed to be a JSON object
|
||||
*/
|
||||
const headerKeyValue = header.split(new RegExp(/:\s(.*)/s));
|
||||
entries.set(headerKeyValue[0], headerKeyValue[1]);
|
||||
});
|
||||
|
||||
const parsedHeaders = Object.fromEntries(entries) as Record<string, string>;
|
||||
const networkResponse: AzureNetworkResponse<T> = {
|
||||
headers: parsedHeaders,
|
||||
data: parseBody(httpStatusCode, statusMessage, parsedHeaders, body) as T,
|
||||
status: httpStatusCode
|
||||
};
|
||||
|
||||
if (((httpStatusCode < HttpStatus.SUCCESS_RANGE_START) || (httpStatusCode > HttpStatus.SUCCESS_RANGE_END)) &&
|
||||
// do not destroy the request for the device code flow
|
||||
// @ts-ignore
|
||||
networkResponse.data['error'] !== HttpClient.AUTHORIZATION_PENDING) {
|
||||
request.destroy();
|
||||
}
|
||||
resolve(networkResponse);
|
||||
});
|
||||
|
||||
socket.on('error', (chunk) => {
|
||||
request.destroy();
|
||||
socket.destroy();
|
||||
reject(new Error(chunk.toString()));
|
||||
});
|
||||
});
|
||||
|
||||
request.on('error', (chunk) => {
|
||||
request.destroy();
|
||||
reject(new Error(chunk.toString()));
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
const networkRequestViaHttps = <T>(
|
||||
urlString: string,
|
||||
httpMethod: string,
|
||||
options?: NetworkRequestOptions,
|
||||
agentOptions?: https.AgentOptions,
|
||||
timeout?: number
|
||||
): Promise<AzureNetworkResponse<T>> => {
|
||||
const isPostRequest = httpMethod === HttpMethod.POST;
|
||||
const isPutRequest = httpMethod === HttpMethod.PUT;
|
||||
const isPatchRequest = httpMethod === HttpMethod.PATCH;
|
||||
// Note: Text Encoder is necessary here because otherwise it was not able to handle Chinese characters in table names.
|
||||
const body = (new TextEncoder()).encode(options?.body || '');
|
||||
const url = new URL(urlString);
|
||||
const optionHeaders = options?.headers || {} as Record<string, string>;
|
||||
let customOptions: https.RequestOptions = {
|
||||
method: httpMethod,
|
||||
headers: optionHeaders,
|
||||
...urlToHttpOptions(url)
|
||||
};
|
||||
|
||||
if (timeout) {
|
||||
customOptions.timeout = timeout;
|
||||
}
|
||||
|
||||
if (agentOptions && Object.keys(agentOptions).length) {
|
||||
customOptions.agent = new https.Agent(agentOptions);
|
||||
}
|
||||
|
||||
if (isPostRequest || isPutRequest || isPatchRequest) {
|
||||
// needed for post request to work
|
||||
customOptions.headers = {
|
||||
...customOptions.headers,
|
||||
'Content-Length': body.length
|
||||
};
|
||||
}
|
||||
|
||||
return new Promise<AzureNetworkResponse<T>>((resolve, reject) => {
|
||||
const request = https.request(customOptions);
|
||||
|
||||
if (timeout) {
|
||||
request.on('timeout', () => {
|
||||
request.destroy();
|
||||
reject(new Error('Request timed out'));
|
||||
});
|
||||
}
|
||||
|
||||
if (isPostRequest || isPutRequest || isPatchRequest) {
|
||||
request.write(body);
|
||||
}
|
||||
|
||||
request.end();
|
||||
|
||||
request.on('response', (response) => {
|
||||
const headers = response.headers;
|
||||
const statusCode = response.statusCode as number;
|
||||
const statusMessage = response.statusMessage;
|
||||
|
||||
const data: Buffer[] = [];
|
||||
response.on('data', (chunk) => {
|
||||
data.push(chunk);
|
||||
});
|
||||
|
||||
response.on('end', () => {
|
||||
// combine all received buffer streams into one buffer, and then into a string
|
||||
const dataBody = Buffer.concat([...data]).toString();
|
||||
|
||||
const parsedHeaders = headers as Record<string, string>;
|
||||
const networkResponse: AzureNetworkResponse<T> = {
|
||||
headers: parsedHeaders,
|
||||
data: parseBody(statusCode, statusMessage, parsedHeaders, dataBody) as T,
|
||||
status: statusCode
|
||||
};
|
||||
|
||||
if (((statusCode < HttpStatus.SUCCESS_RANGE_START) || (statusCode > HttpStatus.SUCCESS_RANGE_END)) &&
|
||||
// do not destroy the request for the device code flow
|
||||
// @ts-ignore
|
||||
networkResponse.data['error'] !== HttpClient.AUTHORIZATION_PENDING) {
|
||||
request.destroy();
|
||||
}
|
||||
resolve(networkResponse);
|
||||
});
|
||||
});
|
||||
|
||||
request.on('error', (chunk) => {
|
||||
request.destroy();
|
||||
reject(new Error(chunk.toString()));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if extra parsing is needed on the response from the server
|
||||
* @param statusCode {number} the status code of the response from the server
|
||||
* @param statusMessage {string | undefined} the status message of the response from the server
|
||||
* @param headers {Record<string, string>} the headers of the response from the server
|
||||
* @param body {string} the body from the response of the server
|
||||
* @returns JSON parsed body or error object
|
||||
*/
|
||||
const parseBody = (statusCode: number, statusMessage: string | undefined, headers: Record<string, string>, body: string) => {
|
||||
/*
|
||||
* Informational responses (100 - 199)
|
||||
* Successful responses (200 - 299)
|
||||
* Redirection messages (300 - 399)
|
||||
* Client error responses (400 - 499)
|
||||
* Server error responses (500 - 599)
|
||||
*/
|
||||
|
||||
let parsedBody: unknown;
|
||||
try {
|
||||
parsedBody = JSON.parse(body);
|
||||
} catch (error) {
|
||||
let errorType;
|
||||
let errorDescriptionHelper;
|
||||
if ((statusCode >= HttpStatus.CLIENT_ERROR_RANGE_START) && (statusCode <= HttpStatus.CLIENT_ERROR_RANGE_END)) {
|
||||
errorType = 'client_error';
|
||||
errorDescriptionHelper = 'A client';
|
||||
} else if ((statusCode >= HttpStatus.SERVER_ERROR_RANGE_START) && (statusCode <= HttpStatus.SERVER_ERROR_RANGE_END)) {
|
||||
errorType = 'server_error';
|
||||
errorDescriptionHelper = 'A server';
|
||||
} else {
|
||||
errorType = 'unknown_error';
|
||||
errorDescriptionHelper = 'An unknown';
|
||||
}
|
||||
|
||||
parsedBody = {
|
||||
error: errorType,
|
||||
error_description: `${errorDescriptionHelper} error occurred.\nHttp status code: ${statusCode}\nHttp status message: ${statusMessage || 'Unknown'}\nHeaders: ${JSON.stringify(headers)}`
|
||||
};
|
||||
}
|
||||
|
||||
return parsedBody;
|
||||
};
|
||||
@@ -7,7 +7,6 @@ import * as azurecore from 'azurecore';
|
||||
|
||||
export const enum SettingIds {
|
||||
marm = 'marm',
|
||||
graph = 'graph',
|
||||
msgraph = 'msgraph',
|
||||
arm = 'arm',
|
||||
sql = 'sql',
|
||||
@@ -49,7 +48,6 @@ export type ProviderSettingsJson = {
|
||||
host: string,
|
||||
clientId: string,
|
||||
microsoftResource: string,
|
||||
graphResource: string,
|
||||
msGraphResource?: string,
|
||||
armResource: string,
|
||||
sqlResource: string,
|
||||
|
||||
@@ -23,11 +23,6 @@ const publicAzureSettings: ProviderSettings = {
|
||||
endpoint: 'https://management.core.windows.net/',
|
||||
azureResourceId: AzureResource.MicrosoftResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: 'https://graph.windows.net/',
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
msGraphResource: {
|
||||
id: SettingIds.msgraph,
|
||||
endpoint: 'https://graph.microsoft.com/',
|
||||
@@ -103,11 +98,6 @@ const usGovAzureSettings: ProviderSettings = {
|
||||
endpoint: 'https://management.core.usgovcloudapi.net/',
|
||||
azureResourceId: AzureResource.MicrosoftResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: 'https://graph.windows.net/',
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
msGraphResource: {
|
||||
id: SettingIds.msgraph,
|
||||
endpoint: 'https://graph.microsoft.us/',
|
||||
@@ -177,11 +167,6 @@ const chinaAzureSettings: ProviderSettings = {
|
||||
endpoint: 'https://management.core.chinacloudapi.cn/',
|
||||
azureResourceId: AzureResource.MicrosoftResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: 'https://graph.chinacloudapi.cn',
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
msGraphResource: {
|
||||
id: SettingIds.msgraph,
|
||||
endpoint: 'https://microsoftgraph.chinacloudapi.cn',
|
||||
|
||||
@@ -75,7 +75,7 @@ export class MsalCachePluginProvider {
|
||||
// Handle deserialization error in cache file in case file gets corrupted.
|
||||
// Clearing cache here will ensure account is marked stale so re-authentication can be triggered.
|
||||
Logger.verbose(`MsalCachePlugin: Error occurred when trying to read cache file, file will be deleted: ${e.message}`);
|
||||
await fsPromises.unlink(this._msalCacheConfiguration.cacheFilePath);
|
||||
await this.unlinkCache(this._msalCacheConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,17 +177,11 @@ export class MsalCachePluginProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes Msal access token cache file
|
||||
* Deletes both cache files.
|
||||
*/
|
||||
public async unlinkMsalCache(): Promise<void> {
|
||||
await fsPromises.unlink(this._msalCacheConfiguration.cacheFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes local access token cache file.
|
||||
*/
|
||||
public async unlinkLocalCache(): Promise<void> {
|
||||
await fsPromises.unlink(this._localCacheConfiguration.cacheFilePath);
|
||||
public async unlinkCacheFiles(): Promise<void> {
|
||||
await this.unlinkCache(this._msalCacheConfiguration);
|
||||
await this.unlinkCache(this._localCacheConfiguration);
|
||||
}
|
||||
|
||||
//#region Private helper methods
|
||||
@@ -225,13 +219,12 @@ export class MsalCachePluginProvider {
|
||||
else {
|
||||
Logger.error(`MsalCachePlugin: Failed to read from cache file: ${e}`);
|
||||
Logger.verbose(`MsalCachePlugin: Error occurred when trying to read cache file ${currentConfig.name}, file will be deleted: ${e.message}`);
|
||||
await fsPromises.unlink(currentConfig.cacheFilePath);
|
||||
|
||||
await this.unlinkCache(currentConfig);
|
||||
// Ensure both configurations are not same.
|
||||
if (currentConfig.name !== alternateConfig.name) {
|
||||
// Delete alternate cache file as well.
|
||||
alternateConfig.lockTaken = await this.waitAndLock(alternateConfig.lockFilePath, alternateConfig.lockTaken);
|
||||
await fsPromises.unlink(alternateConfig.cacheFilePath);
|
||||
await this.unlinkCache(alternateConfig);
|
||||
lockFile.unlockSync(alternateConfig.lockFilePath);
|
||||
alternateConfig.lockTaken = false;
|
||||
Logger.verbose(`MsalCachePlugin: Cache file for ${alternateConfig.name} cache also deleted.`);
|
||||
@@ -276,5 +269,16 @@ export class MsalCachePluginProvider {
|
||||
}
|
||||
return lockTaken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes access token cache file for specified config
|
||||
*/
|
||||
private async unlinkCache(config: CacheConfiguration): Promise<void> {
|
||||
try {
|
||||
await fsPromises.unlink(config.cacheFilePath);
|
||||
} catch (e) {
|
||||
Logger.info(`An error occurred when clearing ${config.name} Cache, safely ignored: ${e}`);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import * as vscode from 'vscode';
|
||||
import { SubscriptionClient } from '@azure/arm-subscriptions';
|
||||
import { AzureAccount, azureResource } from 'azurecore';
|
||||
import { IAzureResourceSubscriptionService } from '../interfaces';
|
||||
import { TokenCredentials } from '@azure/ms-rest-js';
|
||||
import { AzureSubscriptionError } from '../errors';
|
||||
import { AzureResourceErrorMessageUtil } from '../utils';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
@@ -16,6 +15,7 @@ import { Logger } from '../../utils/Logger';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { TenantIgnoredError } from '../../utils/TenantIgnoredError';
|
||||
import { multiple_matching_tokens_error } from '../../constants';
|
||||
import { TokenCredentials } from '@azure/ms-rest-js';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AzureResourceSubscriptionService implements IAzureResourceSubscriptionService {
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as nls from 'vscode-nls';
|
||||
import * as Constants from '../constants';
|
||||
import { ResourceGraphClient } from '@azure/arm-resourcegraph';
|
||||
import { TokenCredentials } from '@azure/ms-rest-js';
|
||||
import { AzureRestResponse, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult, HttpRequestMethod, GetLocationsResult, GetManagedDatabasesResult, CreateResourceGroupResult, GetBlobsResult, GetStorageAccountAccessKeyResult, AzureAccount, azureResource, AzureAccountProviderMetadata, AzureNetworkResponse } from 'azurecore';
|
||||
import { AzureRestResponse, GetResourceGroupsResult, GetSubscriptionsResult, ResourceQueryResult, GetBlobContainersResult, GetFileSharesResult, HttpRequestMethod, GetLocationsResult, GetManagedDatabasesResult, CreateResourceGroupResult, GetBlobsResult, GetStorageAccountAccessKeyResult, AzureAccount, azureResource, AzureAccountProviderMetadata } from 'azurecore';
|
||||
import { EOL } from 'os';
|
||||
import { AppContext } from '../appContext';
|
||||
import { invalidAzureAccount, invalidTenant, unableToFetchTokenError } from '../localizedConstants';
|
||||
@@ -18,9 +18,6 @@ import { IAzureResourceSubscriptionFilterService, IAzureResourceSubscriptionServ
|
||||
import { AzureResourceGroupService } from './providers/resourceGroup/resourceGroupService';
|
||||
import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
||||
import providerSettings from '../account-provider/providerSettings';
|
||||
import { getProxyEnabledHttpClient } from '../utils';
|
||||
import { HttpClient } from '../account-provider/auths/httpClient';
|
||||
import { NetworkRequestOptions } from '@azure/msal-common';
|
||||
import { ErrorResponseBody } from '@azure/arm-subscriptions/esm/models';
|
||||
import { TenantIgnoredError } from '../utils/TenantIgnoredError';
|
||||
import { AzureMonitorResourceService } from './providers/azuremonitor/azuremonitorService';
|
||||
@@ -52,6 +49,7 @@ import { PostgresFlexibleServerTreeDataProvider } from './providers/postgresFlex
|
||||
import { PostgresFlexibleServerService } from './providers/postgresFlexibleServer/postgresFlexibleServerService';
|
||||
import { CosmosDbPostgresTreeDataProvider } from './providers/cosmosdb/postgres/cosmosDbPostgresTreeDataProvider';
|
||||
import { CosmosDbPostgresService } from './providers/cosmosdb/postgres/cosmosDbPostgresService';
|
||||
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -463,7 +461,6 @@ export async function makeHttpRequest<B>(
|
||||
requestHeaders: Record<string, string> = {}
|
||||
): Promise<AzureRestResponse<B>> {
|
||||
const result: AzureRestResponse<B> = { response: undefined, errors: [] };
|
||||
const httpClient: HttpClient = getProxyEnabledHttpClient();
|
||||
|
||||
if (!account?.properties?.tenants || !Array.isArray(account.properties.tenants)) {
|
||||
const error = new Error(invalidAzureAccount);
|
||||
@@ -509,10 +506,9 @@ export async function makeHttpRequest<B>(
|
||||
...requestHeaders
|
||||
}
|
||||
|
||||
const body = JSON.stringify(requestBody || '');
|
||||
let networkRequestOptions: NetworkRequestOptions = {
|
||||
const config: AxiosRequestConfig = {
|
||||
headers: reqHeaders,
|
||||
body
|
||||
validateStatus: () => true // Never throw
|
||||
};
|
||||
|
||||
// Adding '/' if path does not begin with it.
|
||||
@@ -527,26 +523,22 @@ export async function makeHttpRequest<B>(
|
||||
requestUrl = `${account.properties.providerSettings.settings.armResource.endpoint}${path}`;
|
||||
}
|
||||
|
||||
let response: AzureNetworkResponse<B | ErrorResponseBodyWithError> | undefined = undefined;
|
||||
let response: AxiosResponse<B | ErrorResponseBodyWithError> | undefined;
|
||||
switch (requestType) {
|
||||
case HttpRequestMethod.GET:
|
||||
response = await httpClient.sendGetRequestAsync<B | ErrorResponseBodyWithError>(requestUrl, {
|
||||
headers: reqHeaders
|
||||
});
|
||||
response = await axios.get(requestUrl, config);
|
||||
break;
|
||||
case HttpRequestMethod.POST:
|
||||
response = await httpClient.sendPostRequestAsync<B | ErrorResponseBodyWithError>(requestUrl, networkRequestOptions);
|
||||
response = await axios.post(requestUrl, requestBody, config);
|
||||
break;
|
||||
case HttpRequestMethod.PUT:
|
||||
response = await httpClient.sendPutRequestAsync<B | ErrorResponseBodyWithError>(requestUrl, networkRequestOptions);
|
||||
response = await axios.put(requestUrl, requestBody, config);
|
||||
break;
|
||||
case HttpRequestMethod.DELETE:
|
||||
response = await httpClient.sendDeleteRequestAsync<B | ErrorResponseBodyWithError>(requestUrl, {
|
||||
headers: reqHeaders
|
||||
});
|
||||
response = await axios.delete(requestUrl, config);
|
||||
break;
|
||||
case HttpRequestMethod.PATCH:
|
||||
response = await httpClient.sendPatchRequestAsync<B | ErrorResponseBodyWithError>(requestUrl, networkRequestOptions);
|
||||
response = await axios.patch(requestUrl, config);
|
||||
break;
|
||||
default:
|
||||
const error = new Error(`Unknown RequestType "${requestType}"`);
|
||||
@@ -576,7 +568,7 @@ export async function makeHttpRequest<B>(
|
||||
result.errors.push(error);
|
||||
} else {
|
||||
// We know this isn't an error response at this point
|
||||
result.response = response as AzureNetworkResponse<B>;
|
||||
result.response = response as AxiosResponse<B>;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
23
extensions/azurecore/src/azurecore.d.ts
vendored
23
extensions/azurecore/src/azurecore.d.ts
vendored
@@ -8,6 +8,7 @@ declare module 'azurecore' {
|
||||
import * as vscode from 'vscode';
|
||||
import * as msRest from '@azure/ms-rest-js';
|
||||
import { BlobItem } from '@azure/storage-blob';
|
||||
import { AxiosResponse } from 'axios';
|
||||
|
||||
/**
|
||||
* Covers defining what the azurecore extension exports to other extensions
|
||||
@@ -93,11 +94,6 @@ declare module 'azurecore' {
|
||||
*/
|
||||
microsoftResource: Resource
|
||||
|
||||
/**
|
||||
* Information that describes the AAD graph resource
|
||||
*/
|
||||
graphResource: Resource;
|
||||
|
||||
/**
|
||||
* Information that describes the MS graph resource
|
||||
*/
|
||||
@@ -172,7 +168,7 @@ declare module 'azurecore' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a resource exposed by an Azure Active Directory
|
||||
* Represents a resource exposed by a Microsoft Entra identity
|
||||
*/
|
||||
export interface Resource {
|
||||
/**
|
||||
@@ -197,7 +193,7 @@ declare module 'azurecore' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a tenant (an Azure Active Directory instance) to which a user has access
|
||||
* Represents a Microsoft Entra tenant to which a user has access
|
||||
*/
|
||||
export interface Tenant {
|
||||
/**
|
||||
@@ -278,17 +274,6 @@ declare module 'azurecore' {
|
||||
PATCH
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom version of NetworkResponse from @azure\msal-common\dist\network\NetworkManager.d.ts
|
||||
* with body renamed to data to avoid breaking changes with extensions. See
|
||||
* https://github.com/microsoft/azuredatastudio/pull/22761 for details.
|
||||
*/
|
||||
export type AzureNetworkResponse<T> = {
|
||||
headers: Record<string, string>;
|
||||
data: T;
|
||||
status: number;
|
||||
};
|
||||
|
||||
export interface IExtension {
|
||||
/**
|
||||
* Gets the list of subscriptions for the specified AzureAccount
|
||||
@@ -355,7 +340,7 @@ declare module 'azurecore' {
|
||||
export type GetFileSharesResult = { fileShares: azureResource.FileShare[], errors: Error[] };
|
||||
export type CreateResourceGroupResult = { resourceGroup: azureResource.AzureResourceResourceGroup | undefined, errors: Error[] };
|
||||
export type ResourceQueryResult<T extends azureResource.AzureGraphResource> = { resources: T[], errors: Error[] };
|
||||
export type AzureRestResponse<B> = { response: AzureNetworkResponse<B> | undefined, errors: Error[] };
|
||||
export type AzureRestResponse<B> = { response: AxiosResponse<B> | undefined, errors: Error[] };
|
||||
export type GetBlobsResult = { blobs: azureResource.Blob[], errors: Error[] };
|
||||
export type GetStorageAccountAccessKeyResult = { keyName1: string, keyName2: string, errors: Error[] };
|
||||
export type CacheEncryptionKeys = { key: string; iv: string; }
|
||||
|
||||
@@ -112,6 +112,12 @@ export const AADSTS50085 = 'AADSTS50085';
|
||||
* or are revoked by the user or an admin. The app will request a new login from the user.
|
||||
*/
|
||||
export const AADSTS50089 = 'AADSTS50089';
|
||||
/**
|
||||
* ExpiredOrRevokedGrantInactiveToken - The refresh token has expired due to inactivity.
|
||||
* The token was issued on {issueDate} and was inactive for {time}. Expected part of the token lifecycle -
|
||||
* the user went an extended period of time without using the application, so the token was expired when the app attempted to refresh it.
|
||||
*/
|
||||
export const AADSTS700082 = 'AADSTS700082';
|
||||
/**
|
||||
* The refresh token was issued to a single page app (SPA), and therefore has a fixed, limited lifetime of {time}, which can't be extended.
|
||||
* It is now expired and a new sign in request must be sent by the SPA to the sign in page. The token was issued on {issueDate}.
|
||||
|
||||
@@ -10,19 +10,12 @@ import * as constants from './constants';
|
||||
|
||||
import { AzureRegion, azureResource } from 'azurecore';
|
||||
import { AppContext } from './appContext';
|
||||
import { HttpClient } from './account-provider/auths/httpClient';
|
||||
import { parse } from 'url';
|
||||
import { getProxyAgentOptions } from './proxy';
|
||||
import { HttpsProxyAgentOptions } from 'https-proxy-agent';
|
||||
import { ProviderSettings, ProviderSettingsJson, SettingIds } from './account-provider/interfaces';
|
||||
import { AzureResource } from 'azdata';
|
||||
import { Logger } from './utils/Logger';
|
||||
import { TelemetryAction, TelemetryReporter, TelemetryViews } from './telemetry';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const configProxy = 'proxy';
|
||||
const configProxyStrictSSL = 'proxyStrictSSL';
|
||||
const configProxyAuthorization = 'proxyAuthorization';
|
||||
|
||||
/**
|
||||
* Converts a region value (@see AzureRegion) into the localized Display Name
|
||||
@@ -145,10 +138,6 @@ export function getResourceTypeDisplayName(type: string): string {
|
||||
return type;
|
||||
}
|
||||
|
||||
function getHttpConfiguration(): vscode.WorkspaceConfiguration {
|
||||
return vscode.workspace.getConfiguration(constants.httpConfigSectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tenants to be ignored.
|
||||
* @returns Tenants configured in ignore list
|
||||
@@ -217,11 +206,6 @@ function buildCustomCloudProviderSettings(customProvider: ProviderSettingsJson):
|
||||
endpoint: customProvider.settings.metadata.endpoints.armResource,
|
||||
azureResourceId: AzureResource.ResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: customProvider.settings.metadata.endpoints.graphResource,
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
azureStorageResource: {
|
||||
id: SettingIds.storage,
|
||||
endpoint: customProvider.settings.metadata.endpoints.azureStorageResource.endpoint,
|
||||
@@ -308,25 +292,6 @@ export interface IPackageInfo {
|
||||
aiKey: string;
|
||||
}
|
||||
|
||||
export function getProxyEnabledHttpClient(): HttpClient {
|
||||
const proxy = <string>getHttpConfiguration().get(configProxy);
|
||||
const strictSSL = getHttpConfiguration().get(configProxyStrictSSL, true);
|
||||
const authorization = getHttpConfiguration().get(configProxyAuthorization);
|
||||
|
||||
const url = parse(proxy);
|
||||
let agentOptions = getProxyAgentOptions(url, proxy, strictSSL);
|
||||
|
||||
if (authorization && url.protocol === 'https:') {
|
||||
let httpsAgentOptions = agentOptions as HttpsProxyAgentOptions;
|
||||
httpsAgentOptions!.headers = Object.assign(httpsAgentOptions!.headers || {}, {
|
||||
'Proxy-Authorization': authorization
|
||||
});
|
||||
agentOptions = httpsAgentOptions;
|
||||
}
|
||||
|
||||
return new HttpClient(proxy, agentOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display notification with button to reload
|
||||
* @param sectionName Name of section to reload
|
||||
|
||||
@@ -9,22 +9,24 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@azure/arm-resourcegraph@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/arm-resourcegraph/-/arm-resourcegraph-4.0.0.tgz#9f8b1e521124eaec20ac8224935af718ce2d5e7d"
|
||||
integrity sha512-2iCedUV2WACNKeivlt1YLpHDTFaMLvaWMizdkocaHp+e4K8QiV/ToB0FxBWHtT0l9SH9RK4hoHEcgtW5bEEnAg==
|
||||
"@azure/arm-resourcegraph@^4.2.1":
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@azure/arm-resourcegraph/-/arm-resourcegraph-4.2.1.tgz#d529d5da40356393a22eb51a2af4ba91ef1ae1ec"
|
||||
integrity sha512-PDuRJ6I7wpy/bu2dqX3OVvX6fpM3YzXkFLGnmYpevYFBQBgueNhHruBAk5r1xh2VRTv1M0lAdaYy6LmVHiCRTw==
|
||||
dependencies:
|
||||
"@azure/ms-rest-azure-js" "^2.0.1"
|
||||
"@azure/ms-rest-js" "^2.0.4"
|
||||
"@azure/core-auth" "^1.1.4"
|
||||
"@azure/ms-rest-azure-js" "^2.1.0"
|
||||
"@azure/ms-rest-js" "^2.2.0"
|
||||
tslib "^1.10.0"
|
||||
|
||||
"@azure/arm-subscriptions@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/arm-subscriptions/-/arm-subscriptions-3.0.0.tgz#e47b57ee35452c289d820ccd5fcb59ac107616ec"
|
||||
integrity sha512-EIPbFJsjLtp6sEDyCJqqt9UIwYm4sAcMEA5pDVXQmEwKPtUckxmqalmFUN9754crv63QRR+Vy01gccJZDR5m1Q==
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/arm-subscriptions/-/arm-subscriptions-3.1.2.tgz#6afb0754789942f190c2d8e244a521c9e2cdb886"
|
||||
integrity sha512-fO1Sxjn27At53Zkgs0tKW9l6iYavfbVgkK4rCFYa2d3M5yofGctHafYDTHQLnp7dYwUzGzTHrBMlyrKo92QpAQ==
|
||||
dependencies:
|
||||
"@azure/ms-rest-azure-js" "^2.0.1"
|
||||
"@azure/ms-rest-js" "^2.0.4"
|
||||
"@azure/core-auth" "^1.1.4"
|
||||
"@azure/ms-rest-azure-js" "^2.1.0"
|
||||
"@azure/ms-rest-js" "^2.2.0"
|
||||
tslib "^1.10.0"
|
||||
|
||||
"@azure/core-auth@^1.1.4":
|
||||
@@ -102,7 +104,7 @@
|
||||
dependencies:
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/ms-rest-azure-js@^2.0.1":
|
||||
"@azure/ms-rest-azure-js@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-js/-/ms-rest-azure-js-2.1.0.tgz#8c90b31468aeca3146b06c7144b386fd4827f64c"
|
||||
integrity sha512-CjZjB8apvXl5h97Ck6SbeeCmU0sk56YPozPtTyGudPp1RGoHXNjFNtoOvwOG76EdpmMpxbK10DqcygI16Lu60Q==
|
||||
@@ -111,7 +113,7 @@
|
||||
"@azure/ms-rest-js" "^2.2.0"
|
||||
tslib "^1.10.0"
|
||||
|
||||
"@azure/ms-rest-js@^2.0.4", "@azure/ms-rest-js@^2.2.0":
|
||||
"@azure/ms-rest-js@^2.2.0":
|
||||
version "2.6.6"
|
||||
resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-2.6.6.tgz#a2ae4a515565ae1b73729b52b25875853bb3240a"
|
||||
integrity sha512-WYIda8VvrkZE68xHgOxUXvjThxNf1nnGPPe0rAljqK5HJHIZ12Pi3YhEDOn3Ge7UnwaaM3eFO0VtAy4nGVI27Q==
|
||||
@@ -126,24 +128,24 @@
|
||||
uuid "^8.3.2"
|
||||
xml2js "^0.5.0"
|
||||
|
||||
"@azure/msal-common@^11.0.0":
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-11.0.0.tgz#d35bfa6cdd2a5b8c036ce427aa3fd36f8f985239"
|
||||
integrity sha512-SZH8ObQ3Hq5v3ogVGBYJp1nNW7p+MtM4PH4wfNadBP9wf7K0beQHF9iOtRcjPOkwZf+ZD49oXqw91LndIkdk8g==
|
||||
"@azure/msal-common@13.3.0", "@azure/msal-common@^13.3.0":
|
||||
version "13.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-13.3.0.tgz#dfa39810e0fbce6e07ca85a2cf305da58d30b7c9"
|
||||
integrity sha512-/VFWTicjcJbrGp3yQP7A24xU95NiDMe23vxIU1U6qdRPFsprMDNUohMudclnd+WSHE4/McqkZs/nUU3sAKkVjg==
|
||||
|
||||
"@azure/msal-node@^1.16.0":
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.16.0.tgz#0bd469916f5a9da22d844edc879ac7e8225c0ccb"
|
||||
integrity sha512-eGXPp65i++mAIvziafbCH970TCeECB6iaQP7aRzZEjtU238cW4zKm40U8YxkiCn9rR1G2VeMHENB5h6WRk7ZCQ==
|
||||
"@azure/msal-node@^1.18.3":
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.18.3.tgz#e265556d4db0340590eeab5341469fb6740251d0"
|
||||
integrity sha512-lI1OsxNbS/gxRD4548Wyj22Dk8kS7eGMwD9GlBZvQmFV8FJUXoXySL1BiNzDsHUE96/DS/DHmA+F73p1Dkcktg==
|
||||
dependencies:
|
||||
"@azure/msal-common" "^11.0.0"
|
||||
"@azure/msal-common" "13.3.0"
|
||||
jsonwebtoken "^9.0.0"
|
||||
uuid "^8.3.0"
|
||||
|
||||
"@azure/storage-blob@^12.13.0":
|
||||
version "12.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.13.0.tgz#9209cbb5c2cd463fb967a0f2ae144ace20879160"
|
||||
integrity sha512-t3Q2lvBMJucgTjQcP5+hvEJMAsJSk0qmAnjDLie2td017IiduZbbC9BOcFfmwzR6y6cJdZOuewLCNFmEx9IrXA==
|
||||
version "12.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.16.0.tgz#c41fb1e538d6f6e2a6756bfcc69382eededf4fa1"
|
||||
integrity sha512-jz33rUSUGUB65FgYrTRgRDjG6hdPHwfvHe+g/UrwVG8MsyLqSxg9TaW7Yuhjxu1v1OZ5xam2NU6+IpCN0xJO8Q==
|
||||
dependencies:
|
||||
"@azure/abort-controller" "^1.0.0"
|
||||
"@azure/core-http" "^3.0.0"
|
||||
@@ -596,13 +598,14 @@ asynckit@^0.4.0:
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
axios@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
|
||||
integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -991,10 +994,10 @@ flat@^5.0.2:
|
||||
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
|
||||
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
|
||||
|
||||
follow-redirects@^1.14.9:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4"
|
||||
integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
|
||||
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
|
||||
|
||||
form-data@^2.5.0:
|
||||
version "2.5.1"
|
||||
@@ -1582,7 +1585,7 @@ mime-types@^2.1.12:
|
||||
dependencies:
|
||||
mime-db "1.43.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1596,6 +1599,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
@@ -1866,6 +1876,11 @@ process@^0.11.10:
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||
@@ -1877,9 +1892,9 @@ punycode@^2.1.1:
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
qs@^6.9.1:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
version "6.11.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
|
||||
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
@@ -2332,9 +2347,9 @@ wrappy@1:
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
ws@^7.4.6:
|
||||
version "7.4.6"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
|
||||
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
|
||||
version "7.5.9"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
|
||||
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
||||
|
||||
xml2js@^0.5.0:
|
||||
version "0.5.0"
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-azuremonitor ./syntaxes/azuremonitor.tmLanguage"
|
||||
},
|
||||
"dependencies": {
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
|
||||
"figures": "^2.0.0",
|
||||
"find-remove": "1.2.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"azuremonitor.connectionOptions.databaseName.description": "The name of the initial catalog or database in the data source",
|
||||
"azuremonitor.connectionProperties.authType.displayName": "Authentication type",
|
||||
"azuremonitor.connectionProperties.authType.description": "Specifies the method of authenticating with Azure Monitor",
|
||||
"azuremonitor.connectionProperties.authType.categoryValues.azureMFA": "Azure Active Directory - Universal with MFA support",
|
||||
"azuremonitor.connectionProperties.authType.categoryValues.azureMFA": "Microsoft Entra ID - Universal with MFA support",
|
||||
"azuremonitor.connectionProperties.groupName.source": "Source",
|
||||
"azuremonitor.connectionProperties.groupName.security": "Security"
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
|
||||
version "1.3.7"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
@@ -180,9 +180,9 @@ inherits@2:
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"cms.connectionOptions.authType.description": "Specifies the method of authenticating with SQL Server",
|
||||
"cms.connectionOptions.authType.categoryValues.sqlLogin": "SQL Login",
|
||||
"cms.connectionOptions.authType.categoryValues.integrated": "Windows Authentication",
|
||||
"cms.connectionOptions.authType.categoryValues.azureMFA": "Azure Active Directory - Universal with MFA support",
|
||||
"cms.connectionOptions.authType.categoryValues.azureMFA": "Microsoft Entra ID - Universal with MFA support",
|
||||
"cms.connectionOptions.userName.displayName": "User name",
|
||||
"cms.connectionOptions.userName.description": "Indicates the user ID to be used when connecting to the data source",
|
||||
"cms.connectionOptions.password.displayName": "Password",
|
||||
|
||||
@@ -1139,9 +1139,9 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
@@ -1153,6 +1153,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -288,6 +288,7 @@ export function createViewContext(): ViewTestContext {
|
||||
modelBuilder: {
|
||||
listView: undefined!,
|
||||
radioCardGroup: undefined!,
|
||||
chart: undefined!,
|
||||
navContainer: undefined!,
|
||||
divContainer: () => divBuilder,
|
||||
flexContainer: () => flexBuilder,
|
||||
|
||||
@@ -1297,7 +1297,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1311,6 +1311,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -1285,7 +1285,7 @@ micromatch@^4.0.4:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1299,6 +1299,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
"dependencies": {
|
||||
"@microsoft/ads-extension-telemetry": "^3.0.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
|
||||
"vscode-nls": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -597,6 +597,9 @@ export class MockModelBuilder implements azdata.ModelBuilder {
|
||||
listView(): azdata.ComponentBuilder<azdata.ListViewComponent, azdata.ListViewComponentProperties> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
chart<TChartType extends azdata.ChartType, TData extends azdata.ChartData<TChartType>, TOptions extends azdata.ChartOptions<TChartType>>(): azdata.ComponentBuilder<azdata.ChartComponent<TChartType, TData, TOptions>, azdata.ChartComponentProperties<TChartType, TData, TOptions>> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
slider(): azdata.ComponentBuilder<azdata.SliderComponent, azdata.SliderComponentProperties> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
@@ -497,9 +497,9 @@ crypt@0.0.2:
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
|
||||
version "1.3.7"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
@@ -903,9 +903,9 @@ minimatch@5.0.1:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Git static contributions and remote repository picker
|
||||
|
||||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
|
||||
**Notice:** This extension is bundled with Azure Data Studio. It can be disabled but not uninstalled.
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Git integration for Visual Studio Code
|
||||
# Git integration for Azure Data Studio
|
||||
|
||||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
|
||||
**Notice:** This extension is bundled with Azure Data Studio. It can be disabled but not uninstalled.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -17,4 +17,4 @@ The Git extension exposes an API, reachable by any other extension.
|
||||
```ts
|
||||
const gitExtension = vscode.extensions.getExtension<GitExtension>('vscode.git').exports;
|
||||
const git = gitExtension.getAPI(1);
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GitHub for Visual Studio Code
|
||||
# GitHub for Azure Data Studio
|
||||
|
||||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
|
||||
**Notice:** This extension is bundled with Azure Data Studio. It can be disabled but not uninstalled.
|
||||
|
||||
## Features
|
||||
|
||||
|
||||
@@ -155,9 +155,9 @@ graphql-tag@^2.10.3:
|
||||
tslib "^2.1.0"
|
||||
|
||||
graphql@^16.0.0:
|
||||
version "16.6.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb"
|
||||
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==
|
||||
version "16.8.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
|
||||
integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
|
||||
|
||||
is-plain-object@^5.0.0:
|
||||
version "5.0.0"
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
|
||||
"htmlparser2": "^3.10.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
"@microsoft/ads-extension-telemetry": "^3.0.1",
|
||||
|
||||
@@ -572,9 +572,9 @@ crypt@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
|
||||
version "1.3.7"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
@@ -1325,7 +1325,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1339,6 +1339,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -154,24 +154,29 @@
|
||||
tslib "^2.2.0"
|
||||
|
||||
"@azure/msal-browser@^2.26.0":
|
||||
version "2.27.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.27.0.tgz#3db38db6bc2bae44485025ba9bb99c43ed7f4302"
|
||||
integrity sha512-PyATq2WvK+x32waRqqikym8wvn939iO9UhpFqhLwitNrfLa3PHUgJuuI9oLSQOS3/UzjYb8aqN+XzchU3n/ZuQ==
|
||||
version "2.38.2"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.38.2.tgz#707725c892258fe6b3af4dd410e1daff608521b5"
|
||||
integrity sha512-71BeIn2we6LIgMplwCSaMq5zAwmalyJR3jFcVOZxNVfQ1saBRwOD+P77nLs5vrRCedVKTq8RMFhIOdpMLNno0A==
|
||||
dependencies:
|
||||
"@azure/msal-common" "^7.1.0"
|
||||
"@azure/msal-common" "13.3.0"
|
||||
|
||||
"@azure/msal-common@^7.0.0", "@azure/msal-common@^7.1.0":
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-7.1.0.tgz#b77dbf9ae581f1ed254f81d56422e3cdd6664b32"
|
||||
integrity sha512-WyfqE5mY/rggjqvq0Q5DxLnA33KSb0vfsUjxa95rycFknI03L5GPYI4HTU9D+g0PL5TtsQGnV3xzAGq9BFCVJQ==
|
||||
"@azure/msal-common@13.3.0":
|
||||
version "13.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-13.3.0.tgz#dfa39810e0fbce6e07ca85a2cf305da58d30b7c9"
|
||||
integrity sha512-/VFWTicjcJbrGp3yQP7A24xU95NiDMe23vxIU1U6qdRPFsprMDNUohMudclnd+WSHE4/McqkZs/nUU3sAKkVjg==
|
||||
|
||||
"@azure/msal-common@^7.0.0":
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-7.6.0.tgz#b52e97ef540275f72611cff57937dfa0b34cdcca"
|
||||
integrity sha512-XqfbglUTVLdkHQ8F9UQJtKseRr3sSnr9ysboxtoswvaMVaEfvyLtMoHv9XdKUfOc0qKGzNgRFd9yRjIWVepl6Q==
|
||||
|
||||
"@azure/msal-node@^1.10.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.11.0.tgz#d8bd3f15c1f05bf806ba6f9479c48c2eddd6a98d"
|
||||
integrity sha512-KW/XEexfCrPzdYbjY7NVmhq9okZT3Jvck55CGXpz9W5asxeq3EtrP45p+ZXtQVEfko0YJdolpCNqWUyXvanWZg==
|
||||
version "1.18.3"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-1.18.3.tgz#e265556d4db0340590eeab5341469fb6740251d0"
|
||||
integrity sha512-lI1OsxNbS/gxRD4548Wyj22Dk8kS7eGMwD9GlBZvQmFV8FJUXoXySL1BiNzDsHUE96/DS/DHmA+F73p1Dkcktg==
|
||||
dependencies:
|
||||
"@azure/msal-common" "^7.1.0"
|
||||
jsonwebtoken "^8.5.1"
|
||||
"@azure/msal-common" "13.3.0"
|
||||
jsonwebtoken "^9.0.0"
|
||||
uuid "^8.3.0"
|
||||
|
||||
"@babel/code-frame@^7.10.1":
|
||||
@@ -1402,7 +1407,7 @@ json5@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonwebtoken@9.0.0, jsonwebtoken@^8.5.1:
|
||||
jsonwebtoken@9.0.0, jsonwebtoken@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d"
|
||||
integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==
|
||||
@@ -1524,7 +1529,7 @@ mime-types@^2.1.12:
|
||||
dependencies:
|
||||
mime-db "~1.30.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1538,6 +1543,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"vscode": "^1.57.0"
|
||||
"vscode": "^1.57.0",
|
||||
"azdata": "*"
|
||||
},
|
||||
"enabledApiProposals": [
|
||||
"documentPaste",
|
||||
@@ -14,7 +15,7 @@
|
||||
"dropMetadata"
|
||||
],
|
||||
"activationEvents": [
|
||||
"*"
|
||||
"onNotebook:jupyter-notebook"
|
||||
],
|
||||
"extensionKind": [
|
||||
"workspace",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as azdata from 'azdata'; // {{SQL CARBON EDIT}}
|
||||
import { NotebookSerializer } from './notebookSerializer';
|
||||
import { ensureAllNewCellsHaveCellIds } from './cellIdService';
|
||||
import { notebookImagePasteSetup } from './notebookImagePaste';
|
||||
@@ -58,21 +59,27 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
});
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('ipynb.newUntitledIpynb', async () => {
|
||||
const language = 'python';
|
||||
const cell = new vscode.NotebookCellData(vscode.NotebookCellKind.Code, '', language);
|
||||
const data = new vscode.NotebookData([cell]);
|
||||
data.metadata = {
|
||||
custom: {
|
||||
cells: [],
|
||||
metadata: {
|
||||
orig_nbformat: 4
|
||||
},
|
||||
nbformat: 4,
|
||||
nbformat_minor: 2
|
||||
}
|
||||
};
|
||||
const doc = await vscode.workspace.openNotebookDocument('jupyter-notebook', data);
|
||||
await vscode.window.showNotebookDocument(doc);
|
||||
// {{SQL CARBON EDIT}} Open new notebooks using the default ADS notebook viewer if VSCode notebooks aren't enabled.
|
||||
let useVSCodeNotebooks = vscode.workspace.getConfiguration('workbench')?.get<boolean>('useVSCodeNotebooks');
|
||||
if (useVSCodeNotebooks) {
|
||||
const language = 'python';
|
||||
const cell = new vscode.NotebookCellData(vscode.NotebookCellKind.Code, '', language);
|
||||
const data = new vscode.NotebookData([cell]);
|
||||
data.metadata = {
|
||||
custom: {
|
||||
cells: [],
|
||||
metadata: {
|
||||
orig_nbformat: 4
|
||||
},
|
||||
nbformat: 4,
|
||||
nbformat_minor: 2
|
||||
}
|
||||
};
|
||||
const doc = await vscode.workspace.openNotebookDocument('jupyter-notebook', data);
|
||||
await vscode.window.showNotebookDocument(doc);
|
||||
} else {
|
||||
await azdata.nb.showNotebookDocument(vscode.Uri.from({ scheme: 'untitled' }));
|
||||
}
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('ipynb.openIpynbInNotebookEditor', async (uri: vscode.Uri) => {
|
||||
|
||||
10
extensions/ipynb/src/typings/refs.d.ts
vendored
Normal file
10
extensions/ipynb/src/typings/refs.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// {{SQL CARBON EDIT}} Import ADS extension APIs
|
||||
/// <reference path='../../../../src/sql/azdata.d.ts'/>
|
||||
/// <reference path='../../../../src/sql/azdata.proposed.d.ts'/>
|
||||
/// <reference path='../../../../src/vscode-dts/vscode.d.ts'/>
|
||||
/// <reference path='../../../resource-deployment/src/typings/resource-deployment.d.ts'/>
|
||||
@@ -427,7 +427,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
|
||||
"figures": "^2.0.0",
|
||||
"find-remove": "1.2.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"kusto.connectionOptions.databaseName.description": "The name of the initial catalog or database in the data source",
|
||||
"kusto.connectionOptions.authType.displayName": "Authentication type",
|
||||
"kusto.connectionOptions.authType.description": "Specifies the method of authenticating with Kusto Server",
|
||||
"kusto.connectionOptions.authType.categoryValues.azureMFA": "Azure Active Directory - Universal with MFA support",
|
||||
"kusto.connectionOptions.authType.categoryValues.azureMFA": "Microsoft Entra ID - Universal with MFA support",
|
||||
"kusto.connectionOptions.authType.categoryValues.none": "No Authentication",
|
||||
"kusto.connectionOptions.authType.categoryValues.sqlLogin": "User Authentication",
|
||||
"kusto.connectionOptions.userName.displayName": "User name",
|
||||
|
||||
@@ -124,9 +124,9 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
|
||||
version "1.3.7"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
@@ -255,9 +255,9 @@ mime-types@^2.1.12:
|
||||
mime-db "~1.38.0"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ export class SqlRPackageManageProvider extends SqlPackageManageProviderBase impl
|
||||
|
||||
if (connection) {
|
||||
connectionParts.push(utils.getKeyValueString('driver', `"${constants.supportedODBCDriver}"`));
|
||||
let server = connection.serverName.replace('\\', '\\\\');
|
||||
let server = connection.serverName.replace(/\\/g, '\\\\');
|
||||
if (databaseName) {
|
||||
connectionParts.push(utils.getKeyValueString('database', `"${databaseName}"`));
|
||||
}
|
||||
|
||||
@@ -234,6 +234,7 @@ export function createViewContext(): ViewTestContext {
|
||||
modelBuilder: {
|
||||
listView: undefined!,
|
||||
radioCardGroup: undefined!,
|
||||
chart: undefined!,
|
||||
navContainer: undefined!,
|
||||
divContainer: () => divBuilder,
|
||||
flexContainer: () => flexBuilder,
|
||||
|
||||
@@ -1451,7 +1451,7 @@ mime-types@^2.1.12, mime-types@~2.1.19:
|
||||
dependencies:
|
||||
mime-db "1.40.0"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1465,6 +1465,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a class="branding" href="https://code.visualstudio.com/">
|
||||
Visual Studio Code
|
||||
<!-- {{SQL CARBON EDIT}} Update application name and URL to Azure Data Studio -->
|
||||
<a class="branding" href="https://aka.ms/azuredatastudio/">
|
||||
Azure Data Studio
|
||||
</a>
|
||||
<div class="message-container">
|
||||
<div class="message">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "4.9.0.37",
|
||||
"version": "4.10.0.17",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-net7.0.zip",
|
||||
"Windows_64": "win-x64-net7.0.zip",
|
||||
|
||||
@@ -156,6 +156,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.clearPooledConnections",
|
||||
"category": "MSSQL",
|
||||
"title": "%mssql.connection.clearPooledConnections%"
|
||||
}
|
||||
],
|
||||
@@ -178,14 +179,16 @@
|
||||
"description": "%mssql.query.displayBitAsNumber%"
|
||||
},
|
||||
"mssql.query.maxXmlCharsToStore": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 2097152,
|
||||
"description": "%mssql.query.maxXmlCharsToStore%"
|
||||
"description": "%mssql.query.maxXmlCharsToStore%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.maxCharsToStore": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 65535,
|
||||
"description": "%mssql.query.maxCharsToStore%"
|
||||
"description": "%mssql.query.maxCharsToStore%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.format.alignColumnDefinitionsInColumns": {
|
||||
"type": "boolean",
|
||||
@@ -316,19 +319,22 @@
|
||||
]
|
||||
},
|
||||
"mssql.query.rowCount": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "%mssql.query.setRowCount%"
|
||||
"description": "%mssql.query.setRowCount%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.textSize": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 2147483647,
|
||||
"description": "%mssql.query.textSize%"
|
||||
"description": "%mssql.query.textSize%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.executionTimeout": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "%mssql.query.executionTimeout%"
|
||||
"description": "%mssql.query.executionTimeout%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.noCount": {
|
||||
"type": "boolean",
|
||||
@@ -384,14 +390,16 @@
|
||||
"description": "%mssql.query.deadlockPriority%"
|
||||
},
|
||||
"mssql.query.lockTimeout": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": -1,
|
||||
"description": "%mssql.query.lockTimeout%"
|
||||
"description": "%mssql.query.lockTimeout%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.queryGovernorCostLimit": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": -1,
|
||||
"description": "%mssql.query.queryGovernorCostLimit%"
|
||||
"description": "%mssql.query.queryGovernorCostLimit%",
|
||||
"maximum": 2147483647
|
||||
},
|
||||
"mssql.query.ansiDefaults": {
|
||||
"type": "boolean",
|
||||
@@ -474,10 +482,11 @@
|
||||
"description": "%mssql.objectExplorer.groupBySchema%"
|
||||
},
|
||||
"mssql.objectExplorer.expandTimeout": {
|
||||
"type": "number",
|
||||
"type": "integer",
|
||||
"default": 45,
|
||||
"minimum": 1,
|
||||
"description": "%mssql.objectExplorer.expandTimeout%"
|
||||
"description": "%mssql.objectExplorer.expandTimeout%",
|
||||
"maximum": 2147483647
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -570,7 +579,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.renameObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|Table|View|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|Table|View|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@1"
|
||||
},
|
||||
{
|
||||
@@ -580,7 +589,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.detachDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !isCloud && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures && (productQualityType =~ /^(insider|dev)$/ || isDevelopment)",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !isCloud && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@2"
|
||||
},
|
||||
{
|
||||
@@ -611,7 +620,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.objectProperties",
|
||||
"when": "connectionProvider == MSSQL && serverInfo && !isCloud && nodeType =~ /^(Database|Server)$/ && mssql:engineedition != 11 && config.workbench.enablePreviewFeatures && (productQualityType =~ /^(insider|dev)$/ || isDevelopment)",
|
||||
"when": "connectionProvider == MSSQL && serverInfo && !isCloud && nodeType =~ /^(Database|Server)$/ && mssql:engineedition != 11 && config.workbench.enablePreviewFeatures",
|
||||
"group": "z_objectexplorer@3"
|
||||
},
|
||||
{
|
||||
@@ -628,6 +637,11 @@
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType == Tables",
|
||||
"group": "inline@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType == Databases && config.workbench.enablePreviewFeatures",
|
||||
"group": "inline@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType =~ /^(ServerLevelLogins|Users|ServerLevelServerRoles|ApplicationRoles|DatabaseRoles)$/ && config.workbench.enablePreviewFeatures",
|
||||
@@ -1567,7 +1581,7 @@
|
||||
"dependencies": {
|
||||
"@microsoft/ads-extension-telemetry": "^3.0.1",
|
||||
"@microsoft/ads-service-downloader": "^1.2.1",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
|
||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
|
||||
"find-remove": "1.2.1",
|
||||
"vscode-languageclient": "5.2.1",
|
||||
"vscode-nls": "^4.0.0"
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"mssql.connectionOptions.authType.description": "Specifies the method of authenticating with SQL Server",
|
||||
"mssql.connectionOptions.authType.categoryValues.sqlLogin": "SQL Login",
|
||||
"mssql.connectionOptions.authType.categoryValues.integrated": "Windows Authentication",
|
||||
"mssql.connectionOptions.authType.categoryValues.azureMFA": "Azure Active Directory - Universal with MFA support",
|
||||
"mssql.connectionOptions.authType.categoryValues.azureMFA": "Microsoft Entra ID - Universal with MFA support",
|
||||
"mssql.connectionOptions.userName.displayName": "User name",
|
||||
"mssql.connectionOptions.userName.description": "Indicates the user ID to be used when connecting to the data source",
|
||||
"mssql.connectionOptions.password.displayName": "Password",
|
||||
@@ -174,10 +174,10 @@
|
||||
"title.newTable": "New Table",
|
||||
"title.designTable": "Design",
|
||||
"title.changeNotebookConnection": "Change SQL Notebook Connection",
|
||||
"mssql.connection.clearPooledConnections": "SQL Server: Clear Pooled Connections",
|
||||
"mssql.connection.clearPooledConnections": "Clear Pooled Connections",
|
||||
"mssql.parallelMessageProcessing": "[Experimental] Whether the requests to the SQL Tools Service should be handled in parallel. This is introduced to discover the issues there might be when handling all requests in parallel. The default value is false. Azure Data Studio is required to be relaunched when the value is changed.",
|
||||
"mssql.enableSqlAuthenticationProvider": "Enables use of the Sql Authentication Provider for 'Active Directory Interactive' authentication mode when user selects 'AzureMFA' authentication. This enables Server-side resource endpoint integration when fetching access tokens. This option is only supported for 'MSAL' Azure Authentication Library. Azure Data Studio is required to be relaunched when the value is changed.",
|
||||
"mssql.enableConnectionPooling": "Enables connection pooling on MSSQL connections to improve overall performance of Azure Data Studio connectivity. This setting is enabled by default. Azure Data Studio is required to be relaunched when the value is changed. To clear pooled connections, run the command: 'SQL Server: Clear Pooled Connections'",
|
||||
"mssql.enableConnectionPooling": "Enables connection pooling on MSSQL connections to improve overall performance of Azure Data Studio connectivity. This setting is enabled by default. Azure Data Studio is required to be relaunched when the value is changed. To clear pooled connections, run the command: 'MSSQL: Clear Pooled Connections'",
|
||||
"mssql.tableDesigner.preloadDatabaseModel": "Whether to preload the database model when the database node in the object explorer is expanded. When enabled, the loading time of table designer can be reduced. Note: You might see higher than normal memory usage if you need to expand a lot of database nodes.",
|
||||
"mssql.tableDesigner.allowDisableAndReenableDdlTriggers": "Whether to allow table designer to disable and re-enable DDL triggers during publish",
|
||||
"mssql.objectExplorer.groupBySchema": "When enabled, the database objects in Object Explorer will be categorized by schema.",
|
||||
|
||||
@@ -33,6 +33,8 @@ export const configObjectExplorerGroupBySchemaFlagName = 'mssql.objectExplorer.g
|
||||
export const configAsyncParallelProcessingName = 'mssql.parallelMessageProcessing';
|
||||
export const configEnableSqlAuthenticationProviderName = 'mssql.enableSqlAuthenticationProvider';
|
||||
export const configEnableConnectionPoolingName = 'mssql.enableConnectionPooling';
|
||||
export const configHttpProxy = 'http.proxy';
|
||||
export const configHttpProxyStrictSSL = 'http.proxyStrictSSL';
|
||||
|
||||
// COMMANDNAMES //////////////////////////////////////////////////////////
|
||||
export const cmdObjectExplorerEnableGroupBySchemaCommand = 'mssql.enableGroupBySchema';
|
||||
|
||||
@@ -1649,7 +1649,6 @@ export namespace SearchObjectRequest {
|
||||
export interface DetachDatabaseRequestParams {
|
||||
connectionUri: string;
|
||||
database: string;
|
||||
objectUrn: string;
|
||||
dropConnections: boolean;
|
||||
updateStatistics: boolean;
|
||||
generateScript: boolean;
|
||||
@@ -1662,7 +1661,6 @@ export namespace DetachDatabaseRequest {
|
||||
export interface DropDatabaseRequestParams {
|
||||
connectionUri: string;
|
||||
database: string;
|
||||
objectUrn: string;
|
||||
dropConnections: boolean;
|
||||
deleteBackupHistory: boolean;
|
||||
generateScript: boolean;
|
||||
@@ -1700,13 +1698,12 @@ export namespace GetAssociatedFilesRequest {
|
||||
}
|
||||
|
||||
export namespace PurgeQueryStoreDataRequest {
|
||||
export const type = new RequestType<purgeQueryStoreDataRequestParams, void, void, void>('objectManagement/purgeQueryStoreData');
|
||||
export const type = new RequestType<PurgeQueryStoreDataRequestParams, void, void, void>('objectManagement/purgeQueryStoreData');
|
||||
}
|
||||
|
||||
export interface purgeQueryStoreDataRequestParams {
|
||||
export interface PurgeQueryStoreDataRequestParams {
|
||||
connectionUri: string;
|
||||
database: string;
|
||||
objectUrn: string;
|
||||
}
|
||||
|
||||
// ------------------------------- < Object Management > ------------------------------------
|
||||
|
||||
@@ -153,6 +153,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
|
||||
}
|
||||
await displayReloadAds();
|
||||
}
|
||||
// Prompt to reload ADS as we send the proxy URL to STS to instantiate Http Client instances.
|
||||
if (e.affectsConfiguration(Constants.configHttpProxy) || e.affectsConfiguration(Constants.configHttpProxyStrictSSL)) {
|
||||
await displayReloadAds();
|
||||
}
|
||||
}));
|
||||
|
||||
registerTableDesignerCommands(appContext);
|
||||
|
||||
9
extensions/mssql/src/mssql.d.ts
vendored
9
extensions/mssql/src/mssql.d.ts
vendored
@@ -981,13 +981,12 @@ declare module 'mssql' {
|
||||
* Detach a database.
|
||||
* @param connectionUri The URI of the server connection.
|
||||
* @param database The target database.
|
||||
* @param objectUrn SMO Urn of the database to be detached. More information: https://learn.microsoft.com/sql/relational-databases/server-management-objects-smo/overview-smo
|
||||
* @param dropConnections Whether to drop active connections to this database.
|
||||
* @param updateStatistics Whether to update the optimization statistics related to this database.
|
||||
* @param generateScript Whether to generate a TSQL script for the operation instead of detaching the database.
|
||||
* @returns A string value representing the generated TSQL query if generateScript was set to true, and an empty string otherwise.
|
||||
*/
|
||||
detachDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Thenable<string>;
|
||||
detachDatabase(connectionUri: string, database: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Thenable<string>;
|
||||
/**
|
||||
* Attach one or more databases.
|
||||
* @param connectionUri The URI of the server connection.
|
||||
@@ -1000,13 +999,12 @@ declare module 'mssql' {
|
||||
* Drop a database.
|
||||
* @param connectionUri The URI of the server connection.
|
||||
* @param database The target database.
|
||||
* @param objectUrn SMO Urn of the database to be detached. More information: https://learn.microsoft.com/sql/relational-databases/server-management-objects-smo/overview-smo
|
||||
* @param dropConnections Whether to drop active connections to this database.
|
||||
* @param deleteBackupHistory Whether to delete backup and restore history information for this database.
|
||||
* @param generateScript Whether to generate a TSQL script for the operation instead of detaching the database.
|
||||
* @returns A string value representing the generated TSQL query if generateScript was set to true, and an empty string otherwise.
|
||||
*/
|
||||
dropDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string>;
|
||||
dropDatabase(connectionUri: string, database: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string>;
|
||||
/**
|
||||
* Gets the file path for the default database file folder for a SQL Server instance.
|
||||
* @param connectionUri The URI of the connection for the specific server.
|
||||
@@ -1024,9 +1022,8 @@ declare module 'mssql' {
|
||||
* Clears all query store data from the database
|
||||
* @param connectionUri The URI of the server connection.
|
||||
* @param database The target database.
|
||||
* @param objectUrn SMO Urn of the database to be detached. More information: https://learn.microsoft.com/sql/relational-databases/server-management-objects-smo/overview-smo
|
||||
*/
|
||||
purgeQueryStoreData(connectionUri: string, database: string, objectUrn: string): Thenable<void>;
|
||||
purgeQueryStoreData(connectionUri: string, database: string): Thenable<void>;
|
||||
}
|
||||
|
||||
export interface DatabaseFileData {
|
||||
|
||||
@@ -130,7 +130,13 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = getDialog(service, options);
|
||||
const startTime = Date.now();
|
||||
await dialog.open();
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.OpenNewObjectDialog, {
|
||||
objectType: objectType
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenNewObjectDialog, err).withAdditionalProperties({
|
||||
@@ -146,31 +152,33 @@ async function handleObjectPropertiesDialogCommand(context: azdata.ObjectExplore
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
const object = await getObjectInfoForContext(context);
|
||||
try {
|
||||
const parentUrn = context.isConnectionNode ? undefined : await getParentUrn(context);
|
||||
const objectType = context.nodeInfo ? context.nodeInfo.nodeType as ObjectManagement.NodeType : (context.connectionProfile.databaseName === '' ? ObjectManagement.NodeType.Server : ObjectManagement.NodeType.Database);
|
||||
const objectName = context.nodeInfo ? context.nodeInfo.label : (!context.connectionProfile.databaseName ? context.connectionProfile.serverName : context.connectionProfile.databaseName);
|
||||
const objectUrn = context.nodeInfo ? context.nodeInfo!.metadata!.urn : (context.connectionProfile.databaseName === '' ? 'Server' : `Server/Database[@Name='${escapeSingleQuotes(context.connectionProfile.databaseName)}']`);
|
||||
|
||||
const options: ObjectManagementDialogOptions = {
|
||||
connectionUri: connectionUri,
|
||||
isNewObject: false,
|
||||
database: context.connectionProfile!.databaseName!,
|
||||
objectType: objectType,
|
||||
objectName: objectName,
|
||||
parentUrn: parentUrn,
|
||||
objectUrn: objectUrn,
|
||||
database: context.connectionProfile?.databaseName,
|
||||
objectType: object.type,
|
||||
objectName: object.name,
|
||||
parentUrn: object.parentUrn,
|
||||
objectUrn: object.urn,
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = getDialog(service, options);
|
||||
const startTime = Date.now();
|
||||
await dialog.open();
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.OpenPropertiesDialog, {
|
||||
objectType: object.type
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenPropertiesDialog, err).withAdditionalProperties({
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}).send();
|
||||
console.error(err);
|
||||
await vscode.window.showErrorMessage(objectManagementLoc.OpenObjectPropertiesDialogError(objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType), context.nodeInfo!.label, getErrorMessage(err)));
|
||||
await vscode.window.showErrorMessage(objectManagementLoc.OpenObjectPropertiesDialogError(objectManagementLoc.getNodeTypeDisplayName(object.type), object.name, getErrorMessage(err)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,16 +187,18 @@ async function handleDropObjectCommand(context: azdata.ObjectExplorerContext, se
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
|
||||
const object = await getObjectInfoForContext(context);
|
||||
let additionalConfirmationMessage: string | undefined = undefined;
|
||||
switch (context.nodeInfo!.nodeType) {
|
||||
switch (object.type) {
|
||||
case ObjectManagement.NodeType.ServerLevelLogin:
|
||||
additionalConfirmationMessage = objectManagementLoc.DropLoginConfirmationText;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType);
|
||||
let confirmMessage = objectManagementLoc.DropObjectConfirmationText(nodeTypeDisplayName, context.nodeInfo!.label);
|
||||
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(object.type);
|
||||
let confirmMessage = objectManagementLoc.DropObjectConfirmationText(nodeTypeDisplayName, object.name);
|
||||
if (additionalConfirmationMessage) {
|
||||
confirmMessage = `${additionalConfirmationMessage} ${confirmMessage}`;
|
||||
}
|
||||
@@ -197,23 +207,23 @@ async function handleDropObjectCommand(context: azdata.ObjectExplorerContext, se
|
||||
return;
|
||||
}
|
||||
azdata.tasks.startBackgroundOperation({
|
||||
displayName: objectManagementLoc.DropObjectOperationDisplayName(nodeTypeDisplayName, context.nodeInfo!.label),
|
||||
displayName: objectManagementLoc.DropObjectOperationDisplayName(nodeTypeDisplayName, object.name),
|
||||
description: '',
|
||||
isCancelable: false,
|
||||
operation: async (operation) => {
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
await service.drop(connectionUri, context.nodeInfo.nodeType as ObjectManagement.NodeType, context.nodeInfo!.metadata!.urn);
|
||||
await service.drop(connectionUri, object.type, object.urn);
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.DropObject, {
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.DropObjectError(nodeTypeDisplayName, context.nodeInfo!.label, getErrorMessage(err)));
|
||||
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.DropObjectError(nodeTypeDisplayName, object.name, getErrorMessage(err)));
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.DropObject, err).withAdditionalProperties({
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}).send();
|
||||
console.error(err);
|
||||
return;
|
||||
@@ -229,11 +239,12 @@ async function handleRenameObjectCommand(context: azdata.ObjectExplorerContext,
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType);
|
||||
const originalName = context.nodeInfo!.metadata!.name;
|
||||
|
||||
const object = await getObjectInfoForContext(context);
|
||||
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(object.type);
|
||||
const newName = await vscode.window.showInputBox({
|
||||
title: objectManagementLoc.RenameObjectDialogTitle,
|
||||
value: originalName,
|
||||
value: object.name,
|
||||
validateInput: (value: string): string | undefined => {
|
||||
if (!value) {
|
||||
return objectManagementLoc.NameCannotBeEmptyError;
|
||||
@@ -245,28 +256,28 @@ async function handleRenameObjectCommand(context: azdata.ObjectExplorerContext,
|
||||
});
|
||||
|
||||
// return if no change was made or the dialog was canceled.
|
||||
if (newName === originalName || !newName) {
|
||||
if (newName === object.name || !newName) {
|
||||
return;
|
||||
}
|
||||
|
||||
azdata.tasks.startBackgroundOperation({
|
||||
displayName: objectManagementLoc.RenameObjectOperationDisplayName(nodeTypeDisplayName, originalName, newName),
|
||||
displayName: objectManagementLoc.RenameObjectOperationDisplayName(nodeTypeDisplayName, object.name, newName),
|
||||
description: '',
|
||||
isCancelable: false,
|
||||
operation: async (operation) => {
|
||||
try {
|
||||
const startTime = Date.now();
|
||||
await service.rename(connectionUri, context.nodeInfo.nodeType as ObjectManagement.NodeType, context.nodeInfo!.metadata!.urn, newName);
|
||||
await service.rename(connectionUri, object.type, object.urn, newName);
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.RenameObject, {
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.RenameObjectError(nodeTypeDisplayName, originalName, newName, getErrorMessage(err)));
|
||||
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.RenameObjectError(nodeTypeDisplayName, object.name, newName, getErrorMessage(err)));
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.RenameObject, err).withAdditionalProperties({
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}).send();
|
||||
console.error(err);
|
||||
return;
|
||||
@@ -282,24 +293,33 @@ async function handleDetachDatabase(context: azdata.ObjectExplorerContext, servi
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
const object = await getObjectInfoForContext(context);
|
||||
try {
|
||||
const parentUrn = await getParentUrn(context);
|
||||
if (object.type !== ObjectManagement.NodeType.Database) {
|
||||
throw new Error(objectManagementLoc.NotSupportedError(ObjectManagement.NodeType.Database));
|
||||
}
|
||||
const options: ObjectManagementDialogOptions = {
|
||||
connectionUri: connectionUri,
|
||||
isNewObject: false,
|
||||
database: context.connectionProfile!.databaseName!,
|
||||
objectType: context.nodeInfo.nodeType as ObjectManagement.NodeType,
|
||||
objectName: context.nodeInfo.label,
|
||||
parentUrn: parentUrn,
|
||||
objectUrn: context.nodeInfo!.metadata!.urn,
|
||||
database: object.name,
|
||||
objectType: object.type,
|
||||
objectName: object.name,
|
||||
parentUrn: object.parentUrn,
|
||||
objectUrn: object.urn,
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = new DetachDatabaseDialog(service, options);
|
||||
const startTime = Date.now();
|
||||
await dialog.open();
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.OpenDetachDatabaseDialog, {
|
||||
objectType: object.type
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDetachDatabaseDialog, err).withAdditionalProperties({
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
objectType: object.type
|
||||
}).send();
|
||||
console.error(err);
|
||||
await vscode.window.showErrorMessage(objectManagementLoc.OpenDetachDatabaseDialogError(getErrorMessage(err)));
|
||||
@@ -323,7 +343,13 @@ async function handleAttachDatabase(context: azdata.ObjectExplorerContext, servi
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = new AttachDatabaseDialog(service, options);
|
||||
const startTime = Date.now();
|
||||
await dialog.open();
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.OpenAttachDatabaseDialog, {
|
||||
objectType: ObjectManagement.NodeType.Database
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenAttachDatabaseDialog, err).withAdditionalProperties({
|
||||
@@ -339,26 +365,33 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
const object = await getObjectInfoForContext(context);
|
||||
try {
|
||||
const parentUrn = await getParentUrn(context);
|
||||
const objectName = context.nodeInfo?.label ?? context.connectionProfile.databaseName;
|
||||
const objectUrn = context.nodeInfo?.metadata?.urn ?? `Server/Database[@Name='${escapeSingleQuotes(context.connectionProfile.databaseName)}']`;
|
||||
if (object.type !== ObjectManagement.NodeType.Database) {
|
||||
throw new Error(objectManagementLoc.NotSupportedError(ObjectManagement.NodeType.Database));
|
||||
}
|
||||
const options: ObjectManagementDialogOptions = {
|
||||
connectionUri: connectionUri,
|
||||
isNewObject: false,
|
||||
database: context.connectionProfile!.databaseName!,
|
||||
objectType: ObjectManagement.NodeType.Database,
|
||||
objectName: objectName,
|
||||
parentUrn: parentUrn,
|
||||
objectUrn: objectUrn,
|
||||
database: object.name,
|
||||
objectType: object.type,
|
||||
objectName: object.name,
|
||||
parentUrn: object.parentUrn,
|
||||
objectUrn: object.urn,
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = new DropDatabaseDialog(service, options);
|
||||
const startTime = Date.now();
|
||||
await dialog.open();
|
||||
TelemetryReporter.sendTelemetryEvent(TelemetryActions.OpenDropDatabaseDialog, {
|
||||
objectType: object.type
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDropDatabaseDialog, err).withAdditionalProperties({
|
||||
objectType: ObjectManagement.NodeType.Database
|
||||
objectType: object.type
|
||||
}).send();
|
||||
console.error(err);
|
||||
await vscode.window.showErrorMessage(objectManagementLoc.OpenDropDatabaseDialogError(getErrorMessage(err)));
|
||||
@@ -407,3 +440,39 @@ async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<stri
|
||||
}
|
||||
return parentUrn;
|
||||
}
|
||||
|
||||
interface ObjectInfo {
|
||||
parentUrn: string;
|
||||
name: string;
|
||||
type: ObjectManagement.NodeType;
|
||||
urn: string;
|
||||
}
|
||||
|
||||
async function getObjectInfoForContext(context: azdata.ObjectExplorerContext): Promise<ObjectInfo> {
|
||||
let nodeType: ObjectManagement.NodeType;
|
||||
let objectName: string;
|
||||
let objectUrn: string;
|
||||
if (context.nodeInfo) {
|
||||
nodeType = context.nodeInfo.nodeType as ObjectManagement.NodeType;
|
||||
objectName = context.nodeInfo.metadata?.name;
|
||||
objectUrn = context.nodeInfo.metadata?.urn;
|
||||
} else {
|
||||
// Node info will be missing for top level connection items like servers and databases, so make a best guess here based on connection info.
|
||||
if (context.connectionProfile?.databaseName?.length > 0) {
|
||||
nodeType = ObjectManagement.NodeType.Database;
|
||||
objectName = context.connectionProfile.databaseName;
|
||||
objectUrn = `Server/Database[@Name='${escapeSingleQuotes(objectName)}']`;
|
||||
} else {
|
||||
nodeType = ObjectManagement.NodeType.Server;
|
||||
objectName = context.connectionProfile.serverName;
|
||||
objectUrn = 'Server';
|
||||
}
|
||||
}
|
||||
let parentUrn = await getParentUrn(context);
|
||||
return {
|
||||
parentUrn: parentUrn,
|
||||
name: objectName,
|
||||
type: nodeType,
|
||||
urn: objectUrn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export const enum FolderType {
|
||||
}
|
||||
|
||||
export const PublicServerRoleName = 'public';
|
||||
export const Windows = 'Windows';
|
||||
|
||||
export const CreateUserDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/create-user-transact-sql';
|
||||
export const AlterUserDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/alter-user-transact-sql';
|
||||
@@ -53,7 +54,9 @@ export const enum TelemetryActions {
|
||||
UpdateObject = 'UpdateObject',
|
||||
OpenDetachDatabaseDialog = 'OpenDetachDatabaseDialog',
|
||||
OpenAttachDatabaseDialog = 'OpenAttachDatabaseDialog',
|
||||
OpenDropDatabaseDialog = 'OpenDropDatabaseDialog'
|
||||
OpenDropDatabaseDialog = 'OpenDropDatabaseDialog',
|
||||
AttachDatabase = 'AttachDatabase',
|
||||
DetachDatabase = 'DetachDatabase'
|
||||
}
|
||||
|
||||
export const ObjectManagementViewName = 'ObjectManagement';
|
||||
|
||||
@@ -276,7 +276,7 @@ export const enum UserType {
|
||||
*/
|
||||
SqlAuthentication = 'SqlAuthentication',
|
||||
/**
|
||||
* Authenticate with Azure Active Directory.
|
||||
* Authenticate with Microsoft Entra.
|
||||
*/
|
||||
AADAuthentication = 'AADAuthentication',
|
||||
/**
|
||||
@@ -476,7 +476,7 @@ export interface DatabaseViewInfo extends ObjectManagement.ObjectViewInfo<Databa
|
||||
azureMaxSizes?: AzureEditionDetails[];
|
||||
pageVerifyOptions?: string[];
|
||||
restrictAccessOptions?: string[];
|
||||
dscOnOffOptions?: string[];
|
||||
propertiesOnOffOptions?: string[];
|
||||
dscElevateOptions?: string[];
|
||||
dscEnableDisableOptions?: string[];
|
||||
rowDataFileGroupsOptions?: string[];
|
||||
@@ -498,7 +498,7 @@ export interface QueryStoreOptions {
|
||||
queryStoreCaptureMode: string;
|
||||
sizeBasedCleanupMode: string;
|
||||
staleQueryThresholdInDays: number;
|
||||
waitStatisticsCaptureMode?: boolean;
|
||||
waitStatisticsCaptureMode?: string;
|
||||
capturePolicyOptions?: QueryStoreCapturePolicyOptions;
|
||||
currentStorageSizeInMB: number;
|
||||
}
|
||||
@@ -544,7 +544,7 @@ export enum AffinityType {
|
||||
}
|
||||
|
||||
export interface Server extends ObjectManagement.SqlObject {
|
||||
hardwareGeneration: string;
|
||||
hardwareGeneration?: string;
|
||||
language: string;
|
||||
memoryInMB: number;
|
||||
operatingSystem: string;
|
||||
@@ -553,14 +553,14 @@ export interface Server extends ObjectManagement.SqlObject {
|
||||
version: string;
|
||||
isClustered: boolean;
|
||||
isHadrEnabled: boolean;
|
||||
isPolyBaseInstalled: boolean;
|
||||
isXTPSupported: boolean;
|
||||
isPolyBaseInstalled?: boolean;
|
||||
isXTPSupported?: boolean;
|
||||
product: string;
|
||||
reservedStorageSizeMB: number;
|
||||
reservedStorageSizeMB?: number;
|
||||
rootDirectory: string;
|
||||
serverCollation: string;
|
||||
serviceTier: string;
|
||||
storageSpaceUsageInMB: number;
|
||||
serviceTier?: string;
|
||||
storageSpaceUsageInMB?: number;
|
||||
minServerMemory: NumericServerProperty;
|
||||
maxServerMemory: NumericServerProperty;
|
||||
autoProcessorAffinityMaskForAll: boolean;
|
||||
@@ -593,8 +593,8 @@ export interface Server extends ObjectManagement.SqlObject {
|
||||
* The server login types.
|
||||
*/
|
||||
export const enum ServerLoginMode {
|
||||
Integrated, //windows auth only
|
||||
Mixed // both sql server and windows auth
|
||||
Integrated = 1, //windows auth only
|
||||
Mixed = 2// both sql server and windows auth
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,6 +56,7 @@ export const allFiles = localize('objectManagement.allFiles', "All Files");
|
||||
export const labelSelectFolder = localize('objectManagement.labelSelectFolder', "Select Folder");
|
||||
export const DataFileLabel = localize('objectManagement.dataFileLabel', "Data");
|
||||
export const LogFileLabel = localize('objectManagement.logFileLabel', "Log");
|
||||
export const BackButtonLabel = localize('objectManagement.backButtonLabel', "Back");
|
||||
|
||||
export function ExplicitPermissionsTableLabelSelected(name: string): string { return localize('objectManagement.explicitPermissionsTableLabelSelected', "Explicit permissions for: {0}", name); }
|
||||
export function EffectivePermissionsTableLabelSelected(name: string): string { return localize('objectManagement.effectivePermissionsTableLabelSelected', "Effective permissions for: {0}", name); }
|
||||
@@ -247,7 +248,7 @@ export const PermissionToConnectText = localize('objectManagement.login.permissi
|
||||
export const LoginLockedOutText = localize('objectManagement.login.lockedOutLabel', "Login is locked out");
|
||||
export const WindowsAuthenticationTypeDisplayText = localize('objectManagement.login.windowsAuthenticationType', "Windows Authentication");
|
||||
export const SQLAuthenticationTypeDisplayText = localize('objectManagement.login.sqlAuthenticationType', "SQL Authentication");
|
||||
export const AADAuthenticationTypeDisplayText = localize('objectManagement.login.aadAuthenticationType', "Azure Active Directory Authentication");
|
||||
export const AADAuthenticationTypeDisplayText = localize('objectManagement.login.aadAuthenticationType', "Microsoft Entra ID Authentication");
|
||||
export const OldPasswordCannotBeEmptyError = localize('objectManagement.login.oldPasswordCannotBeEmptyError', "Old password cannot be empty.");
|
||||
|
||||
// User
|
||||
@@ -255,7 +256,7 @@ export const UserTypeText = localize('objectManagement.user.type', "Type");
|
||||
export const UserType_LoginMapped = localize('objectManagement.user.loginMapped', "Mapped to a server login");
|
||||
export const UserType_WindowsUser = localize('objectManagement.user.windowsUser', "Mapped to a Windows user/group");
|
||||
export const UserType_SqlAuthentication = localize('objectManagement.user.sqlAuth', "Authenticate with password");
|
||||
export const UserType_AADAuthentication = localize('objectManagement.user.aadAuth', "Authenticate with Azure Active Directory");
|
||||
export const UserType_AADAuthentication = localize('objectManagement.user.aadAuth', "Authenticate with Microsoft Entra");
|
||||
export const UserType_NoLoginAccess = localize('objectManagement.user.noLogin', "No Login Access");
|
||||
export const DefaultSchemaText = localize('objectManagement.user.defaultSchemaLabel', "Default schema");
|
||||
export const LoginText = localize('objectManagement.user.loginLabel', "Login");
|
||||
@@ -350,6 +351,7 @@ export const scanStartupProcsLabel = localize('objectManagement.scanStartupProcs
|
||||
export const twoDigitYearCutoffLabel = localize('objectManagement.twoDigitYearCutoffLabel', "Two Digit Year Cutoff");
|
||||
export const costThresholdParallelismLabel = localize('objectManagement.costThresholdParallelismLabel', "Cost Threshold Parallelism");
|
||||
export const locksLabel = localize('objectManagement.locksLabel', "Locks");
|
||||
export function locksValidation(minValue: number): string { return localize('objectManagement.locksValidation', "Value should be greater than {0}. Choose 0 for default settings.", minValue); }
|
||||
export const maxDegreeParallelismLabel = localize('objectManagement.maxDegreeParallelismLabel', "Max Degree Parallelism");
|
||||
export const queryWaitLabel = localize('objectManagement.queryWaitLabel', "Query Wait");
|
||||
|
||||
@@ -464,7 +466,9 @@ export const QueryStoreUsedText = localize('objectManagement.databaseProperties.
|
||||
export const QueryStoreAvailableText = localize('objectManagement.databaseProperties.queryStoreAvailableText', "Query Store Available");
|
||||
export const PurgeQueryDataButtonText = localize('objectManagement.databaseProperties.purgeQueryDataButtonText', "Purge Query Store Data");
|
||||
export const YesText = localize('objectManagement.databaseProperties.yesText', "Yes");
|
||||
export const NotAvailableText = localize('objectManagement.databaseProperties.notAvailableText', "N/A");
|
||||
export const PurgeQueryStoreDataMessage = (databaseName: string) => localize('objectManagement.databaseProperties.purgeQueryStoreDataMessage', "Are you sure you want to purge the Query Store data from '{0}'?", databaseName);
|
||||
export const fileGroupsNameInput = localize('objectManagement.filegroupsNameInput', "Filegroup Name");
|
||||
|
||||
// Util functions
|
||||
export function getNodeTypeDisplayName(type: string, inTitle: boolean = false): string {
|
||||
|
||||
@@ -66,13 +66,13 @@ export class ObjectManagementService extends BaseService implements IObjectManag
|
||||
return this.runWithErrorHandling(contracts.SearchObjectRequest.type, params);
|
||||
}
|
||||
|
||||
async detachDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Promise<string> {
|
||||
const params: contracts.DetachDatabaseRequestParams = { connectionUri, database, objectUrn, dropConnections, updateStatistics, generateScript };
|
||||
async detachDatabase(connectionUri: string, database: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Promise<string> {
|
||||
const params: contracts.DetachDatabaseRequestParams = { connectionUri, database, dropConnections, updateStatistics, generateScript };
|
||||
return this.runWithErrorHandling(contracts.DetachDatabaseRequest.type, params);
|
||||
}
|
||||
|
||||
async dropDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Promise<string> {
|
||||
const params: contracts.DropDatabaseRequestParams = { connectionUri, database, objectUrn, dropConnections, deleteBackupHistory, generateScript };
|
||||
async dropDatabase(connectionUri: string, database: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Promise<string> {
|
||||
const params: contracts.DropDatabaseRequestParams = { connectionUri, database, dropConnections, deleteBackupHistory, generateScript };
|
||||
return this.runWithErrorHandling(contracts.DropDatabaseRequest.type, params);
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ export class ObjectManagementService extends BaseService implements IObjectManag
|
||||
return this.runWithErrorHandling(contracts.GetAssociatedFilesRequest.type, params);
|
||||
}
|
||||
|
||||
async purgeQueryStoreData(connectionUri: string, database: string, objectUrn: string): Promise<void> {
|
||||
const params: contracts.purgeQueryStoreDataRequestParams = { connectionUri, database, objectUrn };
|
||||
async purgeQueryStoreData(connectionUri: string, database: string): Promise<void> {
|
||||
const params: contracts.PurgeQueryStoreDataRequestParams = { connectionUri, database };
|
||||
return this.runWithErrorHandling(contracts.PurgeQueryStoreDataRequest.type, params);
|
||||
}
|
||||
}
|
||||
@@ -262,7 +262,7 @@ export class TestObjectManagementService implements IObjectManagementService {
|
||||
return this.delayAndResolve(items);
|
||||
}
|
||||
|
||||
async detachDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Promise<string> {
|
||||
async detachDatabase(connectionUri: string, database: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Promise<string> {
|
||||
return this.delayAndResolve('');
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ export class TestObjectManagementService implements IObjectManagementService {
|
||||
return this.delayAndResolve('');
|
||||
}
|
||||
|
||||
dropDatabase(connectionUri: string, database: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string> {
|
||||
dropDatabase(connectionUri: string, database: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string> {
|
||||
return this.delayAndResolve('');
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ export class TestObjectManagementService implements IObjectManagementService {
|
||||
return this.delayAndResolve([]);
|
||||
}
|
||||
|
||||
async purgeQueryStoreData(connectionUri: string, database: string, objectUrn: string): Promise<void> {
|
||||
async purgeQueryStoreData(connectionUri: string, database: string): Promise<void> {
|
||||
return this.delayAndResolve([]);
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ export class TestObjectManagementService implements IObjectManagementService {
|
||||
pageVerifyOptions: ['CHECKSUM', 'NONE', 'TORN_PAGE_DETECTION'],
|
||||
dscElevateOptions: ['OFF', 'WHEN_SUPPORTED', 'FAIL_UNSUPPORTED'],
|
||||
dscEnableDisableOptions: ['ENABLED', 'DISABLED'],
|
||||
dscOnOffOptions: ['ON', 'OFF'],
|
||||
propertiesOnOffOptions: ['ON', 'OFF'],
|
||||
rowDataFileGroupsOptions: ['PRIMARY', 'RowDataGroup1', 'RowDataGroup2'],
|
||||
fileStreamFileGroupsOptions: ['PRIMARY', 'FileStreamGroup1', 'FileStreamGroup2'],
|
||||
fileTypesOptions: ['ROWS', 'LOG', 'FILESTREAM'],
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
|
||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||
import { DatabaseFileData, IObjectManagementService, ObjectManagement } from 'mssql';
|
||||
import { Database, DatabaseViewInfo } from '../interfaces';
|
||||
import { AttachDatabaseDocUrl } from '../constants';
|
||||
import { AttachDatabaseDocUrl, TelemetryActions } from '../constants';
|
||||
import * as loc from '../localizedConstants';
|
||||
import { RemoveText } from '../../ui/localizedConstants';
|
||||
import { DefaultMinTableRowCount, DialogButton, getTableHeight } from '../../ui/dialogBase';
|
||||
@@ -62,16 +62,20 @@ export class AttachDatabaseDialog extends ObjectManagementDialogBase<Database, D
|
||||
const buttonContainer = this.addButtonsForTable(this._databasesTable, addButton, removeButton);
|
||||
|
||||
this._nameField = this.createInputBox(async newValue => {
|
||||
let selectedRow = this._databasesTable.selectedRows[0];
|
||||
let dbFile = this._databasesToAttach[selectedRow];
|
||||
dbFile.databaseName = newValue;
|
||||
if (this._databasesTable.selectedRows?.length > 0) {
|
||||
let selectedRow = this._databasesTable.selectedRows[0];
|
||||
let dbFile = this._databasesToAttach[selectedRow];
|
||||
dbFile.databaseName = newValue;
|
||||
}
|
||||
}, {});
|
||||
this._nameContainer = this.createLabelInputContainer(loc.AttachAsText, this._nameField);
|
||||
|
||||
this._ownerDropdown = this.createDropdown(loc.OwnerText, async newValue => {
|
||||
let selectedRow = this._databasesTable.selectedRows[0];
|
||||
let dbFile = this._databasesToAttach[selectedRow];
|
||||
dbFile.owner = newValue;
|
||||
if (this._databasesTable.selectedRows?.length > 0) {
|
||||
let selectedRow = this._databasesTable.selectedRows[0];
|
||||
let dbFile = this._databasesToAttach[selectedRow];
|
||||
dbFile.owner = newValue;
|
||||
}
|
||||
}, this.viewInfo.loginNames.options, this.viewInfo.loginNames.options[this.viewInfo.loginNames.defaultValueIndex]);
|
||||
this._ownerContainer = this.createLabelInputContainer(loc.OwnerText, this._ownerDropdown);
|
||||
|
||||
@@ -174,6 +178,10 @@ export class AttachDatabaseDialog extends ObjectManagementDialogBase<Database, D
|
||||
return AttachDatabaseDocUrl;
|
||||
}
|
||||
|
||||
protected override get actionName(): string {
|
||||
return TelemetryActions.AttachDatabase;
|
||||
}
|
||||
|
||||
protected override async validateInput(): Promise<string[]> {
|
||||
let errors = [];
|
||||
if (this._databasesToAttach.length === 0) {
|
||||
|
||||
@@ -12,13 +12,13 @@ import { CreateDatabaseDocUrl, DatabaseGeneralPropertiesDocUrl, DatabaseFilesPro
|
||||
import { Database, DatabaseFile, DatabaseScopedConfigurationsInfo, DatabaseViewInfo, FileGrowthType, FileGroup, FileGroupType } from '../interfaces';
|
||||
import { convertNumToTwoDecimalStringInMB } from '../utils';
|
||||
import { isUndefinedOrNull } from '../../types';
|
||||
import { deepClone } from '../../util/objects';
|
||||
import { DatabaseFileDialog } from './databaseFileDialog';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
const MAXDOP_Max_Limit = 32767;
|
||||
const PAUSED_RESUMABLE_INDEX_Max_Limit = 71582;
|
||||
const DscTableRowLength = 15;
|
||||
const Dialog_Width = '750px';
|
||||
|
||||
export class DatabaseDialog extends ObjectManagementDialogBase<Database, DatabaseViewInfo> {
|
||||
// Database Properties tabs
|
||||
@@ -59,8 +59,14 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
private filestreamFilegroupsTable: azdata.TableComponent;
|
||||
private memoryOptimizedFilegroupsTable: azdata.TableComponent;
|
||||
private rowsFilegroupNameInput: azdata.InputBoxComponent;
|
||||
private rowsFilegroupNameContainer: azdata.FlexContainer;
|
||||
private rowsFileGroupButtonContainer: azdata.FlexContainer;
|
||||
private filestreamFilegroupNameInput: azdata.InputBoxComponent;
|
||||
private filestreamFilegroupNameContainer: azdata.FlexContainer;
|
||||
private filestreamFileGroupButtonContainer: azdata.FlexContainer;
|
||||
private memoryOptimizedFilegroupNameInput: azdata.InputBoxComponent;
|
||||
private memoryOptimizedFilegroupNameContainer: azdata.FlexContainer;
|
||||
private memoryOptimizedFileGroupButtonContainer: azdata.FlexContainer;
|
||||
private newFileGroupTemporaryId: number = 0;
|
||||
private rowDataFileGroupsTableRows: FileGroup[] = [];
|
||||
private filestreamDataFileGroupsTableRows: FileGroup[] = [];
|
||||
@@ -82,7 +88,6 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
private readonly dscTabId: string = 'dscDatabaseId';
|
||||
private dscTabSectionsContainer: azdata.Component[] = [];
|
||||
private dscTable: azdata.TableComponent;
|
||||
private dscOriginalData: DatabaseScopedConfigurationsInfo[];
|
||||
private currentRowId: number;
|
||||
private valueForPrimaryDropdown: azdata.DropDownComponent;
|
||||
private valueForSecondaryDropdown: azdata.DropDownComponent;
|
||||
@@ -90,12 +95,10 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
private valueForPrimaryInput: azdata.InputBoxComponent;
|
||||
private valueForSecondaryInput: azdata.InputBoxComponent;
|
||||
private setSecondaryCheckboxForInputType: azdata.CheckBoxComponent;
|
||||
private dscPrimaryValueDropdownGroup: azdata.GroupContainer;
|
||||
private dscSecondaryValueDropdownGroup: azdata.GroupContainer;
|
||||
private dscSecondaryCheckboxForDropdownGroup: azdata.GroupContainer;
|
||||
private dscPrimaryValueInputGroup: azdata.GroupContainer;
|
||||
private dscSecondaryValueInputGroup: azdata.GroupContainer;
|
||||
private dscSecondaryCheckboxForInputGroup: azdata.GroupContainer;
|
||||
private dscPrimaryValueDropdown: azdata.FlexContainer;
|
||||
private dscSecondaryValueDropdown: azdata.FlexContainer;
|
||||
private dscPrimaryValueInput: azdata.FlexContainer;
|
||||
private dscSecondaryValueInput: azdata.FlexContainer;
|
||||
private setFocusToInput: azdata.InputBoxComponent = undefined;
|
||||
private currentRowObjectInfo: DatabaseScopedConfigurationsInfo;
|
||||
// Query store Tab
|
||||
@@ -110,7 +113,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
private queryStoreCaptureMode: azdata.DropDownComponent;
|
||||
private sizeBasedCleanupMode: azdata.DropDownComponent;
|
||||
private stateQueryThresholdInDays: azdata.InputBoxComponent;
|
||||
private waitStatisticsCaptureMode: azdata.CheckBoxComponent;
|
||||
private waitStatisticsCaptureMode: azdata.DropDownComponent;
|
||||
private executionCount: azdata.InputBoxComponent;
|
||||
private staleThreshold: azdata.DropDownComponent;
|
||||
private totalCompileCPUTimeInMS: azdata.InputBoxComponent;
|
||||
@@ -120,6 +123,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
|
||||
|
||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||
options.width = Dialog_Width;
|
||||
super(objectManagementService, options);
|
||||
}
|
||||
|
||||
@@ -213,8 +217,8 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
// Initilaize FileGroups Tab
|
||||
if (!isUndefinedOrNull(this.objectInfo.filegroups)) {
|
||||
const rowsFileGroupSection = await this.initializeRowsFileGroupSection();
|
||||
const fileStreamFileGroupSection = this.initializeFileStreamFileGroupSection();
|
||||
const memoryOptimizedFileGroupSection = this.initializeMemoryOptimizedFileGroupSection();
|
||||
const fileStreamFileGroupSection = await this.initializeFileStreamFileGroupSection();
|
||||
const memoryOptimizedFileGroupSection = await this.initializeMemoryOptimizedFileGroupSection();
|
||||
this.fileGroupsTab = {
|
||||
title: localizedConstants.FileGroupsSectionHeader,
|
||||
id: this.fileGroupsTabId,
|
||||
@@ -265,6 +269,9 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
const propertiesTabGroup = { title: '', tabs: tabs };
|
||||
const propertiesTabbedPannel = this.modelView.modelBuilder.tabbedPanel()
|
||||
.withTabs([propertiesTabGroup])
|
||||
.withLayout({
|
||||
orientation: azdata.TabOrientation.Vertical
|
||||
})
|
||||
.withProps({
|
||||
CSSStyles: {
|
||||
'margin': '-10px 0px 0px -10px'
|
||||
@@ -740,8 +747,9 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
defaultFileGrowthInMb: defaultFileGrowthInMb,
|
||||
defaultFileGrowthInPercent: defaultFileGrowthInPercent,
|
||||
defaultMaxFileSizeLimitedToInMb: defaultMaxFileSizeLimitedToInMb
|
||||
}
|
||||
});
|
||||
},
|
||||
connectionUri: this.options.connectionUri
|
||||
}, this.objectManagementService);
|
||||
await dialog.open();
|
||||
return await dialog.waitForClose();
|
||||
}
|
||||
@@ -785,17 +793,16 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
'margin-left': '10px'
|
||||
}
|
||||
}).component();
|
||||
this.rowsFilegroupNameInput = this.getFilegroupNameInput(this.rowsFilegroupsTable, FileGroupType.RowsFileGroup);
|
||||
this.rowsFilegroupNameContainer = await this.getFilegroupNameGroup(this.rowsFilegroupsTable, FileGroupType.RowsFileGroup);
|
||||
const addButtonComponent: DialogButton = {
|
||||
buttonAriaLabel: localizedConstants.AddFilegroupText,
|
||||
buttonHandler: () => this.onAddDatabaseFileGroupsButtonClicked(this.rowsFilegroupsTable)
|
||||
};
|
||||
const removeButtonComponent: DialogButton = {
|
||||
buttonAriaLabel: localizedConstants.RemoveButton,
|
||||
buttonHandler: () => this.onAddDatabaseFileGroupsButtonClicked(this.rowsFilegroupsTable)
|
||||
buttonHandler: () => this.onRemoveDatabaseFileGroupsButtonClicked(this.rowsFilegroupsTable)
|
||||
};
|
||||
const rowsFileGroupButtonContainer = this.addButtonsForTable(this.rowsFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
|
||||
this.rowsFileGroupButtonContainer = this.addButtonsForTable(this.rowsFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
this.disposables.push(
|
||||
this.rowsFilegroupsTable.onCellAction(async (arg: azdata.ICheckboxCellActionEventArgs) => {
|
||||
let filegroup = this.rowDataFileGroupsTableRows[arg.row];
|
||||
@@ -821,23 +828,21 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
async () => {
|
||||
if (this.rowsFilegroupsTable.selectedRows.length === 1) {
|
||||
const fileGroup = this.rowDataFileGroupsTableRows[this.rowsFilegroupsTable.selectedRows[0]];
|
||||
await this.rowsFilegroupNameInput.updateCssStyles({ 'visibility': fileGroup.id < 0 ? 'visible' : 'hidden' });
|
||||
this.rowsFilegroupNameContainer.display = fileGroup.id < 0 ? 'inline-flex' : 'none';
|
||||
this.rowsFilegroupNameInput.value = fileGroup.name;
|
||||
this.onFormFieldChange();
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
const rowContainer = this.modelView.modelBuilder.flexContainer().withItems([this.rowsFilegroupNameInput]).component();
|
||||
rowContainer.addItems([rowsFileGroupButtonContainer], { flex: '0 0 auto' });
|
||||
return this.createGroup(localizedConstants.RowsFileGroupsSectionText, [this.rowsFilegroupsTable, rowContainer], true);
|
||||
return this.createGroup(localizedConstants.RowsFileGroupsSectionText, [this.rowsFilegroupsTable, this.rowsFilegroupNameContainer, this.rowsFileGroupButtonContainer], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the filestream filegroups section and updates the table data
|
||||
* @returns filestream data filegroups container
|
||||
*/
|
||||
private initializeFileStreamFileGroupSection(): azdata.GroupContainer {
|
||||
private async initializeFileStreamFileGroupSection(): Promise<azdata.GroupContainer> {
|
||||
const data = this.getTableData(FileGroupType.FileStreamDataFileGroup);
|
||||
this.filestreamFilegroupsTable = this.modelView.modelBuilder.table().withProps({
|
||||
columns: [{
|
||||
@@ -861,7 +866,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
'margin-left': '10px'
|
||||
}
|
||||
}).component();
|
||||
this.filestreamFilegroupNameInput = this.getFilegroupNameInput(this.filestreamFilegroupsTable, FileGroupType.FileStreamDataFileGroup);
|
||||
this.filestreamFilegroupNameContainer = await this.getFilegroupNameGroup(this.filestreamFilegroupsTable, FileGroupType.FileStreamDataFileGroup);
|
||||
const addButtonComponent: DialogButton = {
|
||||
buttonAriaLabel: localizedConstants.AddFilegroupText,
|
||||
buttonHandler: () => this.onAddDatabaseFileGroupsButtonClicked(this.filestreamFilegroupsTable)
|
||||
@@ -870,8 +875,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
buttonAriaLabel: localizedConstants.RemoveButton,
|
||||
buttonHandler: () => this.onRemoveDatabaseFileGroupsButtonClicked(this.filestreamFilegroupsTable)
|
||||
};
|
||||
const filestreamFileGroupButtonContainer = this.addButtonsForTable(this.filestreamFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
|
||||
this.filestreamFileGroupButtonContainer = this.addButtonsForTable(this.filestreamFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
this.disposables.push(
|
||||
this.filestreamFilegroupsTable.onCellAction(async (arg: azdata.ICheckboxCellActionEventArgs) => {
|
||||
let filegroup = this.filestreamDataFileGroupsTableRows[arg.row];
|
||||
@@ -893,7 +897,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
async () => {
|
||||
if (this.filestreamFilegroupsTable.selectedRows.length === 1) {
|
||||
const fileGroup = this.filestreamDataFileGroupsTableRows[this.filestreamFilegroupsTable.selectedRows[0]];
|
||||
await this.filestreamFilegroupNameInput.updateCssStyles({ 'visibility': fileGroup.id < 0 ? 'visible' : 'hidden' });
|
||||
this.filestreamFilegroupNameContainer.display = fileGroup.id < 0 ? 'inline-flex' : 'none';
|
||||
this.filestreamFilegroupNameInput.value = fileGroup.name;
|
||||
this.onFormFieldChange();
|
||||
}
|
||||
@@ -901,16 +905,14 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
)
|
||||
);
|
||||
|
||||
const filestreamContainer = this.modelView.modelBuilder.flexContainer().withItems([this.filestreamFilegroupNameInput]).component();
|
||||
filestreamContainer.addItems([filestreamFileGroupButtonContainer], { flex: '0 0 auto' });
|
||||
return this.createGroup(localizedConstants.FileStreamFileGroupsSectionText, [this.filestreamFilegroupsTable, filestreamContainer], true);
|
||||
return this.createGroup(localizedConstants.FileStreamFileGroupsSectionText, [this.filestreamFilegroupsTable, this.filestreamFilegroupNameContainer, this.filestreamFileGroupButtonContainer], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the memory optimized filegroups section and updates the table data
|
||||
* @returns Memory optimized filegroups container
|
||||
*/
|
||||
private initializeMemoryOptimizedFileGroupSection(): azdata.GroupContainer {
|
||||
private async initializeMemoryOptimizedFileGroupSection(): Promise<azdata.GroupContainer> {
|
||||
const data = this.getTableData(FileGroupType.MemoryOptimizedDataFileGroup);
|
||||
this.memoryOptimizedFilegroupsTable = this.modelView.modelBuilder.table().withProps({
|
||||
columns: [{
|
||||
@@ -928,23 +930,23 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
'margin-left': '10px'
|
||||
}
|
||||
}).component();
|
||||
this.memoryOptimizedFilegroupNameInput = this.getFilegroupNameInput(this.memoryOptimizedFilegroupsTable, FileGroupType.MemoryOptimizedDataFileGroup);
|
||||
this.memoryOptimizedFilegroupNameContainer = await this.getFilegroupNameGroup(this.memoryOptimizedFilegroupsTable, FileGroupType.MemoryOptimizedDataFileGroup);
|
||||
const addButtonComponent: DialogButton = {
|
||||
buttonAriaLabel: localizedConstants.AddFilegroupText,
|
||||
buttonHandler: () => this.onAddDatabaseFileGroupsButtonClicked(this.memoryOptimizedFilegroupsTable)
|
||||
buttonHandler: () => this.onAddDatabaseFileGroupsButtonClicked(this.memoryOptimizedFilegroupsTable),
|
||||
enabled: this.memoryoptimizedFileGroupsTableRows.length < 1
|
||||
};
|
||||
const removeButtonComponent: DialogButton = {
|
||||
buttonAriaLabel: localizedConstants.RemoveButton,
|
||||
buttonHandler: () => this.onRemoveDatabaseFileGroupsButtonClicked(this.memoryOptimizedFilegroupsTable)
|
||||
};
|
||||
const memoryOptimizedFileGroupButtonContainer = this.addButtonsForTable(this.memoryOptimizedFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
|
||||
this.memoryOptimizedFileGroupButtonContainer = this.addButtonsForTable(this.memoryOptimizedFilegroupsTable, addButtonComponent, removeButtonComponent);
|
||||
this.disposables.push(
|
||||
this.memoryOptimizedFilegroupsTable.onRowSelected(
|
||||
async () => {
|
||||
if (this.memoryOptimizedFilegroupsTable.selectedRows.length === 1) {
|
||||
const fileGroup = this.memoryoptimizedFileGroupsTableRows[this.memoryOptimizedFilegroupsTable.selectedRows[0]];
|
||||
await this.memoryOptimizedFilegroupNameInput.updateCssStyles({ 'visibility': fileGroup.id < 0 ? 'visible' : 'hidden' });
|
||||
this.memoryOptimizedFilegroupNameContainer.display = fileGroup.id < 0 ? 'inline-flex' : 'none';
|
||||
this.memoryOptimizedFilegroupNameInput.value = fileGroup.name;
|
||||
this.onFormFieldChange();
|
||||
}
|
||||
@@ -952,9 +954,20 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
)
|
||||
);
|
||||
|
||||
const memoryOptimizedContainer = this.modelView.modelBuilder.flexContainer().withItems([this.memoryOptimizedFilegroupNameInput]).component();
|
||||
memoryOptimizedContainer.addItems([memoryOptimizedFileGroupButtonContainer], { flex: '0 0 auto' });
|
||||
return this.createGroup(localizedConstants.MemoryOptimizedFileGroupsSectionText, [this.memoryOptimizedFilegroupsTable, memoryOptimizedContainer], true);
|
||||
return this.createGroup(localizedConstants.MemoryOptimizedFileGroupsSectionText, [this.memoryOptimizedFilegroupsTable, this.memoryOptimizedFilegroupNameContainer, this.memoryOptimizedFileGroupButtonContainer], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides declarative table add button enabled/disabled state
|
||||
* @param table table component
|
||||
* @returns table add button enabled/disabled state
|
||||
*/
|
||||
public override addButtonEnabled(table: azdata.TableComponent | azdata.DeclarativeTableComponent): boolean {
|
||||
let enabled = true;
|
||||
if (table === this.memoryOptimizedFilegroupsTable) {
|
||||
enabled = this.memoryoptimizedFileGroupsTableRows.length < 1;
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1014,6 +1027,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
// Refresh the table with new row data
|
||||
this.updateFileGroupsOptionsAndTableRows();
|
||||
await this.setTableData(table, newData, DefaultMaxTableRowCount);
|
||||
table.setActiveCell(table.data?.length - 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,7 +1060,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
const removeFilegroupIndex = this.objectInfo.filegroups.indexOf(this.rowDataFileGroupsTableRows[this.rowsFilegroupsTable.selectedRows[0]]);
|
||||
this.objectInfo.filegroups?.splice(removeFilegroupIndex, 1);
|
||||
var newData = this.getTableData(FileGroupType.RowsFileGroup);
|
||||
await this.rowsFilegroupNameInput.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.rowsFilegroupNameContainer.display = 'none';
|
||||
}
|
||||
}
|
||||
else if (table === this.filestreamFilegroupsTable) {
|
||||
@@ -1054,7 +1068,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
const removeFilegroupIndex = this.objectInfo.filegroups.indexOf(this.filestreamDataFileGroupsTableRows[this.filestreamFilegroupsTable.selectedRows[0]]);
|
||||
this.objectInfo.filegroups?.splice(removeFilegroupIndex, 1);
|
||||
var newData = this.getTableData(FileGroupType.FileStreamDataFileGroup);
|
||||
await this.filestreamFilegroupNameInput.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.filestreamFilegroupNameContainer.display = 'none';
|
||||
}
|
||||
}
|
||||
else if (table === this.memoryOptimizedFilegroupsTable) {
|
||||
@@ -1062,13 +1076,38 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
const removeFilegroupIndex = this.objectInfo.filegroups.indexOf(this.memoryoptimizedFileGroupsTableRows[this.memoryOptimizedFilegroupsTable.selectedRows[0]]);
|
||||
this.objectInfo.filegroups?.splice(removeFilegroupIndex, 1);
|
||||
var newData = this.getTableData(FileGroupType.MemoryOptimizedDataFileGroup);
|
||||
await this.memoryOptimizedFilegroupNameInput.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.memoryOptimizedFilegroupNameContainer.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the individual table rows object and table with updated data
|
||||
this.updateFileGroupsOptionsAndTableRows();
|
||||
await this.setTableData(table, newData)
|
||||
await this.setTableData(table, newData);
|
||||
if (table.selectedRows !== undefined && table.selectedRows[0] !== undefined && table.selectedRows[0] < table.data?.length) {
|
||||
table.setActiveCell(table.selectedRows[0], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the group container for filegroups input section
|
||||
* @param table table component
|
||||
* @param filegroupType filegroup type
|
||||
* @returns filegroup name group container
|
||||
*/
|
||||
private async getFilegroupNameGroup(table: azdata.TableComponent, filegroupType: FileGroupType): Promise<azdata.FlexContainer> {
|
||||
const fgInput = this.getFilegroupNameInput(table, filegroupType);
|
||||
if (table === this.rowsFilegroupsTable) {
|
||||
this.rowsFilegroupNameInput = fgInput;
|
||||
} else if (table === this.filestreamFilegroupsTable) {
|
||||
this.filestreamFilegroupNameInput = fgInput;
|
||||
} else if (table === this.memoryOptimizedFilegroupsTable) {
|
||||
this.memoryOptimizedFilegroupNameInput = fgInput;
|
||||
}
|
||||
|
||||
let fgInputGroupcontainer = this.createLabelInputContainer(localizedConstants.fileGroupsNameInput, [fgInput], false);
|
||||
await fgInputGroupcontainer.updateCssStyles({ 'margin': '0px 0px -10px 10px' });
|
||||
fgInputGroupcontainer.display = 'none';
|
||||
return fgInputGroupcontainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1100,9 +1139,8 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
inputType: 'text',
|
||||
enabled: true,
|
||||
value: '',
|
||||
width: 200,
|
||||
CSSStyles: { 'margin': '5px 0px 0px 10px', 'visibility': 'hidden' }
|
||||
})
|
||||
width: DefaultInputWidth
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1297,7 +1335,8 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
|
||||
//#region Database Properties - Data Scoped configurations Tab
|
||||
private async initializeDatabaseScopedConfigurationSection(): Promise<void> {
|
||||
this.dscOriginalData = deepClone(this.objectInfo.databaseScopedConfigurations);
|
||||
// Configurations that doesn't support secondary replica
|
||||
let secondaryUnsupportedConfigsSet = new Set<number>([11, 12, 25, 6, 21]);
|
||||
const dscNameColumn: azdata.TableColumn = {
|
||||
type: azdata.ColumnType.text,
|
||||
value: localizedConstants.DatabaseScopedOptionsColumnHeader,
|
||||
@@ -1317,9 +1356,9 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
this.dscTable = this.modelView.modelBuilder.table().withProps({
|
||||
columns: [dscNameColumn, primaryValueColumn, secondaryValueColumn],
|
||||
data: this.objectInfo.databaseScopedConfigurations.map(metaData => {
|
||||
return [metaData.name,
|
||||
return [metaData.name.toLocaleUpperCase(),
|
||||
metaData.valueForPrimary,
|
||||
metaData.valueForSecondary]
|
||||
secondaryUnsupportedConfigsSet.has(metaData.id) ? localizedConstants.NotAvailableText : metaData.valueForSecondary]
|
||||
}),
|
||||
height: getTableHeight(this.objectInfo.databaseScopedConfigurations.length, 1, DscTableRowLength),
|
||||
width: DefaultTableWidth
|
||||
@@ -1355,7 +1394,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
|
||||
// Cannot set the 'ELEVATE_ONLINE (11) and ELEVATE_RESUMABLE (12)' option for the secondaries replica while this option is only allowed to be set for the primary
|
||||
if (this.currentRowObjectInfo.id === 11 || this.currentRowObjectInfo.id === 12) {
|
||||
await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' });
|
||||
await this.dscPrimaryValueDropdown.updateCssStyles({ 'display': 'inline-flex' });
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscElevateOptions) ||
|
||||
this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) {
|
||||
await this.valueForPrimaryDropdown.updateProperties({
|
||||
@@ -1378,7 +1417,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
}
|
||||
// Cannot set the 'AUTO_ABORT_PAUSED_INDEX (25)' option for the secondaries replica while this option is only allowed to be set for the primary.
|
||||
else if (this.currentRowObjectInfo.id === 25) {
|
||||
await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-175px' });
|
||||
await this.dscPrimaryValueInput.updateCssStyles({ 'display': 'inline-flex' });
|
||||
await this.valueForPrimaryInput.updateProperties({
|
||||
value: this.currentRowObjectInfo.valueForPrimary
|
||||
, max: PAUSED_RESUMABLE_INDEX_Max_Limit
|
||||
@@ -1387,18 +1426,18 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
// Can only set OFF/Azure blob storage endpoint to the 'LEDGER_DIGEST_STORAGE_ENDPOINT (38)'s primary and secondary values
|
||||
else if (this.currentRowObjectInfo.id === 38) {
|
||||
await this.showDropdownsSection(isSecondaryCheckboxChecked);
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify([this.viewInfo.dscOnOffOptions[1]]) ||
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify([this.viewInfo.propertiesOnOffOptions[1]]) ||
|
||||
this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) {
|
||||
await this.valueForPrimaryDropdown.updateProperties({
|
||||
values: [this.viewInfo.dscOnOffOptions[1]] // Only OFF is allowed for primary value
|
||||
values: [this.viewInfo.propertiesOnOffOptions[1]] // Only OFF is allowed for primary value
|
||||
, value: this.currentRowObjectInfo.valueForPrimary
|
||||
, editable: true // This is to allow the user to enter the Azure blob storage endpoint
|
||||
});
|
||||
}
|
||||
if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify([this.viewInfo.dscOnOffOptions[1]]) ||
|
||||
if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify([this.viewInfo.propertiesOnOffOptions[1]]) ||
|
||||
this.valueForSecondaryDropdown.value !== this.currentRowObjectInfo.valueForSecondary) {
|
||||
await this.valueForSecondaryDropdown.updateProperties({
|
||||
values: [this.viewInfo.dscOnOffOptions[1]] // Only OFF is allowed for secondary value
|
||||
values: [this.viewInfo.propertiesOnOffOptions[1]] // Only OFF is allowed for secondary value
|
||||
, value: this.currentRowObjectInfo.valueForSecondary
|
||||
, editable: true // This is to allow the user to enter the Azure blob storage endpoint
|
||||
});
|
||||
@@ -1407,11 +1446,11 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
// Cannot set the 'IDENTITY_CACHE (6)' option for the secondaries replica while this option is only allowed to be set for the primary.
|
||||
// Cannot set the 'GLOBAL_TEMPORARY_TABLE_AUTO_DROP (21)' option for the secondaries replica while this option is only allowed to be set for the primary.
|
||||
else if (this.currentRowObjectInfo.id === 6 || this.currentRowObjectInfo.id === 21) {
|
||||
await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' });
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) ||
|
||||
await this.dscPrimaryValueDropdown.updateCssStyles({ 'display': 'inline-flex' });
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.propertiesOnOffOptions) ||
|
||||
this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) {
|
||||
await this.valueForPrimaryDropdown.updateProperties({
|
||||
values: this.viewInfo.dscOnOffOptions
|
||||
values: this.viewInfo.propertiesOnOffOptions
|
||||
, value: this.currentRowObjectInfo.valueForPrimary
|
||||
});
|
||||
}
|
||||
@@ -1437,17 +1476,17 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
// All other options accepts primary and seconday values as ON/OFF/PRIMARY(only secondary)
|
||||
else {
|
||||
await this.showDropdownsSection(isSecondaryCheckboxChecked);
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) ||
|
||||
if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.propertiesOnOffOptions) ||
|
||||
this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) {
|
||||
await this.valueForPrimaryDropdown.updateProperties({
|
||||
values: this.viewInfo.dscOnOffOptions
|
||||
values: this.viewInfo.propertiesOnOffOptions
|
||||
, value: this.currentRowObjectInfo.valueForPrimary
|
||||
});
|
||||
}
|
||||
if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) ||
|
||||
if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify(this.viewInfo.propertiesOnOffOptions) ||
|
||||
this.valueForSecondaryDropdown.value !== this.currentRowObjectInfo.valueForSecondary) {
|
||||
await this.valueForSecondaryDropdown.updateProperties({
|
||||
values: this.viewInfo.dscOnOffOptions
|
||||
values: this.viewInfo.propertiesOnOffOptions
|
||||
, value: this.currentRowObjectInfo.valueForSecondary
|
||||
});
|
||||
}
|
||||
@@ -1481,22 +1520,20 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
width: 150,
|
||||
min: 0
|
||||
});
|
||||
const primaryContainer = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryInput);
|
||||
this.dscPrimaryValueInputGroup = this.createGroup('', [primaryContainer], false, true);
|
||||
await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.dscPrimaryValueInput = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryInput);
|
||||
this.dscPrimaryValueInput.display = 'none';
|
||||
|
||||
// Apply Primary To Secondary checkbox
|
||||
this.setSecondaryCheckboxForInputType = this.createCheckbox(localizedConstants.SetSecondaryText, async (checked) => {
|
||||
await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': checked ? 'hidden' : 'visible' });
|
||||
this.currentRowObjectInfo.valueForSecondary = checked ? this.currentRowObjectInfo.valueForPrimary : this.dscOriginalData[this.currentRowId].valueForSecondary;
|
||||
await this.dscSecondaryValueInput.updateCssStyles({ 'display': checked ? 'none' : 'inline-flex' });
|
||||
this.currentRowObjectInfo.valueForSecondary = this.currentRowObjectInfo.valueForPrimary;
|
||||
await this.valueForSecondaryInput.updateProperties({ value: this.currentRowObjectInfo.valueForSecondary });
|
||||
if (this.dscTable.data[this.currentRowId][2] !== this.currentRowObjectInfo.valueForSecondary) {
|
||||
this.dscTable.data[this.currentRowId][2] = this.currentRowObjectInfo.valueForSecondary;
|
||||
await this.updateDscTable(this.dscTable.data);
|
||||
}
|
||||
}, true);
|
||||
this.dscSecondaryCheckboxForInputGroup = this.createGroup('', [this.setSecondaryCheckboxForInputType], false, true);
|
||||
await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.setSecondaryCheckboxForInputType.display = 'none';
|
||||
|
||||
// Value for Secondary
|
||||
this.valueForSecondaryInput = this.createInputBox(async (newValue) => {
|
||||
@@ -1513,13 +1550,12 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
width: 150,
|
||||
min: 0
|
||||
});
|
||||
const secondaryContainer = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryInput);
|
||||
this.dscSecondaryValueInputGroup = this.createGroup('', [secondaryContainer], false, true);
|
||||
await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.dscSecondaryValueInput = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryInput);
|
||||
this.dscSecondaryValueInput.display = 'none';
|
||||
|
||||
const maxDopGroup = this.createGroup('', [this.dscPrimaryValueInputGroup, this.dscSecondaryCheckboxForInputGroup, this.dscSecondaryValueInputGroup], false, true);
|
||||
await maxDopGroup.updateCssStyles({ 'margin-left': '-10px' });
|
||||
return maxDopGroup;
|
||||
const inputTypegroup = this.createGroup('', [this.dscPrimaryValueInput, this.setSecondaryCheckboxForInputType, this.dscSecondaryValueInput], false, true);
|
||||
await inputTypegroup.updateCssStyles({ 'margin-top': '-30px' });
|
||||
return inputTypegroup;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1543,18 +1579,16 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
await this.updateDscTable(this.dscTable.data);
|
||||
}
|
||||
}, [], '', true, 150)
|
||||
const primaryContainer = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryDropdown);
|
||||
this.dscPrimaryValueDropdownGroup = this.createGroup('', [primaryContainer], false, true);
|
||||
await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.dscPrimaryValueDropdown = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryDropdown);
|
||||
this.dscPrimaryValueDropdown.display = 'none';
|
||||
|
||||
// Apply Primary To Secondary checkbox
|
||||
this.setSecondaryCheckboxForDropdowns = this.createCheckbox(localizedConstants.SetSecondaryText, async (checked) => {
|
||||
await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': checked ? 'hidden' : 'visible' });
|
||||
this.currentRowObjectInfo.valueForSecondary = checked ? this.currentRowObjectInfo.valueForPrimary : this.dscOriginalData[this.currentRowId].valueForSecondary;
|
||||
await this.dscSecondaryValueDropdown.updateCssStyles({ 'display': checked ? 'none' : 'inline-flex' });
|
||||
this.currentRowObjectInfo.valueForSecondary = this.currentRowObjectInfo.valueForPrimary;
|
||||
await this.valueForSecondaryDropdown.updateProperties({ value: this.currentRowObjectInfo.valueForSecondary });
|
||||
}, true);
|
||||
this.dscSecondaryCheckboxForDropdownGroup = this.createGroup('', [this.setSecondaryCheckboxForDropdowns], false, true);
|
||||
await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.setSecondaryCheckboxForDropdowns.display = 'none';
|
||||
|
||||
// Value for Secondary
|
||||
this.valueForSecondaryDropdown = this.createDropdown(localizedConstants.ValueForSecondaryColumnHeader, async (newValue) => {
|
||||
@@ -1566,13 +1600,10 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
}
|
||||
}
|
||||
}, [], '', true, 150);
|
||||
const secondaryContainer = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryDropdown);
|
||||
this.dscSecondaryValueDropdownGroup = this.createGroup('', [secondaryContainer], false, true);
|
||||
await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
this.dscSecondaryValueDropdown = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryDropdown);
|
||||
this.dscSecondaryValueDropdown.display = 'none';
|
||||
|
||||
const valueGroup = this.createGroup('', [this.dscPrimaryValueDropdownGroup, this.dscSecondaryCheckboxForDropdownGroup, this.dscSecondaryValueDropdownGroup], true, true);
|
||||
await valueGroup.updateCssStyles({ 'margin-left': '-10px' });
|
||||
return valueGroup;
|
||||
return this.createGroup('', [this.dscPrimaryValueDropdown, this.setSecondaryCheckboxForDropdowns, this.dscSecondaryValueDropdown], true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1581,9 +1612,9 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
*/
|
||||
private async showDropdownsSection(isSecondaryCheckboxChecked: boolean): Promise<void> {
|
||||
this.setSecondaryCheckboxForDropdowns.checked = isSecondaryCheckboxChecked;
|
||||
await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' });
|
||||
await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'visible' });
|
||||
await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': isSecondaryCheckboxChecked ? 'hidden' : 'visible' });
|
||||
this.setSecondaryCheckboxForDropdowns.display = 'inline-flex';
|
||||
await this.dscPrimaryValueDropdown.updateCssStyles({ 'display': 'inline-flex' });
|
||||
await this.dscSecondaryValueDropdown.updateCssStyles({ 'display': isSecondaryCheckboxChecked ? 'none' : 'inline-flex' });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1592,21 +1623,21 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
*/
|
||||
private async showInputSection(isSecondaryCheckboxChecked: boolean): Promise<void> {
|
||||
this.setSecondaryCheckboxForInputType.checked = isSecondaryCheckboxChecked;
|
||||
await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-175px' });
|
||||
await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-120px' });
|
||||
await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': isSecondaryCheckboxChecked ? 'hidden' : 'visible', 'margin-top': '-85px' });
|
||||
this.setSecondaryCheckboxForInputType.display = 'inline-flex';
|
||||
await this.dscPrimaryValueInput.updateCssStyles({ 'display': 'inline-flex' });
|
||||
await this.dscSecondaryValueInput.updateCssStyles({ 'display': isSecondaryCheckboxChecked ? 'none' : 'inline-flex' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all primary and secondary groups to hidden
|
||||
*/
|
||||
private async hideDropdownAndInputSections(): Promise<void> {
|
||||
await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' });
|
||||
await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' });
|
||||
await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' });
|
||||
await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' });
|
||||
await this.dscPrimaryValueInput.updateCssStyles({ 'display': 'none' });
|
||||
this.setSecondaryCheckboxForInputType.display = 'none';
|
||||
await this.dscSecondaryValueInput.updateCssStyles({ 'display': 'none' });
|
||||
await this.dscPrimaryValueDropdown.updateCssStyles({ 'display': 'none' });
|
||||
this.setSecondaryCheckboxForDropdowns.display = 'none';
|
||||
await this.dscSecondaryValueDropdown.updateCssStyles({ 'display': 'none' });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1727,12 +1758,13 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
|
||||
// Wait Statistics Capture Mode - supported from 2017 or higher
|
||||
if (!isUndefinedOrNull(this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode)) {
|
||||
this.waitStatisticsCaptureMode = this.createCheckbox(localizedConstants.WaitStatisticsCaptureModeText, async (checked) => {
|
||||
this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode = checked;
|
||||
}, this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode, this.areQueryStoreOptionsEnabled);
|
||||
containers.push(this.waitStatisticsCaptureMode);
|
||||
this.waitStatisticsCaptureMode = this.createDropdown(localizedConstants.WaitStatisticsCaptureModeText, async (newValue) => {
|
||||
// waitStatisticsCaptureMode value comes as On/Off, but options we provide are ON/OFF, handling selected value to match with the incoming value
|
||||
this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode = newValue.charAt(0) + newValue.slice(1).toLowerCase() as string;
|
||||
}, this.viewInfo.propertiesOnOffOptions, this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode.toUpperCase(), this.areQueryStoreOptionsEnabled, DefaultInputWidth);
|
||||
containers.push(this.createLabelInputContainer(localizedConstants.WaitStatisticsCaptureModeText, this.waitStatisticsCaptureMode));
|
||||
}
|
||||
const retentionSection = this.createGroup(localizedConstants.WaitStatisticsCaptureModeText, containers, true);
|
||||
const retentionSection = this.createGroup(localizedConstants.QueryStoreRetentionSectionText, containers, true);
|
||||
this.queryStoreTabSectionsContainer.push(retentionSection);
|
||||
}
|
||||
|
||||
@@ -1834,7 +1866,7 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
return;
|
||||
}
|
||||
|
||||
await this.objectManagementService.purgeQueryStoreData(this.options.connectionUri, this.options.database, this.options.objectUrn);
|
||||
await this.objectManagementService.purgeQueryStoreData(this.options.connectionUri, this.options.database);
|
||||
}
|
||||
|
||||
private async toggleQueryStoreOptions(): Promise<void> {
|
||||
@@ -1848,7 +1880,8 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
if (!isUndefinedOrNull(this.objectInfo.queryStoreOptions.waitStatisticsCaptureMode)) {
|
||||
this.waitStatisticsCaptureMode.enabled = this.areQueryStoreOptionsEnabled
|
||||
}
|
||||
await this.toggleQueryCapturePolicySection(this.areQueryStoreOptionsEnabled);
|
||||
await this.toggleQueryCapturePolicySection(this.areQueryStoreOptionsEnabled &&
|
||||
this.queryStoreCaptureMode.value === localizedConstants.QueryStoreCapturemodeCustomText);
|
||||
}
|
||||
|
||||
private async toggleQueryCapturePolicySection(enable: boolean): Promise<void> {
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { DefaultInputWidth, DialogBase } from '../../ui/dialogBase';
|
||||
import * as localizedConstants from '../localizedConstants';
|
||||
import { DatabaseFile, DatabaseViewInfo, FileGrowthType } from '../interfaces';
|
||||
import { isUndefinedOrNull } from '../../types';
|
||||
import { deepClone } from '../../util/objects';
|
||||
import { IObjectManagementService } from 'mssql';
|
||||
|
||||
export interface NewDatabaseFileDialogOptions {
|
||||
title: string;
|
||||
@@ -27,6 +27,7 @@ export interface NewDatabaseFileDialogOptions {
|
||||
defaultFileGrowthInMb: number,
|
||||
defaultMaxFileSizeLimitedToInMb: number
|
||||
};
|
||||
connectionUri: string;
|
||||
}
|
||||
|
||||
const fileSizeInputMaxValueInMbForDataType = 16776192; // Row type supports up to 16 TB (SSMS allows =~ 15.99TB)
|
||||
@@ -58,7 +59,7 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
private originalFileName: string;
|
||||
private isEditingFile: boolean;
|
||||
|
||||
constructor(private readonly options: NewDatabaseFileDialogOptions) {
|
||||
constructor(private readonly options: NewDatabaseFileDialogOptions, private readonly objectManagementService: IObjectManagementService) {
|
||||
super(options.title, 'DatabaseFileDialog');
|
||||
}
|
||||
|
||||
@@ -92,7 +93,10 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
errors.push(localizedConstants.FileNameExistsError(this.result.name.trim()));
|
||||
}
|
||||
// If new file, verify if the file name with extension already exists
|
||||
if (this.options.isNewFile && !!this.options.files.find(file => { return (path.join(file.path, file.fileNameWithExtension) === path.join(this.result.path, this.result.fileNameWithExtension)) })) {
|
||||
if (this.options.isNewFile && !!this.options.files.find(file => {
|
||||
return (this.result.name === file.name &&
|
||||
path.join(file.path, file.fileNameWithExtension) === path.join(this.result.path, this.result.fileNameWithExtension))
|
||||
})) {
|
||||
errors.push(localizedConstants.FileAlreadyExistsError(path.join(this.result.path, this.result.fileNameWithExtension)));
|
||||
}
|
||||
}
|
||||
@@ -157,7 +161,8 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
ariaLabel: localizedConstants.SizeInMbText,
|
||||
inputType: 'number',
|
||||
enabled: this.options.databaseFile.type !== localizedConstants.FilestreamFileType,
|
||||
value: String(this.options.databaseFile.sizeInMb)
|
||||
value: String(this.options.databaseFile.sizeInMb),
|
||||
min: 1
|
||||
});
|
||||
const fileSizeContainer = this.createLabelInputContainer(localizedConstants.SizeInMbText, this.fileSizeInput);
|
||||
containers.push(fileSizeContainer);
|
||||
@@ -212,9 +217,9 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
= this.inMegabytesAutogrowth.enabled
|
||||
= this.autoFilegrowthInput.enabled
|
||||
= this.limitedToMbFileSize.enabled
|
||||
= this.limitedToMbFileSizeInput.enabled
|
||||
= this.unlimitedFileSize.enabled
|
||||
= this.result.isAutoGrowthEnabled = checked;
|
||||
this.limitedToMbFileSizeInput.enabled = checked && this.limitedToMbFileSize.checked;
|
||||
}, true, true);
|
||||
|
||||
// Autogrowth radio button and input section
|
||||
@@ -292,23 +297,12 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
* Creates a file browser and sets the path to the filePath
|
||||
*/
|
||||
private async createFileBrowser(): Promise<void> {
|
||||
let fileUris = await vscode.window.showOpenDialog(
|
||||
{
|
||||
canSelectFiles: false,
|
||||
canSelectFolders: true,
|
||||
canSelectMany: false,
|
||||
defaultUri: vscode.Uri.file(this.options.databaseFile.path),
|
||||
openLabel: localizedConstants.SelectText
|
||||
}
|
||||
);
|
||||
|
||||
if (!fileUris || fileUris.length === 0) {
|
||||
return;
|
||||
let dataFolder = await this.objectManagementService.getDataFolder(this.options.connectionUri);
|
||||
let filePath = await azdata.window.openServerFileBrowserDialog(this.options.connectionUri, dataFolder, [{ label: localizedConstants.allFiles, filters: ['*'] }], true);
|
||||
if (filePath?.length > 0) {
|
||||
this.filePathTextBox.value = filePath;
|
||||
this.result.path = filePath;
|
||||
}
|
||||
|
||||
let fileUri = fileUris[0];
|
||||
this.filePathTextBox.value = fileUri.fsPath;
|
||||
this.result.path = fileUri.fsPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,11 +322,11 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
|
||||
if (selectedOption === localizedConstants.LogFiletype) {
|
||||
fileGroupDdOptions = [localizedConstants.FileGroupForLogTypeText];
|
||||
fileGroupDdValue = localizedConstants.FileGroupForLogTypeText;
|
||||
fileSizeInputMaxValue = fileSizeInputMaxValueInMbForLogType
|
||||
fileSizeInputMaxValue = fileSizeInputMaxValueInMbForLogType;
|
||||
}
|
||||
// File Stream
|
||||
else if (selectedOption === localizedConstants.FilestreamFileType) {
|
||||
fileGroupDdOptions = this.options.filestreamFilegroups;
|
||||
fileGroupDdOptions = this.options.filestreamFilegroups.length > 0 ? this.options.filestreamFilegroups : [localizedConstants.FileGroupForFilestreamTypeText];
|
||||
fileGroupDdValue = this.result.fileGroup;
|
||||
visibility = 'hidden';
|
||||
maxSizeGroupMarginTop = '-130px';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||
import { Database, DatabaseViewInfo } from '../interfaces';
|
||||
import { DetachDatabaseDocUrl } from '../constants';
|
||||
import { DetachDatabaseDocUrl, TelemetryActions } from '../constants';
|
||||
import * as loc from '../localizedConstants';
|
||||
|
||||
export class DetachDatabaseDialog extends ObjectManagementDialogBase<Database, DatabaseViewInfo> {
|
||||
@@ -48,12 +48,16 @@ export class DetachDatabaseDialog extends ObjectManagementDialogBase<Database, D
|
||||
return DetachDatabaseDocUrl;
|
||||
}
|
||||
|
||||
protected override get actionName(): string {
|
||||
return TelemetryActions.DetachDatabase;
|
||||
}
|
||||
|
||||
protected override async saveChanges(contextId: string, object: ObjectManagement.SqlObject): Promise<void> {
|
||||
await this.objectManagementService.detachDatabase(this.options.connectionUri, this.options.database, this.options.objectUrn, this._dropConnections, this._updateStatistics, false);
|
||||
await this.objectManagementService.detachDatabase(this.options.connectionUri, this.options.database, this._dropConnections, this._updateStatistics, false);
|
||||
}
|
||||
|
||||
protected override async generateScript(): Promise<string> {
|
||||
return await this.objectManagementService.detachDatabase(this.options.connectionUri, this.options.database, this.options.objectUrn, this._dropConnections, this._updateStatistics, true);
|
||||
return await this.objectManagementService.detachDatabase(this.options.connectionUri, this.options.database, this._dropConnections, this._updateStatistics, true);
|
||||
}
|
||||
|
||||
protected override async validateInput(): Promise<string[]> {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||
import { Database, DatabaseViewInfo } from '../interfaces';
|
||||
import { DropDatabaseDocUrl } from '../constants';
|
||||
import { DropDatabaseDocUrl, TelemetryActions } from '../constants';
|
||||
import * as loc from '../localizedConstants';
|
||||
|
||||
export class DropDatabaseDialog extends ObjectManagementDialogBase<Database, DatabaseViewInfo> {
|
||||
@@ -52,12 +52,16 @@ export class DropDatabaseDialog extends ObjectManagementDialogBase<Database, Dat
|
||||
return DropDatabaseDocUrl;
|
||||
}
|
||||
|
||||
protected override get actionName(): string {
|
||||
return TelemetryActions.DropObject;
|
||||
}
|
||||
|
||||
protected override async saveChanges(contextId: string, object: ObjectManagement.SqlObject): Promise<void> {
|
||||
await this.objectManagementService.dropDatabase(this.options.connectionUri, this.options.database, this.options.objectUrn, this._dropConnections, this._deleteBackupHistory, false);
|
||||
await this.objectManagementService.dropDatabase(this.options.connectionUri, this.options.database, this._dropConnections, this._deleteBackupHistory, false);
|
||||
}
|
||||
|
||||
protected override async generateScript(): Promise<string> {
|
||||
return await this.objectManagementService.dropDatabase(this.options.connectionUri, this.options.database, this.options.objectUrn, this._dropConnections, this._deleteBackupHistory, true);
|
||||
return await this.objectManagementService.dropDatabase(this.options.connectionUri, this.options.database, this._dropConnections, this._deleteBackupHistory, true);
|
||||
}
|
||||
|
||||
protected override async validateInput(): Promise<string[]> {
|
||||
|
||||
@@ -47,6 +47,11 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
||||
constructor(private readonly objectManagementService: mssql.IObjectManagementService, private readonly options: FindObjectDialogOptions) {
|
||||
super(options.title, 'FindObjectDialog');
|
||||
this.dialogObject.okButton.label = localizedConstants.SelectText;
|
||||
this.dialogObject.okButton.enabled = false;
|
||||
|
||||
// Relabel Cancel button to Back, since clicking cancel on an inner dialog makes it seem like it would close the whole dialog overall
|
||||
this.dialogObject.cancelButton.label = localizedConstants.BackButtonLabel;
|
||||
|
||||
this.result = {
|
||||
selectedObjects: []
|
||||
};
|
||||
@@ -54,7 +59,6 @@ export class FindObjectDialog extends DialogBase<FindObjectDialogResult> {
|
||||
}
|
||||
|
||||
protected override async initialize(): Promise<void> {
|
||||
this.dialogObject.okButton.enabled = false;
|
||||
this.objectTypesTable = this.createTableList<ObjectTypeInfo>(localizedConstants.ObjectTypesText,
|
||||
[localizedConstants.ObjectTypeText],
|
||||
this.options.objectTypes,
|
||||
|
||||
@@ -18,7 +18,6 @@ export class LoginDialog extends PrincipalDialogBase<Login, LoginViewInfo> {
|
||||
private generalSection: azdata.GroupContainer;
|
||||
private sqlAuthSection: azdata.GroupContainer;
|
||||
private serverRoleSection: azdata.GroupContainer;
|
||||
private advancedSection: azdata.GroupContainer;
|
||||
private nameInput: azdata.InputBoxComponent;
|
||||
private authTypeDropdown: azdata.DropDownComponent;
|
||||
private passwordInput: azdata.InputBoxComponent;
|
||||
@@ -99,14 +98,11 @@ export class LoginDialog extends PrincipalDialogBase<Login, LoginViewInfo> {
|
||||
sections.push(this.serverRoleSection);
|
||||
sections.push(this.securableSection);
|
||||
|
||||
if (this.viewInfo.supportAdvancedOptions) {
|
||||
this.initializeAdvancedSection();
|
||||
sections.push(this.advancedSection);
|
||||
}
|
||||
this.formContainer.addItems(sections, this.getSectionItemLayout());
|
||||
}
|
||||
|
||||
private initializeGeneralSection(): void {
|
||||
const items: azdata.Component[] = [];
|
||||
this.nameInput = this.createInputBox(async (newValue) => {
|
||||
this.objectInfo.name = newValue;
|
||||
}, {
|
||||
@@ -115,8 +111,9 @@ export class LoginDialog extends PrincipalDialogBase<Login, LoginViewInfo> {
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.name
|
||||
});
|
||||
|
||||
const nameContainer = this.createLabelInputContainer(objectManagementLoc.NameText, this.nameInput);
|
||||
items.push(nameContainer);
|
||||
|
||||
this.authTypeDropdown = this.createDropdown(objectManagementLoc.AuthTypeText,
|
||||
async (newValue) => {
|
||||
this.objectInfo.authenticationType = objectManagementLoc.getAuthenticationTypeByDisplayName(newValue);
|
||||
@@ -125,13 +122,34 @@ export class LoginDialog extends PrincipalDialogBase<Login, LoginViewInfo> {
|
||||
this.viewInfo.authenticationTypes.map(authType => objectManagementLoc.getAuthenticationTypeDisplayName(authType)),
|
||||
objectManagementLoc.getAuthenticationTypeDisplayName(this.objectInfo.authenticationType),
|
||||
this.options.isNewObject);
|
||||
|
||||
const authTypeContainer = this.createLabelInputContainer(objectManagementLoc.AuthTypeText, this.authTypeDropdown);
|
||||
items.push(authTypeContainer);
|
||||
|
||||
this.enabledCheckbox = this.createCheckbox(objectManagementLoc.EnabledText, async (checked) => {
|
||||
this.objectInfo.isEnabled = checked;
|
||||
}, this.objectInfo.isEnabled);
|
||||
this.generalSection = this.createGroup(objectManagementLoc.GeneralSectionHeader, [nameContainer, authTypeContainer, this.enabledCheckbox], false);
|
||||
items.push(this.enabledCheckbox);
|
||||
|
||||
if (this.viewInfo.supportAdvancedOptions) {
|
||||
this.defaultDatabaseDropdown = this.createDropdown(objectManagementLoc.DefaultDatabaseText, async (newValue) => {
|
||||
this.objectInfo.defaultDatabase = newValue;
|
||||
}, this.viewInfo.databases, this.objectInfo.defaultDatabase);
|
||||
const defaultDatabaseContainer = this.createLabelInputContainer(objectManagementLoc.DefaultDatabaseText, this.defaultDatabaseDropdown);
|
||||
items.push(defaultDatabaseContainer);
|
||||
|
||||
this.defaultLanguageDropdown = this.createDropdown(objectManagementLoc.DefaultLanguageText, async (newValue) => {
|
||||
this.objectInfo.defaultLanguage = newValue;
|
||||
}, this.viewInfo.languages, this.objectInfo.defaultLanguage);
|
||||
const defaultLanguageContainer = this.createLabelInputContainer(objectManagementLoc.DefaultLanguageText, this.defaultLanguageDropdown);
|
||||
items.push(defaultLanguageContainer);
|
||||
|
||||
this.connectPermissionCheckbox = this.createCheckbox(objectManagementLoc.PermissionToConnectText, async (checked) => {
|
||||
this.objectInfo.connectPermission = checked;
|
||||
}, this.objectInfo.connectPermission);
|
||||
items.push(this.connectPermissionCheckbox);
|
||||
}
|
||||
|
||||
this.generalSection = this.createGroup(objectManagementLoc.GeneralSectionHeader, items, false);
|
||||
}
|
||||
|
||||
private initializeSqlAuthSection(): void {
|
||||
@@ -207,28 +225,6 @@ export class LoginDialog extends PrincipalDialogBase<Login, LoginViewInfo> {
|
||||
return this.objectInfo.password !== this.originalObjectInfo.password
|
||||
}
|
||||
|
||||
private initializeAdvancedSection(): void {
|
||||
const items: azdata.Component[] = [];
|
||||
if (this.viewInfo.supportAdvancedOptions) {
|
||||
this.defaultDatabaseDropdown = this.createDropdown(objectManagementLoc.DefaultDatabaseText, async (newValue) => {
|
||||
this.objectInfo.defaultDatabase = newValue;
|
||||
}, this.viewInfo.databases, this.objectInfo.defaultDatabase);
|
||||
const defaultDatabaseContainer = this.createLabelInputContainer(objectManagementLoc.DefaultDatabaseText, this.defaultDatabaseDropdown);
|
||||
|
||||
this.defaultLanguageDropdown = this.createDropdown(objectManagementLoc.DefaultLanguageText, async (newValue) => {
|
||||
this.objectInfo.defaultLanguage = newValue;
|
||||
}, this.viewInfo.languages, this.objectInfo.defaultLanguage);
|
||||
const defaultLanguageContainer = this.createLabelInputContainer(objectManagementLoc.DefaultLanguageText, this.defaultLanguageDropdown);
|
||||
|
||||
this.connectPermissionCheckbox = this.createCheckbox(objectManagementLoc.PermissionToConnectText, async (checked) => {
|
||||
this.objectInfo.connectPermission = checked;
|
||||
}, this.objectInfo.connectPermission);
|
||||
items.push(defaultDatabaseContainer, defaultLanguageContainer, this.connectPermissionCheckbox);
|
||||
}
|
||||
|
||||
this.advancedSection = this.createGroup(objectManagementLoc.AdvancedSectionHeader, items, true, true);
|
||||
}
|
||||
|
||||
private initializeServerRolesSection(): void {
|
||||
this.serverRoleTable = this.createTableList(objectManagementLoc.ServerRoleSectionHeader,
|
||||
[objectManagementLoc.ServerRoleTypeDisplayNameInTitle],
|
||||
|
||||
@@ -68,6 +68,10 @@ export abstract class ObjectManagementDialogBase<ObjectInfoType extends ObjectMa
|
||||
: localizedConstants.UpdateObjectOperationDisplayName(typeDisplayName, this.options.objectName);
|
||||
}
|
||||
|
||||
protected get actionName(): string {
|
||||
return this.options.isNewObject ? TelemetryActions.CreateObject : TelemetryActions.UpdateObject;
|
||||
}
|
||||
|
||||
protected override async initialize(): Promise<void> {
|
||||
await super.initialize();
|
||||
this.dialogObject.registerOperation({
|
||||
@@ -75,7 +79,6 @@ export abstract class ObjectManagementDialogBase<ObjectInfoType extends ObjectMa
|
||||
description: '',
|
||||
isCancelable: false,
|
||||
operation: async (operation: azdata.BackgroundOperation): Promise<void> => {
|
||||
const actionName = this.options.isNewObject ? TelemetryActions.CreateObject : TelemetryActions.UpdateObject;
|
||||
try {
|
||||
if (this.isDirty) {
|
||||
const startTime = Date.now();
|
||||
@@ -89,7 +92,7 @@ export abstract class ObjectManagementDialogBase<ObjectInfoType extends ObjectMa
|
||||
}
|
||||
}
|
||||
|
||||
TelemetryReporter.sendTelemetryEvent(actionName, {
|
||||
TelemetryReporter.sendTelemetryEvent(this.actionName, {
|
||||
objectType: this.options.objectType
|
||||
}, {
|
||||
elapsedTimeMs: Date.now() - startTime
|
||||
@@ -99,7 +102,7 @@ export abstract class ObjectManagementDialogBase<ObjectInfoType extends ObjectMa
|
||||
}
|
||||
catch (err) {
|
||||
operation.updateStatus(azdata.TaskStatus.Failed, getErrorMessage(err));
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, actionName, err).withAdditionalProperties({
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, this.actionName, err).withAdditionalProperties({
|
||||
objectType: this.options.objectType
|
||||
}).send();
|
||||
} finally {
|
||||
|
||||
@@ -40,6 +40,9 @@ export class ObjectSelectionMethodDialog extends DialogBase<ObjectSelectionMetho
|
||||
schema: undefined,
|
||||
objectTypes: []
|
||||
};
|
||||
|
||||
// Relabel Cancel button to Back, since clicking cancel on an inner dialog makes it seem like it would close the whole dialog overall
|
||||
this.dialogObject.cancelButton.label = localizedConstants.BackButtonLabel;
|
||||
}
|
||||
|
||||
protected override async initialize(): Promise<void> {
|
||||
|
||||
@@ -10,6 +10,9 @@ import { IObjectManagementService } from 'mssql';
|
||||
import * as localizedConstants from '../localizedConstants';
|
||||
import * as constants from '../constants';
|
||||
import { Server, ServerViewInfo, NumaNode, AffinityType, ServerLoginMode, AuditLevel } from '../interfaces';
|
||||
import { isUndefinedOrNull } from '../../types';
|
||||
|
||||
const Dialog_Width = '750px';
|
||||
|
||||
export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, ServerViewInfo> {
|
||||
private generalTab: azdata.Tab;
|
||||
@@ -90,9 +93,13 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
private shouldRestartServer: boolean = false;
|
||||
|
||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||
options.width = Dialog_Width;
|
||||
super(objectManagementService, options);
|
||||
this.disposables.push(this.dialogObject.onClosed(async () => {
|
||||
await this.notifyServerRestart();
|
||||
this.disposables.push(this.dialogObject.onClosed(async (reason: azdata.window.CloseReason) => {
|
||||
if (reason === 'ok') {
|
||||
// only show message if user apply changes
|
||||
await this.notifyServerRestart();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -135,6 +142,9 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
const serverPropertiesTabGroup = { title: '', tabs: [this.generalTab, this.memoryTab, this.processorsTab, this.securityTab, this.databaseSettingsTab, this.advancedTab] };
|
||||
const serverPropertiesTabbedPannel = this.modelView.modelBuilder.tabbedPanel()
|
||||
.withTabs([serverPropertiesTabGroup])
|
||||
.withLayout({
|
||||
orientation: azdata.TabOrientation.Vertical
|
||||
})
|
||||
.withProps({
|
||||
CSSStyles: {
|
||||
'margin': '-10px 0px 0px -10px'
|
||||
@@ -148,6 +158,19 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
}
|
||||
|
||||
private initializeGeneralSection(): void {
|
||||
// Information about the platform that the SQL instance is running on
|
||||
let platformItems: azdata.Component[] = [];
|
||||
if (this.objectInfo.hardwareGeneration) {
|
||||
this.hardwareGenerationInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.HardwareGenerationText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.hardwareGeneration.toString()
|
||||
});
|
||||
const hardwareGenerationContainer = this.createLabelInputContainer(localizedConstants.HardwareGenerationText, this.hardwareGenerationInput);
|
||||
platformItems.push(hardwareGenerationContainer);
|
||||
}
|
||||
|
||||
this.nameInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.NameText,
|
||||
inputType: 'text',
|
||||
@@ -155,17 +178,11 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.name
|
||||
});
|
||||
const nameContainer = this.createLabelInputContainer(localizedConstants.NameText, this.nameInput);
|
||||
|
||||
this.hardwareGenerationInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.HardwareGenerationText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.hardwareGeneration.toString()
|
||||
});
|
||||
const hardwareGenerationContainer = this.createLabelInputContainer(localizedConstants.HardwareGenerationText, this.hardwareGenerationInput);
|
||||
platformItems.push(nameContainer);
|
||||
|
||||
this.languageDropdown = this.createDropdown(localizedConstants.LanguageText, async () => { }, [this.objectInfo.language], this.objectInfo.language, this.options.isNewObject);
|
||||
const languageContainer = this.createLabelInputContainer(localizedConstants.LanguageText, this.languageDropdown);
|
||||
platformItems.push(languageContainer);
|
||||
|
||||
this.memoryInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.MemoryText,
|
||||
@@ -174,6 +191,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: localizedConstants.StringValueInMB(this.objectInfo.memoryInMB.toString())
|
||||
});
|
||||
const memoryContainer = this.createLabelInputContainer(localizedConstants.MemoryText, this.memoryInput);
|
||||
platformItems.push(memoryContainer);
|
||||
|
||||
this.operatingSystemInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.OperatingSystemText,
|
||||
@@ -182,6 +200,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.operatingSystem
|
||||
});
|
||||
const operatingSystemContainer = this.createLabelInputContainer(localizedConstants.OperatingSystemText, this.operatingSystemInput);
|
||||
platformItems.push(operatingSystemContainer);
|
||||
|
||||
this.platformInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.PlatformText,
|
||||
@@ -190,6 +209,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.platform
|
||||
});
|
||||
const platformContainer = this.createLabelInputContainer(localizedConstants.PlatformText, this.platformInput);
|
||||
platformItems.push(platformContainer);
|
||||
|
||||
this.processorsInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ProcessorsText,
|
||||
@@ -198,7 +218,10 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.processors
|
||||
});
|
||||
const processorsContainer = this.createLabelInputContainer(localizedConstants.ProcessorsText, this.processorsInput);
|
||||
platformItems.push(processorsContainer);
|
||||
|
||||
// Information about the SQL instance itself
|
||||
let sqlServerItems: azdata.Component[] = [];
|
||||
this.isClusteredInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsClusteredText,
|
||||
inputType: 'text',
|
||||
@@ -206,6 +229,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.isClustered.toString()
|
||||
});
|
||||
const isClusteredContainer = this.createLabelInputContainer(localizedConstants.IsClusteredText, this.isClusteredInput);
|
||||
sqlServerItems.push(isClusteredContainer);
|
||||
|
||||
this.isHadrEnabledInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsHadrEnabledText,
|
||||
@@ -214,22 +238,29 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.isHadrEnabled.toString()
|
||||
});
|
||||
const isHadrEnabledContainer = this.createLabelInputContainer(localizedConstants.IsHadrEnabledText, this.isHadrEnabledInput);
|
||||
sqlServerItems.push(isHadrEnabledContainer);
|
||||
|
||||
this.isPolyBaseInstalledInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsPolyBaseInstalledText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.isPolyBaseInstalled.toString()
|
||||
});
|
||||
const isPolyBaseInstalledContainer = this.createLabelInputContainer(localizedConstants.IsPolyBaseInstalledText, this.isPolyBaseInstalledInput);
|
||||
if (!isUndefinedOrNull(this.objectInfo.isPolyBaseInstalled)) {
|
||||
this.isPolyBaseInstalledInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsPolyBaseInstalledText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.isPolyBaseInstalled.toString()
|
||||
});
|
||||
const isPolyBaseInstalledContainer = this.createLabelInputContainer(localizedConstants.IsPolyBaseInstalledText, this.isPolyBaseInstalledInput);
|
||||
sqlServerItems.push(isPolyBaseInstalledContainer);
|
||||
}
|
||||
|
||||
this.isXTPSupportedInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsXTPSupportedText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.isXTPSupported.toString()
|
||||
});
|
||||
const isXTPSupportedContainer = this.createLabelInputContainer(localizedConstants.IsXTPSupportedText, this.isXTPSupportedInput);
|
||||
if (!isUndefinedOrNull(this.objectInfo.isXTPSupported)) {
|
||||
this.isXTPSupportedInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.IsXTPSupportedText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.isXTPSupported.toString()
|
||||
});
|
||||
const isXTPSupportedContainer = this.createLabelInputContainer(localizedConstants.IsXTPSupportedText, this.isXTPSupportedInput);
|
||||
sqlServerItems.push(isXTPSupportedContainer);
|
||||
}
|
||||
|
||||
this.productInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ProductText,
|
||||
@@ -238,14 +269,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.product
|
||||
});
|
||||
const productContainer = this.createLabelInputContainer(localizedConstants.ProductText, this.productInput);
|
||||
|
||||
this.reservedStorageSizeInMBInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ReservedStorageSizeInMBText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: localizedConstants.StringValueInMB(this.objectInfo.reservedStorageSizeMB.toString())
|
||||
});
|
||||
const reservedStorageSizeInMBContainer = this.createLabelInputContainer(localizedConstants.ReservedStorageSizeInMBText, this.reservedStorageSizeInMBInput);
|
||||
sqlServerItems.push(productContainer);
|
||||
|
||||
this.rootDirectoryInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.RootDirectoryText,
|
||||
@@ -254,6 +278,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.rootDirectory
|
||||
});
|
||||
const rootDirectoryContainer = this.createLabelInputContainer(localizedConstants.RootDirectoryText, this.rootDirectoryInput);
|
||||
sqlServerItems.push(rootDirectoryContainer);
|
||||
|
||||
this.serverCollationInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ServerCollationText,
|
||||
@@ -262,22 +287,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.serverCollation
|
||||
});
|
||||
const serverCollationContainer = this.createLabelInputContainer(localizedConstants.ServerCollationText, this.serverCollationInput);
|
||||
|
||||
this.serviceTierInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ServiceTierText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.serviceTier
|
||||
});
|
||||
const serviceTierContainer = this.createLabelInputContainer(localizedConstants.ServiceTierText, this.serviceTierInput);
|
||||
|
||||
this.storageSpaceUsageInMBInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.StorageSpaceUsageInMBText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: localizedConstants.StringValueInMB(this.objectInfo.storageSpaceUsageInMB.toString())
|
||||
});
|
||||
const storageSpaceUsageInMbContainer = this.createLabelInputContainer(localizedConstants.StorageSpaceUsageInMBText, this.storageSpaceUsageInMBInput);
|
||||
sqlServerItems.push(serverCollationContainer);
|
||||
|
||||
this.versionInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.VersionText,
|
||||
@@ -286,32 +296,39 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
value: this.objectInfo.version
|
||||
});
|
||||
const versionContainer = this.createLabelInputContainer(localizedConstants.VersionText, this.versionInput);
|
||||
sqlServerItems.push(versionContainer);
|
||||
|
||||
let platformItems = [
|
||||
nameContainer,
|
||||
languageContainer,
|
||||
memoryContainer,
|
||||
operatingSystemContainer,
|
||||
platformContainer,
|
||||
processorsContainer
|
||||
];
|
||||
if (!isUndefinedOrNull(this.objectInfo.reservedStorageSizeMB)) {
|
||||
this.reservedStorageSizeInMBInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ReservedStorageSizeInMBText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: localizedConstants.StringValueInMB(this.objectInfo.reservedStorageSizeMB.toString())
|
||||
});
|
||||
const reservedStorageSizeInMBContainer = this.createLabelInputContainer(localizedConstants.ReservedStorageSizeInMBText, this.reservedStorageSizeInMBInput);
|
||||
sqlServerItems.push(reservedStorageSizeInMBContainer);
|
||||
}
|
||||
|
||||
let sqlServerItems = [
|
||||
isClusteredContainer,
|
||||
isHadrEnabledContainer,
|
||||
isPolyBaseInstalledContainer,
|
||||
isXTPSupportedContainer,
|
||||
productContainer,
|
||||
rootDirectoryContainer,
|
||||
serverCollationContainer,
|
||||
versionContainer
|
||||
];
|
||||
if (this.objectInfo.serviceTier) {
|
||||
this.serviceTierInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.ServiceTierText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: this.objectInfo.serviceTier
|
||||
});
|
||||
const serviceTierContainer = this.createLabelInputContainer(localizedConstants.ServiceTierText, this.serviceTierInput);
|
||||
sqlServerItems.push(serviceTierContainer);
|
||||
}
|
||||
|
||||
if (this.engineEdition === azdata.DatabaseEngineEdition.SqlManagedInstance) {
|
||||
platformItems.unshift(hardwareGenerationContainer);
|
||||
sqlServerItems.push(reservedStorageSizeInMBContainer, serviceTierContainer, storageSpaceUsageInMbContainer);
|
||||
// remove isXTPSupported
|
||||
sqlServerItems.splice(3, 1);
|
||||
if (!isUndefinedOrNull(this.objectInfo.storageSpaceUsageInMB)) {
|
||||
this.storageSpaceUsageInMBInput = this.createInputBox(async () => { }, {
|
||||
ariaLabel: localizedConstants.StorageSpaceUsageInMBText,
|
||||
inputType: 'text',
|
||||
enabled: this.options.isNewObject,
|
||||
value: localizedConstants.StringValueInMB(this.objectInfo.storageSpaceUsageInMB.toString())
|
||||
});
|
||||
const storageSpaceUsageInMbContainer = this.createLabelInputContainer(localizedConstants.StorageSpaceUsageInMBText, this.storageSpaceUsageInMBInput);
|
||||
sqlServerItems.push(storageSpaceUsageInMbContainer);
|
||||
}
|
||||
|
||||
this.platformSection = this.createGroup('Platform', platformItems, true);
|
||||
@@ -501,8 +518,9 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
}
|
||||
|
||||
private initializeSecuritySection(): void {
|
||||
const isWindows = this.objectInfo.platform === constants.Windows;
|
||||
// cannot change auth mode in sql managed instance or non windows instances
|
||||
const isEnabled = this.engineEdition !== azdata.DatabaseEngineEdition.SqlManagedInstance && this.objectInfo.platform === 'Windows';
|
||||
const isEnabled = this.engineEdition !== azdata.DatabaseEngineEdition.SqlManagedInstance && isWindows;
|
||||
const radioServerGroupName = 'serverAuthenticationRadioGroup';
|
||||
this.onlyWindowsAuthRadioButton = this.createRadioButton(localizedConstants.onlyWindowsAuthModeText, radioServerGroupName, this.objectInfo.authenticationMode === ServerLoginMode.Integrated, async () => { await this.handleAuthModeChange(); });
|
||||
this.sqlServerAndWindowsAuthRadioButton = this.createRadioButton(localizedConstants.sqlServerAndWindowsAuthText, radioServerGroupName, this.objectInfo.authenticationMode === ServerLoginMode.Mixed, async () => { await this.handleAuthModeChange(); });
|
||||
@@ -518,6 +536,11 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
this.failedLoginsOnlyRadioButton = this.createRadioButton(localizedConstants.failedLoginsOnlyText, radioLoginsGroupName, this.objectInfo.loginAuditing === AuditLevel.Failure, async () => { await this.handleAuditLevelChange(); });
|
||||
this.successfulLoginsOnlyRadioButton = this.createRadioButton(localizedConstants.successfulLoginsOnlyText, radioLoginsGroupName, this.objectInfo.loginAuditing === AuditLevel.Success, async () => { await this.handleAuditLevelChange(); });
|
||||
this.bothFailedAndSuccessfulLoginsRadioButton = this.createRadioButton(localizedConstants.bothFailedAndSuccessfulLoginsText, radioLoginsGroupName, this.objectInfo.loginAuditing === AuditLevel.All, async () => { await this.handleAuditLevelChange(); });
|
||||
// cannot change values in serverLogin section on Linux
|
||||
this.noneRadioButton.enabled = isWindows;
|
||||
this.failedLoginsOnlyRadioButton.enabled = isWindows;
|
||||
this.successfulLoginsOnlyRadioButton.enabled = isWindows;
|
||||
this.bothFailedAndSuccessfulLoginsRadioButton.enabled = isWindows;
|
||||
const serverLoginSection = this.createGroup(localizedConstants.loginAuditingText, [
|
||||
this.noneRadioButton,
|
||||
this.failedLoginsOnlyRadioButton,
|
||||
@@ -652,24 +675,12 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
}
|
||||
|
||||
public async selectFolder(location: string): Promise<string | undefined> {
|
||||
const allFilesFilter = localizedConstants.allFiles;
|
||||
let filter: any = {};
|
||||
filter[allFilesFilter] = '*';
|
||||
let uris = await vscode.window.showOpenDialog({
|
||||
filters: filter,
|
||||
canSelectFiles: false,
|
||||
canSelectMany: false,
|
||||
canSelectFolders: true,
|
||||
defaultUri: vscode.Uri.file(location),
|
||||
openLabel: localizedConstants.labelSelectFolder
|
||||
});
|
||||
if (uris && uris.length > 0) {
|
||||
return uris[0].fsPath;
|
||||
}
|
||||
return undefined;
|
||||
let dataFolder = await this.objectManagementService.getDataFolder(this.options.connectionUri);
|
||||
return await azdata.window.openServerFileBrowserDialog(this.options.connectionUri, dataFolder, [{ label: localizedConstants.allFiles, filters: ['*'] }], true);
|
||||
}
|
||||
|
||||
private initializeAdvancedSection(): void {
|
||||
const isEnabled = this.engineEdition !== azdata.DatabaseEngineEdition.SqlManagedInstance;
|
||||
this.allowTriggerToFireOthersDropdown = this.createDropdown(localizedConstants.allowTriggerToFireOthersLabel, async (newValue) => {
|
||||
this.objectInfo.allowTriggerToFireOthers = newValue === 'True';
|
||||
}, ['True', 'False'], this.objectInfo.allowTriggerToFireOthers ? 'True' : 'False');
|
||||
@@ -733,7 +744,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
|
||||
this.scanStartupProcsDropdown = this.createDropdown(localizedConstants.scanStartupProcsLabel, async (newValue) => {
|
||||
this.objectInfo.scanStartupProcs = newValue === 'True';
|
||||
}, ['True', 'False'], this.objectInfo.scanStartupProcs ? 'True' : 'False');
|
||||
}, ['True', 'False'], this.objectInfo.scanStartupProcs ? 'True' : 'False', isEnabled);
|
||||
const scanStartupProcsContainer = this.createLabelInputContainer(localizedConstants.scanStartupProcsLabel, this.scanStartupProcsDropdown);
|
||||
|
||||
this.twoDigitYearCutoffInput = this.createInputBox(async (newValue) => {
|
||||
@@ -761,8 +772,13 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
||||
}, {
|
||||
ariaLabel: localizedConstants.locksLabel,
|
||||
inputType: 'number',
|
||||
enabled: isEnabled,
|
||||
max: this.objectInfo.locks.maximumValue,
|
||||
value: this.objectInfo.locks.value.toString()
|
||||
min: 0,
|
||||
value: this.objectInfo.locks.value.toString(),
|
||||
validationErrorMessage: localizedConstants.locksValidation(this.objectInfo.locks.minimumValue)
|
||||
}, async () => {
|
||||
return !(+this.locksInput.value < this.objectInfo.locks.minimumValue && +this.locksInput.value !== 0);
|
||||
});
|
||||
const locksContainer = this.createLabelInputContainer(localizedConstants.locksLabel, this.locksInput);
|
||||
|
||||
|
||||
@@ -28,16 +28,18 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
}
|
||||
const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon;
|
||||
const telemetryInfo = await getTelemetryInfo(context, tableIcon);
|
||||
let nonDefaultOptions = await azdata.connection.getNonDefaultOptions(context.connectionProfile);
|
||||
await azdata.designers.openTableDesigner(sqlProviderName, {
|
||||
title: NewTableText,
|
||||
tooltip: `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`,
|
||||
tooltip: context.connectionProfile!.connectionName ? `${context.connectionProfile!.connectionName} - ${NewTableText}` : `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`,
|
||||
server: context.connectionProfile!.serverName,
|
||||
database: context.connectionProfile!.databaseName,
|
||||
isNewTable: true,
|
||||
id: generateUuid(),
|
||||
connectionString: connectionString,
|
||||
accessToken: context.connectionProfile!.options.azureAccountToken as string,
|
||||
tableIcon: tableIcon
|
||||
tableIcon: tableIcon,
|
||||
additionalInfo: `${context.connectionProfile!.serverName + ' - ' + context.connectionProfile!.databaseName}${nonDefaultOptions}`
|
||||
}, telemetryInfo, context);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@@ -48,6 +50,7 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.designTable', async (context: azdata.ObjectExplorerContext) => {
|
||||
try {
|
||||
void showPreloadDbModelSettingPrompt(appContext);
|
||||
const connName = context.connectionProfile!.connectionName;
|
||||
const server = context.connectionProfile!.serverName;
|
||||
const database = context.connectionProfile!.databaseName;
|
||||
const schema = context.nodeInfo!.metadata!.schema;
|
||||
@@ -58,9 +61,10 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
}
|
||||
const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon;
|
||||
const telemetryInfo = await getTelemetryInfo(context, tableIcon);
|
||||
let nonDefaultOptions = await azdata.connection.getNonDefaultOptions(context.connectionProfile);
|
||||
await azdata.designers.openTableDesigner(sqlProviderName, {
|
||||
title: `${schema}.${name}`,
|
||||
tooltip: `${server} - ${database} - ${schema}.${name}`,
|
||||
tooltip: connName ? `${connName} - ${schema}.${name}` : `${server} - ${database} - ${schema}.${name}`,
|
||||
server: server,
|
||||
database: database,
|
||||
isNewTable: false,
|
||||
@@ -69,7 +73,8 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
id: `${sqlProviderName}|${server}|${database}|${schema}|${name}`,
|
||||
connectionString: connectionString,
|
||||
accessToken: context.connectionProfile!.options.azureAccountToken as string,
|
||||
tableIcon: tableIcon
|
||||
tableIcon: tableIcon,
|
||||
additionalInfo: `${server + ' - ' + database}${nonDefaultOptions}`
|
||||
}, telemetryInfo, context);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
||||
@@ -24,7 +24,8 @@ export function getTableHeight(rowCount: number, minRowCount: number = DefaultMi
|
||||
|
||||
export interface DialogButton {
|
||||
buttonAriaLabel: string;
|
||||
buttonHandler: (button: azdata.ButtonComponent) => Promise<void>
|
||||
buttonHandler: (button: azdata.ButtonComponent) => Promise<void>,
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
export type TableListItemEnabledStateGetter<T> = (item: T) => boolean;
|
||||
@@ -80,6 +81,8 @@ export abstract class DialogBase<DialogResult> {
|
||||
|
||||
protected removeButtonEnabled(table: azdata.TableComponent): boolean { return true; }
|
||||
|
||||
protected addButtonEnabled(table: azdata.TableComponent): boolean { return true; }
|
||||
|
||||
protected validateInput(): Promise<string[]> { return Promise.resolve([]); }
|
||||
|
||||
public async open(): Promise<void> {
|
||||
@@ -295,12 +298,13 @@ export abstract class DialogBase<DialogResult> {
|
||||
if (editButton !== undefined) {
|
||||
editButtonComponent.enabled = tableSelectedRowsLengthCheck;
|
||||
}
|
||||
addButtonComponent.enabled = this.addButtonEnabled(table);
|
||||
removeButtonComponent.enabled = !!isRemoveEnabled && tableSelectedRowsLengthCheck;
|
||||
}
|
||||
addButtonComponent = this.createButton(uiLoc.AddText, addbutton.buttonAriaLabel, async () => {
|
||||
await addbutton.buttonHandler(addButtonComponent);
|
||||
updateButtons();
|
||||
});
|
||||
}, addbutton.enabled ?? true);
|
||||
buttonComponents.push(addButtonComponent);
|
||||
|
||||
if (editButton !== undefined) {
|
||||
|
||||
@@ -63,13 +63,16 @@ export abstract class ScriptableDialogBase<OptionsType extends ScriptableDialogO
|
||||
protected abstract get isDirty(): boolean;
|
||||
|
||||
protected override onFormFieldChange(): void {
|
||||
this._scriptButton.enabled = this.isDirty;
|
||||
this.updateScriptButtonState();
|
||||
this.dialogObject.okButton.enabled = this.isDirty;
|
||||
}
|
||||
|
||||
protected override async initialize(): Promise<void> {
|
||||
await this.initializeData();
|
||||
await this.initializeUI();
|
||||
this.disposables.push(this.modelView.onValidityChanged(() => {
|
||||
this.updateScriptButtonState();
|
||||
}));
|
||||
}
|
||||
|
||||
protected override updateLoadingStatus(isLoading: boolean, loadingText?: string, loadingCompletedText?: string): void {
|
||||
@@ -131,4 +134,8 @@ export abstract class ScriptableDialogBase<OptionsType extends ScriptableDialogO
|
||||
this.updateLoadingStatus(false, localizedConstants.GeneratingScriptText, localizedConstants.GeneratingScriptCompletedText);
|
||||
}
|
||||
}
|
||||
|
||||
private updateScriptButtonState(): void {
|
||||
this._scriptButton.enabled = this.isDirty && this.modelView.valid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ const parallelMessageProcessingConfig = 'parallelMessageProcessing';
|
||||
const enableSqlAuthenticationProviderConfig = 'enableSqlAuthenticationProvider';
|
||||
const enableConnectionPoolingConfig = 'enableConnectionPooling';
|
||||
const tableDesignerPreloadConfig = 'tableDesigner.preloadDatabaseModel';
|
||||
const httpConfig = 'http';
|
||||
const configProxy = 'proxy';
|
||||
const configProxyStrictSSL = 'proxyStrictSSL';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -85,6 +88,19 @@ export function getConfigLogRetentionSeconds(): number | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
export function getHttpProxyUrl(): string | undefined {
|
||||
let config = getConfiguration(httpConfig);
|
||||
if (config) {
|
||||
return config[configProxy];
|
||||
} return undefined;
|
||||
}
|
||||
|
||||
export function getHttpProxyStrictSSL(): boolean {
|
||||
let config = getConfiguration(httpConfig);
|
||||
if (config) {
|
||||
return config.get<boolean>(configProxyStrictSSL, true); // true by default
|
||||
} return true; // true by default.
|
||||
}
|
||||
/**
|
||||
* The tracing level defined in the package.json
|
||||
*/
|
||||
@@ -202,6 +218,15 @@ export function getCommonLaunchArgsAndCleanupOldLogFiles(logPath: string, fileNa
|
||||
}
|
||||
// Always enable autoflush so that log entries are written immediately to disk, otherwise we can end up with partial logs
|
||||
launchArgs.push('--autoflush-log');
|
||||
|
||||
let httpProxy = getHttpProxyUrl();
|
||||
if (httpProxy) {
|
||||
launchArgs.push('--http-proxy-url');
|
||||
launchArgs.push(httpProxy);
|
||||
if (getHttpProxyStrictSSL()) {
|
||||
launchArgs.push('--http-proxy-strict-ssl')
|
||||
}
|
||||
}
|
||||
return launchArgs;
|
||||
}
|
||||
|
||||
|
||||
@@ -511,9 +511,9 @@ crypt@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
|
||||
version "1.3.7"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
|
||||
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
|
||||
version "1.3.8"
|
||||
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
|
||||
dependencies:
|
||||
vscode-languageclient "5.2.1"
|
||||
|
||||
@@ -1080,7 +1080,7 @@ md5@^2.1.0:
|
||||
crypt "~0.0.1"
|
||||
is-buffer "~1.1.1"
|
||||
|
||||
minimatch@3.0.4, minimatch@^3.0.4:
|
||||
minimatch@3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
@@ -1094,6 +1094,13 @@ minimatch@5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
},
|
||||
{
|
||||
"command": "jupyter.cmd.managePackages",
|
||||
"when": "false"
|
||||
"when": "notebook:pythonInstalled && !notebook:runningOnSAW"
|
||||
},
|
||||
{
|
||||
"command": "notebook.command.saveBook",
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"config.jupyter.kernelConfigValuesDescription": "Configuration options for Jupyter kernels. This is automatically managed and not recommended to be manually edited.",
|
||||
"title.reinstallNotebookDependencies": "Reinstall Notebook dependencies",
|
||||
"title.configurePython": "Configure Python for Notebooks",
|
||||
"title.managePackages": "Manage Packages",
|
||||
"title.managePackages": "Manage Notebook Packages",
|
||||
"title.SQL19PreviewBook": "SQL Server 2019 Guide",
|
||||
"books-preview-category": "Jupyter Books",
|
||||
"title.saveJupyterBook": "Save Jupyter Book",
|
||||
|
||||
@@ -52,6 +52,10 @@ export function executeBufferedCommand(cmd: string, options: childProcess.ExecOp
|
||||
});
|
||||
}
|
||||
|
||||
export function executeBufferedCommandSync(cmd: string, options: childProcess.ExecOptions): string {
|
||||
return childProcess.execSync(cmd, options).toString();
|
||||
}
|
||||
|
||||
export function executeStreamedCommand(cmd: string, options: childProcess.SpawnOptions, outputChannel?: vscode.OutputChannel): Thenable<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
// Start the command
|
||||
|
||||
@@ -27,7 +27,7 @@ export class ManagePackagesDialog {
|
||||
* Opens a dialog to manage packages used by notebooks.
|
||||
*/
|
||||
public showDialog(): void {
|
||||
this.dialog = azdata.window.createModelViewDialog(localize('managePackages.dialogName', "Manage Packages"));
|
||||
this.dialog = azdata.window.createModelViewDialog(localize('managePackages.dialogName', "Manage Notebook Packages"));
|
||||
|
||||
this.installedPkgTab = new InstalledPackagesTab(this, this.jupyterInstallation);
|
||||
this.addNewPkgTab = new AddNewPackageTab(this, this.jupyterInstallation);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { AppContext } from './common/appContext';
|
||||
import { IExtensionApi, IPackageManageProvider } from './types';
|
||||
import { CellType } from './contracts/content';
|
||||
import { NotebookUriHandler } from './protocol/notebookUriHandler';
|
||||
import { BuiltInCommands, unsavedBooksContextKey } from './common/constants';
|
||||
import { BuiltInCommands, CommandContext, unsavedBooksContextKey } from './common/constants';
|
||||
import { RemoteBookController } from './book/remoteBookController';
|
||||
import { RemoteBookDialog } from './dialog/remoteBookDialog';
|
||||
import { RemoteBookDialogModel } from './dialog/remoteBookDialogModel';
|
||||
@@ -22,6 +22,7 @@ import { BookTreeItem } from './book/bookTreeItem';
|
||||
import Logger from './common/logger';
|
||||
import { sendNotebookActionEvent, NbTelemetryView, NbTelemetryAction } from './telemetry';
|
||||
import { TelemetryReporter } from './telemetry';
|
||||
import { JupyterServerInstallation } from './jupyter/jupyterServerInstallation';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -39,6 +40,11 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
|
||||
if (vscode.env.uiKind === vscode.UIKind.Web) {
|
||||
await config.update('allowRoot', true, vscode.ConfigurationTarget.Global);
|
||||
}
|
||||
|
||||
// Check if python is already installed in order to enable the Manage Notebook Packages dialog
|
||||
let pythonInstalled = JupyterServerInstallation.isPythonInstalled();
|
||||
await vscode.commands.executeCommand(BuiltInCommands.SetContext, CommandContext.NotebookPythonInstalled, pythonInstalled);
|
||||
|
||||
/**
|
||||
* ***** IMPORTANT *****
|
||||
* If changes are made to bookTreeView.openBook, please ensure backwards compatibility with its current state.
|
||||
@@ -154,7 +160,6 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
const bookTreeViewProvider = appContext.bookTreeViewProvider;
|
||||
await bookTreeViewProvider.initialized;
|
||||
const providedBookTreeViewProvider = appContext.providedBookTreeViewProvider;
|
||||
|
||||
@@ -155,21 +155,26 @@ export class JupyterController {
|
||||
}
|
||||
|
||||
public async doManagePackages(options?: ManagePackageDialogOptions | vscode.Uri): Promise<void> {
|
||||
try {
|
||||
if (!options || options instanceof vscode.Uri) {
|
||||
options = {
|
||||
defaultLocation: constants.localhostName,
|
||||
defaultProviderId: LocalPipPackageManageProvider.ProviderId
|
||||
};
|
||||
}
|
||||
let model = new ManagePackagesDialogModel(this._jupyterInstallation, this._packageManageProviders, options);
|
||||
// Handle the edge case where python is installed and then deleted manually from the user settings.
|
||||
if (!JupyterServerInstallation.isPythonInstalled()) {
|
||||
await vscode.window.showErrorMessage(localize('pythonNotSetup', "Python is not currently configured for notebooks. The 'Configure Python for Notebooks' command must be run before being able to manage notebook packages."));
|
||||
} else {
|
||||
try {
|
||||
if (!options || options instanceof vscode.Uri) {
|
||||
options = {
|
||||
defaultLocation: constants.localhostName,
|
||||
defaultProviderId: LocalPipPackageManageProvider.ProviderId
|
||||
};
|
||||
}
|
||||
let model = new ManagePackagesDialogModel(this._jupyterInstallation, this._packageManageProviders, options);
|
||||
|
||||
await model.init();
|
||||
let packagesDialog = new ManagePackagesDialog(model, this.extensionContext);
|
||||
packagesDialog.showDialog();
|
||||
} catch (error) {
|
||||
let message = utils.getErrorMessage(error);
|
||||
void vscode.window.showErrorMessage(message);
|
||||
await model.init();
|
||||
let packagesDialog = new ManagePackagesDialog(model, this.extensionContext);
|
||||
packagesDialog.showDialog();
|
||||
} catch (error) {
|
||||
let message = utils.getErrorMessage(error);
|
||||
await vscode.window.showErrorMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import * as utils from '../common/utils';
|
||||
import { Deferred } from '../common/promise';
|
||||
import { ConfigurePythonWizard } from '../dialog/configurePython/configurePythonWizard';
|
||||
import { IKernelInfo } from '../contracts/content';
|
||||
import { requiredJupyterPackages } from './requiredJupyterPackages';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const msgInstallPkgProgress = localize('msgInstallPkgProgress', "Notebook dependencies installation is in progress");
|
||||
@@ -78,22 +79,6 @@ export interface IJupyterServerInstallation {
|
||||
installedPythonVersion: string;
|
||||
}
|
||||
|
||||
export const requiredJupyterPkg: PythonPkgDetails = {
|
||||
name: 'jupyter',
|
||||
version: '1.0.0'
|
||||
};
|
||||
|
||||
export const requiredNotebookPkg: PythonPkgDetails = {
|
||||
name: 'notebook',
|
||||
version: '6.5.5',
|
||||
installExactVersion: true
|
||||
};
|
||||
|
||||
export const requiredPowershellPkg: PythonPkgDetails = {
|
||||
name: 'powershell-kernel',
|
||||
version: '0.1.4'
|
||||
};
|
||||
|
||||
export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
public extensionPath: string;
|
||||
public pythonBinPath: string;
|
||||
@@ -113,14 +98,14 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
private _oldUserInstalledPipPackages: PythonPkgDetails[] = [];
|
||||
private _upgradePrompted: boolean = false;
|
||||
|
||||
private _installInProgress: boolean;
|
||||
private _installInProgress = false;
|
||||
private _installCompletion: Deferred<void>;
|
||||
|
||||
public static readonly DefaultPythonLocation = path.join(utils.getUserHome(), 'azuredatastudio-python');
|
||||
|
||||
private _kernelSetupCache: Map<string, boolean>;
|
||||
private readonly _requiredKernelPackages: Map<string, PythonPkgDetails[]>;
|
||||
private readonly _requiredPackagesSet: Set<string>;
|
||||
private readonly _kernelSetupCache = new Map<string, boolean>();
|
||||
private readonly _requiredKernelPackages = new Map<string, PythonPkgDetails[]>();
|
||||
private readonly _requiredPackageNames: Set<string>;
|
||||
|
||||
private readonly _runningOnSAW: boolean;
|
||||
private readonly _tsgopsweb: boolean;
|
||||
@@ -144,22 +129,21 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
this._pythonInstallationPath = JupyterServerInstallation.getPythonInstallPath();
|
||||
this._usingExistingPython = JupyterServerInstallation.getExistingPythonSetting();
|
||||
}
|
||||
this._installInProgress = false;
|
||||
|
||||
this._kernelSetupCache = new Map<string, boolean>();
|
||||
this._requiredKernelPackages = new Map<string, PythonPkgDetails[]>();
|
||||
let allPackages = requiredJupyterPackages.sharedPackages;
|
||||
for (let kernelInfo of requiredJupyterPackages.kernels) {
|
||||
// Add this kernel's specific dependencies to the running list of packages for All Kernels.
|
||||
allPackages = allPackages.concat(kernelInfo.packages);
|
||||
|
||||
this._requiredKernelPackages.set(constants.ipykernelDisplayName, [requiredJupyterPkg, requiredNotebookPkg]);
|
||||
this._requiredKernelPackages.set(constants.python3DisplayName, [requiredJupyterPkg, requiredNotebookPkg]);
|
||||
this._requiredKernelPackages.set(constants.powershellDisplayName, [requiredJupyterPkg, requiredPowershellPkg, requiredNotebookPkg]);
|
||||
// Combine this kernel's specific dependencies with the shared list of packages to get its
|
||||
// full list of dependencies
|
||||
let packages = requiredJupyterPackages.sharedPackages.concat(kernelInfo.packages);
|
||||
this._requiredKernelPackages.set(kernelInfo.name, packages);
|
||||
}
|
||||
|
||||
let allPackages = [requiredJupyterPkg, requiredNotebookPkg, requiredPowershellPkg];
|
||||
this._requiredKernelPackages.set(constants.allKernelsName, allPackages);
|
||||
|
||||
this._requiredPackagesSet = new Set<string>();
|
||||
allPackages.forEach(pkg => {
|
||||
this._requiredPackagesSet.add(pkg.name);
|
||||
});
|
||||
this._requiredPackageNames = new Set<string>(allPackages.map(pkg => pkg.name));
|
||||
}
|
||||
|
||||
private async installDependencies(backgroundOperation: azdata.BackgroundOperation, forceInstall: boolean, packages: PythonPkgDetails[]): Promise<void> {
|
||||
@@ -453,8 +437,10 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
await notebookConfig.update(constants.existingPythonConfigKey, this._usingExistingPython, vscode.ConfigurationTarget.Global);
|
||||
await this.configurePackagePaths();
|
||||
|
||||
await vscode.commands.executeCommand(constants.BuiltInCommands.SetContext, constants.CommandContext.NotebookPythonInstalled, true);
|
||||
this._installCompletion.resolve();
|
||||
this._installInProgress = false;
|
||||
|
||||
if (this._upgradeInProcess) {
|
||||
// Pass in false for restartJupyterServer parameter since the jupyter server has already been shutdown
|
||||
// when removing the old Python version on Windows.
|
||||
@@ -627,7 +613,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
|
||||
public uninstallPipPackages(packages: PythonPkgDetails[]): Promise<void> {
|
||||
for (let pkg of packages) {
|
||||
if (this._requiredPackagesSet.has(pkg.name)) {
|
||||
if (this._requiredPackageNames.has(pkg.name)) {
|
||||
this._kernelSetupCache.clear();
|
||||
break;
|
||||
}
|
||||
@@ -679,7 +665,7 @@ export class JupyterServerInstallation implements IJupyterServerInstallation {
|
||||
public async uninstallCondaPackages(packages: PythonPkgDetails[]): Promise<void> {
|
||||
if (this.condaExecutable) {
|
||||
for (let pkg of packages) {
|
||||
if (this._requiredPackagesSet.has(pkg.name)) {
|
||||
if (this._requiredPackageNames.has(pkg.name)) {
|
||||
this._kernelSetupCache.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import { JupyterServerInstallation } from './jupyterServerInstallation';
|
||||
import * as utils from '../common/utils';
|
||||
import { IServerInstance } from './common';
|
||||
import { PerFolderServerInstance, IInstanceOptions } from './serverInstance';
|
||||
import { CommandContext, BuiltInCommands } from '../common/constants';
|
||||
|
||||
export interface IServerManagerOptions {
|
||||
documentPath: string;
|
||||
@@ -105,7 +104,6 @@ export class LocalJupyterServerManager implements nb.ServerManager, vscode.Dispo
|
||||
private async doStartServer(kernelSpec: nb.IKernelSpec): Promise<IServerInstance> { // We can't find or create servers until the installation is complete
|
||||
let installation = this.options.jupyterInstallation;
|
||||
await installation.promptForPythonInstall(kernelSpec.display_name);
|
||||
void vscode.commands.executeCommand(BuiltInCommands.SetContext, CommandContext.NotebookPythonInstalled, true);
|
||||
|
||||
// Calculate the path to use as the notebook-dir for Jupyter based on the path of the uri of the
|
||||
// notebook to open. This will be the workspace folder if the notebook uri is inside a workspace
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user