Couchdb does it the right way, it simply keeps all versions and lets the application logic decide which is the "one true state".
Couchdb does it the right way, it simply keeps all versions and lets the application logic decide which is the "one true state".
If there are conflicts, it returns a _conflicts property on the object so you can retrieve the other conflicting alternatives so the application logic can write another change if it wants to use a different alternative than the one that was automatically chosen.
The linked project README, and even the CRDT Wikipedia page, seem to claim that conflicts are avoided, whereas, at least in my mind, these are more like strategies to automatically privilege one version in the event of a conflict.
// Pretend doc1 and doc2 are already Automerge objects
let doc1 = { x: 1 }
let doc2 = { x: 2 }
// x will be either 1 or 2 (arbitrarily chosen), but
// res1 will always == res2 regardless of choice
let res1 = Automerge.merge(doc1, doc2)
let res2 = Automerge.merge(doc2, doc1)
res1 == res2 // true
However, there may be cases where you want to manually resolve conflicts, and if that is the case, the `_conflicts` property is there so that you can undo whatever merge occurred automatically and set the "winner" yourself.doc1 = { 'a': {'b': {'c': ... }}}
doc2 = {}
So one has been deleted entirely and the other has modified some attribute deep down inside of it.
If you always have to check and resolve conflicts yourself, then it's not really useful.
If you want to build an editor you probably have to ask yourself what your 'attributes' are, but probably the individual letters.
Last year I built something fairly similar to automerge but with a focus on offline clients. I use it to sync my app's data from different clients to an WebDAV server. As some Clients are sometimes offline when changes occur the, resolving conflicts can occur easily but resolving them in an expected way isn't that hard if you do the time trick.