Example #1
0
  return promisify(async (name, opts, cb) => {
    if (typeof opts === 'function') {
      cb = opts
      opts = {}
    }

    opts = opts || {}

    if (!isIpfs.path(name)) {
      return setImmediate(() => cb(new Error('invalid argument ' + name)))
    }

    // TODO remove this and update subsequent code when IPNS is implemented
    if (!isIpfs.ipfsPath(name)) {
      return setImmediate(() => cb(new Error('resolve non-IPFS names is not implemented')))
    }

    const split = name.split('/') // ['', 'ipfs', 'hash', ...path]
    const cid = new CID(split[2])

    if (split.length === 3) {
      return setImmediate(() => cb(null, `/ipfs/${cidToString(cid, { base: opts.cidBase })}`))
    }

    const path = split.slice(3).join('/')

    const results = self._ipld.resolve(cid, path)
    let value = cid
    let remainderPath = path
    try {
      for await (const result of results) {
        if (result.remainderPath === '') {
          // Use values from previous iteration if the value isn't a CID
          if (CID.isCID(result.value)) {
            value = result.value
            remainderPath = ''
          }

          if (result.value && CID.isCID(result.value.Hash)) {
            value = result.value.Hash
            remainderPath = ''
          }

          break
        }

        value = result.value
        remainderPath = result.remainderPath
      }
    } catch (error) {
      return cb(error)
    }
    return cb(null, `/ipfs/${cidToString(value, { base: opts.cidBase })}${remainderPath ? '/' + remainderPath : ''}`)
  })
Example #2
0
test('should add and take last', async t => {
  const { node } = t.context
  const data = randomBytes(randomInteger(1, 256))
  const { cid, path } = await node.add(data).last()
  t.true(CID.isCID(cid))
  t.true(isString(path))
})
Example #3
0
  return promisify((args, opts, callback) => {
    // TODO this needs to be adjusted with the new go-ipfs http-api
    if (args && CID.isCID(args)) {
      args = multihash.toB58String(args.multihash)
    }

    if (typeof (opts) === 'function') {
      callback = opts
      opts = {}
    }

    const request = {
      path: 'block/stat',
      args: args,
      qs: opts
    }

    // Transform the response from { Key, Size } objects to { key, size } objects
    const transform = (stats, callback) => {
      callback(null, {
        key: stats.Key,
        size: stats.Size
      })
    }

    send.andTransform(request, transform, callback)
  })
Example #4
0
    const generator = async function * () {
      // End iteration if there isn't a CID to follow anymore
      while (cid !== null) {
        const format = await this._getFormat(cid.codec)

        // get block
        // use local resolver
        // update path value
        const block = await promisify(this.bs.get.bind(this.bs))(cid)
        const result = await promisify(format.resolver.resolve)(block.data, path)

        // Prepare for the next iteration if there is a `remainderPath`
        path = result.remainderPath
        let value = result.value
        // NOTE vmx 2018-11-29: Not all IPLD Formats return links as
        // CIDs yet. Hence try to convert old style links to CIDs
        if (Object.keys(value).length === 1 && '/' in value) {
          try {
            value = new CID(value['/'])
          } catch (_error) {
            value = null
          }
        }
        cid = CID.isCID(value) ? value : null

        yield {
          remainderPath: path,
          value
        }
      }
    }.bind(this)
Example #5
0
    hasDescendant: (root, childhash, callback) => {
      const seen = {}

      if (CID.isCID(childhash) || Buffer.isBuffer(childhash)) {
        childhash = toB58String(childhash)
      }

      return searchChildren(root, callback)

      function searchChildren (root, cb) {
        someSeries(root.Links, (link, done) => {
          const cid = link.Hash
          const bs58Link = toB58String(cid)

          if (bs58Link === childhash) {
            return done(null, true)
          }

          if (bs58Link in seen) {
            return done(null, false)
          }

          seen[bs58Link] = true

          dag.get(cid, '', { preload: false }, (err, res) => {
            if (err) {
              return done(err)
            }

            searchChildren(res.value, done)
          })
        }, cb)
      }
    },
