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

* initial refactor

* fix projectFolder cases

* update create azure function with sql binding when no folder is opened

* corner case exit browse file

* add version since targetFramework is set to specific core tools version

* update telemetry and address comments

* use project folder instead
This commit is contained in:
Vasu Bhog
2022-04-26 13:12:10 -07:00
committed by GitHub
parent c4d0754954
commit c86085352e
7 changed files with 280 additions and 266 deletions

View File

@@ -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);
@@ -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);
}
}
@@ -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 = '';
@@ -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));
}
});
@@ -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;
}

View File

@@ -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...")}`;

View File

@@ -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',
@@ -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'
}

View File

@@ -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;