import { BespokeClient } from "./bespoke-client" ; import { LambdaServer } from "./lambda-server" ; import { BSTProcess } from "./bst-config" ; import { Global } from "../core/global" ; import { BSTConfig } from "./bst-config" ; import { FunctionServer } from "./function-server" ; import { LoggingHelper } from "../core/logging-helper" ; import { BstStatistics , BstCommand } from "../statistics/bst-statistics" ; export enum ProxyType { GOOGLE_CLOUD_FUNCTION , HTTP , LAMBDA } const DefaultLambdaPort = 10000 ; /**
 * Exposes the BST proxy command for use.
 *
 * The proxy creates a tunnel to the Bespoken Proxy server.
 *
 * To start it a proxy programmatically, simply call:
 * ```javascript
 * const proxy = BSTProxy.lambda("index.js").("SECRET_KEY").start(() => {
 *      // Stuff to do on start
 * });
 * ```
 *
 * To stop, call:
 * ```javascript
 * proxy.stop(() => {
 *     // Stuff to do on stop
 *     // If being used in unit tests, good to wait for this to ensure resources are properly cleaned up
 * });
 * ```
 *
 * Your secret key can be found in the ~/.bst/config file.
 */ export class BSTProxy { private bespokenClient : BespokeClient = null ; private functionServer : FunctionServer = null ; private lambdaServer : LambdaServer = null ; private proxySecretKey : string ; private isSecure : boolean = false ; private bespokenHost : string = "proxy.bespoken.tools" ; private bespokenPort : number = 80 ; private functionFile : string ; private functionName : string ; private httpPort : number ; private httpDomain : string = "localhost" ; public constructor ( public proxyType ) { } param targetPort returns { BSTProxy } public static http ( targetPort ) { let tool = new BSTProxy ( ProxyType . HTTP ) ; tool . httpPort = targetPort ; return tool ; } param lambdaFile returns { BSTProxy } public static lambda ( lambdaFile ? , functionName ? ) { let tool = new BSTProxy ( ProxyType . LAMBDA ) ; tool . functionFile = lambdaFile ; tool . functionName = functionName ; tool . httpPort = DefaultLambdaPort ; return tool ; } param functionFile param functionName returns { BSTProxy } public static cloudFunction ( functionFile , functionName ? ) { let tool = new BSTProxy ( ProxyType . GOOGLE_CLOUD_FUNCTION ) ; tool . functionFile = functionFile ; tool . functionName = functionName ; tool . httpPort = DefaultLambdaPort ; return tool ; } param host param port returns { BSTProxy } public bespokenServer ( host , port ) { this . bespokenHost = host ; this . bespokenPort = port ; return this ; } public targetDomain ( host ) { this . httpDomain = host ; return this ; } public secretKey ( secretKey ) { this . proxySecretKey = secretKey ; return this ; } /**
     * Enables security which validates that the secret key is present in query or headers
     */ public activateSecurity ( ) { this . isSecure = true ; } param port public port ( port ) { this . httpPort = port ; return this ; } public startWithConfig ( onStarted ? ) { this . bespokenClient = new BespokeClient ( this . proxySecretKey , this . bespokenHost , this . bespokenPort , this . httpDomain , this . httpPort , this . isSecure ? this . proxySecretKey : undefined ) ; let callbackCountDown = 1 ; const callback = function ( ) { callbackCountDown -- ; if ( callbackCountDown === 0 && onStarted !== undefined ) { onStarted ( ) ; } } ; this . bespokenClient . onConnect = callback ; this . bespokenClient . connect ( ) ; if ( this . proxyType === ProxyType . LAMBDA ) { callbackCountDown ++ ; this . lambdaServer = new LambdaServer ( this . functionFile , this . httpPort , false , this . functionName ) ; this . lambdaServer . start ( callback ) ; } if ( this . proxyType === ProxyType . GOOGLE_CLOUD_FUNCTION ) { callbackCountDown ++ ; this . functionServer = new FunctionServer ( this . functionFile , this . functionName , this . httpPort ) ; this . functionServer . start ( callback ) ; } BstStatistics . instance ( ) . record ( BstCommand . proxy , undefined , this . proxySecretKey , Global . version ( ) ) ; return this ; } public start ( onStarted ? ) { const self = this ; if ( Global . config ( ) ) { BSTProcess . run ( this . httpPort , this . proxyType , process . pid ) ; this . proxySecretKey = Global . config ( ) . secretKey ( ) ; this . startWithConfig ( onStarted ) ; } else { if ( ! this . proxySecretKey ) { BSTConfig . load ( ) . then ( ( config ) => { self . proxySecretKey = config . secretKey ( ) ; self . startWithConfig ( onStarted ) ; LoggingHelper . initialize ( false ) ; } ) ; return ; } self . startWithConfig ( onStarted ) ; LoggingHelper . initialize ( false ) ; } } public stop ( onStopped ? ) { if ( this . bespokenClient !== null ) { this . bespokenClient . shutdown ( ) ; } if ( this . lambdaServer !== null ) { this . lambdaServer . stop ( onStopped ) ; } else if ( this . functionServer !== null ) { this . functionServer . stop ( onStopped ) ; } else { if ( onStopped !== undefined && onStopped !== null ) { onStopped ( ) ; } } } }