import { from, Observable } from 'rxjs' import { applyPatch, Operation } from 'fast-json-patch' import { observable, runInAction } from 'mobx' import { toStream } from 'mobx-utils' export class Store { private o: { data: T } constructor (data: T) { this.o = observable({ data }) } get peek (): T { return this.o.data } 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.peekAccess(...args), true)) } set (data: T): void { runInAction(() => this.o.data = data) } applyPatchDocument (patch: Operation[]): { oldDocument: T, newDocument: T } { const oldDocument = this.o.data const newDocument = patchDocument(patch, oldDocument) this.set(newDocument) return { oldDocument, newDocument } } private peekAccess (...args: (string | number)[]): any { try { return args.reduce((acc, next) => (acc as any)[`${next}`], this.o.data) } catch (e) { return undefined } } } export function patchDocument (patch: Operation[], doc: T): T { return applyPatch(doc, patch, true, false).newDocument }