Example #6
0
test('should add from iterable of string', async t => {
  const { node } = t.context
  const data = randomArray(1, 100, () => randomBytes(randomInteger(1, 64)).toString('hex'))
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #7
0
test('should add from object of string', async t => {
  const { node } = t.context
  const data = { content: randomBytes(randomInteger(1, 64)).toString('hex') }
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #8
0
test('should add from Node.js stream', async t => {
  const { node } = t.context
  const data = Fs.createReadStream(__filename)
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #9
0
test('should add from buffer', async t => {
  const { node } = t.context
  const data = randomBytes(randomInteger(1, 256))
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #10
0
test('should add from iterable of object of iterable', async t => {
  const { node } = t.context
  const data = randomArray(2, 100, () => randomBytes(randomInteger(1, 64)))
    .map(chunk => ({ content: [chunk] }))
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #11
0
 /**
  * Return a CID instance if it is a link.
  *
  * If something is a link `{"/": "baseencodedcid"}` or a CID, then return
  * a CID object, else return `null`.
  *
  * @param {*} link - The object to check
  * @returns {?CID} - A CID instance
  */
 static _maybeCID (link) {
   if (CID.isCID(link)) {
     return link
   }
   if (link && link['/'] !== undefined) {
     return new CID(link['/'])
   }
   return null
 }
Example #12
0
test('should add from iterator of buffer', async t => {
  const { node } = t.context
  const data = randomArray(1, 100, () => randomBytes(randomInteger(1, 64)))
  const iterator = function * () {
    for (let i = 0; i < data.length; i++) yield data[i]
  }
  for await (const { cid, path } of node.add(iterator())) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #13
0
  return promisify((args, opts, callback) => {
    if (typeof opts === 'function') {
      callback = opts
      opts = {}
    }

    // TODO this needs to be adjusted with the new go-ipfs http-api
    let cid
    try {
      if (CID.isCID(args)) {
        cid = args
        args = cid.toBaseEncodedString()
      } else if (Buffer.isBuffer(args)) {
        cid = new CID(args)
        args = cid.toBaseEncodedString()
      } else if (typeof args === 'string') {
        cid = new CID(args)
      } else {
        return callback(new Error('invalid argument'))
      }
    } catch (err) {
      return callback(err)
    }

    // Transform the response from Buffer or a Stream to a Block
    const transform = (res, callback) => {
      if (Buffer.isBuffer(res)) {
        callback(null, new Block(res, cid))
      // For empty blocks, concat-stream can't infer the encoding so we are
      // passed back an empty array
      } else if (Array.isArray(res) && res.length === 0) {
        callback(null, new Block(Buffer.alloc(0), cid))
      } else {
        streamToValue(res, (err, data) => {
          if (err) {
            return callback(err)
          }
          // For empty blocks, concat-stream can't infer the encoding so we are
          // passed back an empty array
          if (!data.length) data = Buffer.alloc(0)
          callback(null, new Block(data, cid))
        })
      }
    }

    const request = {
      path: 'block/get',
      args: args,
      qs: opts
    }

    send.andTransform(request, transform, callback)
  })
Example #14
0
test('should add from object of iterator', async t => {
  const { node } = t.context
  const data = {
    content: (function * () {
      yield randomBytes(randomInteger(1, 64))
    })()
  }
  for await (const { cid, path } of node.add(data)) {
    t.true(CID.isCID(cid))
    t.true(isString(path))
  }
})
Example #15
0
module.exports = function (cid) {
  if (Buffer.isBuffer(cid)) {
    return new CID(cid).toString()
  }
  if (CID.isCID(cid)) {
    return cid.toString()
  }
  if (typeof cid !== 'string') {
    throw new Error('unexpected cid type: ' + typeof cid)
  }
  new CID(cid.split('/')[0]) // eslint-disable-line no-new
  return cid
}
Example #16
0
test('should stat a directory', async t => {
  const { node } = t.context
  const path = `/test/test-stat-${shortid()}.txt`
  const data = randomBytes(256)

  await node.write(path, data, { parents: true })
  const stats = await node.stat(Path.dirname(path))

  t.true(CID.isCID(stats.cid))
  t.is(stats.size, 0)
  t.true(stats.cumulativeSize > data.length)
  t.is(stats.blocks, 1)
  t.is(stats.type, 'directory')
})
Example #17
0
test('should stat a file', async t => {
  const { node } = t.context
  const path = `/test-stat-${shortid()}.txt`
  const data = randomBytes(256)

  await node.write(path, data)
  const stats = await node.stat(path)

  t.true(CID.isCID(stats.cid))
  t.is(stats.size, data.length)
  t.true(stats.cumulativeSize > data.length)
  t.is(stats.blocks, 1)
  t.is(stats.type, 'file')
})
Example #18
0
 res.forEach(({ cid, path }) => {
   t.true(CID.isCID(cid))
   t.true(isString(path))
 })