From 0044c5ac4fcde269ce63c4430127672c8c7d1c16 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Wed, 14 Sep 2022 11:08:00 -0600 Subject: [PATCH] better compare --- client/lib/json-patch-lib.ts | 8 ++++---- client/lib/patch-db.ts | 38 +++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/client/lib/json-patch-lib.ts b/client/lib/json-patch-lib.ts index 10b0d94..8748b89 100644 --- a/client/lib/json-patch-lib.ts +++ b/client/lib/json-patch-lib.ts @@ -43,6 +43,10 @@ export function applyOperation( doc.data = recursiveApply(doc.data, jsonPathToKeyArray(path), op, value) } +export function jsonPathToKeyArray(path: string): string[] { + return path.split('/').slice(1) +} + function recursiveApply | any[]>( data: T, path: readonly string[], @@ -105,7 +109,3 @@ function recursiveApplyArray( function isObject(val: any): val is Record { return typeof val === 'object' && val !== null && !Array.isArray(val) } - -function jsonPathToKeyArray(path: string): string[] { - return path.split('/').slice(1) -} diff --git a/client/lib/patch-db.ts b/client/lib/patch-db.ts index f91966c..dd59c7f 100644 --- a/client/lib/patch-db.ts +++ b/client/lib/patch-db.ts @@ -1,10 +1,19 @@ import { Bootstrapper, DBCache, Dump, Revision, Update } from './types' import { BehaviorSubject, Observable, Subscription, withLatestFrom } from 'rxjs' -import { applyOperation, getValueByPointer } from './json-patch-lib' +import { + applyOperation, + getValueByPointer, + jsonPathToKeyArray, +} from './json-patch-lib' export class PatchDB { private sub: Subscription | null = null - private watchedNodes: { [path: string]: BehaviorSubject } = {} + private watchedNodes: { + [path: string]: { + subject: BehaviorSubject + pathArr: string[] + } + } = {} readonly cache$ = new BehaviorSubject({ sequence: 0, data: {} as T }) @@ -27,7 +36,7 @@ export class PatchDB { stop() { if (!this.sub) return - Object.values(this.watchedNodes).forEach(node => node.complete()) + Object.values(this.watchedNodes).forEach(node => node.subject.complete()) this.watchedNodes = {} this.sub.unsubscribe() this.sub = null @@ -109,15 +118,18 @@ export class PatchDB { > > watch$(...args: (string | number)[]): Observable { - const path = `/${args.join('/')}` + const path = args.length ? `/${args.join('/')}` : '' if (!this.watchedNodes[path]) { const data = this.cache$.value.data const value = getValueByPointer(data, path) - this.watchedNodes[path] = new BehaviorSubject(value) + this.watchedNodes[path] = { + subject: new BehaviorSubject(value), + pathArr: jsonPathToKeyArray(path), + } } - return this.watchedNodes[path] + return this.watchedNodes[path].subject } proccessUpdates(updates: Update[], cache: DBCache) { @@ -157,8 +169,9 @@ export class PatchDB { } private updateWatchedNodes(revisionPath: string, data: T): void { - Object.keys(this.watchedNodes).forEach(path => { - if (path.includes(revisionPath) || revisionPath.includes(path)) { + const r = jsonPathToKeyArray(revisionPath) + Object.entries(this.watchedNodes).forEach(([path, { pathArr }]) => { + if (startsWith(pathArr, r) || startsWith(r, pathArr)) { this.updateWatchedNode(path, data) } }) @@ -166,10 +179,17 @@ export class PatchDB { private updateWatchedNode(path: string, data: T): void { const value = getValueByPointer(data, path) - this.watchedNodes[path].next(value) + this.watchedNodes[path].subject.next(value) } private isRevision(update: Update): update is Revision { return 'patch' in update } } + +function startsWith(a: string[], b: string[]) { + for (let i = 0; i < b.length; i++) { + if (a[i] !== b[i]) return false + } + return true +}