Created
May 13, 2019 10:46
-
-
Save frankshaka/caa3ec35a4a9a80fc9063297e069b0a6 to your computer and use it in GitHub Desktop.
Automerge for moving topics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Automerge = require('automerge') | |
function printTopicTree(topic, indent = 2) { | |
let text = '* ' + topic.id | |
for (let i = 0; i < indent; i++) { | |
text = ' ' + text | |
} | |
console.log(text) | |
for (let subtopic of topic.topics) { | |
printTopicTree(subtopic, indent + 2) | |
} | |
} | |
let baseDoc1 = Automerge.init() | |
baseDoc1 = Automerge.change(baseDoc1, 'Set initial data', doc => { | |
doc.rootTopic = { | |
id: 'T1', | |
topics: [ | |
{ | |
id: 'T2', | |
topics: [ | |
{ id: 'T100', topics: [] } | |
] | |
}, | |
{ | |
id: 'T3', | |
topics: [] | |
}, | |
{ | |
id: 'T4', | |
topics: [] | |
} | |
] | |
} | |
}) | |
let baseDoc2 = Automerge.init() | |
baseDoc2 = Automerge.merge(baseDoc2, baseDoc1) | |
console.log('Base Doc:') | |
console.log('-------------------------') | |
printTopicTree(baseDoc1.rootTopic) | |
console.log('') | |
let doc1 = Automerge.change(baseDoc1, 'Move T100 to T3', doc => { | |
let t2 = doc.rootTopic.topics[0] | |
let t3 = doc.rootTopic.topics[1] | |
let t100 = t2.topics[0] | |
delete t2.topics[0] | |
t3.topics.push(t100) | |
}) | |
console.log('Doc (Device 1):') | |
console.log('-------------------------') | |
printTopicTree(doc1.rootTopic) | |
console.log('') | |
let doc2 = Automerge.change(baseDoc2, 'Move T100 to T4', doc => { | |
let t2 = doc.rootTopic.topics[0] | |
let t4 = doc.rootTopic.topics[2] | |
let t100 = t2.topics[0] | |
delete t2.topics[0] | |
t4.topics.push(t100) | |
}) | |
console.log('Doc (Device 2):') | |
console.log('-------------------------') | |
printTopicTree(doc2.rootTopic) | |
console.log('') | |
let finalDoc = Automerge.merge(doc1, doc2) | |
console.log('Merged Doc:') | |
console.log('-------------------------') | |
printTopicTree(findlDoc.rootTopic) | |
Since duplicated id is not acceptable, here's another solution.
We have another doc, say, docServer, doc1 commit it's changes to docServer, then doc2 commit it's change to docServer.
Like this:
let finalDoc = Automerge.merge(docServer, doc1)
finalDoc = Automerge.merge(docServer, doc2)
the delete action in doc2 will be performed correctly and remain only one topic.
@MichaelDuo Doesn’t the third doc break the sync? In a production scenario, doc1 is kept on device 1, and doc2 on device 2. Where do we keep docServer
? And how does it sync to each device?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think to avoid this type of error, the value assigned to a key should be a newly created object, Automerge internally has
id
for each object, and assigning same one to different parent indeed will confuse the algorithm.Quick fix for this code:
change line 57 to
t3.topics.push(JSON.parse(JSON.stringify(t100)))
change line 65 to
t4.topics.push(JSON.parse(JSON.stringify(t100)))
It will create two copies of t100 under t3 and t4.