import { IncomingMessage } from "http" ; import { LoggingHelper } from "../core/logging-helper" ; import { ModuleManager } from "./module-manager" ; const bodyParser = require ( "body-parser" ) ; const express = require ( "express" ) ; let Logger = "BST-FUNCTION" ; /**
 * The FunctionServer wraps a Google Cloud Function routine in a simple HTTP service.
 *
 * It makes it easy to test Cloud Functions locally, and in conjunction with our other tools.
 *
 * To use it, simply provide the filename of the Cloud function along with the port the HTTP server should listen on.
 */ export class FunctionServer { private moduleManager : ModuleManager ; private requests : Array < IncomingMessage > = [ ] ; private server : any = null ; param file param functionName param port param verbose public constructor ( private file , private functionName , private port , private verbose ? ) { } param callback public start ( callback ? ) { let self = this ; this . moduleManager = new ModuleManager ( process . cwd ( ) ) ; this . moduleManager . start ( ) ; const app = express ( ) ; app . use ( bodyParser . json ( ) ) ; app . use ( ( request , response ) => { self . requests . push ( request ) ; self . invoke ( request , response ) ; } ) ; this . server = app . listen ( this . port , function ( ) { LoggingHelper . info ( Logger , "CloudFunctionServer started on port: " + self . port ) ; if ( callback !== undefined && callback !== null ) { callback ( ) ; } } ) ; } param onStop public stop ( onStop ? ) { this . moduleManager . stop ( ) ; let request = null ; for ( request of this . requests ) { try { request . socket . end ( ) ; } catch ( e ) { } } this . server . close ( function ( ) { if ( onStop !== undefined && onStop !== null ) { onStop ( ) ; } } ) ; } private invoke ( request , response ) { let path = this . file ; LoggingHelper . debug ( Logger , "Invoking Function: " + this . file ) ; const cloudFunction = this . moduleManager . module ( path ) ; if ( ! ( this . functionName in cloudFunction ) ) { const message = "Function: " + this . functionName + " does not exist or has not been exported from module: " + this . file ; LoggingHelper . error ( Logger , message ) ; response . status ( 500 ) . send ( message ) ; return ; } try { cloudFunction [ this . functionName ] . call ( cloudFunction , request , response ) ; } catch ( e ) { if ( e . stack ) { console . error ( e . stack ) ; } else { console . error ( e ) ; } const message = "Unhandled Exception from Cloud Function: " + e ; response . status ( 500 ) . send ( message ) ; } } }