All files index.js

100% Statements 42/42
100% Branches 20/20
100% Functions 7/7
100% Lines 42/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 1001x 1x   1x         1x                     2x 2x     2x 2x 2x 1x 1x     2x 2x         5x 7x 7x 7x 6x 6x 1x 1x 1x 1x 5x 2x   3x     1x 1x     4x                   3x 3x 3x                   2x 2x 2x 2x 2x 1x 1x       2x 2x               7x    
const CID = require('cids')
const multihashes = require('multihashes')
 
module.exports = class Graph {
  /**
   * @param {Object} ipfsDag an instance of [ipfs.dag](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dag-api)
   */
  constructor (ipfsDag) {
    this._dag = ipfsDag
  }
 
  /**
   * sets a value on a root object given its path
   * @param {Object} root
   * @param {String} path
   * @param {*} value
   * @return {Promise}
   */
  async set (root, path, value) {
    path = path.split('/')
    value = {
      '/': value
    }
    const last = path.pop()
    let {value: foundVal, remainderPath: remainder} = await this._get(root, path)
    if (remainder) {
      for (const elem of remainder) {
        foundVal = foundVal[elem] = {}
      }
    }
    foundVal[last] = value
    return root
  }
 
  async _get (root, path) {
    let edge
    while (path.length) {
      const name = path.shift()
      edge = root[name]
      if (edge && typeof edge !== 'string') {
        const link = edge['/']
        if (isValidCID(link)) {
          const cid = new CID(link)
          edge.format = cid.codec
          edge.hashAlg = multihashes.decode(cid.multihash).name
          root = edge['/'] = (await this._dag.get(cid)).value
        } else if (link) {
          root = link
        } else {
          root = edge
        }
      } else {
        path.unshift(name)
        return {value: root, remainderPath: path}
      }
    }
    return {value: root}
  }
 
  /**
   * traverses an object's path and returns the resulting value in a Promise
   * @param {Object} root
   * @param {String} path
   * @return {Promise}
   */
  async get (root, path) {
    path = path.split('/')
    const {value} = await this._get(root, path)
    return value
  }
 
  /**
   * flush an object to ipfs returning the resulting CID in a promise
   * @param {Object} root
   * @param {Object} opts - encoding options for [`dag.put`](https://github.com/ipfs/interface-ipfs-core/tree/master/API/dag#dagput)
   * @return {Promise}
   */
  async flush (root, opts) {
    const awaiting = []
    for (const name in root) {
      const edge = root[name]
      const link = edge['/']
      if (link && !isValidCID(link)) {
        awaiting.push(this.flush(link).then(cid => {
          edge['/'] = cid.toBaseEncodedString()
        }))
      }
    }
    await Promise.all(awaiting)
    return this._dag.put(root, opts || root.options || {
      format: 'dag-cbor',
      hashAlg: 'sha2-256'
    })
  }
}
 
function isValidCID (link) {
  return (typeof link === 'string' || Buffer.isBuffer(link)) && !link.options
}