From 8b8bef04013da5deaddfa6166754c1c955875e3b Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Wed, 2 Sep 2020 11:58:30 -0700 Subject: [PATCH] add strict compile for restore (#12067) --- src/sql/azdata.d.ts | 4 +- .../workbench/browser/modal/dialogHelper.ts | 8 +- .../workbench/browser/modal/optionsDialog.ts | 40 +-- .../browser/modal/optionsDialogHelper.ts | 11 +- .../services/restore/browser/restoreDialog.ts | 236 +++++++++--------- .../restore/browser/restoreServiceImpl.ts | 69 +++-- .../restore/browser/restoreViewModel.ts | 36 ++- .../test/browser/restoreViewModel.test.ts | 39 ++- src/tsconfig.vscode.json | 1 - 9 files changed, 214 insertions(+), 230 deletions(-) diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index db036ad541..fe4e47464e 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -1901,7 +1901,7 @@ declare module 'azdata' { export interface RestoreInfo { options: { [key: string]: any }; - taskExecutionMode: TaskExecutionMode; + taskExecutionMode?: TaskExecutionMode; } export interface RestoreDatabaseFileInfo { @@ -1939,7 +1939,7 @@ declare module 'azdata' { sessionId: string; backupSetsToRestore: DatabaseFileInfo[]; canRestore: boolean; - errorMessage: string; + errorMessage?: string; dbFiles: RestoreDatabaseFileInfo[]; databaseNamesFromBackupSets: string[]; planDetails: { [key: string]: RestorePlanDetailInfo }; diff --git a/src/sql/workbench/browser/modal/dialogHelper.ts b/src/sql/workbench/browser/modal/dialogHelper.ts index 640ebf35b0..c381f9f512 100644 --- a/src/sql/workbench/browser/modal/dialogHelper.ts +++ b/src/sql/workbench/browser/modal/dialogHelper.ts @@ -49,8 +49,8 @@ export function getBooleanValueFromStringOrBoolean(value: any): boolean { return false; } -export function getCategoryDisplayName(categories: azdata.CategoryValue[], categoryName: string) { - let displayName: string; +export function getCategoryDisplayName(categories: azdata.CategoryValue[], categoryName: string): string | undefined { + let displayName: string | undefined; categories.forEach(c => { if (c.name === categoryName) { displayName = c.displayName; @@ -59,8 +59,8 @@ export function getCategoryDisplayName(categories: azdata.CategoryValue[], categ return displayName; } -export function getCategoryName(categories: azdata.CategoryValue[], categoryDisplayName: string) { - let categoryName: string; +export function getCategoryName(categories: azdata.CategoryValue[], categoryDisplayName: string): string | undefined { + let categoryName: string | undefined; categories.forEach(c => { if (c.displayName === categoryDisplayName) { categoryName = c.name; diff --git a/src/sql/workbench/browser/modal/optionsDialog.ts b/src/sql/workbench/browser/modal/optionsDialog.ts index 2a6a19424f..66abd08529 100644 --- a/src/sql/workbench/browser/modal/optionsDialog.ts +++ b/src/sql/workbench/browser/modal/optionsDialog.ts @@ -36,14 +36,14 @@ export interface IOptionsDialogOptions extends IModalOptions { } export class OptionsDialog extends Modal { - private _body: HTMLElement; - private _optionGroupsContainer: HTMLElement; + private _body?: HTMLElement; + private _optionGroupsContainer?: HTMLElement; private _categoryTitles: HTMLElement[] = []; - private _dividerBuilder: HTMLElement; - private _optionTitle: HTMLElement; - private _optionDescription: HTMLElement; + private _dividerBuilder?: HTMLElement; + private _optionTitle?: HTMLElement; + private _optionDescription?: HTMLElement; private _optionElements: { [optionName: string]: OptionsDialogHelper.IOptionElement } = {}; - private _optionValues: { [optionName: string]: string }; + private _optionValues: { [optionName: string]: string } = {}; private _onOk = new Emitter(); public onOk: Event = this._onOk.event; @@ -54,7 +54,7 @@ export class OptionsDialog extends Modal { constructor( title: string, name: string, - options: IOptionsDialogOptions, + options: IOptionsDialogOptions | undefined, @ILayoutService layoutService: ILayoutService, @IThemeService themeService: IThemeService, @IContextViewService private _contextViewService: IContextViewService, @@ -99,25 +99,25 @@ export class OptionsDialog extends Modal { // Update theming that is specific to options dialog flyout body private updateTheme(theme: IColorTheme): void { const borderColor = theme.getColor(contrastBorder); - const border = borderColor ? borderColor.toString() : null; + const border = borderColor ? borderColor.toString() : ''; const backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND); if (this._dividerBuilder) { - this._dividerBuilder.style.borderTopWidth = border ? '1px' : null; - this._dividerBuilder.style.borderTopStyle = border ? 'solid' : null; + this._dividerBuilder.style.borderTopWidth = border ? '1px' : ''; + this._dividerBuilder.style.borderTopStyle = border ? 'solid' : ''; this._dividerBuilder.style.borderTopColor = border; } this._categoryTitles.forEach(titleElement => { - titleElement.style.borderWidth = border ? '1px 0px' : null; - titleElement.style.borderStyle = border ? 'solid none' : null; + titleElement.style.borderWidth = border ? '1px 0px' : ''; + titleElement.style.borderStyle = border ? 'solid none' : ''; titleElement.style.borderColor = border; - titleElement.style.backgroundColor = backgroundColor ? backgroundColor.toString() : null; + titleElement.style.backgroundColor = backgroundColor ? backgroundColor.toString() : ''; }); } private onOptionLinkClicked(optionName: string): void { let option = this._optionElements[optionName].option; - this._optionTitle.innerText = option.displayName; - this._optionDescription.innerText = option.description; + this._optionTitle!.innerText = option.displayName; + this._optionDescription!.innerText = option.description; } private fillInOptions(container: HTMLElement, options: azdata.ServiceOption[]): void { @@ -193,18 +193,18 @@ export class OptionsDialog extends Modal { public open(options: azdata.ServiceOption[], optionValues: { [name: string]: any }) { this._optionValues = optionValues; - let firstOption: string; + let firstOption: string | undefined; let categoryMap = OptionsDialogHelper.groupOptionsByCategory(options); - clearNode(this._optionGroupsContainer); + clearNode(this._optionGroupsContainer!); for (let category in categoryMap) { - const title = append(this._optionGroupsContainer, $('h2.option-category-title')); + const title = append(this._optionGroupsContainer!, $('h2.option-category-title')); title.innerText = category; this._categoryTitles.push(title); let serviceOptions: azdata.ServiceOption[] = categoryMap[category]; let bodyContainer = $('table.optionsDialog-table'); this.fillInOptions(bodyContainer, serviceOptions); - append(this._optionGroupsContainer, bodyContainer); + append(this._optionGroupsContainer!, bodyContainer); if (!firstOption) { firstOption = serviceOptions[0].name; @@ -212,7 +212,7 @@ export class OptionsDialog extends Modal { } this.updateTheme(this._themeService.getColorTheme()); this.show(); - let firstOptionWidget = this._optionElements[firstOption].optionWidget; + let firstOptionWidget = this._optionElements[firstOption!].optionWidget; this.registerStyling(); setTimeout(() => firstOptionWidget.focus(), 1); } diff --git a/src/sql/workbench/browser/modal/optionsDialogHelper.ts b/src/sql/workbench/browser/modal/optionsDialogHelper.ts index 26264a6f1b..9c3afb3067 100644 --- a/src/sql/workbench/browser/modal/optionsDialogHelper.ts +++ b/src/sql/workbench/browser/modal/optionsDialogHelper.ts @@ -11,7 +11,6 @@ import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import * as types from 'vs/base/common/types'; import * as azdata from 'azdata'; import { localize } from 'vs/nls'; -import { startsWith } from 'vs/base/common/strings'; import { ServiceOptionType } from 'sql/platform/connection/common/interfaces'; export interface IOptionElement { @@ -21,11 +20,11 @@ export interface IOptionElement { } export function createOptionElement(option: azdata.ServiceOption, rowContainer: HTMLElement, options: { [name: string]: any }, - optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name) => void): IOptionElement { + optionsMap: { [optionName: string]: IOptionElement }, contextViewService: IContextViewService, onFocus: (name: string) => void): IOptionElement { let possibleInputs: SelectOptionItemSQL[] = []; let optionValue = getOptionValueAndCategoryValues(option, options, possibleInputs); let optionWidget: any; - let inputElement: HTMLElement; + let inputElement: HTMLElement | undefined; let missingErrorMessage = localize('optionsDialog.missingRequireField', " is required."); let invalidInputMessage = localize('optionsDialog.invalidInput', "Invalid input. Numeric value expected."); @@ -65,7 +64,9 @@ export function createOptionElement(option: azdata.ServiceOption, rowContainer: } const optionElement = { optionWidget: optionWidget, option: option, optionValue: optionValue }; optionsMap[option.name] = optionElement; - inputElement.onfocus = () => onFocus(option.name); + if (inputElement) { + inputElement.onfocus = () => onFocus(option.name); + } return optionElement; } @@ -153,7 +154,7 @@ export function findElement(container: HTMLElement, className: string): HTMLElem let elementBuilder = container; while (elementBuilder) { let htmlElement = elementBuilder; - if (startsWith(htmlElement.className, className)) { + if (htmlElement.className.startsWith(className)) { break; } elementBuilder = elementBuilder.firstChild as HTMLElement; diff --git a/src/sql/workbench/services/restore/browser/restoreDialog.ts b/src/sql/workbench/services/restore/browser/restoreDialog.ts index 730581f2f9..30fd4c6e34 100644 --- a/src/sql/workbench/services/restore/browser/restoreDialog.ts +++ b/src/sql/workbench/services/restore/browser/restoreDialog.ts @@ -61,27 +61,27 @@ const LocalizedStrings = { export class RestoreDialog extends Modal { public viewModel: RestoreViewModel; - private _scriptButton: Button; - private _restoreButton: Button; - private _closeButton: Button; + private _scriptButton?: Button; + private _restoreButton?: Button; + private _closeButton?: Button; private _optionsMap: { [name: string]: SelectBox | InputBox | Checkbox } = {}; - private _restoreLabel: string; - private _restoreTitle: string; - private _databaseTitle: string; - private _backupFileTitle: string; - private _ownerUri: string; - private _databaseDropdown: Dropdown; - private _isBackupFileCheckboxChanged: boolean; + private _restoreLabel = localize('restoreDialog.restore', "Restore"); + private _restoreTitle = localize('restoreDialog.restoreTitle', "Restore database"); + private _databaseTitle = localize('restoreDialog.database', "Database"); + private _backupFileTitle = localize('restoreDialog.backupFile', "Backup file"); + private _ownerUri?: string; + private _databaseDropdown?: Dropdown; + private _isBackupFileCheckboxChanged?: boolean; // General options - private _filePathInputBox: InputBox; - private _browseFileButton: Button; - private _destinationRestoreToInputBox: InputBox; - private _restoreFromSelectBox: SelectBox; - private _sourceDatabaseSelectBox: SelectBox; + private _filePathInputBox?: InputBox; + private _browseFileButton?: Button; + private _destinationRestoreToInputBox?: InputBox; + private _restoreFromSelectBox?: SelectBox; + private _sourceDatabaseSelectBox?: SelectBox; - private _panel: TabbedPanel; - private _generalTabId: PanelTabIdentifier; + private _panel?: TabbedPanel; + private _generalTabId?: PanelTabIdentifier; // File option private readonly _relocateDatabaseFilesOption = 'relocateDbFiles'; @@ -102,17 +102,17 @@ export class RestoreDialog extends Modal { private readonly _closeExistingConnectionsOption = 'closeExistingConnections'; - private _restoreFromBackupFileElement: HTMLElement; + private _restoreFromBackupFileElement?: HTMLElement; - private _fileListTable: Table; - private _fileListData: TableDataView; - private _fileListTableContainer: HTMLElement; + private _fileListTable?: Table; + private _fileListData?: TableDataView; + private _fileListTableContainer?: HTMLElement; - private _restorePlanTable: Table; - private _restorePlanData: TableDataView; - private _restorePlanColumn; - private _restorePlanTableContainer: HTMLElement; - private _isRenderedRestorePlanTable: boolean; + private _restorePlanTable?: Table; + private _restorePlanData?: TableDataView; + private _restorePlanColumn?: Slick.Column[]; + private _restorePlanTableContainer?: HTMLElement; + private _isRenderedRestorePlanTable = false; private _onRestore = new Emitter(); public onRestore: Event = this._onRestore.event; @@ -142,10 +142,6 @@ export class RestoreDialog extends Modal { @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService ) { super(localize('RestoreDialogTitle', "Restore database"), TelemetryKeys.Restore, telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasErrors: true, width: 'wide', hasSpinner: true }); - this._restoreTitle = localize('restoreDialog.restoreTitle', "Restore database"); - this._databaseTitle = localize('restoreDialog.database', "Database"); - this._backupFileTitle = localize('restoreDialog.backupFile', "Backup file"); - this._restoreLabel = localize('restoreDialog.restore', "Restore"); // view model this.viewModel = new RestoreViewModel(optionsMetadata); @@ -157,8 +153,6 @@ export class RestoreDialog extends Modal { this.viewModel.onSetRestoreOption((optionParams) => this.updateRestoreOption(optionParams)); this.viewModel.onUpdateBackupSetsToRestore((backupSets) => this.updateBackupSetsToRestore(backupSets)); this.viewModel.onUpdateRestoreDatabaseFiles((files) => this.updateRestoreDatabaseFiles(files)); - - this._isRenderedRestorePlanTable = false; } public render() { @@ -169,7 +163,7 @@ export class RestoreDialog extends Modal { this._restoreButton = this.addFooterButton(this._restoreLabel, () => this.restore(false)); this._closeButton = this.addFooterButton(cancelLabel, () => this.cancel()); this.registerListeners(); - this._destinationRestoreToInputBox.disable(); + this._destinationRestoreToInputBox!.disable(); } protected renderBody(container: HTMLElement) { @@ -228,14 +222,14 @@ export class RestoreDialog extends Modal { }); this._databaseDropdown.onBlur(() => { - this.databaseSelected(this._databaseDropdown.value); + this.databaseSelected(this._databaseDropdown!.value); }); this._databaseDropdown.onFocus(() => { this._onDatabaseListFocused.fire(); }); - this._databaseDropdown.value = this.viewModel.targetDatabaseName; + this._databaseDropdown.value = this.viewModel.targetDatabaseName!; attachEditableDropdownStyler(this._databaseDropdown, this._themeService); this._destinationRestoreToInputBox = this.createInputBoxHelper(destinationElement, localize('restoreTo', "Restore to")); @@ -375,14 +369,14 @@ export class RestoreDialog extends Modal { this._fileListTable.autosizeColumns(); } if (c !== this._generalTabId) { - this._restoreFromSelectBox.hideMessage(); + this._restoreFromSelectBox!.hideMessage(); } }); this._restorePlanTable.grid.onKeyDown.subscribe(e => { let event = new StandardKeyboardEvent(e as KeyboardEvent); if (event.equals(KeyMod.Shift | KeyCode.Tab)) { - this._destinationRestoreToInputBox.isEnabled() ? this._destinationRestoreToInputBox.focus() : this._databaseDropdown.focus(); + this._destinationRestoreToInputBox!.isEnabled() ? this._destinationRestoreToInputBox!.focus() : this._databaseDropdown!.focus(); e.stopImmediatePropagation(); } else if (event.equals(KeyCode.Tab)) { this.focusOnFirstEnabledFooterButton(); @@ -409,12 +403,12 @@ export class RestoreDialog extends Modal { } private focusOnFirstEnabledFooterButton() { - if (this._scriptButton.enabled) { - this._scriptButton.focus(); - } else if (this._restoreButton.enabled) { - this._restoreButton.focus(); + if (this._scriptButton!.enabled) { + this._scriptButton!.focus(); + } else if (this._restoreButton!.enabled) { + this._restoreButton!.focus(); } else { - this._closeButton.focus(); + this._closeButton!.focus(); } } @@ -426,7 +420,7 @@ export class RestoreDialog extends Modal { } public set databaseListOptions(vals: string[]) { - this._databaseDropdown.values = vals; + this._databaseDropdown!.values = vals; } private createLabelElement(container: HTMLElement, content: string, isHeader?: boolean) { @@ -438,7 +432,7 @@ export class RestoreDialog extends Modal { } private createOptionControl(container: HTMLElement, optionName: string): void { - const option = this.viewModel.getOptionMetadata(optionName); + const option = this.viewModel.getOptionMetadata(optionName)!; let propertyWidget: SelectBox | InputBox | Checkbox; switch (option.valueType) { case ServiceOptionType.boolean: @@ -446,7 +440,7 @@ export class RestoreDialog extends Modal { DialogHelper.getBooleanValueFromStringOrBoolean(option.defaultValue), () => this.onBooleanOptionChecked(optionName)); break; case ServiceOptionType.category: - propertyWidget = this.createSelectBoxHelper(container, option.description, option.categoryValues.map(c => c.displayName), DialogHelper.getCategoryDisplayName(option.categoryValues, option.defaultValue)); + propertyWidget = this.createSelectBoxHelper(container, option.description, option.categoryValues.map(c => c.displayName), DialogHelper.getCategoryDisplayName(option.categoryValues, option.defaultValue)!); this._register(attachSelectBoxStyler(propertyWidget, this._themeService)); this._register(propertyWidget.onDidSelect(selectedDatabase => { this.onCatagoryOptionChanged(optionName); @@ -460,7 +454,7 @@ export class RestoreDialog extends Modal { })); } - this._optionsMap[optionName] = propertyWidget; + this._optionsMap[optionName] = propertyWidget!; } private onBooleanOptionChecked(optionName: string) { @@ -510,46 +504,46 @@ export class RestoreDialog extends Modal { } private clearRestorePlanDataTable(): void { - if (this._restorePlanData.getLength() > 0) { - this._restorePlanData.clear(); - DOM.hide(this._restorePlanTableContainer); + if (this._restorePlanData!.getLength() > 0) { + this._restorePlanData!.clear(); + DOM.hide(this._restorePlanTableContainer!); } } private clearFileListTable(): void { - if (this._fileListData.getLength() > 0) { - this._fileListData.clear(); - DOM.hide(this._fileListTableContainer); + if (this._fileListData!.getLength() > 0) { + this._fileListData!.clear(); + DOM.hide(this._fileListTableContainer!); } } private resetRestoreContent(): void { this.clearRestorePlanDataTable(); this.clearFileListTable(); - this._restoreButton.enabled = false; - this._scriptButton.enabled = false; + this._restoreButton!.enabled = false; + this._scriptButton!.enabled = false; } public onValidateResponseFail(errorMessage: string) { this.resetRestoreContent(); if (this.isRestoreFromDatabaseSelected) { - this._sourceDatabaseSelectBox.showMessage({ type: MessageType.ERROR, content: errorMessage }); + this._sourceDatabaseSelectBox!.showMessage({ type: MessageType.ERROR, content: errorMessage }); } else { - this._sourceDatabaseSelectBox.setOptions([]); - this._filePathInputBox.showMessage({ type: MessageType.ERROR, content: errorMessage }); + this._sourceDatabaseSelectBox!.setOptions([]); + this._filePathInputBox!.showMessage({ type: MessageType.ERROR, content: errorMessage }); } } public removeErrorMessage() { - this._filePathInputBox.hideMessage(); - this._sourceDatabaseSelectBox.hideMessage(); - this._destinationRestoreToInputBox.hideMessage(); + this._filePathInputBox!.hideMessage(); + this._sourceDatabaseSelectBox!.hideMessage(); + this._destinationRestoreToInputBox!.hideMessage(); } public enableRestoreButton(enabled: boolean) { this.spinner = false; - this._restoreButton.enabled = enabled; - this._scriptButton.enabled = enabled; + this._restoreButton!.enabled = enabled; + this._scriptButton!.enabled = enabled; } public showError(errorMessage: string): void { @@ -557,7 +551,7 @@ export class RestoreDialog extends Modal { } private backupFileCheckboxChanged(e: Slick.EventData, data: Slick.OnSelectedRowsChangedEventArgs): void { - let selectedFiles = []; + let selectedFiles: string[] = []; data.grid.getSelectedRows().forEach(row => { selectedFiles.push(data.grid.getDataItem(row)['Id']); }); @@ -575,37 +569,37 @@ export class RestoreDialog extends Modal { private registerListeners(): void { // Theme styler - this._register(attachInputBoxStyler(this._filePathInputBox, this._themeService)); - this._register(attachInputBoxStyler(this._destinationRestoreToInputBox, this._themeService)); - this._register(attachSelectBoxStyler(this._restoreFromSelectBox, this._themeService)); - this._register(attachSelectBoxStyler(this._sourceDatabaseSelectBox, this._themeService)); - this._register(attachButtonStyler(this._browseFileButton, this._themeService)); - this._register(attachButtonStyler(this._scriptButton, this._themeService)); - this._register(attachButtonStyler(this._restoreButton, this._themeService)); - this._register(attachButtonStyler(this._closeButton, this._themeService)); - this._register(attachTableStyler(this._fileListTable, this._themeService)); - this._register(attachTableStyler(this._restorePlanTable, this._themeService)); + this._register(attachInputBoxStyler(this._filePathInputBox!, this._themeService)); + this._register(attachInputBoxStyler(this._destinationRestoreToInputBox!, this._themeService)); + this._register(attachSelectBoxStyler(this._restoreFromSelectBox!, this._themeService)); + this._register(attachSelectBoxStyler(this._sourceDatabaseSelectBox!, this._themeService)); + this._register(attachButtonStyler(this._browseFileButton!, this._themeService)); + this._register(attachButtonStyler(this._scriptButton!, this._themeService)); + this._register(attachButtonStyler(this._restoreButton!, this._themeService)); + this._register(attachButtonStyler(this._closeButton!, this._themeService)); + this._register(attachTableStyler(this._fileListTable!, this._themeService)); + this._register(attachTableStyler(this._restorePlanTable!, this._themeService)); - this._register(this._filePathInputBox.onLoseFocus(params => { + this._register(this._filePathInputBox!.onLoseFocus(params => { this.onFilePathLoseFocus(params); })); - this._browseFileButton.onDidClick(() => { + this._browseFileButton!.onDidClick(() => { this.onFileBrowserRequested(); }); - this._register(this._sourceDatabaseSelectBox.onDidSelect(selectedDatabase => { + this._register(this._sourceDatabaseSelectBox!.onDidSelect(selectedDatabase => { this.onSourceDatabaseChanged(selectedDatabase.selected); })); - this._register(this._restoreFromSelectBox.onDidSelect(selectedRestoreFrom => { + this._register(this._restoreFromSelectBox!.onDidSelect(selectedRestoreFrom => { this.onRestoreFromChanged(selectedRestoreFrom.selected); })); } private onFileBrowserRequested(): void { - this.fileBrowserDialogService.showDialog(this._ownerUri, - this.viewModel.defaultBackupFolder, + this.fileBrowserDialogService.showDialog(this._ownerUri!, + this.viewModel.defaultBackupFolder!, fileFiltersSet, FileValidationConstants.restore, true, @@ -613,15 +607,15 @@ export class RestoreDialog extends Modal { } private onFileBrowsed(filepath: string) { - const oldFilePath = this._filePathInputBox.value; - if (strings.isFalsyOrWhitespace(this._filePathInputBox.value)) { - this._filePathInputBox.value = filepath; + const oldFilePath = this._filePathInputBox!.value; + if (strings.isFalsyOrWhitespace(this._filePathInputBox!.value)) { + this._filePathInputBox!.value = filepath; } else { - this._filePathInputBox.value = this._filePathInputBox.value + ', ' + filepath; + this._filePathInputBox!.value = this._filePathInputBox!.value + ', ' + filepath; } - if (oldFilePath !== this._filePathInputBox.value) { - this.onFilePathChanged(this._filePathInputBox.value); + if (oldFilePath !== this._filePathInputBox!.value) { + this.onFilePathChanged(this._filePathInputBox!.value); } } @@ -635,13 +629,13 @@ export class RestoreDialog extends Modal { private onFilePathChanged(filePath: string) { this.viewModel.filePath = filePath; - this.viewModel.selectedBackupSets = null; + this.viewModel.selectedBackupSets = undefined; this.validateRestore(true); } private onSourceDatabaseChanged(selectedDatabase: string) { this.viewModel.sourceDatabaseName = selectedDatabase; - this.viewModel.selectedBackupSets = null; + this.viewModel.selectedBackupSets = undefined; this.validateRestore(true); } @@ -649,28 +643,28 @@ export class RestoreDialog extends Modal { this.removeErrorMessage(); if (selectedRestoreFrom === this._backupFileTitle) { this.viewModel.onRestoreFromChanged(true); - DOM.show(this._restoreFromBackupFileElement); + DOM.show(this._restoreFromBackupFileElement!); } else { this.viewModel.onRestoreFromChanged(false); - DOM.hide(this._restoreFromBackupFileElement); + DOM.hide(this._restoreFromBackupFileElement!); } this.resetRestoreContent(); } private get isRestoreFromDatabaseSelected(): boolean { - return this._restoreFromSelectBox.value === this._databaseTitle; + return this._restoreFromSelectBox!.value === this._databaseTitle; } public validateRestore(overwriteTargetDatabase: boolean = false, isBackupFileCheckboxChanged: boolean = false): void { this._isBackupFileCheckboxChanged = isBackupFileCheckboxChanged; this.spinner = true; - this._restoreButton.enabled = false; - this._scriptButton.enabled = false; + this._restoreButton!.enabled = false; + this._scriptButton!.enabled = false; this._onValidate.fire(overwriteTargetDatabase); } public restore(isScriptOnly: boolean): void { - if (this._restoreButton.enabled) { + if (this._restoreButton!.enabled) { this._onRestore.fire(isScriptOnly); } } @@ -702,10 +696,10 @@ export class RestoreDialog extends Modal { private resetDialog(): void { this.hideError(); - this._restoreFromSelectBox.selectWithOptionName(this._databaseTitle); + this._restoreFromSelectBox!.selectWithOptionName(this._databaseTitle); this.onRestoreFromChanged(this._databaseTitle); - this._sourceDatabaseSelectBox.select(0); - this._panel.showTab(this._generalTabId); + this._sourceDatabaseSelectBox!.select(0); + this._panel!.showTab(this._generalTabId!); this._isBackupFileCheckboxChanged = false; this.removeErrorMessage(); this.resetRestoreContent(); @@ -716,7 +710,7 @@ export class RestoreDialog extends Modal { this._ownerUri = ownerUri; this.show(); - this._restoreFromSelectBox.focus(); + this._restoreFromSelectBox!.focus(); } protected layout(height?: number): void { @@ -733,13 +727,13 @@ export class RestoreDialog extends Modal { } private updateLastBackupTaken(value: string) { - this._destinationRestoreToInputBox.value = value; + this._destinationRestoreToInputBox!.value = value; } private updateFilePath(value: string) { - this._filePathInputBox.value = value; + this._filePathInputBox!.value = value; if (!value) { - this._filePathInputBox.hideMessage(); + this._filePathInputBox!.hideMessage(); } } @@ -753,12 +747,12 @@ export class RestoreDialog extends Modal { } else { dbNames = databaseNamesParam.databaseNames; } - this._sourceDatabaseSelectBox.setOptions(dbNames); - this._sourceDatabaseSelectBox.selectWithOptionName(databaseNamesParam.selectedDatabase); + this._sourceDatabaseSelectBox!.setOptions(dbNames); + this._sourceDatabaseSelectBox!.selectWithOptionName(databaseNamesParam.selectedDatabase); } private updateTargetDatabaseName(value: string) { - this._databaseDropdown.value = value; + this._databaseDropdown!.value = value; } private updateRestoreOption(optionParam: RestoreOptionParam) { @@ -797,13 +791,13 @@ export class RestoreDialog extends Modal { restoreAs: dbFiles[i].restoreAsFileName }; } - DOM.show(this._fileListTableContainer); - this._fileListData.push(data); + DOM.show(this._fileListTableContainer!); + this._fileListData!.push(data); // Set data and Select the first row for the table by default - this._fileListTable.setData(this._fileListData); - this._fileListTable.setSelectedRows([0]); - this._fileListTable.setActiveCell(0, 0); + this._fileListTable!.setData(this._fileListData!); + this._fileListTable!.setSelectedRows([0]); + this._fileListTable!.setActiveCell(0, 0); } } @@ -815,7 +809,7 @@ export class RestoreDialog extends Modal { selectedRow.push(i); } } - this._restorePlanTable.setSelectedRows(selectedRow); + this._restorePlanTable!.setSelectedRows(selectedRow); } else { this.clearRestorePlanDataTable(); if (backupSetsToRestore && backupSetsToRestore.length > 0) { @@ -831,16 +825,16 @@ export class RestoreDialog extends Modal { const checkboxSelectColumn = new CheckboxSelectColumn({ title: this._restoreLabel, toolTip: this._restoreLabel, width: 15 }); this._restorePlanColumn.unshift(checkboxSelectColumn.definition); - this._restorePlanTable.columns = this._restorePlanColumn; - this._restorePlanTable.registerPlugin(checkboxSelectColumn); - this._restorePlanTable.autosizeColumns(); + this._restorePlanTable!.columns = this._restorePlanColumn; + this._restorePlanTable!.registerPlugin(checkboxSelectColumn); + this._restorePlanTable!.autosizeColumns(); } - const data = []; - const selectedRow = []; + const data: Slick.SlickData[] = []; + const selectedRow: number[] = []; for (let i = 0; i < backupSetsToRestore.length; i++) { const backupFile = backupSetsToRestore[i]; - const newData = {}; + const newData: Slick.SlickData = {}; for (let j = 0; j < backupFile.properties.length; j++) { newData[backupFile.properties[j].propertyName] = backupFile.properties[j].propertyValueDisplayName; } @@ -849,15 +843,15 @@ export class RestoreDialog extends Modal { selectedRow.push(i); } } - DOM.show(this._restorePlanTableContainer); - this._restorePlanData.push(data); - this._restorePlanTable.setSelectedRows(selectedRow); - this._restorePlanTable.setActiveCell(selectedRow[0], 0); + DOM.show(this._restorePlanTableContainer!); + this._restorePlanData!.push(data); + this._restorePlanTable!.setSelectedRows(selectedRow); + this._restorePlanTable!.setActiveCell(selectedRow[0], 0); if (!this._isRenderedRestorePlanTable) { this._isRenderedRestorePlanTable = true; - this._restorePlanTable.resizeCanvas(); - this._restorePlanTable.autosizeColumns(); + this._restorePlanTable!.resizeCanvas(); + this._restorePlanTable!.autosizeColumns(); } } } diff --git a/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts b/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts index 087688fdd9..c88548e303 100644 --- a/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts +++ b/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts @@ -22,7 +22,6 @@ import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { invalidProvider } from 'sql/base/common/errors'; import { ILogService } from 'vs/platform/log/common/log'; -import { find } from 'vs/base/common/arrays'; import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; export class RestoreService implements IRestoreService { @@ -76,7 +75,7 @@ export class RestoreService implements IRestoreService { }); } - private getProvider(connectionUri: string): { provider: azdata.RestoreProvider, providerName: string } { + private getProvider(connectionUri: string): { provider: azdata.RestoreProvider, providerName: string } | undefined { let providerId: string = this._connectionService.getProviderIdFromUri(connectionUri); if (providerId) { return { provider: this._providers[providerId], providerName: providerId }; @@ -135,9 +134,9 @@ export class RestoreDialogController implements IRestoreDialogController { _serviceBrand: undefined; private _restoreDialogs: { [provider: string]: RestoreDialog | OptionsDialog } = {}; - private _currentProvider: string; - private _ownerUri: string; - private _sessionId: string; + private _currentProvider?: string; + private _ownerUri?: string; + private _sessionId?: string; private readonly _restoreFeature = 'Restore'; private readonly _restoreTaskName: string = 'Restore Database'; private readonly _restoreCompleted: string = 'Completed'; @@ -157,21 +156,20 @@ export class RestoreDialogController implements IRestoreDialogController { private handleOnRestore(isScriptOnly: boolean = false): void { let restoreOption = this.setRestoreOption(isScriptOnly ? TaskExecutionMode.script : TaskExecutionMode.executeAndScript); - this._restoreService.restore(this._ownerUri, restoreOption).then(result => { - const self = this; - let connectionProfile = self._connectionService.getConnectionProfile(self._ownerUri); - let activeNode = self._objectExplorerService.getObjectExplorerNode(connectionProfile); + this._restoreService.restore(this._ownerUri!, restoreOption).then(result => { + let connectionProfile = this._connectionService.getConnectionProfile(this._ownerUri!); + let activeNode = this._objectExplorerService.getObjectExplorerNode(connectionProfile)!; this._taskService.onTaskComplete(async response => { if (result.taskId === response.id && this.isSuccessfulRestore(response) && activeNode) { try { - await self._objectExplorerService.refreshTreeNode(activeNode.getSession(), activeNode); - await self._objectExplorerService.getServerTreeView().refreshTree(); + await this._objectExplorerService.refreshTreeNode(activeNode.getSession()!, activeNode); + await this._objectExplorerService.getServerTreeView()!.refreshTree(); } catch (e) { this._logService.error(e); } } }); - let restoreDialog = this._restoreDialogs[this._currentProvider]; + let restoreDialog = this._restoreDialogs[this._currentProvider!]; restoreDialog.close(); }); } @@ -186,8 +184,8 @@ export class RestoreDialogController implements IRestoreDialogController { } private handleMssqlOnValidateFile(overwriteTargetDatabase: boolean = false): void { - let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog; - this._restoreService.getRestorePlan(this._ownerUri, this.setRestoreOption(TaskExecutionMode.execute, overwriteTargetDatabase)).then(restorePlanResponse => { + let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog; + this._restoreService.getRestorePlan(this._ownerUri!, this.setRestoreOption(TaskExecutionMode.execute, overwriteTargetDatabase)).then(restorePlanResponse => { this._sessionId = restorePlanResponse.sessionId; if (restorePlanResponse.errorMessage) { @@ -212,7 +210,7 @@ export class RestoreDialogController implements IRestoreDialogController { * Will remove this function once there is a fix in the service (bug #2572) */ private isEmptyBackupset(): boolean { - let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog; + let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog; if (!types.isUndefinedOrNull(restoreDialog.viewModel.selectedBackupSets) && restoreDialog.viewModel.selectedBackupSets.length === 0) { return true; } @@ -221,8 +219,8 @@ export class RestoreDialogController implements IRestoreDialogController { private getMssqlRestoreConfigInfo(): Promise { return new Promise((resolve, reject) => { - let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog; - this._restoreService.getRestoreConfigInfo(this._ownerUri).then(restoreConfigInfo => { + let restoreDialog = this._restoreDialogs[this._currentProvider!] as RestoreDialog; + this._restoreService.getRestoreConfigInfo(this._ownerUri!).then(restoreConfigInfo => { restoreDialog.viewModel.updateOptionWithConfigInfo(restoreConfigInfo.configInfo); resolve(); }, error => { @@ -233,22 +231,20 @@ export class RestoreDialogController implements IRestoreDialogController { } private setRestoreOption(taskExecutionMode: TaskExecutionMode, overwriteTargetDatabase: boolean = false): azdata.RestoreInfo { - let restoreInfo = undefined; - let providerId: string = this.getCurrentProviderId(); if (providerId === ConnectionConstants.mssqlProviderName) { - restoreInfo = new MssqlRestoreInfo(taskExecutionMode); + let restoreInfo = new MssqlRestoreInfo(taskExecutionMode); if (this._sessionId) { restoreInfo.sessionId = this._sessionId; } let restoreDialog = this._restoreDialogs[providerId] as RestoreDialog; - restoreInfo.backupFilePaths = restoreDialog.viewModel.filePath; + restoreInfo.backupFilePaths = restoreDialog.viewModel.filePath!; - restoreInfo.readHeaderFromMedia = restoreDialog.viewModel.readHeaderFromMedia; - restoreInfo.selectedBackupSets = restoreDialog.viewModel.selectedBackupSets; - restoreInfo.sourceDatabaseName = restoreDialog.viewModel.sourceDatabaseName; + restoreInfo.readHeaderFromMedia = restoreDialog.viewModel.readHeaderFromMedia!; + restoreInfo.selectedBackupSets = restoreDialog.viewModel.selectedBackupSets!; + restoreInfo.sourceDatabaseName = restoreDialog.viewModel.sourceDatabaseName!; if (restoreDialog.viewModel.targetDatabaseName) { restoreInfo.targetDatabaseName = restoreDialog.viewModel.targetDatabaseName; } @@ -256,11 +252,10 @@ export class RestoreDialogController implements IRestoreDialogController { // Set other restore options restoreDialog.viewModel.getRestoreAdvancedOptions(restoreInfo.options); + return restoreInfo; } else { - restoreInfo = { options: this._optionValues }; + return { options: this._optionValues }; } - - return restoreInfo; } private getRestoreOption(): azdata.ServiceOption[] { @@ -269,7 +264,7 @@ export class RestoreDialogController implements IRestoreDialogController { let providerCapabilities = this._capabilitiesService.getLegacyCapabilities(providerId); if (providerCapabilities) { - let restoreMetadataProvider = find(providerCapabilities.features, f => f.featureName === this._restoreFeature); + let restoreMetadataProvider = providerCapabilities.features.find(f => f.featureName === this._restoreFeature); if (restoreMetadataProvider) { options = restoreMetadataProvider.optionsMetadata; } @@ -278,14 +273,14 @@ export class RestoreDialogController implements IRestoreDialogController { } private handleOnClose(): void { - this._connectionService.disconnect(this._ownerUri).catch((e) => this._logService.error(e)); + this._connectionService.disconnect(this._ownerUri!).catch((e) => this._logService.error(e)); } private handleOnCancel(): void { let restoreInfo = new MssqlRestoreInfo(TaskExecutionMode.execute); - restoreInfo.sessionId = this._sessionId; - this._restoreService.cancelRestorePlan(this._ownerUri, restoreInfo).then(() => { - this._connectionService.disconnect(this._ownerUri); + restoreInfo.sessionId = this._sessionId!; + this._restoreService.cancelRestorePlan(this._ownerUri!, restoreInfo).then(() => { + this._connectionService.disconnect(this._ownerUri!); }); } @@ -301,10 +296,10 @@ export class RestoreDialogController implements IRestoreDialogController { if (!this._connectionService.isConnected(this._ownerUri)) { this._connectionService.connect(connection, this._ownerUri).then(connectionResult => { - this._sessionId = null; + this._sessionId = undefined; this._currentProvider = this.getCurrentProviderId(); if (!this._restoreDialogs[this._currentProvider]) { - let newRestoreDialog: RestoreDialog | OptionsDialog = undefined; + let newRestoreDialog: RestoreDialog | OptionsDialog; if (this._currentProvider === ConnectionConstants.mssqlProviderName) { let provider = this._currentProvider; newRestoreDialog = this._instantiationService.createInstance(RestoreDialog, this.getRestoreOption()); @@ -326,7 +321,7 @@ export class RestoreDialogController implements IRestoreDialogController { let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog; restoreDialog.viewModel.resetRestoreOptions(connection.databaseName); this.getMssqlRestoreConfigInfo().then(() => { - restoreDialog.open(connection.serverName, this._ownerUri); + restoreDialog.open(connection.serverName, this._ownerUri!); restoreDialog.validateRestore(); }, restoreConfigError => { reject(restoreConfigError); @@ -345,11 +340,11 @@ export class RestoreDialogController implements IRestoreDialogController { } private getCurrentProviderId(): string { - return this._connectionService.getProviderIdFromUri(this._ownerUri); + return this._connectionService.getProviderIdFromUri(this._ownerUri!); } private fetchDatabases(provider: string): void { - this._connectionService.listDatabases(this._ownerUri).then(result => { + this._connectionService.listDatabases(this._ownerUri!).then(result => { if (result && result.databaseNames) { (this._restoreDialogs[provider]).databaseListOptions = result.databaseNames; } diff --git a/src/sql/workbench/services/restore/browser/restoreViewModel.ts b/src/sql/workbench/services/restore/browser/restoreViewModel.ts index 18a5fe9edf..d9fbaa3327 100644 --- a/src/sql/workbench/services/restore/browser/restoreViewModel.ts +++ b/src/sql/workbench/services/restore/browser/restoreViewModel.ts @@ -9,6 +9,7 @@ import * as types from 'vs/base/common/types'; import { Event, Emitter } from 'vs/base/common/event'; import { ServiceOptionType } from 'sql/workbench/api/common/sqlExtHostTypes'; +import { coalesce } from 'vs/base/common/arrays'; export interface RestoreOptionsElement { optionMetadata: azdata.ServiceOption; @@ -30,21 +31,21 @@ export interface RestoreOptionParam { */ export interface SouceDatabaseNamesParam { databaseNames: string[]; - selectedDatabase: string; + selectedDatabase?: string; } /** * View model for restore dialog */ export class RestoreViewModel { - public filePath: string; - public sourceDatabaseName: string; - public targetDatabaseName: string; - public lastBackupTaken: string; - public databaseList: string[]; - public readHeaderFromMedia: boolean; - public selectedBackupSets: string[]; - public defaultBackupFolder: string; + public filePath?: string; + public sourceDatabaseName?: string; + public targetDatabaseName?: string; + public lastBackupTaken?: string; + public databaseList?: string[]; + public readHeaderFromMedia?: boolean; + public selectedBackupSets?: string[]; + public defaultBackupFolder?: string; private _onSetLastBackupTaken = new Emitter(); public onSetLastBackupTaken: Event = this._onSetLastBackupTaken.event; @@ -111,14 +112,14 @@ export class RestoreViewModel { this.updateFilePath(''); this.updateSourceDatabaseNames([], undefined); } else { - this.updateSourceDatabaseNames(this.databaseList, this.databaseList[0]); + this.updateSourceDatabaseNames(this.databaseList!, this.databaseList![0]); } } /** * Get option metadata from the option map */ - public getOptionMetadata(optionName: string): azdata.ServiceOption { + public getOptionMetadata(optionName: string): azdata.ServiceOption | undefined { return this._optionsMap[optionName] ? this._optionsMap[optionName].optionMetadata : undefined; } @@ -234,14 +235,9 @@ export class RestoreViewModel { * Update backup sets to restore */ public updateBackupSetsToRestore(backupSetsToRestore: azdata.DatabaseFileInfo[]): void { - this.selectedBackupSets = null; + this.selectedBackupSets = undefined; if (backupSetsToRestore) { - this.selectedBackupSets = []; - backupSetsToRestore.forEach(backupFile => { - if (backupFile.isSelected) { - this.selectedBackupSets.push(backupFile.id); - } - }); + this.selectedBackupSets = coalesce(backupSetsToRestore.map(f => f.isSelected ? f.id : undefined)); this._onUpdateBackupSetsToRestore.fire(backupSetsToRestore); } } @@ -256,7 +252,7 @@ export class RestoreViewModel { this.updateFilePath(''); this.updateLastBackupTaken(''); this.databaseList = []; - this.selectedBackupSets = null; + this.selectedBackupSets = undefined; for (let key in this._optionsMap) { this._optionsMap[key].defaultValue = this.getDisplayValue(this._optionsMap[key].optionMetadata, this._optionsMap[key].optionMetadata.defaultValue); this._optionsMap[key].currentValue = this._optionsMap[key].defaultValue; @@ -283,7 +279,7 @@ export class RestoreViewModel { /** * Update source database names and selected database */ - public updateSourceDatabaseNames(options: string[], selectedDatabase: string) { + public updateSourceDatabaseNames(options: string[], selectedDatabase?: string) { this.sourceDatabaseName = selectedDatabase; this._onSetSourceDatabaseNames.fire({ databaseNames: options, selectedDatabase: selectedDatabase }); } diff --git a/src/sql/workbench/services/restore/test/browser/restoreViewModel.test.ts b/src/sql/workbench/services/restore/test/browser/restoreViewModel.test.ts index 32f93e16e9..a97f7b53a3 100644 --- a/src/sql/workbench/services/restore/test/browser/restoreViewModel.test.ts +++ b/src/sql/workbench/services/restore/test/browser/restoreViewModel.test.ts @@ -73,12 +73,12 @@ suite('Restore Dialog view model tests', () => { stringServiceOption = { name: option1String, displayName: 'Option 1', - description: null, - groupName: null, + description: null!, + groupName: null!, valueType: ServiceOptionType.string, defaultValue: 'default', - objectType: null, - categoryValues: null, + objectType: null!, + categoryValues: null!, isRequired: false, isArray: false }; @@ -86,11 +86,11 @@ suite('Restore Dialog view model tests', () => { categoryServiceOption = { name: option2Category, displayName: 'Option 2', - description: null, - groupName: null, + description: null!, + groupName: null!, valueType: ServiceOptionType.category, defaultValue: 'catagory1', - objectType: null, + objectType: null!, categoryValues: [{ displayName: 'Catagory 1', name: 'catagory1' @@ -106,12 +106,12 @@ suite('Restore Dialog view model tests', () => { booleanServiceOption = { name: option3Boolean, displayName: 'Option 3', - description: null, - groupName: null, + description: null!, + groupName: null!, valueType: ServiceOptionType.boolean, defaultValue: 'true', - objectType: null, - categoryValues: null, + objectType: null!, + categoryValues: null!, isRequired: false, isArray: false }; @@ -171,7 +171,6 @@ suite('Restore Dialog view model tests', () => { sessionId: '123', backupSetsToRestore: backupSets, canRestore: true, - errorMessage: null, dbFiles: [], databaseNamesFromBackupSets: ['dbSource', 'dbSource2'], planDetails: planDetails @@ -191,8 +190,8 @@ suite('Restore Dialog view model tests', () => { // verify that selected backup sets get set correctly let selectedBackupSets = viewModel.selectedBackupSets; - assert.equal(1, selectedBackupSets.length); - assert.equal('file2', selectedBackupSets[0]); + assert.equal(1, selectedBackupSets!.length); + assert.equal('file2', selectedBackupSets![0]); }); @@ -201,7 +200,6 @@ suite('Restore Dialog view model tests', () => { sessionId: '123', backupSetsToRestore: backupSets, canRestore: true, - errorMessage: null, dbFiles: [], databaseNamesFromBackupSets: ['dbSource', 'dbSource2'], planDetails: planDetails @@ -217,7 +215,7 @@ suite('Restore Dialog view model tests', () => { assert.equal('db2', viewModel.sourceDatabaseName); assert.equal('db2', viewModel.targetDatabaseName); assert.equal('', viewModel.lastBackupTaken); - assert.equal(0, viewModel.databaseList.length); + assert.equal(0, viewModel.databaseList!.length); // verify that advanced options get set correctly options = {}; @@ -235,10 +233,11 @@ suite('Restore Dialog view model tests', () => { configInfo['sourceDatabaseNamesWithBackupSets'] = databaseList; configInfo[option1String] = 'option1 from config info'; viewModel.updateOptionWithConfigInfo(configInfo); - assert.equal(3, viewModel.databaseList.length); - assert.equal('', viewModel.databaseList[0]); - assert.equal(databaseList[1], viewModel.databaseList[1]); - assert.equal(databaseList[2], viewModel.databaseList[2]); + assert.ok(viewModel.databaseList); + assert.equal(3, viewModel.databaseList!.length); + assert.equal('', viewModel.databaseList![0]); + assert.equal(databaseList[1], viewModel.databaseList![1]); + assert.equal(databaseList[2], viewModel.databaseList![2]); assert.equal('option1 from config info', viewModel.getOptionValue(option1String)); // verify that the options from get restore advanced options doesn't contain option1String diff --git a/src/tsconfig.vscode.json b/src/tsconfig.vscode.json index bb8c5524f4..9bd0f836ad 100644 --- a/src/tsconfig.vscode.json +++ b/src/tsconfig.vscode.json @@ -83,7 +83,6 @@ "./sql/workbench/services/objectExplorer/**/*.ts", // 301 errors "./sql/workbench/services/query/**/*.ts", // 3127 errors "./sql/workbench/services/queryEditor/**/*.ts", // 3127 errors - "./sql/workbench/services/restore/**/*.ts", // 83 errors "./sql/workbench/test/**/*.ts", // 3461 errors "./sql/workbench/update/**/*.ts", // 3102 errors "./vs/workbench/api/browser/**/*.ts", // 3187 errors