UNPKG

tre-prototypes

Version:

javascript-style prototype-chains for ssb messages

91 lines (80 loc) 2.44 kB
const computed = require('mutant/computed') const WatchHeads = require('tre-watch-heads') const isObservable = require('mutant/is-observable') const oll = require('observable-linked-list') const merge = require('lodash.merge') const ref = require('ssb-ref') module.exports = function(ssb, deps) { deps = deps || {} // fir testing const watchHeads = deps.watchHeads || WatchHeads(ssb) const isMsgId = deps.isMsgId || ref.isMsgId return function watch_merged(revRoot_or_obv, opts) { opts = opts || {} function getObs(revRoot) { return watchHeads(revRoot, { allowAllAuthors: opts.allowAllAuthors }) } const is_obv = isObservable(revRoot_or_obv) const head_kv = is_obv ? revRoot_or_obv : getObs(revRoot_or_obv) const chain_kv = oll(head_kv, proto(isMsgId), getObs) return computed(chain_kv, kvs => { if (kvs.length > 1 && opts.suppressIntermediate && kvs.includes(null)) { // for some reason returning null here // results in better performance return null //return computed.NO_CHANGE } const prototypes = kvs.slice(1).map(kv => revRoot(kv)) if (!prototypes.length) return kvs[0] const merged = merge({}, ...kvs.slice().reverse(), { value: { content: { // do not inherit revisionRoot or revisionBranch revisionRoot: kvs[0].value.content.revisionRoot, revisionBranch: kvs[0].value.content.revisionBranch } } }) if (opts.meta !== false) { merged.meta = Object.assign({}, mergeMeta(kvs.map(kvm => { return kvm && kvm.meta || {} })), {"prototype-chain": kvs} ) } else { delete merged.meta } return merged }) } } // -- utils function mergeMeta(metas) { const result = { forked: false, incomplete: false, change_requests: 0 } metas.forEach(meta => { if (meta.forked) result.forked = true if (meta.incomplete) result.incomplete = true result.change_requests += meta.change_requests || 0 }) return result } function content(kv) { return kv && kv.value && kv.value.content } function proto(isMsgId) { return function(kv) { const c = content(kv) const p = c && c.prototype return isMsgId(p) ? p : null } } function revRoot(kv) { const c = content(kv) return c && c.revisionRoot || kv && kv.key }