UNPKG

@ssb-graphql/whakapapa

Version:

GraphQL types and resolvers for the ssb-whakapapa plugin

105 lines (86 loc) 3.86 kB
const { isMsg } = require('ssb-ref') const pull = require('pull-stream') const paraMap = require('pull-paramap') const { promisify: p } = require('util') // NOTE 2021-04-21 mix // this was extracted from getLinks as a specific case where you want to find a link record // when you know it's two end points // TODO 2021-11-23 cherese // this code needs to be split up and refactored as its handling multiple things including: // - getting parent-child links // - getting partner links module.exports = function GetWhakapapaLink (sbot, { getProfile }) { if (typeof getProfile !== 'function') throw new Error('the getter provided was not a function') function getLinks ({ parentId, childId, type }, cb) { if (!parentId || !childId) { return cb(new Error('get-whakapapa-link expects both a parentId AND childId')) } sbot.whakapapa.link.getLinksOfType(parentId, type, (err, links) => { // NOTE link.id is (questionably) defind asthe end of the link that is NOT the parentId // i.e. the childId if (err) return cb(err) const outputIdToLink = {} pull( pull.values(links.childLinks), pull.filter(link => link.tombstone === null && link.id === childId), pull.unique(link => link.id), pull.map(link => { outputIdToLink[link.id] = link // keep a copy of this link return link.id // map links to id }), paraMap((key, cb) => { // use the getter to fetch the full object of the type (e.g. story, profile, artefact, etc...) getProfile(key, (err, output) => { if (err) { console.error(`Unable to get record ${key}, error:`) console.error(err) return cb(null, null) // HACK : don't kill all record getting if just one fails } cb(null, output) }) }, 4), pull.filter(Boolean), // filter out null values pull.filter(output => output.tombstone === null), // filter out tombstoned items pull.map(output => ({ ...outputIdToLink[output.id], linkId: outputIdToLink[output.id].linkId, profile: output // could include link author + recps here later })), pull.collect((err, links) => { if (err) cb(err) else cb(null, links) }) ) }) } return function getWhakapapaLink ({ parent, child, type, isExactLink = true }, cb) { if (cb === undefined) return p(getWhakapapaLink)({ parent, child, type, isExactLink }) if (!isMsg(parent) || !isMsg(child)) { return cb(new Error('parent or child query expected %msgId, got ' + parent)) } getLinks({ parentId: parent, childId: child, type }, (err, links) => { if (err) return cb(err) const finalise = (links, parent, child) => links.map(link => { delete link.id delete link.profile link.type = type link.parent = parent link.child = child return link })[0] // decide which link to return here... if (links && links.length) return cb(null, finalise(links, parent, child)) // NOTE: if isExactLink = true, then it means the parent and child link is a direct query // if isExactLink = false, means the link could be either { child: childId, parent: parentId } OR { child: parentId, parent: childId } if (type !== 'link/profile-profile/partner' && isExactLink) return cb(null, null) // if we are querying for partners and didnt find any, switch the parent/child and // see if we can find a link that way getLinks({ parentId: child, childId: parent, type }, (err, links) => { if (err) return cb(err) if (links && links.length === 0) return cb(null, null) cb(null, finalise(links, child, parent)) }) }) } }