Skip to content
This repository has been archived by the owner on Aug 11, 2021. It is now read-only.

Awesome IPLD endeavour #60

Merged
merged 15 commits into from
Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# IPFS IPLD
# IPLD Resolver

[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](http://ipn.io)
[![](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://ipfs.io/)
[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23ipfs)
[![Coverage Status](https://coveralls.io/repos/github/ipfs/js-ipld-resolver/badge.svg?branch=master)](https://coveralls.io/github/ipfs/js-ipld-resolver?branch=master)
[![Travis CI](https://travis-ci.org/ipfs/js-ipld-resolver.svg?branch=master)](https://travis-ci.org/ipfs/js-ipld-resolver)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's move this to the ipld organization as part of this effort

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it's already on the IPLD org, forgot to change the badges. Good catch :)

[![Circle CI](https://circleci.com/gh/ipfs/js-ipld-resolver.svg?style=svg)](https://circleci.com/gh/ipfs/js-ipld-resolver)
[![Dependency Status](https://david-dm.org/ipfs/js-ipld-resolver.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipld-resolver)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![Coverage Status](https://coveralls.io/repos/github/ipfs/js-ipfs-ipld/badge.svg?branch=master)](https://coveralls.io/github/ipfs/js-ipfs-ipld?branch=master)
[![Travis CI](https://travis-ci.org/ipfs/js-ipfs-ipld.svg?branch=master)](https://travis-ci.org/ipfs/js-ipfs-ipld)
[![Circle CI](https://circleci.com/gh/ipfs/js-ipfs-ipld.svg?style=svg)](https://circleci.com/gh/ipfs/js-ipfs-ipld)
[![Dependency Status](https://david-dm.org/ipfs/js-ipfs-ipld.svg?style=flat-square)](https://david-dm.org/ipfs/js-ipfs-ipld) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard)

> JavaScript implementation of the IPLDService
> JavaScript implementation of the IPLD Resolver

## Table of Contents

Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ipfs-ipld",
"name": "ipld-resolver",
"version": "3.0.0",
"description": "IPLD implementation in JavaScript",
"description": "IPLD Resolver Implementation in JavaScript",
"main": "lib/index.js",
"jsnext:main": "src/index.js",
"pre-commit": [
Expand Down Expand Up @@ -34,7 +34,7 @@
"homepage": "https://github.com/ipfs/js-ipfs-ipld#readme",
"license": "MIT",
"devDependencies": {
"aegir": "^8.0.1",
"aegir": "^8.1.2",
"async": "^2.0.1",
"buffer-loader": "0.0.1",
"chai": "^3.5.0",
Expand All @@ -48,7 +48,9 @@
"rimraf": "^2.5.4"
},
"dependencies": {
"async": "^2.1.1",
"babel-runtime": "^6.11.6",
"interface-pull-blob-store": "^0.5.0",
"ipfs-block": "^0.3.0",
"ipld": "^0.6.0",
"is-ipfs": "^0.2.0",
Expand All @@ -64,4 +66,4 @@
"greenkeeperio-bot <support@greenkeeper.io>",
"nicola <me@nicola.io>"
]
}
}
168 changes: 166 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,168 @@
'use strict'

exports.IPLDService = require('./ipld-service')
exports.resolve = require('./resolve')
const Block = require('ipfs-block')
const pull = require('pull-stream')
const traverse = require('pull-traverse')
const utils = require('./utils')
const CID = require('cids')
const until = require('async/until')
const IPFSRepo = require('ipfs-repo')
const MemoryStore = require('../node_modules/interface-pull-blob-store/lib/reference.js')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do require('interface-pull-blob-store/lib/reference.js') instead, no need for the full path

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right! (I do remember fighting with this one and this was how I got it to reference to the right one, not sure what was the error without node_modules though).

Could you also check ipfs-inactive/interface-pull-blob-store#6, this way we don't even have to point to a path inside.

const BlockService = require('ipfs-block-service')

const dagPB = require('ipld-dag-pb')
const dagCBOR = require('ipld-dag-cbor')

class IPLDResolver {
constructor (blockService) {
// nicola will love this!
if (!blockService) {
const repo = new IPFSRepo('in-memory', { stores: MemoryStore })
blockService = new BlockService(repo)
}

this.bs = blockService
this.resolvers = {}

// Support by default dag-pb and dag-cbor
this.support(dagPB.resolver.multicodec, dagPB.resolver, dagPB.util)
this.support(dagCBOR.resolver.multicodec, dagCBOR.resolver, dagCBOR.util)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should there be a way to disable these defaults?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about having functions to add and remove, so that:

  • this.support.add
  • this.support.rm

}

// Adds support for an IPLD format
// default ones are dag-pb and dag-cbor
support (multicodec, resolver, util) {
this.resolvers[multicodec] = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe warn on overriding?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

resolver: resolver,
util: util
}
}

resolve (cid, path, callback) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are cid and path two different inputs?
Can we not just pass cid+path?
the "deconcatenation" is something that I will happen to do often

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicola note that CID is a instance of class CID that has several utility methods https://github.com/ipfs/js-cid/tree/feat/complete

What you are proposing is to use cids always as strings, which would assume that we have to be constantly parsing and mounting them again to get their props.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see, perfect then.

There must be up in the levels of abstraction a sort of resolver that takes a path and resolve that (by using this, I guess)

if (path === '/') {
return this.get(cid, callback)
}

let value

until(
() => {
if (!path || path === '' || path === '/') {
return true
} else {
// continue traversing
if (value) {
cid = new CID(value['/'])
}
return false
}
},
(cb) => {
// get block
// use local resolver
// update path value
this.bs.get(cid, (err, block) => {
if (err) {
return cb(err)
}
const result = this.resolvers[cid.codec].resolver.resolve(block, path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be a check with a nice error message for this.resolvers[cid.codec] as this can easily be undefined

value = result.value
path = result.remainderPath
cb()
})
},
(err, results) => {
if (err) {
return callback(err)
}
return callback(null, value)
}
)
}

// Node operations (get and retrieve nodes, not values)

put (nodeAndCID, callback) {
callback = callback || noop
pull(
pull.values([nodeAndCID]),
this.putStream(callback)
)
}

putStream (callback) {
callback = callback || noop

return pull(
pull.map((nodeAndCID) => {
const cid = nodeAndCID.cid
const r = this.resolvers[cid.codec]
return {
block: new Block(r.util.serialize(nodeAndCID.node)),
cid: cid
}
}),
this.bs.putStream(),
pull.onEnd(callback)
)
}

get (cid, callback) {
pull(
this.getStream(cid),
pull.collect((err, res) => {
if (err) {
return callback(err)
}
callback(null, res[0])
})
)
}

getStream (cid) {
return pull(
this.bs.getStream(cid),
pull.map((block) => {
const r = this.resolvers[cid.codec]
if (r) {
return r.util.deserialize(block.data)
} else { // multicodec unknown, send back raw data
return block.data
}
})
)
}

// TODO: Consider if we still want this (fact: no one is using it
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets use this opportunity to drop the recursive methods

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍

// right now and this will be just an IPLD selector anyway
getRecursive (cid, callback) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During the Toronto's IPLD call, we mentioned that this should be a BFS and should have an optional parameter x where if set to false or -1, we explore recursively the entire graph, otherwise, we just move with depth x

Copy link
Member Author

@daviddias daviddias Oct 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What we talked was .tree method inside an IPLD format.

This getRecursive is an old method that comes from the previous "DAGService", which was never used in practice. This method returns the nodes directly, not their values.

What you make me think is that we should have a .tree at the main IPLD Resolver and make that option part of the interface-ipld-format for local resolvers too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ perfect

pull(
this.getRecursiveStream(cid),
pull.collect(callback)
)
}

getRecursiveStream (cid) {
return pull(
this.getStream(cid),
pull.map((node) => {
traverse.widthFirst(node, (node) => {
return pull(
pull.values(utils.getKeys(node)),
pull.map((link) => this.getStream(link)),
pull.flatten()
)
})
}),
pull.flatten()
)
}

remove (cids, callback) {
this.bs.delete(cids, callback)
}
}

function noop () {}

module.exports = IPLDResolver
115 changes: 0 additions & 115 deletions src/ipld-service.js

This file was deleted.

Loading