mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add basic structure for publish project quickpick (#16008)
* Add basic structure for publish project quickpick * fixes * feedback
This commit is contained in:
@@ -90,7 +90,7 @@ export function currentTargetPlatform(projectName: string, currentTargetPlatform
|
|||||||
// Publish dialog strings
|
// Publish dialog strings
|
||||||
|
|
||||||
export const publishDialogName = localize('publishDialogName', "Publish project");
|
export const publishDialogName = localize('publishDialogName', "Publish project");
|
||||||
export const publishDialogOkButtonText = localize('publishDialogOkButtonText', "Publish");
|
export const publish = localize('publish', "Publish");
|
||||||
export const cancelButtonText = localize('cancelButtonText', "Cancel");
|
export const cancelButtonText = localize('cancelButtonText', "Cancel");
|
||||||
export const generateScriptButtonText = localize('generateScriptButtonText', "Generate Script");
|
export const generateScriptButtonText = localize('generateScriptButtonText', "Generate Script");
|
||||||
export const databaseNameLabel = localize('databaseNameLabel', "Database");
|
export const databaseNameLabel = localize('databaseNameLabel', "Database");
|
||||||
@@ -109,6 +109,19 @@ export const profile = localize('profile', "Profile");
|
|||||||
export const selectConnection = localize('selectConnection', "Select connection");
|
export const selectConnection = localize('selectConnection', "Select connection");
|
||||||
export const server = localize('server', "Server");
|
export const server = localize('server', "Server");
|
||||||
export const defaultUser = localize('default', "default");
|
export const defaultUser = localize('default', "default");
|
||||||
|
export const selectProfile = localize('selectProfile', "Select publish profile to load");
|
||||||
|
export const dontUseProfile = localize('dontUseProfile', "Don't use profile");
|
||||||
|
export const browseForProfile = localize('browseForProfile', "Browse for profile");
|
||||||
|
export const chooseAction = localize('chooseAction', "Choose action");
|
||||||
|
export const chooseSqlcmdVarsToModify = localize('chooseSqlcmdVarsToModify', "Choose SQLCMD variables to modify");
|
||||||
|
export const enterNewValueForVar = (varName: string) => localize('enterNewValueForVar', "Enter new value for variable '{0}'", varName);
|
||||||
|
export const resetAllVars = localize('resetAllVars', "Reset all variables");
|
||||||
|
export const createNew = localize('createNew', "<Create New>");
|
||||||
|
export const enterNewDatabaseName = localize('enterNewDatabaseName', "Enter new database name");
|
||||||
|
export const newDatabaseTitle = (name: string) => localize({ key: 'newDatabaseTitle', comment: ['Name is the name of a new database being created'] }, "{0} (new)", name);
|
||||||
|
export const selectDatabase = localize('selectDatabase', "Select database");
|
||||||
|
export const done = localize('done', "Done");
|
||||||
|
export const nameMustNotBeEmpty = localize('nameMustNotBeEmpty', "Name must not be empty");
|
||||||
|
|
||||||
// Add Database Reference dialog strings
|
// Add Database Reference dialog strings
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export default class MainController implements vscode.Disposable {
|
|||||||
vscode.commands.registerCommand('sqlDatabaseProjects.properties', async (node: WorkspaceTreeItem) => { await vscode.window.showErrorMessage(`Properties not yet implemented: ${node.element.uri.path}`); }); // TODO
|
vscode.commands.registerCommand('sqlDatabaseProjects.properties', async (node: WorkspaceTreeItem) => { await vscode.window.showErrorMessage(`Properties not yet implemented: ${node.element.uri.path}`); }); // TODO
|
||||||
|
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.build', async (node: WorkspaceTreeItem) => { await this.projectsController.buildProject(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.build', async (node: WorkspaceTreeItem) => { await this.projectsController.buildProject(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.publish', async (node: WorkspaceTreeItem) => { await this.projectsController.publishProject(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.publish', async (node: WorkspaceTreeItem) => { this.projectsController.publishProject(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.schemaCompare', async (node: WorkspaceTreeItem) => { await this.projectsController.schemaCompare(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.schemaCompare', async (node: WorkspaceTreeItem) => { await this.projectsController.schemaCompare(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.createProjectFromDatabase', async (profile: azdataType.IConnectionProfile) => { await this.projectsController.createProjectFromDatabase(profile); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.createProjectFromDatabase', async (profile: azdataType.IConnectionProfile) => { await this.projectsController.createProjectFromDatabase(profile); });
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import * as templates from '../templates/templates';
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import type * as azdataType from 'azdata';
|
import type * as azdataType from 'azdata';
|
||||||
import * as dataworkspace from 'dataworkspace';
|
import * as dataworkspace from 'dataworkspace';
|
||||||
|
import type * as mssqlVscode from 'vscode-mssql';
|
||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||||
@@ -33,9 +34,12 @@ import { CreateProjectFromDatabaseDialog } from '../dialogs/createProjectFromDat
|
|||||||
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
|
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
|
||||||
import { IconPathHelper } from '../common/iconHelper';
|
import { IconPathHelper } from '../common/iconHelper';
|
||||||
import { DashboardData, PublishData, Status } from '../models/dashboardData/dashboardData';
|
import { DashboardData, PublishData, Status } from '../models/dashboardData/dashboardData';
|
||||||
|
import { launchPublishDatabaseQuickpick } from '../dialogs/publishDatabaseQuickpick';
|
||||||
|
|
||||||
const maxTableLength = 10;
|
const maxTableLength = 10;
|
||||||
|
|
||||||
|
export type IDacFxService = mssql.IDacFxService | mssqlVscode.IDacFxService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for managing lifecycle of projects
|
* Controller for managing lifecycle of projects
|
||||||
*/
|
*/
|
||||||
@@ -231,17 +235,22 @@ export class ProjectsController {
|
|||||||
* @param project Project to be built and published
|
* @param project Project to be built and published
|
||||||
*/
|
*/
|
||||||
public publishProject(project: Project): PublishDatabaseDialog;
|
public publishProject(project: Project): PublishDatabaseDialog;
|
||||||
public publishProject(context: Project | dataworkspace.WorkspaceTreeItem): PublishDatabaseDialog {
|
public publishProject(context: Project | dataworkspace.WorkspaceTreeItem): PublishDatabaseDialog | undefined {
|
||||||
const project: Project = this.getProjectFromContext(context);
|
const project: Project = this.getProjectFromContext(context);
|
||||||
let publishDatabaseDialog = this.getPublishDialog(project);
|
if (utils.getAzdataApi()) {
|
||||||
|
let publishDatabaseDialog = this.getPublishDialog(project);
|
||||||
|
|
||||||
publishDatabaseDialog.publish = async (proj, prof) => await this.publishProjectCallback(proj, prof);
|
publishDatabaseDialog.publish = async (proj, prof) => await this.publishProjectCallback(proj, prof);
|
||||||
publishDatabaseDialog.generateScript = async (proj, prof) => await this.publishProjectCallback(proj, prof);
|
publishDatabaseDialog.generateScript = async (proj, prof) => await this.publishProjectCallback(proj, prof);
|
||||||
publishDatabaseDialog.readPublishProfile = async (profileUri) => await this.readPublishProfileCallback(profileUri);
|
publishDatabaseDialog.readPublishProfile = async (profileUri) => await this.readPublishProfileCallback(profileUri);
|
||||||
|
|
||||||
publishDatabaseDialog.openDialog();
|
publishDatabaseDialog.openDialog();
|
||||||
|
|
||||||
return publishDatabaseDialog;
|
return publishDatabaseDialog;
|
||||||
|
} else {
|
||||||
|
launchPublishDatabaseQuickpick(project);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async publishProjectCallback(project: Project, settings: IPublishSettings | IGenerateScriptSettings): Promise<mssql.DacFxResult | undefined> {
|
public async publishProjectCallback(project: Project, settings: IPublishSettings | IGenerateScriptSettings): Promise<mssql.DacFxResult | undefined> {
|
||||||
@@ -284,13 +293,26 @@ export class ProjectsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const azdataApi = utils.getAzdataApi();
|
||||||
if ((<IPublishSettings>settings).upgradeExisting) {
|
if ((<IPublishSettings>settings).upgradeExisting) {
|
||||||
telemetryProps.publishAction = 'deploy';
|
telemetryProps.publishAction = 'deploy';
|
||||||
result = await dacFxService.deployDacpac(tempPath, settings.databaseName, (<IPublishSettings>settings).upgradeExisting, settings.connectionUri, utils.getAzdataApi()!.TaskExecutionMode.execute, settings.sqlCmdVariables, settings.deploymentOptions);
|
if (azdataApi) {
|
||||||
|
result = await (dacFxService as mssql.IDacFxService).deployDacpac(tempPath, settings.databaseName, (<IPublishSettings>settings).upgradeExisting, settings.connectionUri, azdataApi.TaskExecutionMode.execute, settings.sqlCmdVariables, settings.deploymentOptions);
|
||||||
|
} else {
|
||||||
|
// TODO@chgagnon Fix typing
|
||||||
|
result = await (dacFxService as mssqlVscode.IDacFxService).deployDacpac(tempPath, settings.databaseName, (<IPublishSettings>settings).upgradeExisting, settings.connectionUri, <mssqlVscode.TaskExecutionMode><any>azdataApi!.TaskExecutionMode.execute, settings.sqlCmdVariables, <mssqlVscode.DeploymentOptions><any>settings.deploymentOptions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
telemetryProps.publishAction = 'generateScript';
|
telemetryProps.publishAction = 'generateScript';
|
||||||
result = await dacFxService.generateDeployScript(tempPath, settings.databaseName, settings.connectionUri, utils.getAzdataApi()!.TaskExecutionMode.script, settings.sqlCmdVariables, settings.deploymentOptions);
|
if (azdataApi) {
|
||||||
|
result = await (dacFxService as mssql.IDacFxService).generateDeployScript(tempPath, settings.databaseName, settings.connectionUri, azdataApi.TaskExecutionMode.script, settings.sqlCmdVariables, settings.deploymentOptions);
|
||||||
|
} else {
|
||||||
|
// TODO@chgagnon Fix typing
|
||||||
|
result = await (dacFxService as mssqlVscode.IDacFxService).generateDeployScript(tempPath, settings.databaseName, settings.connectionUri, <any>undefined/*mssqlVscode.TaskExecutionMode.script*/, settings.sqlCmdVariables, <mssqlVscode.DeploymentOptions><any>settings.deploymentOptions);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const actionEndTime = new Date().getTime();
|
const actionEndTime = new Date().getTime();
|
||||||
@@ -807,11 +829,17 @@ export class ProjectsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getDaxFxService(): Promise<mssql.IDacFxService> {
|
public async getDaxFxService(): Promise<IDacFxService> {
|
||||||
const ext: vscode.Extension<any> = vscode.extensions.getExtension(mssql.extension.name)!;
|
if (utils.getAzdataApi()) {
|
||||||
|
const ext: vscode.Extension<mssql.IExtension> = vscode.extensions.getExtension(mssql.extension.name)!;
|
||||||
|
const extensionApi = await ext.activate();
|
||||||
|
return extensionApi.dacFx;
|
||||||
|
} else {
|
||||||
|
const ext: vscode.Extension<mssqlVscode.IExtension> = vscode.extensions.getExtension(mssql.extension.name)!;
|
||||||
|
const extensionApi = await ext.activate();
|
||||||
|
return extensionApi.dacFx;
|
||||||
|
}
|
||||||
|
|
||||||
await ext.activate();
|
|
||||||
return (ext.exports as mssql.IExtension).dacFx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export class PublishDatabaseDialog {
|
|||||||
|
|
||||||
public openDialog(): void {
|
public openDialog(): void {
|
||||||
this.initializeDialog();
|
this.initializeDialog();
|
||||||
this.dialog.okButton.label = constants.publishDialogOkButtonText;
|
this.dialog.okButton.label = constants.publish;
|
||||||
this.dialog.okButton.enabled = false;
|
this.dialog.okButton.enabled = false;
|
||||||
this.toDispose.push(this.dialog.okButton.onClick(async () => await this.publishClick()));
|
this.toDispose.push(this.dialog.okButton.onClick(async () => await this.publishClick()));
|
||||||
|
|
||||||
@@ -536,17 +536,7 @@ export class PublishDatabaseDialog {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
loadProfileButton.onDidClick(async () => {
|
loadProfileButton.onDidClick(async () => {
|
||||||
const fileUris = await vscode.window.showOpenDialog(
|
const fileUris = await promptForPublishProfile(this.project.projectFolderPath);
|
||||||
{
|
|
||||||
canSelectFiles: true,
|
|
||||||
canSelectFolders: false,
|
|
||||||
canSelectMany: false,
|
|
||||||
defaultUri: vscode.Uri.file(this.project.projectFolderPath),
|
|
||||||
filters: {
|
|
||||||
[constants.publishSettingsFiles]: ['publish.xml']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!fileUris || fileUris.length === 0) {
|
if (!fileUris || fileUris.length === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -628,3 +618,17 @@ export class PublishDatabaseDialog {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function promptForPublishProfile(defaultPath: string): Thenable<vscode.Uri[] | undefined> {
|
||||||
|
return vscode.window.showOpenDialog(
|
||||||
|
{
|
||||||
|
canSelectFiles: true,
|
||||||
|
canSelectFolders: false,
|
||||||
|
canSelectMany: false,
|
||||||
|
defaultUri: vscode.Uri.file(defaultPath),
|
||||||
|
filters: {
|
||||||
|
[constants.publishSettingsFiles]: ['publish.xml']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as constants from '../common/constants';
|
||||||
|
import { IGenerateScriptSettings, IPublishSettings } from '../models/IPublishSettings';
|
||||||
|
import { Project } from '../models/project';
|
||||||
|
import { promptForPublishProfile } from './publishDatabaseDialog';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create flow for Publishing a database using only VS Code-native APIs such as QuickPick
|
||||||
|
*/
|
||||||
|
export async function launchPublishDatabaseQuickpick(project: Project): Promise<void> {
|
||||||
|
|
||||||
|
// 1. Select publish settings file (optional)
|
||||||
|
// TODO@chgagnon: Hook up to dacfx service
|
||||||
|
const browseProfileOption = await vscode.window.showQuickPick(
|
||||||
|
[constants.dontUseProfile, constants.browseForProfile],
|
||||||
|
{ title: constants.selectProfile, ignoreFocusOut: true });
|
||||||
|
if (!browseProfileOption) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let publishSettingsFile: vscode.Uri | undefined;
|
||||||
|
if (browseProfileOption === constants.browseForProfile) {
|
||||||
|
const locations = await promptForPublishProfile(project.projectFolderPath);
|
||||||
|
if (!locations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// publishSettingsFile = locations[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Select connection
|
||||||
|
// TODO@chgagnon: Hook up to MSSQL
|
||||||
|
const connectionProfile = await vscode.window.showQuickPick(
|
||||||
|
['Connection 1', 'Connection 2', 'Create New Connection'],
|
||||||
|
{ title: constants.selectConnection, ignoreFocusOut: true });
|
||||||
|
if (!connectionProfile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dbs = ['db1', 'db2'];
|
||||||
|
const dbQuickpicks = dbs.map(db => {
|
||||||
|
return {
|
||||||
|
label: db,
|
||||||
|
dbName: db
|
||||||
|
} as vscode.QuickPickItem & { dbName: string, isCreateNew?: boolean };
|
||||||
|
});
|
||||||
|
// Ensure the project name is an option, either adding it if it doesn't already exist or moving it to the top if it does
|
||||||
|
const projectNameIndex = dbs.findIndex(db => db === project.projectFileName);
|
||||||
|
if (projectNameIndex === -1) {
|
||||||
|
dbQuickpicks.unshift({ label: constants.newDatabaseTitle(project.projectFileName), dbName: project.projectFileName });
|
||||||
|
} else {
|
||||||
|
dbQuickpicks.splice(projectNameIndex, 1);
|
||||||
|
dbQuickpicks.unshift({ label: project.projectFileName, dbName: project.projectFileName });
|
||||||
|
}
|
||||||
|
|
||||||
|
dbQuickpicks.push({ label: constants.createNew, dbName: '', isCreateNew: true });
|
||||||
|
// 3. Select database
|
||||||
|
// TODO@chgagnon: Hook up to MSSQL
|
||||||
|
let databaseName = '';
|
||||||
|
while (databaseName === '') {
|
||||||
|
const selectedDatabase = await vscode.window.showQuickPick(
|
||||||
|
dbQuickpicks,
|
||||||
|
{ title: constants.selectDatabase, ignoreFocusOut: true });
|
||||||
|
if (!selectedDatabase) {
|
||||||
|
// User cancelled
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
databaseName = selectedDatabase.dbName;
|
||||||
|
if (selectedDatabase.isCreateNew) {
|
||||||
|
databaseName = await vscode.window.showInputBox(
|
||||||
|
{
|
||||||
|
title: constants.enterNewDatabaseName,
|
||||||
|
ignoreFocusOut: true,
|
||||||
|
validateInput: input => input ? undefined : constants.nameMustNotBeEmpty
|
||||||
|
}
|
||||||
|
) ?? '';
|
||||||
|
// If user cancels out of this just return them to the db select quickpick in case they changed their mind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 4. Modify sqlcmd vars
|
||||||
|
// TODO@chgagnon: Concat ones from publish profile
|
||||||
|
let sqlCmdVariables = Object.assign({}, project.sqlCmdVariables);
|
||||||
|
|
||||||
|
if (Object.keys(sqlCmdVariables).length > 0) {
|
||||||
|
// Continually loop here, allowing the user to modify SQLCMD variables one
|
||||||
|
// at a time until they're done (either by selecting the "Done" option or
|
||||||
|
// escaping out of the quick pick dialog). Users can modify each variable
|
||||||
|
// as many times as they wish - with an option to reset all the variables
|
||||||
|
// to their starting values being provided as well.
|
||||||
|
while (true) {
|
||||||
|
const quickPickItems = Object.keys(sqlCmdVariables).map(key => {
|
||||||
|
return {
|
||||||
|
label: key,
|
||||||
|
description: sqlCmdVariables[key],
|
||||||
|
key: key
|
||||||
|
} as vscode.QuickPickItem & { key?: string, isResetAllVars?: boolean, isDone?: boolean };
|
||||||
|
});
|
||||||
|
quickPickItems.push({ label: constants.resetAllVars, isResetAllVars: true });
|
||||||
|
quickPickItems.unshift({ label: constants.done, isDone: true });
|
||||||
|
const sqlCmd = await vscode.window.showQuickPick(
|
||||||
|
quickPickItems,
|
||||||
|
{ title: constants.chooseSqlcmdVarsToModify, ignoreFocusOut: true }
|
||||||
|
);
|
||||||
|
if (!sqlCmd) {
|
||||||
|
// When user hits escape then we continue on here, we don't exit the publish
|
||||||
|
// flow since this is an optional step
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sqlCmd.key) {
|
||||||
|
const newValue = await vscode.window.showInputBox(
|
||||||
|
{
|
||||||
|
title: constants.enterNewValueForVar(sqlCmd.key),
|
||||||
|
value: sqlCmdVariables[sqlCmd.key],
|
||||||
|
ignoreFocusOut: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (newValue) {
|
||||||
|
sqlCmdVariables[sqlCmd.key] = newValue;
|
||||||
|
}
|
||||||
|
} else if (sqlCmd.isResetAllVars) {
|
||||||
|
sqlCmdVariables = Object.assign({}, project.sqlCmdVariables);
|
||||||
|
} else if (sqlCmd.isDone) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Select action to take
|
||||||
|
const action = await vscode.window.showQuickPick(
|
||||||
|
[constants.generateScriptButtonText, constants.publish],
|
||||||
|
{ title: constants.chooseAction, ignoreFocusOut: true });
|
||||||
|
if (!action) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO@chgagnon: Get deployment options
|
||||||
|
// 6. Generate script/publish
|
||||||
|
let settings: IPublishSettings | IGenerateScriptSettings = {
|
||||||
|
databaseName: databaseName,
|
||||||
|
serverName: '', // TODO@chgagnon: Get from connection profile
|
||||||
|
connectionUri: '', // TODO@chgagnon: Get from connection profile
|
||||||
|
sqlCmdVariables: undefined, // this.getSqlCmdVariablesForPublish(),
|
||||||
|
deploymentOptions: undefined, // await this.getDeploymentOptions(),
|
||||||
|
profileUsed: true, // this.profileUsed,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO@chgagnon Consolidate creation of the settings into one place
|
||||||
|
if (action === constants.publish) {
|
||||||
|
(settings as IPublishSettings).upgradeExisting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,12 @@ import * as xmldom from 'xmldom';
|
|||||||
import * as constants from '../../common/constants';
|
import * as constants from '../../common/constants';
|
||||||
import * as utils from '../../common/utils';
|
import * as utils from '../../common/utils';
|
||||||
import * as mssql from '../../../../mssql';
|
import * as mssql from '../../../../mssql';
|
||||||
|
import * as vscodeMssql from 'vscode-mssql';
|
||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { Uri } from 'vscode';
|
import { Uri } from 'vscode';
|
||||||
import { SqlConnectionDataSource } from '../dataSources/sqlConnectionStringSource';
|
import { SqlConnectionDataSource } from '../dataSources/sqlConnectionStringSource';
|
||||||
|
import { IDacFxService } from '../../controllers/projectController';
|
||||||
|
|
||||||
// only reading db name, connection string, and SQLCMD vars from profile for now
|
// only reading db name, connection string, and SQLCMD vars from profile for now
|
||||||
export interface PublishProfile {
|
export interface PublishProfile {
|
||||||
@@ -19,13 +21,13 @@ export interface PublishProfile {
|
|||||||
connectionId: string;
|
connectionId: string;
|
||||||
connection: string;
|
connection: string;
|
||||||
sqlCmdVariables: Record<string, string>;
|
sqlCmdVariables: Record<string, string>;
|
||||||
options?: mssql.DeploymentOptions;
|
options?: mssql.DeploymentOptions | vscodeMssql.DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parses the specified file to load publish settings
|
* parses the specified file to load publish settings
|
||||||
*/
|
*/
|
||||||
export async function load(profileUri: Uri, dacfxService: mssql.IDacFxService): Promise<PublishProfile> {
|
export async function load(profileUri: Uri, dacfxService: IDacFxService): Promise<PublishProfile> {
|
||||||
const profileText = await fs.readFile(profileUri.fsPath);
|
const profileText = await fs.readFile(profileUri.fsPath);
|
||||||
const profileXmlDoc = new xmldom.DOMParser().parseFromString(profileText.toString());
|
const profileXmlDoc = new xmldom.DOMParser().parseFromString(profileText.toString());
|
||||||
|
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ describe('ProjectsController', function (): void {
|
|||||||
projController.callBase = true;
|
projController.callBase = true;
|
||||||
projController.setup(x => x.getPublishDialog(TypeMoq.It.isAny())).returns(() => publishDialog.object);
|
projController.setup(x => x.getPublishDialog(TypeMoq.It.isAny())).returns(() => publishDialog.object);
|
||||||
|
|
||||||
await projController.object.publishProject(new Project('FakePath'));
|
projController.object.publishProject(new Project('FakePath'));
|
||||||
should(opened).equal(true);
|
should(opened).equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -376,12 +376,12 @@ describe('ProjectsController', function (): void {
|
|||||||
return Promise.resolve(undefined);
|
return Promise.resolve(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
let dialog = await projController.object.publishProject(proj);
|
let dialog = projController.object.publishProject(proj);
|
||||||
await dialog.publishClick();
|
await dialog.publishClick();
|
||||||
|
|
||||||
should(holler).equal(publishHoller, 'executionCallback() is supposed to have been setup and called for Publish scenario');
|
should(holler).equal(publishHoller, 'executionCallback() is supposed to have been setup and called for Publish scenario');
|
||||||
|
|
||||||
dialog = await projController.object.publishProject(proj);
|
dialog = projController.object.publishProject(proj);
|
||||||
await dialog.generateScriptClick();
|
await dialog.generateScriptClick();
|
||||||
|
|
||||||
should(holler).equal(generateHoller, 'executionCallback() is supposed to have been setup and called for GenerateScript scenario');
|
should(holler).equal(generateHoller, 'executionCallback() is supposed to have been setup and called for GenerateScript scenario');
|
||||||
|
|||||||
291
extensions/sql-database-projects/src/typings/vscode-mssql.d.ts
vendored
Normal file
291
extensions/sql-database-projects/src/typings/vscode-mssql.d.ts
vendored
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
declare module 'vscode-mssql' {
|
||||||
|
/**
|
||||||
|
* Covers defining what the vscode-mssql extension exports to other extensions
|
||||||
|
*
|
||||||
|
* IMPORTANT: THIS IS NOT A HARD DEFINITION unlike vscode; therefore no enums or classes should be defined here
|
||||||
|
* (const enums get evaluated when typescript -> javascript so those are fine)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export const enum extension {
|
||||||
|
name = 'Microsoft.mssql'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APIs provided by Mssql extension
|
||||||
|
*/
|
||||||
|
export interface IExtension {
|
||||||
|
|
||||||
|
readonly dacFx: IDacFxService;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum ExtractTarget {
|
||||||
|
dacpac = 0,
|
||||||
|
file = 1,
|
||||||
|
flat = 2,
|
||||||
|
objectType = 3,
|
||||||
|
schema = 4,
|
||||||
|
schemaObjectType = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDacFxService {
|
||||||
|
exportBacpac(databaseName: string, packageFilePath: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
|
importBacpac(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
|
extractDacpac(databaseName: string, packageFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
|
createProjectFromDatabase(databaseName: string, targetFilePath: string, applicationName: string, applicationVersion: string, ownerUri: string, extractTarget: ExtractTarget, taskExecutionMode: TaskExecutionMode): Thenable<DacFxResult>;
|
||||||
|
deployDacpac(packageFilePath: string, databaseName: string, upgradeExisting: boolean, ownerUri: string, taskExecutionMode: TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<DacFxResult>;
|
||||||
|
generateDeployScript(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: TaskExecutionMode, sqlCommandVariableValues?: Record<string, string>, deploymentOptions?: DeploymentOptions): Thenable<DacFxResult>;
|
||||||
|
generateDeployPlan(packageFilePath: string, databaseName: string, ownerUri: string, taskExecutionMode: TaskExecutionMode): Thenable<GenerateDeployPlanResult>;
|
||||||
|
getOptionsFromProfile(profilePath: string): Thenable<DacFxOptionsResult>;
|
||||||
|
validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable<ValidateStreamingJobResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TaskExecutionMode {
|
||||||
|
execute = 0,
|
||||||
|
script = 1,
|
||||||
|
executeAndScript = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeploymentOptions {
|
||||||
|
ignoreTableOptions: boolean;
|
||||||
|
ignoreSemicolonBetweenStatements: boolean;
|
||||||
|
ignoreRouteLifetime: boolean;
|
||||||
|
ignoreRoleMembership: boolean;
|
||||||
|
ignoreQuotedIdentifiers: boolean;
|
||||||
|
ignorePermissions: boolean;
|
||||||
|
ignorePartitionSchemes: boolean;
|
||||||
|
ignoreObjectPlacementOnPartitionScheme: boolean;
|
||||||
|
ignoreNotForReplication: boolean;
|
||||||
|
ignoreLoginSids: boolean;
|
||||||
|
ignoreLockHintsOnIndexes: boolean;
|
||||||
|
ignoreKeywordCasing: boolean;
|
||||||
|
ignoreIndexPadding: boolean;
|
||||||
|
ignoreIndexOptions: boolean;
|
||||||
|
ignoreIncrement: boolean;
|
||||||
|
ignoreIdentitySeed: boolean;
|
||||||
|
ignoreUserSettingsObjects: boolean;
|
||||||
|
ignoreFullTextCatalogFilePath: boolean;
|
||||||
|
ignoreWhitespace: boolean;
|
||||||
|
ignoreWithNocheckOnForeignKeys: boolean;
|
||||||
|
verifyCollationCompatibility: boolean;
|
||||||
|
unmodifiableObjectWarnings: boolean;
|
||||||
|
treatVerificationErrorsAsWarnings: boolean;
|
||||||
|
scriptRefreshModule: boolean;
|
||||||
|
scriptNewConstraintValidation: boolean;
|
||||||
|
scriptFileSize: boolean;
|
||||||
|
scriptDeployStateChecks: boolean;
|
||||||
|
scriptDatabaseOptions: boolean;
|
||||||
|
scriptDatabaseCompatibility: boolean;
|
||||||
|
scriptDatabaseCollation: boolean;
|
||||||
|
runDeploymentPlanExecutors: boolean;
|
||||||
|
registerDataTierApplication: boolean;
|
||||||
|
populateFilesOnFileGroups: boolean;
|
||||||
|
noAlterStatementsToChangeClrTypes: boolean;
|
||||||
|
includeTransactionalScripts: boolean;
|
||||||
|
includeCompositeObjects: boolean;
|
||||||
|
allowUnsafeRowLevelSecurityDataMovement: boolean;
|
||||||
|
ignoreWithNocheckOnCheckConstraints: boolean;
|
||||||
|
ignoreFillFactor: boolean;
|
||||||
|
ignoreFileSize: boolean;
|
||||||
|
ignoreFilegroupPlacement: boolean;
|
||||||
|
doNotAlterReplicatedObjects: boolean;
|
||||||
|
doNotAlterChangeDataCaptureObjects: boolean;
|
||||||
|
disableAndReenableDdlTriggers: boolean;
|
||||||
|
deployDatabaseInSingleUserMode: boolean;
|
||||||
|
createNewDatabase: boolean;
|
||||||
|
compareUsingTargetCollation: boolean;
|
||||||
|
commentOutSetVarDeclarations: boolean;
|
||||||
|
blockWhenDriftDetected: boolean;
|
||||||
|
blockOnPossibleDataLoss: boolean;
|
||||||
|
backupDatabaseBeforeChanges: boolean;
|
||||||
|
allowIncompatiblePlatform: boolean;
|
||||||
|
allowDropBlockingAssemblies: boolean;
|
||||||
|
dropConstraintsNotInSource: boolean;
|
||||||
|
dropDmlTriggersNotInSource: boolean;
|
||||||
|
dropExtendedPropertiesNotInSource: boolean;
|
||||||
|
dropIndexesNotInSource: boolean;
|
||||||
|
ignoreFileAndLogFilePath: boolean;
|
||||||
|
ignoreExtendedProperties: boolean;
|
||||||
|
ignoreDmlTriggerState: boolean;
|
||||||
|
ignoreDmlTriggerOrder: boolean;
|
||||||
|
ignoreDefaultSchema: boolean;
|
||||||
|
ignoreDdlTriggerState: boolean;
|
||||||
|
ignoreDdlTriggerOrder: boolean;
|
||||||
|
ignoreCryptographicProviderFilePath: boolean;
|
||||||
|
verifyDeployment: boolean;
|
||||||
|
ignoreComments: boolean;
|
||||||
|
ignoreColumnCollation: boolean;
|
||||||
|
ignoreAuthorizer: boolean;
|
||||||
|
ignoreAnsiNulls: boolean;
|
||||||
|
generateSmartDefaults: boolean;
|
||||||
|
dropStatisticsNotInSource: boolean;
|
||||||
|
dropRoleMembersNotInSource: boolean;
|
||||||
|
dropPermissionsNotInSource: boolean;
|
||||||
|
dropObjectsNotInSource: boolean;
|
||||||
|
ignoreColumnOrder: boolean;
|
||||||
|
doNotDropObjectTypes: SchemaObjectType[];
|
||||||
|
excludeObjectTypes: SchemaObjectType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Values from <DacFx>\Product\Source\DeploymentApi\ObjectTypes.cs
|
||||||
|
*/
|
||||||
|
export const enum SchemaObjectType {
|
||||||
|
Aggregates = 0,
|
||||||
|
ApplicationRoles = 1,
|
||||||
|
Assemblies = 2,
|
||||||
|
AssemblyFiles = 3,
|
||||||
|
AsymmetricKeys = 4,
|
||||||
|
BrokerPriorities = 5,
|
||||||
|
Certificates = 6,
|
||||||
|
ColumnEncryptionKeys = 7,
|
||||||
|
ColumnMasterKeys = 8,
|
||||||
|
Contracts = 9,
|
||||||
|
DatabaseOptions = 10,
|
||||||
|
DatabaseRoles = 11,
|
||||||
|
DatabaseTriggers = 12,
|
||||||
|
Defaults = 13,
|
||||||
|
ExtendedProperties = 14,
|
||||||
|
ExternalDataSources = 15,
|
||||||
|
ExternalFileFormats = 16,
|
||||||
|
ExternalTables = 17,
|
||||||
|
Filegroups = 18,
|
||||||
|
Files = 19,
|
||||||
|
FileTables = 20,
|
||||||
|
FullTextCatalogs = 21,
|
||||||
|
FullTextStoplists = 22,
|
||||||
|
MessageTypes = 23,
|
||||||
|
PartitionFunctions = 24,
|
||||||
|
PartitionSchemes = 25,
|
||||||
|
Permissions = 26,
|
||||||
|
Queues = 27,
|
||||||
|
RemoteServiceBindings = 28,
|
||||||
|
RoleMembership = 29,
|
||||||
|
Rules = 30,
|
||||||
|
ScalarValuedFunctions = 31,
|
||||||
|
SearchPropertyLists = 32,
|
||||||
|
SecurityPolicies = 33,
|
||||||
|
Sequences = 34,
|
||||||
|
Services = 35,
|
||||||
|
Signatures = 36,
|
||||||
|
StoredProcedures = 37,
|
||||||
|
SymmetricKeys = 38,
|
||||||
|
Synonyms = 39,
|
||||||
|
Tables = 40,
|
||||||
|
TableValuedFunctions = 41,
|
||||||
|
UserDefinedDataTypes = 42,
|
||||||
|
UserDefinedTableTypes = 43,
|
||||||
|
ClrUserDefinedTypes = 44,
|
||||||
|
Users = 45,
|
||||||
|
Views = 46,
|
||||||
|
XmlSchemaCollections = 47,
|
||||||
|
Audits = 48,
|
||||||
|
Credentials = 49,
|
||||||
|
CryptographicProviders = 50,
|
||||||
|
DatabaseAuditSpecifications = 51,
|
||||||
|
DatabaseEncryptionKeys = 52,
|
||||||
|
DatabaseScopedCredentials = 53,
|
||||||
|
Endpoints = 54,
|
||||||
|
ErrorMessages = 55,
|
||||||
|
EventNotifications = 56,
|
||||||
|
EventSessions = 57,
|
||||||
|
LinkedServerLogins = 58,
|
||||||
|
LinkedServers = 59,
|
||||||
|
Logins = 60,
|
||||||
|
MasterKeys = 61,
|
||||||
|
Routes = 62,
|
||||||
|
ServerAuditSpecifications = 63,
|
||||||
|
ServerRoleMembership = 64,
|
||||||
|
ServerRoles = 65,
|
||||||
|
ServerTriggers = 66,
|
||||||
|
ExternalStreams = 67,
|
||||||
|
ExternalStreamingJobs = 68
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ResultStatus from d.ts
|
||||||
|
*/
|
||||||
|
export interface ResultStatus {
|
||||||
|
success: boolean;
|
||||||
|
errorMessage: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DacFxResult extends ResultStatus {
|
||||||
|
operationId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerateDeployPlanResult extends DacFxResult {
|
||||||
|
report: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DacFxOptionsResult extends ResultStatus {
|
||||||
|
deploymentOptions: DeploymentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidateStreamingJobResult extends ResultStatus { }
|
||||||
|
|
||||||
|
export interface ExportParams {
|
||||||
|
databaseName: string;
|
||||||
|
packageFilePath: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImportParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExtractParams {
|
||||||
|
databaseName: string;
|
||||||
|
packageFilePath: string;
|
||||||
|
applicationName: string;
|
||||||
|
applicationVersion: string;
|
||||||
|
ownerUri: string;
|
||||||
|
extractTarget?: ExtractTarget;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeployParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
upgradeExisting: boolean;
|
||||||
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: DeploymentOptions;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerateDeployScriptParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
sqlCommandVariableValues?: Record<string, string>;
|
||||||
|
deploymentOptions?: DeploymentOptions;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GenerateDeployPlanParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
databaseName: string;
|
||||||
|
ownerUri: string;
|
||||||
|
taskExecutionMode: TaskExecutionMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetOptionsFromProfileParams {
|
||||||
|
profilePath: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ValidateStreamingJobParams {
|
||||||
|
packageFilePath: string;
|
||||||
|
createStreamingJobTsql: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user