import * as Y from "yjs" ; import { observeYJS } from ".." ; import { Atom , createAtom , reaction } from "../observableProvider" ; const docsObserved = new WeakSet < Y . Doc > ( ) ; export function observeDoc ( doc ) { if ( docsObserved . has ( doc ) ) { return doc ; } docsObserved . add ( doc ) ; let selfAtom ; function reportSelfAtom ( ) { if ( ! selfAtom ) { let oldKeys = Array . from ( doc . share . keys ( ) ) ; const handler = ( tr ) => { const newKeys = Array . from ( doc . share . keys ( ) ) ; if ( JSON . stringify ( oldKeys ) !== JSON . stringify ( newKeys ) ) { oldKeys = newKeys ; selfAtom ! . reportChanged ( ) ; } } ; selfAtom = createAtom ( "map" , ( ) => { doc . on ( "beforeObserverCalls" , handler ) ; } , ( ) => { doc . off ( "beforeObserverCalls" , handler ) ; } ) ; } selfAtom . reportObserved ( ( doc as any ) . _implicitObserver ) ; } const originalGet = doc . get ; doc . get = function ( key ) { if ( typeof key !== "string" ) { throw new Error ( "unexpected" ) ; } const ret = Reflect . apply ( originalGet , this , arguments ) ; observeYJS ( ret ) ; return ret ; } ; function patch ( method ) { const originalFunction = doc [ method ] ; let previous ; doc [ method ] = function ( ) { let ret ; let args = arguments ; reportSelfAtom ( ) ; if ( previous ) { previous . removeObservers ( ) ; } previous = reaction ( ( ) => { ret = Reflect . apply ( originalFunction , doc , args ) ; return ret ; } , ( ) => selfAtom ! . reportChanged ( ) ) ; return ret ; } ; } patch ( "toJSON" ) ; Object . defineProperty ( doc , "keys" , { get : ( ) => { reportSelfAtom ( ) ; return Object . keys ( doc . share ) ; } , } ) ; return doc ; }