Closed ept closed 3 years ago
This is tremendously exciting! I'll try and build a little something on it ASAP.
Thx @ept. This works great for me. What about providing also the change
to the callback on top of the existing (diff, before, after, local)
?
@echarles Added the binary changes as a fifth callback argument. (It's an array of changes since you can call Automerge.applyChanges()
with a whole bunch of changes in one go, and you will receive one observer callback for the whole batch.)
I have merged this since it seems to be useful, and doesn't require any coordination with the Rust implementation. However, I marked the API as experimental, and noted in the changelog that this means the API may change in incompatible ways without a major version bump. This gives us the freedom to revise the API if we think of a better one, even once it is baked into a 1.0 release.
Thx @ept This is really useful and needed for our case. Happy to see this experimental API evolve/change based on users' feedbacks.
There have been requests for an observer-style API, where an application's callback function gets called whenever a certain part of an Automerge document changes. For example, this is useful when integrating a text editing widget with Automerge, where the widget state needs to be updated whenever the Automerge document changes (especially as a result of remote changes arriving from the network).
This PR is based on #288, allowing hooking into patch application, but based on the performance branch rather than main. Moreover, I've extended the API with a new class
Automerge.Observable
, which allows observing individual objects as well as the entire document. The callback is given a description of the change in the Automerge patch format (including, for example, a description of which elements to insert or delete in a list or text object), as well as the before and after state of the object, and a flag indicating whether the change is the result of a local call toAutomerge.change
or whether it came formAutomerge.applyChanges
(typically a remote change).I made
Observable
a separate class because an Automerge document is immutable, and so it doesn't make much sense to register observers on it directly. On the other hand, the Observable class is mutable, allowing observers to be added.Basic usage example:
You can pass an
observable
option toAutomerge.init()
,Automerge.from()
, orAutomerge.load()
. See the tests for some more examples of how to use this API.Observable is based on a slightly lower-level API (which allows observing only an entire document, not individual objects within it) called
patchCallback
: