export const UNCAUGHT = '<UNCAUGHT>' ; export type Interceptor = ( send : ( chain : string | string [ ] , detail ? : object ) => void , chain : string [ ] , detail : object ) => boolean | void ; export interface InterceptRules { [ spyId ] : Interceptor | InterceptRules ; } const currentRules = { } ; function isInterceptor ( rule ) { return typeof rule === 'function' ; } function assign ( target , rules , chain = [ ] ) { Object . keys ( rules ) . forEach ( spyId => { const rule = rules [ spyId ] ; const exists = target . hasOwnProperty ( spyId ) ; if ( isInterceptor ( rule ) ) { exists && console . warn ( '[react-spy] Oops, the intersection of interceptors.' , 'spy:' , chain . concat ( spyId ) , ', current:' , currentRules [ spyId ] , ', next:' , rule ) ; target [ spyId ] = rule ; } else { ! exists && ( target [ spyId ] = { } ) ; assign ( < InterceptRules > target [ spyId ] , < InterceptRules > rule ) ; } } ) ; } function find ( rules , chain , idx , uncaught ? ) { const id = chain [ idx ] ; const rule = rules [ id ] ; uncaught = rules [ UNCAUGHT ] as Interceptor || uncaught || null ; if ( rule != null ) { if ( isInterceptor ( rule ) ) { return rule as Interceptor ; } else if ( chain . length > idx + 1 ) { return find ( rule , chain , idx + 1 , uncaught ) ; } } return uncaught ; } export function intercept ( rules ) { assign ( currentRules , rules ) ; } export function findInterceptor ( chain ) { return find ( currentRules , chain , 0 ) || null ; }