import * as extract from 'extract-zip' ; import * as fse from 'fs-extra' ; import * as path from 'path' ; import { IActionContext } from 'vscode-azureextensionui' ; import { ext } from '../../extensionVariables' ; import { FuncVersion } from '../../FuncVersion' ; import { bundleFeedUtils } from '../../utils/bundleFeedUtils' ; import { cliFeedUtils } from '../../utils/cliFeedUtils' ; import { getRandomHexString } from '../../utils/fs' ; import { requestUtils } from '../../utils/requestUtils' ; import { IBindingTemplate } from '../IBindingTemplate' ; import { IFunctionTemplate } from '../IFunctionTemplate' ; import { ITemplates } from '../ITemplates' ; import { TemplateProviderBase , TemplateType } from '../TemplateProviderBase' ; import { english , getScriptResourcesLanguage } from './getScriptResourcesLanguage' ; import { parseScriptTemplates } from './parseScriptTemplates' ; export class ScriptTemplateProvider extends TemplateProviderBase { public templateType : TemplateType = TemplateType . Script ; protected get backupSubpath ( ) : string { return path . join ( 'script' , this . version ) ; } protected _rawResources : object ; protected _rawTemplates : object [ ] ; protected _rawBindings : object ; private readonly _templatesKey : string = 'FunctionTemplates' ; private readonly _bindingsKey : string = 'FunctionTemplateConfig' ; private readonly _resourcesKey : string = 'FunctionTemplateResources' ; public async getCachedTemplates ( ) { const cachedResources = await this . getCachedValue ( this . _resourcesKey ) ; const cachedTemplates = await this . getCachedValue ( this . _templatesKey ) ; const cachedConfig = await this . getCachedValue ( this . _bindingsKey ) ; if ( cachedResources && cachedTemplates && cachedConfig ) { return parseScriptTemplates ( cachedResources , cachedTemplates , cachedConfig ) ; } else { return undefined ; } } public async getLatestTemplateVersion ( context ) { return await cliFeedUtils . getLatestVersion ( context , this . version ) ; } public async getLatestTemplates ( context , latestTemplateVersion ) { const templateRelease = await cliFeedUtils . getRelease ( context , latestTemplateVersion ) ; const templatesPath = path . join ( ext . context . globalStoragePath , 'script' , getRandomHexString ( ) ) ; try { const filePath = path . join ( templatesPath , 'templates.zip' ) ; await requestUtils . downloadFile ( context , templateRelease . templates , filePath ) ; await extract ( filePath , { dir : templatesPath } ) ; return await this . parseTemplates ( templatesPath ) ; } finally { if ( await fse . pathExists ( templatesPath ) ) { await fse . remove ( templatesPath ) ; } } } public async getBackupTemplates ( ) { return await this . parseTemplates ( this . getBackupPath ( ) ) ; } public async updateBackupTemplates ( ) { const paths = this . getTemplatePaths ( this . getBackupPath ( ) ) ; const fileData = [ [ paths . resources , this . _rawResources ] , [ paths . templates , this . _rawTemplates ] , [ paths . bindings , this . _rawBindings ] ] ; for ( const [ file , data ] of fileData ) { await fse . ensureFile ( file ) ; await fse . writeJSON ( file , data ) ; } } public async cacheTemplates ( ) { await this . updateCachedValue ( this . _templatesKey , this . _rawTemplates ) ; await this . updateCachedValue ( this . _bindingsKey , this . _rawBindings ) ; await this . updateCachedValue ( this . _resourcesKey , this . _rawResources ) ; } public async clearCachedTemplates ( ) { await this . deleteCachedValue ( this . _templatesKey ) ; await this . deleteCachedValue ( this . _bindingsKey ) ; await this . deleteCachedValue ( this . _resourcesKey ) ; } public includeTemplate ( template ) { return this . version === FuncVersion . v1 || ! bundleFeedUtils . isBundleTemplate ( template ) ; } protected async parseTemplates ( rootPath ) { const paths = this . getTemplatePaths ( rootPath ) ; this . _rawResources = < object > await fse . readJSON ( paths . resources ) ; this . _rawTemplates = < object [ ] > await fse . readJSON ( paths . templates ) ; this . _rawBindings = < object > await fse . readJSON ( paths . bindings ) ; return parseScriptTemplates ( this . _rawResources , this . _rawTemplates , this . _rawBindings ) ; } protected getResourcesLanguage ( ) { return this . resourcesLanguage || getScriptResourcesLanguage ( ) ; } private getTemplatePaths ( rootPath ) { const language = this . getResourcesLanguage ( ) ; const resources = path . join ( rootPath , 'resources' , `Resources${ language === english ? '' : '.' + language }.json` ) ; const templates = path . join ( rootPath , 'templates' , 'templates.json' ) ; const bindings = path . join ( rootPath , 'bindings' , 'bindings.json' ) ; return { resources , templates , bindings } ; } } interface ITemplatePaths { resources : string ; templates : string ; bindings : string ; }