npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ssb-whakapapa

v4.0.0

Published

an ssb-server plugin for creating, reading, managing relationship links in scuttlebutt

Downloads

31

Readme

ssb-whakapapa

An ssb-server plugin for creating, reading, updating relationships between profiles

Example Usage

const Server = require('ssb-server')
const Config = require('ssb-config/inject')

const config = Config({})

const server = Server
  .use(require('ssb-master'))
  .use(require('ssb-backlinks'))
  .use(require('ssb-whakapapa')) // <<<<<<
  .call(null, config)

const details = {
  child: '%P5r79KsntEGPMp0Zd24bvfDBMtfx1SADMEE7yxBdVVw=.sha256',
  parent: '%4BmROhXcW6H4VyATrIj7uOWqHyW5q5jFZpDHo5RofSc=.sha256',
}

const opts = {
  relationshipType: 'birth',

  recps: [
    '@ye+QM09iPcDJD6YvQYjoQc7sLF/IFhmNbEqgdzQo3lQ=.ed25519'
  ]
}

server.whakapapa.child.create(details, opts, (err, linkId) => {
  // ...
})
// later:
server.whakapapa.get('%P5r79KsntEGPMp0Zd24bvfDBMtfx1SADMEE7yxBdVVw=.sha256', (err, data) => {
  console.log(data)
  // => {
  //   id: '%P5r79KsntEGPMp0Zd24bvfDBMtfx1SADMEE7yxBdVVw=.sha256',
  //   parentLinks: [
  //     {
  //       id: '%4BmROhXcW6H4VyATrIj7uOWqHyW5q5jFZpDHo5RofSc=.sha256',
  //       linkId: '%W5q4BmROhXcW6H4VyATrIj7uOWqHy5jFZpDHo5RofSc=.sha256',
  //
  //       relationshipType: 'birth',
  //       legallyAdopted: null // null means it hasnt been set
  //       tombstone: null
  //     }
  //   ],
  //   childLinks: []
  // }
})

API

Views: - view.create - view.get - view.update - view.tombstone - view.list

Relationships: - get - child - child.create - child.get - child.update - child.tombstone - child.list - partner - partner.create - partner.get - partner.update - partner.tombstone - partner.list

Links:


view:

server.whakapapa.view.get

Fetch a "view" of whakapapa - this is a minimal record which stores the sdetails needed to construct a particular perspective on a graph of relationships.

e.g. we might want to see all the descendants of a particular ancestor. To do this we store the profileId of that ancestor and the mode of drawing (down!). We might also include preferences about whether to include whangai or adopted descendants for example.

