Skip to content

Commit

Permalink
Add local settings node under local project in workspace view (#4367)
Browse files Browse the repository at this point in the history
* add local settings node

* change

* update appsettings package
  • Loading branch information
motm32 authored Jan 31, 2025
1 parent 4e3d5d0 commit 5089ef7
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 9 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@
"@azure/core-rest-pipeline": "^1.11.0",
"@azure/storage-blob": "^12.5.0",
"@microsoft/vscode-azext-azureappservice": "^3.3.1",
"@microsoft/vscode-azext-azureappsettings": "^0.2.1",
"@microsoft/vscode-azext-azureappsettings": "^0.2.2",
"@microsoft/vscode-azext-azureutils": "^3.1.3",
"@microsoft/vscode-azext-serviceconnector": "^0.1.3",
"@microsoft/vscode-azext-utils": "^2.5.7",
Expand Down
64 changes: 64 additions & 0 deletions src/commands/appSettings/localSettings/LocalSettingsClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type StringDictionary } from "@azure/arm-appservice";
import { type AppSettingsClientProvider, type IAppSettingsClient } from "@microsoft/vscode-azext-azureappsettings";
import { AzExtFsExtra, callWithTelemetryAndErrorHandling, type IActionContext } from "@microsoft/vscode-azext-utils";
import * as vscode from 'vscode';
import { type ILocalSettingsJson } from "../../../funcConfig/local.settings";
import { type LocalProjectTreeItem } from "../../../tree/localProject/LocalProjectTreeItem";
import { decryptLocalSettings } from "./decryptLocalSettings";
import { encryptLocalSettings } from "./encryptLocalSettings";
import { getLocalSettingsFileNoPrompt } from "./getLocalSettingsFile";

export class LocalSettingsClientProvider implements AppSettingsClientProvider {
private _node: LocalProjectTreeItem;
constructor(node: LocalProjectTreeItem) {
this._node = node;
}

public async createClient(): Promise<IAppSettingsClient> {
return new LocalSettingsClient(this._node);
}
}

