import { Observable } from 'rxjs' ; import { classToPlain , Expose , plainToClassFromExist , serialize } from 'class-transformer' ; import { AttemptOptions , retry } from '@lifeomic/attempt' ; import * as Chance from 'chance' ; import { IgResponseError } from '../errors' ; import { Repository } from './repository' ; import { Enumerable } from '../decorators' ; export abstract class Feed < Response = any , Item = any > extends Repository { public attemptOptions : Partial < AttemptOptions < any > > = { delay : 60000 , factor : 1.5 , maxAttempts : 10 , minDelay : 60000 , maxDelay : 300000 , jitter : true , } ; public get items$ ( ) { return this . observable ( ) ; } public observable ( semaphore ? , attemptOptions ? ) { return new Observable < Item [ ] > ( observer => { let subscribed = true ; process . nextTick ( async ( ) => { do { try { await retry ( async ( ) => { const items = await this . items ( ) ; observer . next ( items ) ; if ( typeof semaphore === 'function' ) { await semaphore ( ) ; } } , { handleError ( error , context ) { if ( error instanceof IgResponseError && [ 400 , 429 , 500 , 502 ] . includes ( error . response . statusCode ) && subscribed ) { return ; } else { context . abort ( ) ; } } , ... ( attemptOptions || this . attemptOptions ) , } ) ; } catch ( e ) { observer . error ( e ) ; } } while ( this . isMoreAvailable ( ) && subscribed ) ; observer . complete ( ) ; } ) ; return function unsubscribe ( ) { subscribed = false ; } ; } ) ; } @ Expose ( ) protected moreAvailable : boolean ; @ Enumerable ( false ) protected chance = new Chance ( ) ; @ Expose ( ) protected rankToken = this . chance . guid ( ) ; protected abstract set state ( response ) ; abstract request ( ... args ) ; abstract items ( ) ; public serialize ( ) { return serialize ( this , { strategy : 'excludeAll' } ) ; } public deserialize ( data ) { plainToClassFromExist ( this , JSON . parse ( data ) ) ; } public toPlain ( ) { return classToPlain ( this , { strategy : 'excludeAll' } ) ; } public isMoreAvailable ( ) { return ! ! this . moreAvailable ; } }