/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; import type * as azdataType from 'azdata'; // eslint-disable-line no-duplicate-imports import * as vscode from 'vscode'; import * as mssql from 'mssql'; import * as os from 'os'; import * as loc from './localizedConstants'; import * as dataworkspace from 'dataworkspace'; import { promises as fs } from 'fs'; export interface IPackageInfo { name: string; version: string; aiKey: string; } export function getPackageInfo(packageJson: any): IPackageInfo { if (packageJson) { return { name: packageJson.name, version: packageJson.version, aiKey: packageJson.aiKey }; } } /** * Map an error message into a short name for the type of error. * @param msg The error message to map */ export function getTelemetryErrorType(msg: string): string { if (msg && msg.indexOf('Object reference not set to an instance of an object') !== -1) { return 'ObjectReferenceNotSet'; } else { return 'Other'; } } export function getSchemaCompareEndpointString(endpointType: mssql.SchemaCompareEndpointType): string { switch (endpointType) { case mssql.SchemaCompareEndpointType.Database: return 'Database'; case mssql.SchemaCompareEndpointType.Dacpac: return 'Dacpac'; case mssql.SchemaCompareEndpointType.Project: return 'Project'; default: return `Unknown: ${endpointType}`; } } /** * Return the appropriate endpoint name depending on if the endpoint is a dacpac or a database * @param endpoint endpoint to get the name of */ export function getEndpointName(endpoint: mssql.SchemaCompareEndpointInfo): string { if (!endpoint) { return ' '; } if (endpoint.endpointType === mssql.SchemaCompareEndpointType.Database) { if (!endpoint.serverName && endpoint.connectionDetails) { endpoint.serverName = endpoint.connectionDetails['serverName']; } if (!endpoint.databaseName && endpoint.connectionDetails) { endpoint.databaseName = endpoint.connectionDetails['databaseName']; } if (endpoint.connectionName && endpoint.databaseName) { return `${endpoint.connectionName}.${endpoint.databaseName}`; } if (endpoint.serverName && endpoint.databaseName) { return `${endpoint.serverName}.${endpoint.databaseName}`; } else { return ' '; } } else if (endpoint.endpointType === mssql.SchemaCompareEndpointType.Dacpac) { return endpoint.packageFilePath; } else { return endpoint.projectFilePath; } } function connectionInfoToConnectionProfile(details: azdata.ConnectionInfo): azdata.IConnectionProfile { return { serverName: details['serverName'], databaseName: details['databaseName'], authenticationType: details['authenticationType'], providerName: 'MSSQL', connectionName: '', userName: details['userName'], password: details['password'], savePassword: false, groupFullName: undefined, saveProfile: true, id: undefined, groupId: undefined, options: details['options'] }; } export async function verifyConnectionAndGetOwnerUri(endpoint: mssql.SchemaCompareEndpointInfo, caller: string): Promise { let ownerUri = undefined; if (endpoint.endpointType === mssql.SchemaCompareEndpointType.Database && endpoint.connectionDetails) { let connectionProfile = connectionInfoToConnectionProfile(endpoint.connectionDetails); let connection = await azdata.connection.connect(connectionProfile, false, false); if (connection) { ownerUri = await azdata.connection.getUriForConnection(connection.connectionId); if (!ownerUri) { let connectionList = await azdata.connection.getConnections(true); let userConnection; userConnection = connectionList.find(connection => (endpoint.connectionDetails['authenticationType'] === azdata.connection.AuthenticationType.SqlLogin && endpoint.connectionDetails['serverName'] === connection.options.server && endpoint.connectionDetails['userName'] === connection.options.user && (endpoint.connectionDetails['databaseName'].toLowerCase() === connection.options.database.toLowerCase() || connection.options.database.toLowerCase() === 'master'))); if (userConnection === undefined) { const getConnectionString = loc.getConnectionString(caller); // need only yes button - since the modal dialog has a default cancel let result = await vscode.window.showWarningMessage(getConnectionString, { modal: true }, loc.YesButtonText); if (result === loc.YesButtonText) { userConnection = await azdata.connection.openConnectionDialog(undefined, connectionProfile); } } if (userConnection !== undefined) { ownerUri = await azdata.connection.getUriForConnection(userConnection.connectionId); } } if (!ownerUri && connection.errorMessage) { vscode.window.showErrorMessage(connection.errorMessage); } } } return ownerUri; } /** * Returns the folder open in Explorer if there is one, otherwise returns the home directory */ export function getRootPath(): string { return vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : os.homedir(); } export async function exists(path: string): Promise { try { await fs.access(path); return true; } catch (e) { return false; } } // Try to load the azdata API - but gracefully handle the failure in case we're running // in a context where the API doesn't exist (such as VS Code) let azdataApi: typeof azdataType | undefined = undefined; try { azdataApi = require('azdata'); if (!azdataApi?.version) { // webpacking makes the require return an empty object instead of throwing an error so make sure we clear the var azdataApi = undefined; } } catch { // no-op } /** * Gets the azdata API if it's available in the context this extension is running in. * @returns The azdata API if it's available */ export function getAzdataApi(): typeof azdataType | undefined { return azdataApi; } export function getDataWorkspaceExtensionApi(): dataworkspace.IExtension { const extension = vscode.extensions.getExtension(dataworkspace.extension.name)!; return extension.exports; }