export class LocalSettingsClient implements IAppSettingsClient {
public fullName: string;
public isLinux: boolean;
private _node: LocalProjectTreeItem;

constructor(node: LocalProjectTreeItem) {
this.isLinux = false;
this.fullName = 'local';
this._node = node;
}

public async listApplicationSettings(): Promise<StringDictionary> {
const result = await callWithTelemetryAndErrorHandling<StringDictionary | undefined>('listApplicationSettings', async (context: IActionContext) => {
const localSettingsPath: string | undefined = await getLocalSettingsFileNoPrompt(context, this._node.workspaceFolder);
if (localSettingsPath === undefined) {
return { properties: {} };
} else {
const localSettingsUri: vscode.Uri = vscode.Uri.file(localSettingsPath);

let localSettings: ILocalSettingsJson = <ILocalSettingsJson>await AzExtFsExtra.readJSON(localSettingsPath);
if (localSettings.IsEncrypted) {
await decryptLocalSettings(context, localSettingsUri);
try {
localSettings = await AzExtFsExtra.readJSON<ILocalSettingsJson>(localSettingsPath);
} finally {
await encryptLocalSettings(context, localSettingsUri);
}
}
return { properties: localSettings.Values };
}
});
return result ?? { properties: {} };
}

public async updateApplicationSettings(): Promise<StringDictionary> {
throw new Error('Method not implemented.');
}
}
17 changes: 14 additions & 3 deletions src/commands/appSettings/localSettings/getLocalSettingsFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { AzExtFsExtra, type IActionContext } from '@microsoft/vscode-azext-utils';
import * as path from 'path';
import { type WorkspaceFolder } from "vscode";
import type * as vscode from 'vscode';
import { localSettingsFileName } from '../../../constants';
import { getRootWorkspaceFolder, selectWorkspaceFile } from '../../../utils/workspace';
import { tryGetFunctionProjectRoot } from '../../createNewProject/verifyIsProject';
Expand All @@ -14,7 +14,7 @@ import { tryGetFunctionProjectRoot } from '../../createNewProject/verifyIsProjec
* If only one project is open and the default local settings file exists, return that.
* Otherwise, prompt
*/
export async function getLocalSettingsFile(context: IActionContext, message: string, workspaceFolder?: WorkspaceFolder): Promise<string> {
export async function getLocalSettingsFile(context: IActionContext, message: string, workspaceFolder?: vscode.WorkspaceFolder): Promise<string> {
workspaceFolder ||= await getRootWorkspaceFolder();
if (workspaceFolder) {
const projectPath: string | undefined = await tryGetFunctionProjectRoot(context, workspaceFolder);
Expand All @@ -26,8 +26,19 @@ export async function getLocalSettingsFile(context: IActionContext, message: str
}
}

return await selectWorkspaceFile(context, message, async (f: WorkspaceFolder): Promise<string> => {
return await selectWorkspaceFile(context, message, async (f: vscode.WorkspaceFolder): Promise<string> => {
const projectPath: string = await tryGetFunctionProjectRoot(context, f) || f.uri.fsPath;
return path.relative(f.uri.fsPath, path.join(projectPath, localSettingsFileName));
});
}

export async function getLocalSettingsFileNoPrompt(context: IActionContext, workspaceFolder: vscode.WorkspaceFolder): Promise<string | undefined> {
const projectPath: string | undefined = await tryGetFunctionProjectRoot(context, workspaceFolder);
if (projectPath) {
const localSettingsFile: string = path.join(projectPath, localSettingsFileName);
if (await AzExtFsExtra.pathExists(localSettingsFile)) {
return localSettingsFile;
}
}
return undefined;
}
9 changes: 8 additions & 1 deletion src/tree/localProject/LocalProjectTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { AppSettingsTreeItem } from '@microsoft/vscode-azext-azureappsettings';
import { callWithTelemetryAndErrorHandling, type AzExtParentTreeItem, type AzExtTreeItem, type IActionContext } from '@microsoft/vscode-azext-utils';
import * as path from 'path';
import { Disposable, type TaskScope, type WorkspaceFolder } from 'vscode';
import { type FuncVersion } from '../../FuncVersion';
import { LocalSettingsClientProvider } from '../../commands/appSettings/localSettings/LocalSettingsClient';
import { onDotnetFuncTaskReady } from '../../commands/pickFuncProcess';
import { functionJsonFileName, localSettingsFileName, type ProjectLanguage } from '../../constants';
import { ext } from '../../extensionVariables';
import { type IParsedHostJson } from '../../funcConfig/host';
import { onFuncTaskStarted } from '../../funcCoreTools/funcHostTask';
import { type LocalProjectInternal } from '../../workspace/listLocalProjects';
Expand All @@ -35,6 +38,7 @@ export class LocalProjectTreeItem extends LocalProjectTreeItemBase implements Di

private readonly _disposables: Disposable[] = [];
private readonly _localFunctionsTreeItem: LocalFunctionsTreeItem;
private readonly _localSettingsTreeItem: AppSettingsTreeItem;

public constructor(parent: AzExtParentTreeItem, localProject: LocalProjectInternal) {
const options = localProject.options;
Expand All @@ -56,6 +60,9 @@ export class LocalProjectTreeItem extends LocalProjectTreeItemBase implements Di
this._disposables.push(onDotnetFuncTaskReady(async scope => this.onFuncTaskChanged(scope)));

this._localFunctionsTreeItem = new LocalFunctionsTreeItem(this);
this._localSettingsTreeItem = new AppSettingsTreeItem(this, new LocalSettingsClientProvider(this), ext.prefix, {
contextValuesToAdd: ['localSettings']
});
}

public async getHostRequest(context: IActionContext): Promise<FuncHostRequest> {
Expand All @@ -72,7 +79,7 @@ export class LocalProjectTreeItem extends LocalProjectTreeItemBase implements Di

// eslint-disable-next-line @typescript-eslint/require-await
public async loadMoreChildrenImpl(_clearCache: boolean): Promise<AzExtTreeItem[]> {
return [this._localFunctionsTreeItem];
return [this._localFunctionsTreeItem, this._localSettingsTreeItem];
}

public isAncestorOfImpl(contextValue: string | RegExp): boolean {
Expand Down

0 comments on commit 5089ef7

Please sign in to comment.