import type { NestedHooks , HookCallback } from './types' ; export function flatHooks < T > ( configHooks , hooks = { } as T , parentName ? ) { for ( const key in configHooks ) { const subHook = configHooks [ key ] ; const name = parentName ? `${ parentName }:${ key }` : key ; if ( typeof subHook === 'object' && subHook !== null ) { flatHooks ( subHook , hooks , name ) ; } else if ( typeof subHook === 'function' ) { hooks [ name ] = subHook ; } } return hooks as any ; } export function mergeHooks < T > ( ... hooks ) { const finalHooks = { } as any ; for ( const hook of hooks ) { const flatenHook = flatHooks ( hook ) ; for ( const key in flatenHook ) { if ( finalHooks [ key ] ) { finalHooks [ key ] . push ( flatenHook [ key ] ) ; } else { finalHooks [ key ] = [ flatenHook [ key ] ] ; } } } for ( const key in finalHooks ) { if ( finalHooks [ key ] . length > 1 ) { const arr = finalHooks [ key ] ; finalHooks [ key ] = ( ... args ) => serial ( arr , ( fn ) => fn ( ... args ) ) ; } else { finalHooks [ key ] = finalHooks [ key ] [ 0 ] ; } } return finalHooks as any ; } export function serial < T > ( tasks , fn ) { return tasks . reduce ( ( promise , task ) => promise . then ( ( ) => fn ( task ) ) , Promise . resolve ( null ) ) ; } export function serialCaller ( hooks , args ? ) { return hooks . reduce ( ( promise , hookFn ) => promise . then ( ( ) => hookFn . apply ( undefined , args ) ) , Promise . resolve ( null ) ) ; } export function parallelCaller ( hooks , args ? ) { return Promise . all ( hooks . map ( hook => hook . apply ( undefined , args ) ) ) ; }