All files index.js

100% Statements 42/42
100% Branches 19/19
100% Functions 8/8
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 100 101 102 103 104 105 106 107 1081x 1x   1x         1x                     2x 2x     2x 2x 2x 1x 1x     2x 2x         5x 7x 7x 7x 6x 6x 1x 1x 1x 5x 2x   3x     1x 1x     4x                   3x 3x 3x                   2x 2x 2x 2x 2x 1x 1x       2x 2x                       1x         7x    
const deepcopy = require('deepcopy')
const CID = require('cids')
 
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
          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) {
    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, root.options || {
      format: 'dag-cbor',
      hashAlg: 'sha2-256'
    })
  }
 
  /**
   * clones an Object via a deeep copy
   * @param {Object} root
   * return {Object}
   */
  clone (root) {
    return deepcopy(root)
  }
}
 
function isValidCID (link) {
  return typeof link === 'string' || Buffer.isBuffer(link) && !link.options
}