server.whakapapa.view.get(viewId, cb)

  • viewId MessageId - the id of the root message of a view
  • cb function - a callback of signature (err, data), where data is an Object with properties:
    • name String - the name of this whakapapa view
    • description String - the name of this whakapapa view
    • recordCount Integer - number of decendants linked to the focus (starting profile)
    • ignoredProfiles Array - an array of ProfileIds which have been marked to ignore (don't render these please). Returns [] if there are none.
    • focus ProfileId - the id of the profile we start from
    • mode String - the way to draw the graph. (can be 'descendants' | 'ancestors')
    • tombstone Object - date and reason
    • permissionString - whether tribe members can 'edit | view | submit' this whakapapa record

If any of these are not set, these properties will still be present, but the values will be null

server.whakapapa.view.create

Creates a new message of type whakapapa/view

server.whakapapa.view.create(details, cb)

  • details Object - contains information to start off view
  • cb function - a form (err, viewId)

The expected form of details is :

{
  name: String,            // required (for create)
  description: String,
  image: Image,
  focus: ProfileId,
  recordCount: Integer,
  mode: Mode,
  permission: String,
  tombstone: Tombstone,
  ignoredProfiles: { add: [ProfileId] },
  importantRelationships: {
    [ProfileId]: [ProfileId, ... ]     // a way of declaring relationship priorities for specific profiles
  },
  recps: [GroupId, FeedId, ...]
}

Notes:

  • Mode can be 'descendants' | 'ancestors'
  • Permission can be 'view' | 'edit | submit'
  • Image is an Object of form { blob: '&07xxrn0wWbtRx/gp4IF7THPeWZUT1LWt93IVHTbitFE=.sha256', mimeType: 'image/png' }
  • Tombstone is an Object of form { reason: String, date: UnixTime }
  • importantRelationships exists as a way to resolve some challenges with drawing whakapapa
    • sometimes because of intermarriage, a person can appear in two places on a graph
    • if you only want them drawn once, you can specify who is is most important for a particular profile
    • e.g. { @tamaId: ['@whangaiDadId', '@birthMumId'] } is a way to express "I would like tama to be drawn closer to their whangai dad in this whakapapa, but secondarily also show a link across the graph to their birth mum".
  • recps is a special field which encrypts the view (and all subsequent updates) to a specified set of FeedIds

server.whakapapa.view.update

server.whakapapa.view.update(viewId, details, cb)

  • viewId MessageId - the id of the view to update
  • details Object - same as in view.create, except
    • ignoredProfiles can also be { ignoredProfiles: { remove: [ProfileId] } } for updates
    • recps is inherrited from the create message (root), so setting it here does nothing.
    • name is not required
  • cb function - callback with signature (err)

server.whakapapa.get

Get children and parents of a particular profile.

server.whakapapa.get(ProfileId, cb)

  • ProfileId String - the id for a profile
  • cb Function - a callback of signature (err, data)

data format

{
  parentLinks: [
    {
      id: '%4BmROhXcW6H4VyATrIj7uOWqHyW5q5jFZpDHo5RofSc=.sha256',
      linkId: '%47uOWqHyW5q5jFZpDHo5RofBmROhXcW6H4VyATrIjSc=.sha256',
      relationshipType: 'birth',
      legallyAdopted: null,
      tombstone: null
    },
    { 
      id: '%r86qOq2KNY3GlifR6UgQaB05ZfXmHlnxxoFlyi9OI0A=.sha256'
      linkId: '%W5q5j47uOWqHyFZpDHo5RofBmROhXcW6H4VyATrIjSc=.sha256',
      relationshipType: null, // this means relationshipType hasnt been set
      legallyAdopted: null,
      tombstone: {
        date:  
      }
    }
  ],
  childLinks: [
    {
      id: '%pCt2QB3ZxZEsKIYvxGI9QBmytrUNZfuuRbNk8i0V7ug=.sha256',
      linkId: '%yFZpDHo5RoW5q5j47uOWqHfBmROhXcW6H4VyATrIjSc=.sha256',
      relationshipType: 'whangai',
      legallyAdopted: false,
      tombstone: null
    }
  ]
}

server.whakapapa.view.tombstone

server.whakapapa.view.tombstone(viewId, opts, cb)

  • viewId MessageId - the root key of the whakapapa view record
  • opts Object with properties:
    • reason String (optional) give a reason for why you're tombstoning the record
    • undo Boolean (optional) set to true to remove the tombstone
  • cb function - callback with signature (err)

server.whakapapa.view.list

Find all whakapapa/view record, options to narrow that query down.

server.whakapapa.child.lists(opts, cb)

  • opts Object - see ssb-crut list opts
  • cb function - callback with signature (err, links), where links is an Array of link records

relationships - child

server.whakapapa.child.create

Creates a new updateable message of type link/profile-profile/child connecting two profiles - a parent and a child.

server.whakapapa.child.create({ child, parent }, opts, cb)

  • child String a scuttlebutt MessageId pointing to a profile root
  • parent String a scuttlebutt MessageId pointing to a profile root
  • opts Object - describes the values to set on that relationship and who can read it.
  • cb Function - a callback of signature (err, linkId) where linkId is the id of the relationship which has just been created

opts format

{
  relationshipType: ParentType, // optional
  legallyAdopted: Boolean       // optional
  tombstone: TombStone          // optional

  recps: [ FeedId ]             // optional
}
  • MessageId is scuttlebutt message cypherlink e.g. %4BmROhXcW6H4VyATrIj7uOWqHyW5q5jFZpDHo5RofSc=.sha256
  • ParentType is any of 'birth' | 'adopted' | 'whangai' | 'unknown'
  • legallyAdopted should only be set if relationshipType is 'adopted' or 'whangai'
  • Tombstone is an Object of form { date: UnixTime, reason: String } and marks a link as deleted.
  • recps is an Array of FeedId (e.g. '@ye+QM09iPcDJD6YvQYjoQc7sLF/IFhmNbEqgdzQo3lQ=.ed25519'). If this is provided this relationship will automatically be encrypted so only the mentioned parties will be able to see this. (NOTE - you cannot change this later)

Notes

  • If you don't want to add any optional opts, set opts to null or {}
  • this is now a wrapper over whakapapa.link.create

:construction: TODO

  • add GroupId to recps once we have private-groups released
  • add some way to validate whakapapa links
    • e.g. an approval system so that kaitiaki (custodians) at each end of the relationship can approve the link?
    • need to make sure that can't change pointer for child / parent after an "approval" of link

server.whakapapa.child.update

This updates a child relationship (not the child themself).

server.whakapapa.child.update(linkId, opts, cb)

  • linkId MessageId - the root key of the relationship
  • opts Object - same as in child.create, except recps is set for you based on what the first message was.
  • cb function - callback with signature (err)

:construction: TODO

  • needed for tombstoning

server.whakapapa.child.tombstone

server.whakapapa.child.tombstone(linkId, opts, cb)

  • linkId MessageId - the root key of the relationship
  • opts Object with properties:
    • reason String (optional) give a reason for why you're tombstoning the record
    • undo Boolean (optional) set to true to remove the tombstone
  • cb function - callback with signature (err)

server.whakapapa.child.list

Find all link/profile-profile/child links, options to narrow that query down.

server.whakapapa.child.lists(opts, cb)

  • opts Object - see ssb-crut list opts
  • cb function - callback with signature (err, links), where links is an Array of link records

partner methods

Similar to child methods, but details are empty The valid mutations are:

  • relationshipType is any of 'partners' | 'married' | 'divorced' | 'unknown'
  • tombstone (same as for child)

server.whakapapa.partner.create

server.whakapapa.partner.get

server.whakapapa.partner.update

server.whakapapa.partner.tombstone

server.whakapapa.partner.list


link methods

server.whakapapa.link.create

A generic link creating method

server.whakapapa.link.create({ type, parent, child }, details, cb)

  • type String - the sort of link you want to make. This will become the message type, one of:

    • link/profile-profile/child
    • link/profile-profile/partner
    • link/story-profile/contributor
    • link/story-profile/creator
    • link/story-profile/mention
    • link/story-artefact
    • link/story-story
  • parent MessageId - the id of the "parent" end the link

  • details Object - a collection of initial transformations for the link. Useful for storing meta-data, and declaring recps (private recipients). The valid form of this depends on the type

    • only the "child" link currently has any details
  • cb

server.whakapapa.link.get

server.whakapapa.link.get(id, cb)

  • id MessageId - the id of the thing you're inspecting for links

server.whakapapa.link.update

A generic link updating method, this figures out what sort of link it is and updates accordingly.

server.whakapapa.link.update(id, details, cb)

  • id MessageId - the id of the thing you're inspecting for links
  • details Object - same as #create method details (except you can't change recps here)
  • cb

server.whakapapa.link.tombstone

server.whakapapa.link.get(id, details, cb)

  • id MessageId - the id of the thing you're inspecting for links
  • details Object which accepts optional inputs details.reason, details.undo = true

server.whakapapa.link.getLinksOfType

Find all links of type type attached to a particular messaged id.

server.whakapapa.link.getLinksOfType(id, type, cb)

  • id MessageId - the id of the thing you're inspecting for links
  • type String - the "type" of links you want to surface (e.g link/story-artefact)
  • cb

server.whakapapa.link.list

Find all links of a particular "type", with options to narrow that query down.

server.whakapapa.link.list(type, opts, cb)

  • type String - one of the valid link types this module works with
  • opts Object - see ssb-crut list opts