Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@ import { type Progress } from 'vscode';
import { setLocalAppSetting } from '../../../funcConfig/local.settings';
import { localize } from '../../../localize';
import { type IBindingSetting } from '../../../templates/IBindingTemplate';
import { nonNullProp } from '../../../utils/nonNull';
import { setBindingSetting } from '../../createFunction/IFunctionWizardContext';
import { type IBindingWizardContext } from '../IBindingWizardContext';
import { type ParsedInput } from '../../../templates/script/parseScriptTemplatesV2';
import { setBindingSetting, type IFunctionWizardContext } from '../../createFunction/IFunctionWizardContext';

export interface IConnection {
name: string;
connectionString: string;
}

export abstract class AzureConnectionCreateStepBase<T extends IBindingWizardContext> extends AzureWizardExecuteStep<T> {
export abstract class AzureConnectionCreateStepBase<T extends IFunctionWizardContext> extends AzureWizardExecuteStep<T> {
public priority: number = 200;

private readonly _setting: IBindingSetting;
private readonly _setting: IBindingSetting | ParsedInput;
private readonly _resourceType: string;

constructor(setting: IBindingSetting) {
constructor(setting: IBindingSetting | ParsedInput) {
super();
this._setting = setting;
this._resourceType = (setting as IBindingSetting).resourceType ?? (setting as ParsedInput).resource ?? '';
}

public abstract getConnection(context: T): Promise<IConnection>;
Expand All @@ -33,7 +34,7 @@ export abstract class AzureConnectionCreateStepBase<T extends IBindingWizardCont
progress.report({ message: localize('retrieving', 'Retrieving connection string...') });

const result: IConnection = await this.getConnection(context);
let appSettingKey: string = `${result.name}_${nonNullProp(this._setting, 'resourceType').toUpperCase()}`;
let appSettingKey: string = `${result.name}_${this._resourceType.toUpperCase()}`;
appSettingKey = appSettingKey.replace(/[^a-z0-9_\.]/gi, ''); // remove invalid chars
setBindingSetting(context, this._setting, appSettingKey);
await setLocalAppSetting(context, context.projectPath, appSettingKey, result.connectionString);
Expand Down
20 changes: 11 additions & 9 deletions src/commands/addBinding/settingSteps/BindingSettingStepBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@
import { AzureWizardPromptStep } from "@microsoft/vscode-azext-utils";
import { type BindingSettingValue } from "../../../funcConfig/function";
import { type IBindingSetting } from "../../../templates/IBindingTemplate";
import { getBindingSetting, setBindingSetting } from "../../createFunction/IFunctionWizardContext";
import { type IBindingWizardContext } from "../IBindingWizardContext";
import { type ParsedInput } from "../../../templates/script/parseScriptTemplatesV2";
import { getBindingSetting, setBindingSetting, type IFunctionWizardContext } from "../../createFunction/IFunctionWizardContext";

export abstract class BindingSettingStepBase extends AzureWizardPromptStep<IBindingWizardContext> {
protected readonly _setting: IBindingSetting;
export abstract class BindingSettingStepBase extends AzureWizardPromptStep<IFunctionWizardContext> {
protected readonly _setting: IBindingSetting | ParsedInput;
protected readonly _resourceType: string;

constructor(setting: IBindingSetting) {
constructor(setting: IBindingSetting | ParsedInput) {
super();
this._setting = setting;
this.id = setting.name;
this._resourceType = (setting as IBindingSetting).resourceType ?? (setting as ParsedInput).resource ?? '';
}

public abstract promptCore(context: IBindingWizardContext): Promise<BindingSettingValue>;
public abstract promptCore(context: IFunctionWizardContext): Promise<BindingSettingValue>;

public async prompt(context: IBindingWizardContext): Promise<void> {
setBindingSetting(context, this._setting, await this.promptCore(context));
public async prompt(context: IFunctionWizardContext): Promise<void> {
setBindingSetting(context, this._setting as IBindingSetting, await this.promptCore(context));
}

public shouldPrompt(context: IBindingWizardContext): boolean {
public shouldPrompt(context: IFunctionWizardContext): boolean {
return !getBindingSetting(context, this._setting);
}
}
3 changes: 2 additions & 1 deletion src/commands/addBinding/settingSteps/BooleanPromptStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { type IAzureQuickPickItem } from "@microsoft/vscode-azext-utils";
import { type BindingSettingValue } from "../../../funcConfig/function";
import { type IBindingSetting } from "../../../templates/IBindingTemplate";
import { envUtils } from "../../../utils/envUtils";
import { type IBindingWizardContext } from "../IBindingWizardContext";
import { BindingSettingStepBase } from "./BindingSettingStepBase";
Expand All @@ -18,6 +19,6 @@ export class BooleanPromptStep extends BindingSettingStepBase {
picks = picks.reverse();
}

return (await context.ui.showQuickPick(picks, { placeHolder: this._setting.description || this._setting.label })).data;
return (await context.ui.showQuickPick(picks, { placeHolder: (this._setting as IBindingSetting).description || this._setting.label })).data;
}
}
3 changes: 2 additions & 1 deletion src/commands/addBinding/settingSteps/EnumPromptStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@

import { type IAzureQuickPickItem } from "@microsoft/vscode-azext-utils";
import { type BindingSettingValue } from "../../../funcConfig/function";
import { type IBindingSetting } from "../../../templates/IBindingTemplate";
import { type IBindingWizardContext } from "../IBindingWizardContext";
import { BindingSettingStepBase } from "./BindingSettingStepBase";

export class EnumPromptStep extends BindingSettingStepBase {
public async promptCore(context: IBindingWizardContext): Promise<BindingSettingValue> {
const picks: IAzureQuickPickItem<string>[] = this._setting.enums.map(e => { return { data: e.value, label: e.displayName }; });
const picks: IAzureQuickPickItem<string>[] = (this._setting as IBindingSetting).enums.map(e => { return { data: e.value, label: e.displayName }; });
return (await context.ui.showQuickPick(picks, { placeHolder: this._setting.label })).data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ import { localSettingsFileName } from '../../../constants';
import { setLocalAppSetting } from '../../../funcConfig/local.settings';
import { localize } from '../../../localize';
import { type IBindingSetting } from '../../../templates/IBindingTemplate';
import { type ParsedInput } from '../../../templates/script/parseScriptTemplatesV2';
import { nonNullProp, nonNullValue } from '../../../utils/nonNull';
import { getBindingSetting } from '../../createFunction/IFunctionWizardContext';
import { getBindingSetting, setBindingSetting } from '../../createFunction/IFunctionWizardContext';
import { type IBindingWizardContext } from '../IBindingWizardContext';

export class LocalAppSettingCreateStep extends AzureWizardExecuteStep<IBindingWizardContext> {
public priority: number = 210;

private readonly _setting: IBindingSetting;
private readonly _setting: IBindingSetting | ParsedInput;
private readonly _valueKey: string;

constructor(setting: IBindingSetting, valueKey: string) {
constructor(setting: IBindingSetting | ParsedInput, valueKey: string) {
super();
this._setting = setting;
this._valueKey = valueKey;
Expand All @@ -29,6 +30,10 @@ export class LocalAppSettingCreateStep extends AzureWizardExecuteStep<IBindingWi
progress.report({ message: localize('updatingLocalSettings', 'Updating {0}...', localSettingsFileName) });
const appSettingName = String(nonNullValue(getBindingSetting(context, this._setting), this._setting.name));
await setLocalAppSetting(context, context.projectPath, appSettingName, nonNullProp(context, this._valueKey as keyof IBindingWizardContext) as string);
// if the binding isn't already set then a new one was created
if (!getBindingSetting(context, this._setting)) {
setBindingSetting(context, this._setting, nonNullProp(context, this._valueKey as keyof IBindingWizardContext) as string);
}
}

public shouldExecute(context: IBindingWizardContext): boolean {
Expand Down
18 changes: 10 additions & 8 deletions src/commands/addBinding/settingSteps/LocalAppSettingListStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import { getLocalSettingsJson, type ILocalSettingsJson } from '../../../funcConf
import { localize } from '../../../localize';
import { ResourceType } from '../../../templates/IBindingTemplate';
import { type IEventHubsConnectionWizardContext } from '../../appSettings/connectionSettings/eventHubs/IEventHubsConnectionWizardContext';
import { getBindingSetting } from '../../createFunction/IFunctionWizardContext';
import { getBindingSetting, type FunctionV2WizardContext, type IFunctionWizardContext } from '../../createFunction/IFunctionWizardContext';
import { EventHubsNamespaceListStep } from '../../createFunction/durableSteps/netherite/EventHubsNamespaceListStep';
import { type IBindingWizardContext } from '../IBindingWizardContext';
import { BindingSettingStepBase } from './BindingSettingStepBase';
import { LocalAppSettingCreateStep } from './LocalAppSettingCreateStep';
import { LocalAppSettingNameStep } from './LocalAppSettingNameStep';
Expand All @@ -33,7 +32,7 @@ const showHiddenValuesItem = { label: localize('showHiddenValues', '$(eye) Show
const hideHiddenValuesItem = { label: localize('hideHiddenValues', '$(eye-closed) Hide hidden values'), data: 'hiddenValues' }
export class LocalAppSettingListStep extends BindingSettingStepBase {
private _showHiddenValues: boolean = false;
public async promptCore(context: IBindingWizardContext): Promise<BindingSettingValue> {
public async promptCore(context: IFunctionWizardContext): Promise<BindingSettingValue> {
const localSettingsPath: string = path.join(context.projectPath, localSettingsFileName);
const settings: ILocalSettingsJson = await getLocalSettingsJson(context, localSettingsPath);
const existingSettings: [string, string][] = settings.Values ? Object.entries(settings.Values) : [];
Expand All @@ -43,7 +42,10 @@ export class LocalAppSettingListStep extends BindingSettingStepBase {
do {
let picks: IAzureQuickPickItem<string | undefined>[] = [{ label: localize('newAppSetting', '$(plus) Create new local app setting'), data: undefined }];
picks = picks.concat(existingSettings.map((s: [string, string]) => { return { data: s[0], label: s[0], description: this._showHiddenValues ? s[1] : '******' }; }));
picks.push(this._showHiddenValues ? hideHiddenValuesItem : showHiddenValuesItem);
if (picks.length > 1) {
// don't add hidden values item if there are no existing settings
picks.push(this._showHiddenValues ? hideHiddenValuesItem : showHiddenValuesItem);
}
result = (await context.ui.showQuickPick(picks, { placeHolder })).data;
if (result === 'hiddenValues') {
this._showHiddenValues = !this._showHiddenValues;
Expand All @@ -54,11 +56,11 @@ export class LocalAppSettingListStep extends BindingSettingStepBase {
} while (true);
}

public async getSubWizard(context: IBindingWizardContext): Promise<IWizardOptions<IBindingWizardContext> | undefined> {
public async getSubWizard(context: IFunctionWizardContext): Promise<IWizardOptions<IFunctionWizardContext & FunctionV2WizardContext> | undefined> {
if (!getBindingSetting(context, this._setting)) {
const azurePromptSteps: AzureWizardPromptStep<IBindingWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
const azureExecuteSteps: AzureWizardExecuteStep<IBindingWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
switch (this._setting.resourceType) {
const azurePromptSteps: AzureWizardPromptStep<IFunctionWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
const azureExecuteSteps: AzureWizardExecuteStep<IFunctionWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
switch (this._resourceType) {
case ResourceType.DocumentDB:
azurePromptSteps.push(new CosmosDBListStep());
azureExecuteSteps.push(new CosmosDBConnectionCreateStep(this._setting));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@

import { type BindingSettingValue } from '../../../funcConfig/function';
import { localize } from '../../../localize';
import { nonNullProp } from '../../../utils/nonNull';
import { type IBindingWizardContext } from '../IBindingWizardContext';
import { BindingSettingStepBase } from './BindingSettingStepBase';

export class LocalAppSettingNameStep extends BindingSettingStepBase {
public async promptCore(context: IBindingWizardContext): Promise<BindingSettingValue> {
const appSettingSuffix: string = `_${nonNullProp(this._setting, 'resourceType').toUpperCase()}`;
const appSettingSuffix: string = `_${this._resourceType.toUpperCase()}`;
return await context.ui.showInputBox({
placeHolder: localize('appSettingKeyPlaceholder', 'Local app setting key'),
prompt: localize('appSettingKeyPrompt', 'Provide a key for a connection string'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

import { type IStorageAccountWizardContext } from '@microsoft/vscode-azext-azureutils';
import { getStorageConnectionString } from '../../appSettings/connectionSettings/getLocalConnectionSetting';
import { type IBindingWizardContext } from '../IBindingWizardContext';
import { type IFunctionWizardContext } from '../../createFunction/IFunctionWizardContext';
import { AzureConnectionCreateStepBase, type IConnection } from './AzureConnectionCreateStepBase';

export class StorageConnectionCreateStep extends AzureConnectionCreateStepBase<IStorageAccountWizardContext & IBindingWizardContext> {
public async getConnection(context: IStorageAccountWizardContext & Partial<IBindingWizardContext>): Promise<IConnection> {
export class StorageConnectionCreateStep extends AzureConnectionCreateStepBase<IStorageAccountWizardContext & IFunctionWizardContext> {
public async getConnection(context: IStorageAccountWizardContext & IFunctionWizardContext): Promise<IConnection> {
return await getStorageConnectionString(context);
}

public shouldExecute(context: IStorageAccountWizardContext & Partial<IBindingWizardContext>): boolean {
public shouldExecute(context: IStorageAccountWizardContext & IFunctionWizardContext): boolean {
return !!context.storageAccount || !!context.useStorageEmulator;
}
}
19 changes: 10 additions & 9 deletions src/commands/addBinding/settingSteps/StorageTypePromptStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import { StorageAccountKind, StorageAccountListStep, StorageAccountPerformance,
import { AzureWizardPromptStep, type AzureWizardExecuteStep, type IAzureQuickPickItem, type ISubscriptionActionContext, type IWizardOptions } from "@microsoft/vscode-azext-utils";
import { localize } from "../../../localize";
import { type IBindingSetting } from "../../../templates/IBindingTemplate";
import { type ParsedInput } from "../../../templates/script/parseScriptTemplatesV2";
import { type IEventHubsConnectionWizardContext } from "../../appSettings/connectionSettings/eventHubs/IEventHubsConnectionWizardContext";
import { type IBindingWizardContext } from "../IBindingWizardContext";
import { type IFunctionWizardContext } from "../../createFunction/IFunctionWizardContext";
import { StorageConnectionCreateStep } from "./StorageConnectionCreateStep";

export class StorageTypePromptStep extends AzureWizardPromptStep<IBindingWizardContext> {
private readonly _setting: IBindingSetting;
export class StorageTypePromptStep extends AzureWizardPromptStep<IFunctionWizardContext> {
private readonly _setting: IBindingSetting | ParsedInput;

constructor(setting: IBindingSetting) {
constructor(setting: IBindingSetting | ParsedInput) {
super();
this._setting = setting;
}

public async prompt(context: IBindingWizardContext): Promise<void> {
public async prompt(context: IFunctionWizardContext): Promise<void> {
const picks: IAzureQuickPickItem<boolean>[] = [
{ label: localize('useAzurite', 'Use Azurite emulator for local storage'), data: true },
{ label: localize('useAzureStorage', 'Use Azure Storage for remote storage'), data: false }
Expand All @@ -29,13 +30,13 @@ export class StorageTypePromptStep extends AzureWizardPromptStep<IBindingWizardC
return;
}

public shouldPrompt(context: IBindingWizardContext): boolean {
public shouldPrompt(context: IFunctionWizardContext): boolean {
return context.useStorageEmulator === undefined;
}

public async getSubWizard(context: IBindingWizardContext): Promise<IWizardOptions<IBindingWizardContext> | undefined> {
const promptSteps: AzureWizardPromptStep<IBindingWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
const executeSteps: AzureWizardExecuteStep<IBindingWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
public async getSubWizard(context: IFunctionWizardContext): Promise<IWizardOptions<IFunctionWizardContext> | undefined> {
const promptSteps: AzureWizardPromptStep<IFunctionWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];
const executeSteps: AzureWizardExecuteStep<IFunctionWizardContext & ISubscriptionActionContext & IEventHubsConnectionWizardContext>[] = [];

if (!context.useStorageEmulator) {
promptSteps.push(new StorageAccountListStep(
Expand Down
6 changes: 4 additions & 2 deletions src/commands/addBinding/settingSteps/StringPromptStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

import { type BindingSettingValue } from "../../../funcConfig/function";
import { localize } from "../../../localize";
import { type IBindingSetting } from "../../../templates/IBindingTemplate";
import { type IBindingWizardContext } from "../IBindingWizardContext";
import { BindingSettingStepBase } from "./BindingSettingStepBase";

// not used by v2 schema so assume IBindingSetting
export class StringPromptStep extends BindingSettingStepBase {
public async promptCore(context: IBindingWizardContext): Promise<BindingSettingValue> {
return await context.ui.showInputBox({
placeHolder: this._setting.label,
prompt: this._setting.description || localize('stringSettingPrompt', 'Provide a \'{0}\'', this._setting.label),
prompt: (this._setting as IBindingSetting).description || localize('stringSettingPrompt', 'Provide a \'{0}\'', this._setting.label),
validateInput: async (s): Promise<string | undefined> => await this.validateInput(context, s),
value: await this.getDefaultValue(context)
});
Expand All @@ -25,6 +27,6 @@ export class StringPromptStep extends BindingSettingStepBase {

// eslint-disable-next-line @typescript-eslint/require-await
public async validateInput(_wizardContext: IBindingWizardContext, val: string | undefined): Promise<string | undefined> {
return this._setting.validateSetting(val);
return (this._setting as IBindingSetting).validateSetting(val);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { type CosmosDBManagementClient, type DatabaseAccountGetResults, type Dat
import { getResourceGroupFromId } from '@microsoft/vscode-azext-azureutils';
import { createCosmosDBClient } from '../../../../utils/azureClients';
import { nonNullProp } from '../../../../utils/nonNull';
import { type IBindingWizardContext } from '../../IBindingWizardContext';
import { type IFunctionWizardContext } from '../../../createFunction/IFunctionWizardContext';
import { AzureConnectionCreateStepBase, type IConnection } from '../AzureConnectionCreateStepBase';
import { type ICosmosDBWizardContext } from './ICosmosDBWizardContext';

export class CosmosDBConnectionCreateStep extends AzureConnectionCreateStepBase<IBindingWizardContext & ICosmosDBWizardContext> {
export class CosmosDBConnectionCreateStep extends AzureConnectionCreateStepBase<IFunctionWizardContext & ICosmosDBWizardContext> {
public async getConnection(context: ICosmosDBWizardContext): Promise<IConnection> {
const databaseAccount: DatabaseAccountGetResults = nonNullProp(context, 'databaseAccount');
const name: string = nonNullProp(databaseAccount, 'name');
Expand Down
Loading