import bytes from 'bytes' ; interface IResult { name : string ; size : number ; running ? : number ; loading ? : number ; total ? : number ; } const EmptyResult = { name : '-' , size : 0 , running : 0 , loading : 0 , total : 0 , } ; class SizeLimit { static SIZE_RESULTS_HEADER = [ 'Path' , 'Size' ] ; static TIME_RESULTS_HEADER = [ 'Path' , 'Size' , 'Loading time (3g)' , 'Running time (snapdragon)' , 'Total time' , ] ; private formatBytes ( size ) { return bytes . format ( size , { unitSeparator : ' ' } ) ; } private formatTime ( seconds ) { if ( seconds >= 1 ) { return `${ Math . ceil ( seconds * 10 ) / 10 } s` ; } return `${ Math . ceil ( seconds * 1000 ) } ms` ; } private formatChange ( base = 0 , current = 0 ) { if ( current === 0 ) { return '-100%' ; } const value = ( ( current - base ) / current ) * 100 ; const formatted = ( Math . sign ( value ) * Math . ceil ( Math . abs ( value ) * 100 ) ) / 100 ; if ( value > 0 ) { return `+${ formatted }% 🔺` ; } if ( value === 0 ) { return `${ formatted }%` ; } return `${ formatted }% 🔽` ; } private formatLine ( value , change ) { return `${ value } (${ change })` ; } formatSizeLog ( name , current ) { return `${ name }: ${ this . formatBytes ( current . size ) }` ; } private formatSizeResult ( name , base , current ) { return [ name , this . formatLine ( this . formatBytes ( current . size ) , this . formatChange ( base . size , current . size ) ) , ] ; } private formatTimeResult ( name , base , current ) { return [ name , this . formatLine ( this . formatBytes ( current . size ) , this . formatChange ( base . size , current . size ) ) , this . formatLine ( this . formatTime ( current . loading ) , this . formatChange ( base . loading , current . loading ) ) , this . formatLine ( this . formatTime ( current . running ) , this . formatChange ( base . running , current . running ) ) , this . formatTime ( current . total ) , ] ; } parseResults ( output ) { const results = JSON . parse ( output ) ; return results . reduce ( ( current , result ) => { let time = { } ; if ( result . loading !== undefined && result . running !== undefined ) { const loading = + result . loading ; const running = + result . running ; time = { running , loading , total : loading + running , } ; } return { ... current , [ result . name ] : { name : result . name , size : + result . size , ... time , } , } ; } , { } ) ; } formatResults ( base , current ) { const names = [ ... new Set ( [ ... Object . keys ( base ) , ... Object . keys ( current ) ] ) ] ; const isSize = names . some ( ( name ) => current [ name ] && current [ name ] . total === undefined ) ; const header = isSize ? SizeLimit . SIZE_RESULTS_HEADER : SizeLimit . TIME_RESULTS_HEADER ; const fields = names . map ( ( name ) => { const baseResult = base [ name ] || EmptyResult ; const currentResult = current [ name ] || EmptyResult ; if ( isSize ) { return this . formatSizeResult ( name , baseResult , currentResult ) ; } return this . formatTimeResult ( name , baseResult , currentResult ) ; } ) ; return [ header , ... fields ] ; } } export default SizeLimit ;