@ssb-graphql/whakapapa
Version:
GraphQL types and resolvers for the ssb-whakapapa plugin
97 lines (81 loc) • 2.96 kB
JavaScript
const pull = require('pull-stream')
const paraMap = require('pull-paramap')
const flatMap = require('pull-flatmap')
const { promisify: p } = require('util')
const CHILD_LINK = require('ssb-whakapapa/spec/link/profile-profile/child').type
const PARTNER_LINK = require('ssb-whakapapa/spec/link/profile-profile/partner').type
const State = require('../link-state-helper')
module.exports = function LoadFamilyOfPerson (getLinks) {
const mapLinks = {
fromParentId () {
return pull(
paraMap((parentId, cb) => getLinks({ type: CHILD_LINK, parentId }, cb), 5),
flatMap(links => links)
)
},
fromChildId () {
return pull(
paraMap((childId, cb) => getLinks({ type: CHILD_LINK, childId }, cb), 5),
flatMap(links => links)
)
},
fromPartnerId () {
return pull(
paraMap((id, cb) => getLinks({ type: PARTNER_LINK, parentId: id, childId: id }, cb), 5),
// NOTE - setting parentId = childId = id means "look up links which have
// EITHER parentId === id OR childId === id
flatMap(links => links)
)
}
}
return function loadFamilyOfPerson (targetId, { extended }, cb) {
if (cb === undefined) return p(loadFamilyOfPerson)(targetId, { extended })
// NOTE this currently doesn't have a way to check for tombstoned profiles
const state = State(targetId)
process(state, [targetId], (err) => {
if (err) return cb(err)
cb(null, state.output)
})
function process (state, parentIds, cb) {
state.resetNewAdults()
pull(
// for the parents
pull.values(parentIds),
// load the links from those parents to children, register them
mapLinks.fromParentId(),
pull.through(state.addChildLink),
// for the children we discovered
pull.map(link => link.child),
// load the link from those children to parents, register them
mapLinks.fromChildId(),
// in default mode, only include birth-links of children up to parents
// in extended mode, include all birth-links
!extended ? pull.filter(isBirthLink) : null,
pull.drain(
state.addChildLink,
(err) => {
if (err) return cb(err)
// now load up the partnerLinks from the initial parents
pull(
pull.values(parentIds),
mapLinks.fromPartnerId(),
pull.drain(
state.addPartnerLink,
(err) => {
if (err) return cb(err)
// decide if we're going around for another round!
if (!extended) return cb(null)
if (!state.newAdults.length) return cb(null)
process(state, state.newAdults, cb)
}
)
)
}
)
)
}
}
}
function isBirthLink (link) {
return link.relationshipType === 'birth'
}