import { Callback , Context , Handler } from "aws-lambda" ; import { logError } from "./log" ; export type OnWrapFunc < T = ( ... args : any [ ] ) => any > = ( fn : T ) => T ; /**
 * Wraps a lambda handler function, adding an onStart and onComplete hook.
 */ export function wrap < TEvent , TResult > ( handler , onStart , onComplete , onWrap ? ) { const promHandler = promisifiedHandler ( handler ) ; return async ( event , context ) => { try { await onStart ( event , context ) ; } catch ( error ) { if ( error instanceof Error ) { logError ( "Pre-lambda hook threw error" , error as Error ) ; } } let result ; let handlerError ; let wrappedHandler = promHandler ; try { wrappedHandler = onWrap !== undefined ? onWrap ( promHandler ) : promHandler ; } catch ( error ) { if ( error instanceof Error ) { logError ( "Failed to apply wrap to handler function" , error as Error ) ; } } try { result = await wrappedHandler ( event , context ) ; } catch ( error ) { if ( error instanceof Error ) { handlerError = error ; } throw error ; } finally { try { if ( handlerError ) { await onComplete ( event , context , handlerError ) ; } else { await onComplete ( event , context ) ; } } catch ( error ) { if ( error instanceof Error ) { logError ( "Post-lambda hook threw error" , error as Error ) ; } } } return result ; } ; } export function promisifiedHandler < TEvent , TResult > ( handler ) { return ( event , context ) => { let modifiedCallback = ( ) => { } ; let modifiedLegacyDoneCallback = ( ) => { } ; let modifiedLegacySucceedCallback = ( ) => { } ; let modifiedLegacyFailCallback = ( ) => { } ; const callbackProm = new Promise < TResult | undefined > ( ( resolve , reject ) => { modifiedCallback = ( err , result ) => { if ( err !== undefined && err !== null ) { reject ( err ) ; } else { resolve ( result ) ; } } ; modifiedLegacyDoneCallback = ( err , result ) => { context . callbackWaitsForEmptyEventLoop = false ; if ( err !== undefined && err !== null ) { reject ( err ) ; } else { resolve ( result ) ; } } ; modifiedLegacySucceedCallback = ( result ) => { context . callbackWaitsForEmptyEventLoop = false ; resolve ( result ) ; } ; modifiedLegacyFailCallback = ( err ) => { context . callbackWaitsForEmptyEventLoop = false ; reject ( err ) ; } ; } ) ; context . done = modifiedLegacyDoneCallback ; context . succeed = modifiedLegacySucceedCallback ; context . fail = modifiedLegacyFailCallback ; const asyncProm = handler ( event , context , modifiedCallback ) as Promise < TResult > | undefined ; let promise = callbackProm ; if ( asyncProm !== undefined && typeof asyncProm . then === "function" ) { promise = Promise . race ( [ callbackProm , asyncProm ] ) ; } return promise ; } ; }