import { BehaviorSubject, from, Observable } from 'rxjs' import { observable } from 'mobx' import { toStream } from 'mobx-utils' import { DBCache, Dump, Revision, Update } from './types' import { applyPatch } from 'fast-json-patch' export class Store { sequence: number o: { data: T | { } } cache$: BehaviorSubject> constructor ( readonly initialCache: DBCache, ) { this.sequence = initialCache.sequence this.o = observable({ data: this.initialCache.data }) this.cache$ = new BehaviorSubject(initialCache) } watch$ (): Observable watch$ (p1: P1): Observable watch$ (p1: P1, p2: P2): Observable watch$ (p1: P1, p2: P2, p3: P3): Observable watch$ (p1: P1, p2: P2, p3: P3, p4: P4): Observable watch$ (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): Observable watch$ (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): Observable watch$ (...args: (string | number)[]): Observable { return from(toStream(() => this.peekNode(...args), true)) } watchCache$ (): Observable> { return this.cache$.asObservable() } update (update: Update): void { if ((update as Revision).patch) { if (this.sequence + 1 !== update.id) throw new Error(`Outdated sequence: current: ${this.sequence}, new: ${update.id}`) applyPatch(this.o.data, (update as Revision).patch, true, true) } else { this.o.data = (update as Dump).value } this.sequence = update.id this.cache$.next({ sequence: this.sequence, data: this.o.data }) } reset (): void { this.cache$.next({ sequence: 0, data: { }, }) } private peekNode (...args: (string | number)[]): any { try { return args.reduce((acc, next) => (acc as any)[`${next}`], this.o.data) } catch (e) { return undefined } } }