A database that tracks changing revisions of data.
Each revision is accessible through a unique ref which is based on a cryptographic hash of the data's content and history. A ref is similar to a git commit hash.
Each written data object is combined with a link to its ancestors - the combination is called a revision. A revision can be compared to a git commit object.
Revisions look like this:
ancestors: 'someref'data: 'some data'
The cryptographic hash of the revision is its ref.
revisions.createDB(opts) -> db
db.put(data, [ancestorRefs], cb)
db.head(cb) -> ref
db.setHead(ref, [previousHead], cb)
db.setRemoteHead(remoteName, ref, cb)
db.refDifference(fromRef, toRef, cb)
db.commonAncestor(ref1, ref2, cb)
db.createStream(refs) -> stream
revisions.createSynchronizer(sourceDB, targetDB) -> synchronizer
###require('histo-revisions') -> revisions
name: 'your-db-name' // will generate uuid if omittedrevisionStore: revStorebranchStore: branchStore
revStore being an object with a content-addressable store interface:
put(data, cb): should write some data and responds with a unique identifier of the data in the callback
get(identifier, cb): should respond with the data in the callback
del(identifier, cb): should delete the data for the specified identifier
branchStore is expected to be a simple key-value store interface:
put(key, value, cb)
###db.put(data, [ancestorRefs], cb) Writes some data to the db. If `ancestorRefs is not specified the current head is used as the ancestor. On success a ref to the written data is passed to the callback.
###db.setHead(ref, [previousHead], cb) Explicitly sets the head to a known ref. You can pass in the previous head if you want to use optimistic locking. If the head has been updated in the meantime, the function will callback with an error.
The difference is computed using the graph-difference module.
The common ancestor is computed using the ancestor module.
refDifference(fromRef, toRef, cb)
targetDB requires the following set of functions:
setRemoteHead(remoteName, ref, cb)
###Merging synchronized data Synchronizing two databases does not update the target databases' head. It will only write all revisions to the target. To merge the data you need to read the remote head of the source database, get the corresponding data, merge the data and write a new revision:
dbremoteHeadremoteNamedbgetremoteHeadcbnull head: remoteHead data: remoteData;;;dbheaddbgetlocalHeadcbnull head: localHead data: remoteData;;;readRemoteRevtargetDB 'your-remote-name'readLocalRevtargetDBvar mergedData = yourMergeFunctionremoteRevdata localRevdata;var ancestors = remoteRevhead localRevhead;targetDBputmergedData ancestorstargetDBsetHeadmergedRef localRevhead// on err repeat merging with new local head;;;;
##Contributors This project was created by Mirko Kiefer (@mirkokiefer).