import debounce from 'just-debounce-it' ; import isNode from 'detect-node' ; import { Effect , Event , Store } from 'effector' ; import { createName , getPath } from './lib' ; const SEPARATOR = isNode ? '  ' : '' ; const storeListToInit = [ ] ; const eventListToInit = [ ] ; const effectListToInit = [ ] ; const styles = { block : 'padding-left: 4px; padding-right: 4px; font-weight: normal;' , chunk : 'padding-left: 4px; padding-right: 4px; font-weight: normal;' , effector : 'line-height:1.5; color: #000; font-family: "Apple Emoji Font"; font-weight: normal !important;' , new : 'background-color: #29b6f6; color: #000' , store : 'background-color: #7e57c2; color: #fff' , event : 'background-color: #9ccc65; color: #000' , effect : 'background-color: #26a69a; color: #000' , emoji : '' , file : 'color: #9e9e9e; padding-left: 20px;' , reset : 'color: currentColor; background-color: transparent;' , } ; const effectorLabel = [ [ '☄️' , '%s' , styles . effector ] , [ 'effector' , '%s' , 'font-family: Menlo, monospace;' ] ] ; const reset = ( index , count , style ) : string => index === count - 1 ? styles . reset : style ; type Block = [ string , string , string ] ; type Chunk = [ any , string , string ] ; function log ( blocks , chunks , group = undefined ) { const str = [ ] ; const params = [ ] ; blocks . unshift ( ... effectorLabel ) ; blocks . forEach ( ( [ value , view , style ] , index ) => { str . push ( `%c${ view }%c` ) ; params . push ( `${ styles . block } ${ style }` , value , reset ( index , blocks . length , `${ styles . block } ${ style }` ) ) ; } ) ; chunks . forEach ( ( [ value , view , style ] ) => { str . push ( `%c${ view }` ) ; params . push ( `${ styles . chunk } ${ style }` , value ) ; } ) ; const args = [ str . join ( SEPARATOR ) , ... params ] ; if ( group === 'open' ) { console . group ( ... args ) ; } else if ( group === 'collapsed' ) { console . groupCollapsed ( ... args ) ; } else { console . log ( ... args ) ; } } const blockNew = [ 'new' , '%s' , styles . new ] ; const blockStore = [ 'store' , '%s' , styles . store ] ; const blockEvent = [ 'event' , '%s' , styles . event ] ; const blockEffect = [ 'effect' , '%s' , styles . effect ] ; const stripDomain = ( name ) => name . split ( '/' ) . pop ( ) || name ; const createBlockStore = ( name ) => [ stripDomain ( name ) , '%s' , styles . store ] ; const createBlockEvent = ( name ) => [ stripDomain ( name ) , '%s' , styles . event ] ; const createBlockEffect = ( name ) => [ stripDomain ( name ) , '%s' , styles . effect ] ; const logAdded = debounce ( ( ) => { const stores = storeListToInit . splice ( 0 ) ; const events = eventListToInit . splice ( 0 ) ; const effects = effectListToInit . splice ( 0 ) ; if ( stores . length + events . length + effects . length > 0 ) { log ( [ blockNew ] , [ [ 'Initialized' , '%s' , '' ] , [ `events(${ events . length })` , '%s' , '' ] , [ `effects(${ effects . length })` , '%s' , '' ] , [ `stores(${ stores . length })` , '%s' , '' ] , ] , 'collapsed' ) ; if ( stores . length ) { stores . forEach ( ( store ) => { const name = createName ( store . compositeName ) ; const fileName = getPath ( store ) ; log ( [ blockNew , createBlockStore ( name ) ] , [ [ '-> ' , '%s' , '' ] , [ store . getState ( ) , '%o' , '' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , '' ] , ] ) ; } ) ; } if ( events . length > 0 ) { events . forEach ( ( event ) => { const name = createName ( event . compositeName ) ; const fileName = getPath ( event ) ; log ( [ blockNew , createBlockEvent ( name ) ] , [ [ fileName , '%s' , styles . file ] , [ name , '%s' , '' ] , ] ) ; } ) ; } if ( effects . length > 0 ) { effects . forEach ( ( effect ) => { const name = createName ( effect . compositeName ) ; const fileName = getPath ( effect ) ; log ( [ blockNew , createBlockEffect ( name ) ] , [ [ fileName , '%s' , styles . file ] , [ name , '%s' , '' ] , ] ) ; } ) ; } console . groupEnd ( ) ; } } , 5 ) ; export function storeAdded ( store ) { storeListToInit . push ( store ) ; logAdded ( ) ; } export function eventAdded ( event ) { eventListToInit . push ( event ) ; logAdded ( ) ; } export function effectAdded ( effect ) { effectListToInit . push ( effect ) ; logAdded ( ) ; } export function storeUpdated ( name , fileName , value ) { log ( [ createBlockStore ( name ) ] , [ [ '-> ' , '%s' , '' ] , [ value , '%o' , '' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , styles . file ] , ] ) ; } export function eventCalled ( name , fileName , payload ) { log ( [ createBlockEvent ( name ) ] , [ [ payload , '%o' , 'padding-left: 4px;' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , styles . file ] , ] ) ; } export function effectCalled ( name , fileName , parameters ) { log ( [ createBlockEffect ( name ) ] , [ [ parameters , '%o' , 'padding-left: 4px;' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , styles . file ] , ] ) ; } export function effectDone ( name , fileName , parameters , result ) { log ( [ createBlockEffect ( name ) ] , [ [ 'done ✅' , '%s' , styles . emoji ] , [ parameters , '(%o)' , 'padding-left: 4px;' ] , [ '-> ' , '%s' , '' ] , [ result , '%o' , 'padding: 0;' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , styles . file ] , ] ) ; } export function effectFail ( name , fileName , parameters , error ) { const instanceofError = error instanceof Error ; log ( [ createBlockEffect ( name ) ] , [ [ 'fail ❌' , '%s' , styles . emoji ] , [ parameters , '(%o)' , 'padding-left: 4px;' ] , [ '-> ' , '%s' , '' ] , instanceofError ? [ String ( error ) , '%s' , '' ] : [ error , '%o' , 'padding: 0;' ] , [ fileName , '%s' , styles . file ] , [ name , '%s' , styles . file ] , ] , instanceofError ? 'collapsed' : undefined ) ; if ( instanceofError ) { log ( [ ] , [ [ ' ' , '%s' , '' ] , [ error , '%o' , 'padding-left: 20px;' ] , ] ) ; } console . groupEnd ( ) ; }