Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Create Azure Function with SQL Binding more efficient and simple #19187

Merged
merged 16 commits into from
Apr 26, 2022
Merged
44 changes: 31 additions & 13 deletions extensions/sql-bindings/src/common/azureFunctionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,21 @@ export async function getHostFiles(): Promise<string[] | undefined> {

/**
* Gets the local.settings.json file path
* @param projectFile path of the azure function project
* @param projectFolder The path to the project the setting should be added to
* @returns the local.settings.json file path
*/
export async function getSettingsFile(projectFile: string): Promise<string | undefined> {
return path.join(path.dirname(projectFile), 'local.settings.json');
export async function getSettingsFile(projectFolder: string): Promise<string | undefined> {
return path.join(projectFolder, 'local.settings.json');
}

/**
* Retrieves the new function file once the file is created and the watcher disposable
* @param projectFile is the path to the project file
* New azure function file watcher and watcher disposable to be used to watch for changes to the azure function project
* @param projectFolder is the parent directory to the project file
* @returns the function file path once created and the watcher disposable
*/
export function waitForNewFunctionFile(projectFile: string): IFileFunctionObject {
export function waitForNewFunctionFile(projectFolder: string): IFileFunctionObject {
const watcher = vscode.workspace.createFileSystemWatcher((
path.dirname(projectFile), '**/*.cs'), false, true, true);
new vscode.RelativePattern(projectFolder, '**/*.cs')), false, true, true);
const filePromise = new Promise<string>((resolve, _) => {
watcher.onDidCreate((e) => {
resolve(e.fsPath);
Expand Down Expand Up @@ -243,12 +243,13 @@ export async function addNugetReferenceToProjectFile(selectedProjectFile: string
/**
* Adds the Sql Connection String to the local.settings.json
* @param connectionString of the SQL Server connection that was chosen by the user
* @param projectFile The path to the project the setting should be added to
* @param projectFolder The path to the project the setting should be added to
* @param settingName The name of the setting to add to the local.settings.json
*/
export async function addConnectionStringToConfig(connectionString: string, projectFile: string): Promise<void> {
const settingsFile = await getSettingsFile(projectFile);
export async function addConnectionStringToConfig(connectionString: string, projectFolder: string, settingName: string = constants.sqlConnectionStringSetting): Promise<void> {
const settingsFile = await getSettingsFile(projectFolder);
if (settingsFile) {
await setLocalAppSetting(path.dirname(settingsFile), constants.sqlConnectionStringSetting, connectionString);
await setLocalAppSetting(path.dirname(settingsFile), settingName, connectionString);
}
}

Expand Down Expand Up @@ -426,7 +427,6 @@ export async function promptAndUpdateConnectionStringSetting(projectUri: vscode.
continue;
}

// show the connection string methods (user input and connection profile options)
const listOfConnectionStringMethods = [constants.connectionProfile, constants.userConnectionString];
let selectedConnectionStringMethod: string | undefined;
let connectionString: string | undefined = '';
Expand Down Expand Up @@ -560,7 +560,7 @@ export async function promptConnectionStringPasswordAndUpdateConnectionString(co
// if user does not want to include password or user does not enter password, show warning message that they will have to enter it manually later in local.settings.json
void vscode.window.showWarningMessage(constants.userPasswordLater, constants.openFile, constants.closeButton).then(async (result) => {
if (result === constants.openFile) {
// open local.settings.json file
// open local.settings.json file (if it exists)
void vscode.commands.executeCommand(constants.vscodeOpenCommand, vscode.Uri.file(localSettingsPath));
}
});
Expand All @@ -575,3 +575,21 @@ export async function promptConnectionStringPasswordAndUpdateConnectionString(co
return undefined;
}
}

export async function promptSelectDatabase(connectionInfo: IConnectionInfo): Promise<string | undefined> {
const vscodeMssqlApi = await utils.getVscodeMssqlApi();

let connectionURI = await vscodeMssqlApi.connect(connectionInfo);
let listDatabases = await vscodeMssqlApi.listDatabases(connectionURI);
const selectedDatabase = (await vscode.window.showQuickPick(listDatabases, {
canPickMany: false,
title: constants.selectDatabase,
ignoreFocusOut: true
}));

if (!selectedDatabase) {
// User cancelled
return undefined;
}
return selectedDatabase;
}
1 change: 1 addition & 0 deletions extensions/sql-bindings/src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const timeoutProjectError = localize('timeoutProjectError', 'Timed out wa
export function errorNewAzureFunction(error: any): string { return localize('errorNewAzureFunction', 'Error creating new Azure Function: {0}', utils.getErrorMessage(error)); }
export const azureFunctionsExtensionNotInstalled = localize('azureFunctionsExtensionNotInstalled', 'Azure Functions extension must be installed in order to use this feature.');
export const azureFunctionsProjectMustBeOpened = localize('azureFunctionsProjectMustBeOpened', 'A C# Azure Functions project must be present in order to create a new Azure Function for this table.');
export const workspaceMustBeUsed = localize('workspaceMustBeUsed', 'The current folder is not a workspace folder. Please open a workspace folder and try again.');
export const needConnection = localize('needConnection', 'A connection is required to use Azure Function with SQL Binding');
export const selectDatabase = localize('selectDatabase', 'Select Database');
export const browseEllipsisWithIcon = `$(folder) ${localize('browseEllipsis', "Browse...")}`;
Expand Down
29 changes: 27 additions & 2 deletions extensions/sql-bindings/src/common/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ export enum TelemetryViews {
export enum TelemetryActions {
// Create Azure Function with Sql Binding from Table
startCreateAzureFunctionWithSqlBinding = 'startCreateAzureFunctionWithSqlBinding',
helpCreateAzureFunctionProject = 'helpCreateAzureFunctionProject',
learnMore = 'learnMore',
finishCreateAzureFunctionWithSqlBinding = 'finishCreateAzureFunctionWithSqlBinding',
exitCreateAzureFunctionQuickpick = 'exitCreateAzureFunctionQuickpick',

Expand All @@ -31,3 +29,30 @@ export enum TelemetryActions {
finishAddSqlBinding = 'finishAddSqlBinding',
exitSqlBindingsQuickpick = 'exitSqlBindingsQuickpick',
}

export enum CreateAzureFunctionStep {
getAzureFunctionProject = 'getAzureFunctionProject',
learnMore = 'learnMore',
helpCreateAzureFunctionProject = 'helpCreateAzureFunctionProject',
getSelectedFolder = 'getSelectedFolder',
getBindingType = 'getBindingType',
launchFromCommandPalette = 'launchFromCommandPalette',
launchFromTable = 'launchFromTable',
getConnectionProfile = 'getConnectionProfile',
getDatabase = 'getDatabase',
getObjectName = 'getObjectName',
getConnectionString = 'getConnectionString',
getAzureFunctionName = 'getAzureFunctionName',
getTemplateId = 'getTemplateId',
setAzureWebJobsStorage = 'setAzureWebJobsStorage',
getConnectionStringSettingName = 'getConnectionStringSettingName',
promptForIncludePassword = 'promptForIncludePassword',
}

export enum ExitReason {
cancelled = 'cancelled',
finishCreate = 'finishCreate',
timeout = 'timeout',
error = 'error',
exit = 'exit'
}
9 changes: 7 additions & 2 deletions extensions/sql-bindings/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,16 @@ export function timeoutPromise(errorMessage: string, ms: number = 10000): Promis
* Gets a unique file name
* Increment the file name by adding 1 to function name if the file already exists
* Undefined if the filename suffix count becomes greater than 1024
* @param folderPath selected project folder path
* @param fileName base filename to use
* @param folderPath selected project folder path
* @returns a promise with the unique file name, or undefined
*/
export async function getUniqueFileName(folderPath: string, fileName: string): Promise<string | undefined> {
export async function getUniqueFileName(fileName: string, folderPath?: string): Promise<string | undefined> {
if (!folderPath) {
// user is creating a brand new azure function project
return undefined;
}

let count: number = 0;
const maxCount: number = 1024;
let uniqueFileName = fileName;
Expand Down
Loading