module twilio-labs import debug from 'debug' ; import FormData from 'form-data' ; import { FunctionApiResource , FunctionList , FunctionResource , ServerlessResourceConfig , Sid , VersionResource , ClientConfig , FunctionContent , FunctionVersion , } from '../types' ; import { TwilioServerlessApiClient } from '../client' ; import { getContentType } from '../utils/content-type' ; import { ClientApiError } from '../utils/error' ; import { getApiUrl } from './utils/api-client' ; import { getPaginatedResource } from './utils/pagination' ; const log = debug ( 'twilio-serverless-api:functions' ) ; param { string } name param { string } serviceSid param { TwilioServerlessApiClient } client returns { Promise < FunctionApiResource > } export async function createFunctionResource ( name , serviceSid , client ) { try { const resp = await client . request ( 'post' , `Services/${ serviceSid }/Functions` , { form : { FriendlyName : name , } , } ) ; return ( resp . body as unknown ) as FunctionApiResource ; } catch ( err ) { log ( '%O' , new ClientApiError ( err ) ) ; throw new Error ( `Failed to create "${ name }" function` ) ; } } export param { string } serviceSid param { TwilioServerlessApiClient } client returns export async function listFunctionResources ( serviceSid , client ) { try { return getPaginatedResource < FunctionList , FunctionApiResource > ( client , `Services/${ serviceSid }/Functions` ) ; } catch ( err ) { log ( '%O' , new ClientApiError ( err ) ) ; throw err ; } } export param { FileInfo [ ] } functions param { string } serviceSid param { TwilioServerlessApiClient } client returns { Promise < FunctionResource [ ] > } export async function getOrCreateFunctionResources ( functions , serviceSid , client ) { const output = [ ] ; const existingFunctions = await listFunctionResources ( serviceSid , client ) ; const functionsToCreate = [ ] ; functions . forEach ( ( fn ) => { const existingFn = existingFunctions . find ( ( f ) => fn . name === f . friendly_name ) ; if ( ! existingFn ) { functionsToCreate . push ( { ... fn } ) ; } else { output . push ( { ... fn , sid : existingFn . sid , } ) ; } } ) ; const createdFunctions = await Promise . all ( functionsToCreate . map ( async ( fn ) => { const newFunction = await createFunctionResource ( fn . name , serviceSid , client ) ; return { ... fn , sid : newFunction . sid , } ; } ) ) ; return [ ... output , ... createdFunctions ] ; } param { FunctionResource } fn param { string } serviceSid param { TwilioServerlessApiClient } client returns { Promise < VersionResource > } async function createFunctionVersion ( fn , serviceSid , client , clientConfig ) { try { const contentType = ( await getContentType ( fn . content , fn . filePath || 'application/json' ) ) || 'application/javascript' ; log ( 'Uploading asset via form data with content-type "%s"' , contentType ) ; const contentOpts = { filename : fn . name , contentType : contentType , } ; const form = new FormData ( ) ; form . append ( 'Path' , fn . path ) ; form . append ( 'Visibility' , fn . access ) ; form . append ( 'Content' , fn . content , contentOpts ) ; const resp = await client . request ( 'post' , `Services/${ serviceSid }/Functions/${ fn . sid }/Versions` , { responseType : 'text' , prefixUrl : getApiUrl ( clientConfig , 'serverless-upload' ) , body : form , } ) ; return JSON . parse ( resp . body ) as VersionResource ; } catch ( err ) { log ( '%O' , new ClientApiError ( err ) ) ; throw new Error ( `Failed to upload Function ${ fn . name }` ) ; } } export param { FunctionResource } fn param { string } serviceSid param { TwilioServerlessApiClient } client returns { Promise < Sid > } export async function uploadFunction ( fn , serviceSid , client , clientConfig ) { const version = await createFunctionVersion ( fn , serviceSid , client , clientConfig ) ; return version . sid ; } export param { string } str returns export function isFunctionSid ( str ) { return str . startsWith ( 'ZH' ) && str . length === 34 ; } export async function listFunctionVersions ( serviceSid , functionSid , client ) { const resp = await client . request ( 'get' , `Services/${ serviceSid }/Functions/${ functionSid }/Versions` ) ; return ( resp . body as unknown ) as FunctionVersion [ ] ; } export async function downloadFunctionVersion ( serviceSid , functionSid , functionVersionSid , client ) { const resp = await client . request ( 'get' , `Services/${ serviceSid }/Functions/${ functionSid }/Versions/${ functionVersionSid }/Content` ) ; return ( resp . body as unknown ) as FunctionContent ; }