import { IGetItem } from 'debe' ; export function hashCode ( str = '' ) { var hash = 0 , i , chr ; if ( str . length === 0 ) return hash ; for ( i = 0 ; i < str . length ; i ++ ) { chr = str . charCodeAt ( i ) ; hash = ( hash << 5 ) - hash + chr ; hash |= 0 ; } return hash ; } export function getLastItemRev ( items = [ ] , revField , comparer ? ) { const result = items [ items . length - 1 ] ? items [ items . length - 1 ] [ revField ] : undefined ; if ( ! comparer || result > comparer ) { return result ; } return comparer ; } export const maxRetries = 5 ; export const maxTimeout = 2500 ; export const defaultInterval = ( tries ) => { switch ( tries ) { case 0 : return 100 ; case 1 : return 200 ; case 2 : return 400 ; case 3 : return 800 ; case 4 : return 1600 ; default : return 3200 ; } } ; export async function waitFor < T > ( cb , { interval = defaultInterval } = { } ) { let tries = 0 ; let result ; while ( ! ( result = await cb ( ) ) && tries <= maxRetries ) { tries += 1 ; await new Promise ( yay => setTimeout ( yay , typeof interval === 'function' ? interval ( tries ) : interval ) ) ; } return Promise . resolve ( result ) ; } export function getBigger ( comparer0 ? , comparer1 ? ) { if ( ! comparer0 || ! comparer1 ) { return undefined ; } if ( ! comparer1 || comparer0 > comparer1 ) { return comparer0 ; } return comparer1 ; } type IFetchCount = ( ) => Promise < number > | number ; type IFetchItems < TResult = any > = ( page : number ) => Promise < TResult [ ] > | TResult [ ] ; type ITransferItems < TInput , TResult = TInput > = ( items : TInput [ ] ) => Promise < TResult [ ] > ; export async function batchTransfer < TFetchResult = any , TTransferResult = any > ( { fetchCount , fetchItems , transferItems , reporter , shouldCancel } ) { const canceled = shouldCancel ? shouldCancel : ( ) => false ; let changeCount = await fetchCount ( ) ; let current = changeCount ; let page = 0 ; let items = [ ] ; let transferred = [ ] ; while ( current > 0 ) { const changes = await fetchItems ( page ) ; if ( changes . length && ! canceled ( ) ) { if ( transferItems ) { transferred = transferred . concat ( await transferItems ( changes ) ) ; } items = items . concat ( changes ) ; } else { break ; } current = current - changes . length ; page = page + 1 ; if ( reporter ) { reporter ( Math . abs ( ( 100 / changeCount ) * current - 100 ) ) ; } } if ( transferItems ) { return [ items , transferred ] ; } return [ items , [ ] ] ; }