import { delay } from './delay' ; export interface BaseRetryOpts { maxAttempts : number ; delayMs ? : number ; } export interface RetryOpts extends BaseRetryOpts { isRetryable ? : ( err : Error ) => boolean ; } param { AsyncFunction } fn param { RetryOpts } opts returns export function retry < T extends Function > ( fn , retryOpts ) { return ( ( async ( ... args ) : Promise < any > => { let lastErr = new Error ( `Could not complete function within ${ retryOpts . maxAttempts } attempts` ) ; for ( let i = 0 ; i < retryOpts . maxAttempts ; ++ i ) { try { return await fn ( ... args ) ; } catch ( err ) { if ( retryOpts . isRetryable && ! retryOpts . isRetryable ( err ) ) { throw err ; } lastErr = err ; } if ( retryOpts . delayMs ) { await delay ( retryOpts . delayMs ) ; } } throw lastErr ; } ) as any ) as T ; } param { AsyncFunction } fn param { BaseRetryOpts } opts returns export function until < T extends ( ... args : any [ ] ) => Promise < any > > ( fn , retryOpts ) { return ( async ( ... args ) : Promise < any > => { for ( let i = 0 ; i < retryOpts . maxAttempts ; ++ i ) { const result = await fn ( ... args ) ; if ( ! ! result ) { return result ; } if ( retryOpts . delayMs ) { await delay ( retryOpts . delayMs ) ; } } throw new Error ( `Could not complete function within ${ retryOpts . maxAttempts } attempts` ) ; } ) as T ; }