import { Action , BaseModel , BaseResource , Constructor , exceptions , Logger , OperationStatus , Optional , ProgressEvent , ResourceHandlerRequest , SessionProxy } from 'cfn-rpdk' ; import Aws from 'aws-sdk/clients/all' ; type ClientMap = typeof Aws ; type ServiceName = keyof ClientMap ; type Client = InstanceType < ClientMap [ ServiceName ] > ; type HandlerEvents = Map < Action , string | symbol > ; export type HandlerArgs < R extends BaseModel , T extends Record < string , any > = Record < string , any > > = { session : Optional < SessionProxy > ; request : ResourceHandlerRequest < R > ; callbackContext : T ; logger ? : Logger ; } ; export interface commonAwsOptions { deprecated serviceName ? : ServiceName ; service ? : Constructor < Client > ; action ? : Action ; debug ? : boolean ; } interface Session { client : ( ... args : any [ ] ) => Client ; } returns { MethodDecorator } export function commonAws < T extends Record < string , any > , R extends BaseModel > ( options ) { return function ( target , propertyKey , descriptor ) : PropertyDescriptor { const { debug , service , serviceName } = options ; if ( ! descriptor ) { descriptor = Object . getOwnPropertyDescriptor ( target , propertyKey ) ; } const originalMethod = descriptor . value ; function retrieveClient ( session , service ) { let errorMessage = '' ; if ( session && ( session instanceof SessionProxy || typeof session . client === 'function' ) ) { try { const client = session . client ( service ) ; if ( client ) { return client ; } } catch ( err ) { errorMessage = err . message ; } } throw new exceptions . InvalidCredentials ( `no aws session found - did you forget to register the execution role?\n${ errorMessage }` ) ; } descriptor . value = async function ( session , request , callbackContext , logger ? ) : Promise < ProgressEvent < R , T > > { let action = options . action ; if ( ! action ) { const events = Reflect . getMetadata ( 'handlerEvents' , target ) ; events . forEach ( ( value , key ) => { if ( value === propertyKey ) { action = key ; } } ) ; } logger = logger || console ; const handlerArgs = { session , request , callbackContext , logger } ; const desiredResourceState = request . desiredResourceState || { } ; let ModelClass = Object . getPrototypeOf ( desiredResourceState ) . constructor ; if ( 'modelTypeReference' in this ) { ModelClass = this [ 'modelTypeReference' ] || ModelClass ; } const model = new ModelClass ( desiredResourceState ) ; const progress = ProgressEvent . progress < ProgressEvent < R , T > > ( model ) ; if ( debug ) logger . log ( { action , request , callbackContext } ) ; const client = retrieveClient ( session , service || serviceName ) ; if ( debug ) logger . log ( { action , message : 'before perform common task' } ) ; const modified = await originalMethod . apply ( this , [ action , handlerArgs , client , model ] ) ; if ( debug ) logger . log ( { action , message : 'after perform common task' } ) ; if ( modified !== undefined ) { if ( Array . isArray ( modified ) ) { progress . resourceModel = null ; progress . resourceModels = modified ; } else { progress . resourceModel = modified ; progress . resourceModels = null ; } } progress . status = OperationStatus . Success ; return Promise . resolve ( progress ) ; } ; return descriptor ; } ; }