import * as LRU from 'lru-cache' ; import { number } from 'joi' ; function escape ( str ) { return str . replace ( /\+/g , '-' ) . replace ( /\//g , '_' ) . replace ( /=/g , '' ) ; } function unescape ( str ) { return ( str + '===' . slice ( ( str . length + 3 ) % 4 ) ) . replace ( /-/g , '+' ) . replace ( /_/g , '/' ) ; } export function base64encode ( email ) { return escape ( Buffer . from ( email , 'utf8' ) . toString ( 'base64' ) ) ; } export function base64decode ( str ) { return Buffer . from ( unescape ( str ) , 'base64' ) . toString ( 'utf8' ) ; } export function intersect < T > ( a , b ) { return a . filter ( ai => b . indexOf ( ai ) > - 1 ) ; } export function difference < T > ( a , b ) { return a . filter ( ai => b . indexOf ( ai ) < 0 ) ; } param srcArray param size export function chunkArray < T > ( srcArray , size ) { return Array . from ( Array ( Math . ceil ( srcArray . length / size ) ) , ( _ , i ) => srcArray . slice ( i * size , i * size + size ) ) ; } param items param chunkSize param mapFunc export async function processAsyncIntRangeByChunks < R > ( from , to , step , chunkSize , mapFunc ) { if ( from > to ) { throw new Error ( 'Invalid range' ) ; } let data = [ ] ; let numbers ; let j ; while ( from <= to ) { numbers = [ ] ; for ( j = 0 ; j < chunkSize && from <= to ; ++ j , from += step ) { numbers . push ( from ) ; } data = data . concat ( await Promise . all ( numbers . map ( mapFunc ) ) ) ; } return data ; } param items param chunkSize param mapFunc export async function processAsyncItemsByChunks < T , R > ( items , chunkSize , mapFunc ) { const parts = chunkArray ( items , Math . max ( chunkSize , 1 ) ) ; let data = [ ] ; for ( let i = 0 ; i < parts . length ; i ++ ) { data = data . concat ( await Promise . all ( parts [ i ] . map ( mapFunc ) ) ) ; } return data ; } /**
 * Execute methods and cache it value by key.
 */ export class CacheMethodResult { private cache : LRU ; param maxCount param ttl constructor ( maxCount , ttl ) { this . cache = LRU ( { max : maxCount , maxAge : ttl } ) ; } param key param method async run < T > ( key , method ) { if ( this . cache . has ( key ) ) { return this . cache . get ( key ) ; } return method ( ) . then ( val => { this . cache . set ( key , val ) ; return val ; } ) ; } }