import * as semver from 'semver' ; import { IActionContext } from 'vscode-azureextensionui' ; import { ext , TemplateSource } from '../extensionVariables' ; import { IBundleMetadata , IHostJsonV2 } from '../funcConfig/host' ; import { localize } from '../localize' ; import { IBindingTemplate } from '../templates/IBindingTemplate' ; import { IFunctionTemplate } from '../templates/IFunctionTemplate' ; import { feedUtils } from './feedUtils' ; import { nugetUtils } from './nugetUtils' ; export namespace bundleFeedUtils { export const defaultBundleId = 'Microsoft.Azure.Functions.ExtensionBundle' ; export const defaultVersionRange = '[1.*, 2.0.0)' ; interface IBundleFeed { defaultVersionRange : string ; bundleVersions : { [ bundleVersion ] : { templates : string ; } ; } ; templates : { v1 : { [ templateVersion ] : ITemplatesRelease ; } ; } ; } export interface ITemplatesRelease { functions : string ; bindings : string ; resources : string ; } export async function getLatestTemplateVersion ( context , bundleMetadata ) { bundleMetadata = bundleMetadata || { } ; const feed = await getBundleFeed ( context , bundleMetadata ) ; const validVersions = Object . keys ( feed . bundleVersions ) . filter ( ( v ) => ! ! semver . valid ( v ) ) ; const bundleVersion = nugetUtils . tryGetMaxInRange ( bundleMetadata . version || feed . defaultVersionRange , validVersions ) ; if ( ! bundleVersion ) { throw new Error ( localize ( 'failedToFindBundleVersion' , 'Failed to find bundle version satisfying range "{0}".' , bundleMetadata . version ) ) ; } else { return feed . bundleVersions [ bundleVersion ] . templates ; } } export async function getRelease ( context , bundleMetadata , templateVersion ) { const feed = await getBundleFeed ( context , bundleMetadata ) ; return feed . templates . v1 [ templateVersion ] ; } export function isBundleTemplate ( template ) { const bundleTemplateTypes = [ 'durable' , 'signalr' ] ; return ( ! template . isHttpTrigger && ! template . isTimerTrigger ) || bundleTemplateTypes . some ( t => isTemplateOfType ( template , t ) ) ; } export async function getLatestVersionRange ( context ) { const feed = await getBundleFeed ( context , undefined ) ; return feed . defaultVersionRange ; } export async function addDefaultBundle ( context , hostJson ) { let versionRange ; try { versionRange = await getLatestVersionRange ( context ) ; } catch { versionRange = defaultVersionRange ; } hostJson . extensionBundle = { id : defaultBundleId , version : versionRange } ; } function isTemplateOfType ( template , templateType ) { return ! ! template . id ?. toLowerCase ( ) . includes ( templateType . toLowerCase ( ) ) ; } async function getBundleFeed ( context , bundleMetadata ) { const bundleId = bundleMetadata && bundleMetadata . id || defaultBundleId ; const envVarUri = process . env . FUNCTIONS_EXTENSIONBUNDLE_SOURCE_URI ; let url ; const templateProvider = ext . templateProvider . get ( context ) ; if ( ! envVarUri && bundleId === defaultBundleId && templateProvider . templateSource !== TemplateSource . Staging ) { url = 'https://aka.ms/AA66i2x' ; } else { const suffix = templateProvider . templateSource === TemplateSource . Staging ? 'staging' : '' ; const baseUrl = envVarUri || `https://functionscdn${ suffix }.azureedge.net/public` ; url = `${ baseUrl }/ExtensionBundles/${ bundleId }/index-v2.json` ; } return feedUtils . getJsonFeed ( context , url ) ; } }