import { WebSiteManagementModels } from '@azure/arm-appservice' ; import * as fse from 'fs-extra' ; import * as path from 'path' ; import { ThemeIcon } from 'vscode' ; import { AzExtTreeItem , GenericTreeItem , IActionContext } from 'vscode-azureextensionui' ; import { functionJsonFileName } from '../../constants' ; import { ParsedFunctionJson } from '../../funcConfig/function' ; import { runningFuncTaskMap } from '../../funcCoreTools/funcHostTask' ; import { localize } from '../../localize' ; import { nonNullProp } from '../../utils/nonNull' ; import { requestUtils } from '../../utils/requestUtils' ; import { telemetryUtils } from '../../utils/telemetryUtils' ; import { findFiles } from '../../utils/workspace' ; import { FunctionsTreeItemBase } from '../FunctionsTreeItemBase' ; import { LocalFunctionTreeItem } from './LocalFunctionTreeItem' ; import { LocalProjectTreeItem } from './LocalProjectTreeItem' ; export class LocalFunctionsTreeItem extends FunctionsTreeItemBase { public readonly parent : LocalProjectTreeItem ; public isReadOnly : boolean ; public constructor ( parent ) { super ( parent ) ; this . isReadOnly = ! ! this . parent . preCompiledProjectPath ; } public hasMoreChildrenImpl ( ) { return false ; } public async loadMoreChildrenImpl ( _clearCache , context ) { if ( this . parent . isIsolated ) { return await this . getChildrenForIsolatedProject ( context ) ; } else { const functions = await getFunctionFolders ( context , this . parent . effectiveProjectPath ) ; const children = await this . createTreeItemsWithErrorHandling ( functions , 'azFuncInvalidLocalFunction' , async ( func ) => { const functionJsonPath = path . join ( this . parent . effectiveProjectPath , func , functionJsonFileName ) ; const config = new ParsedFunctionJson ( await fse . readJSON ( functionJsonPath ) ) ; return LocalFunctionTreeItem . create ( context , this , func , config , functionJsonPath , undefined ) ; } , ( func ) => func ) ; if ( this . parent . preCompiledProjectPath ) { const ti = new GenericTreeItem ( this , { label : localize ( 'runBuildTask' , 'Run build task to update this list...' ) , iconPath : new ThemeIcon ( 'info' ) , commandId : 'workbench.action.tasks.build' , contextValue : 'runBuildTask' } ) ; ti . commandArgs = [ ] ; children . push ( ti ) ; } return children ; } } public compareChildrenImpl ( item1 , item2 ) { if ( item1 instanceof GenericTreeItem && ! ( item2 instanceof GenericTreeItem ) ) { return - 1 ; } else if ( ! ( item1 instanceof GenericTreeItem ) && item2 instanceof GenericTreeItem ) { return 1 ; } else { return super . compareChildrenImpl ( item1 , item2 ) ; } } /**
     * .NET Isolated projects don't have typical "function.json" files, so we'll have to ping localhost to get functions (only available if the project is running)
     */ private async getChildrenForIsolatedProject ( context ) { if ( runningFuncTaskMap . has ( this . parent . workspaceFolder ) ) { const hostRequest = await this . parent . getHostRequest ( context ) ; const functions = await requestUtils . sendRequestWithExtTimeout ( context , { url : `${ hostRequest . url }/admin/functions` , method : 'GET' , rejectUnauthorized : hostRequest . rejectUnauthorized } ) ; return await this . createTreeItemsWithErrorHandling ( < WebSiteManagementModels . FunctionEnvelope [ ] > functions . parsedBody , 'azFuncInvalidLocalFunction' , async ( func ) => { func = requestUtils . convertToAzureSdkObject ( func ) ; return LocalFunctionTreeItem . create ( context , this , nonNullProp ( func , 'name' ) , func . config , undefined , func ) ; } , func => func . name ) ; } else { const ti = new GenericTreeItem ( this , { label : localize ( 'startDebugging' , 'Start debugging to update this list...' ) , iconPath : new ThemeIcon ( 'info' ) , commandId : 'workbench.action.debug.start' , contextValue : 'startDebugging' } ) ; ti . commandArgs = [ ] ; return [ ti ] ; } } } export async function getFunctionFolders ( context , projectPath ) { return await telemetryUtils . runWithDurationTelemetry ( context , 'getFuncs' , async ( ) => { const funcJsonUris = await findFiles ( projectPath , `*/${ functionJsonFileName }` ) ; return funcJsonUris . map ( uri => path . basename ( path . dirname ( uri . fsPath ) ) ) ; } ) ; }