import { Logger } from '@nestjs/common' ; import { performance } from 'perf_hooks' ; import { types } from 'util' ; import type { Func } from './debug.interface' ; const MethodLog = ( context ? ) : MethodDecorator => ( ( target , propertyKey , descriptor ) : void => { const originalMethod = descriptor . value ; if ( typeof originalMethod !== 'function' ) { return ; } const log = function ( time , args ) : void { const ownKey = ( typeof target === 'function' ) ? `${ target . name }` : '' ; const name = context ? `${ ownKey }.${ String ( propertyKey ) }` : String ( propertyKey ) ; const params = ( args . length > 0 ) ? `(${ args })` : '' ; Logger . debug ( `${ name }${ params } +${ time . toFixed ( 2 ) }ms` , context || ownKey ) ; } ; if ( types . isAsyncFunction ( originalMethod ) ) { descriptor . value = async function ( ... args ) : Promise < unknown > { const start = performance . now ( ) ; const result = await originalMethod . apply ( this , args ) ; const end = performance . now ( ) ; log ( end - start , args ) ; return result ; } ; } else { descriptor . value = function ( ... args ) : unknown { const start = performance . now ( ) ; const result = originalMethod . apply ( this , args ) ; const end = performance . now ( ) ; log ( end - start , args ) ; return result ; } ; } } ) ; /**
 * https://stackoverflow.com/questions/47621364
 * https://github.com/Papooch/decorate-all
 */ const ClassLog = ( context ? ) : ClassDecorator => ( ( target ) : void => { const descriptors = Object . getOwnPropertyDescriptors ( target . prototype ) ; for ( const [ propertyKey , descriptor ] of Object . entries ( descriptors ) ) { const originalMethod = descriptor . value ; if ( ! ( originalMethod instanceof Function ) || propertyKey === 'constructor' ) { continue ; } MethodLog ( context ) ( target , propertyKey , descriptor ) ; if ( originalMethod !== descriptor . value ) { const metadataKeys = Reflect . getMetadataKeys ( originalMethod ) ; for ( const key of metadataKeys ) { const value = Reflect . getMetadata ( key , originalMethod ) ; Reflect . defineMetadata ( key , value , < object > descriptor . value ) ; } } Object . defineProperty ( target . prototype , propertyKey , descriptor ) ; } } ) ; export const DebugLog = ( context ? ) : ClassDecorator & MethodDecorator => ( ( target , propertyKey ? , descriptor ? ) : void => { if ( ! descriptor ) { ClassLog ( context ) ( < Func > target ) ; } else if ( propertyKey ) { MethodLog ( context ) ( target , propertyKey , descriptor ) ; } } ) ;