import { AngularFireAction , ChildEvent , DatabaseQuery , DataSnapshot , SnapshotAction } from '../interfaces' ; import { stateChanges } from './state-changes' ; import { Observable , SchedulerLike } from 'rxjs' ; import { fromRef } from '../observable/fromRef' ; import { map , scan , skipWhile , withLatestFrom } from 'rxjs/operators' ; export function auditTrail < T > ( query , events ? , scheduler ? ) { const auditTrail$ = stateChanges < T > ( query , events ) . pipe ( scan ( ( current , action ) => [ ... current , action ] , [ ] ) ) ; return waitForLoaded < T > ( query , auditTrail$ , scheduler ) ; } interface LoadedMetadata { data : AngularFireAction < DataSnapshot > ; lastKeyToLoad : any ; } function loadedData < T > ( query , scheduler ? ) { return fromRef < T > ( query , 'value' , 'on' , scheduler ) . pipe ( map ( data => { let lastKeyToLoad ; data . payload . forEach ( child => { lastKeyToLoad = child . key ; return false ; } ) ; return { data , lastKeyToLoad } ; } ) ) ; } function waitForLoaded < T > ( query , action$ , scheduler ? ) { const loaded$ = loadedData < T > ( query , scheduler ) ; return loaded$ . pipe ( withLatestFrom ( action$ ) , map ( ( [ loaded , actions ] ) => { const lastKeyToLoad = loaded . lastKeyToLoad ; const loadedKeys = actions . map ( snap => snap . key ) ; return { actions , lastKeyToLoad , loadedKeys } ; } ) , skipWhile ( meta => meta . loadedKeys . indexOf ( meta . lastKeyToLoad ) === - 1 ) , map ( meta => meta . actions ) ) ; }