Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

More DAG API goodness #123

Merged
merged 8 commits into from
Mar 13, 2017
Merged
Show file tree
Hide file tree
Changes from 5 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
88 changes: 83 additions & 5 deletions API/dag/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,22 @@ dag API

- `dagNode` - a DAG node that follows one of the supported IPLD formats.
- `options` - a object that might contain the follwing values:
- `format` - The IPLD format multicodec.
- `hashAlg` - The hash algorithm to be used over the serialized dagNode.
- `cid` - the CID of the node passed.
- `format` - The IPLD format multicodec.
- `hashAlg` - The hash algorithm to be used over the serialized dagNode.
- or
- `cid` - the CID of the node passed.
- **Note** - You should only pass the CID or the format + hashAlg pair and not both
- `callback` must follow `function (err) {}` signature, where `err` is an error if the operation was not successful.
- `callback` must follow `function (err, cid) {}` signature, where `err` is an error if the operation was not successful and CID is the CID generated through the process or the one that was passed

If no `callback` is passed, a [promise][] is returned.

**Example:**

```JavaScript
```

[A great source of examples can be found in the tests for this API.][examples]

#### `dag.get`

> Retrieve an IPLD format node
Expand All @@ -29,7 +37,10 @@ If no `callback` is passed, a [promise][] is returned.

##### `JavaScript` - ipfs.dag.get(cid [, path, options], callback)

- `cid` - a [CID][https://github.com/ipfs/js-cid] instance.
- `cid` - can be one of the following:
- a [CID](https://github.com/ipfs/js-cid) instance.
- a CID in its String format (i.e: zdpuAkxd9KzGwJFGhymCZRkPCXtBmBW7mB2tTuEH11HLbES9Y)
- a CID in its String format concatenated with the path to be resolved
- `path` - the path to be resolved. Optional.
- `options` - a object that might contain the following values:
- `localResolve` - bool - if set to true, it will avoid resolving through different objects.
Expand All @@ -38,3 +49,70 @@ If no `callback` is passed, a [promise][] is returned.

- `value` - the value or node that was fetched during the get operation.
- `remainderPath` - The remainder of the Path that the node was unable to resolve or what was left in a localResolve scenario.

If no `callback` is passed, a [promise][] is returned.

**Example:**

```JavaScript
```

[A great source of examples can be found in the tests for this API.][examples]

#### `dag.ls`

> Enumerate all the first level link names

##### `Go` **WIP**

##### `JavaScript` - ipfs.dag.ls(cid [, options], callback)

- `cid` - can be one of the following:
- a [CID](https://github.com/ipfs/js-cid) instance.
- a CID in its String format (i.e: zdpuAkxd9KzGwJFGhymCZRkPCXtBmBW7mB2tTuEH11HLbES9Y)
- a CID in its String format concatenated with the path to be resolved
- `options` - a object that might contain the following values:
- `stream` - bool - if set to true, it will return a Node.js Readable Stream.
- `pull` - bool - if set to true, it will return a pull-stream.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dignifiedquire what is your take on this (options for streaming)? See #121

Copy link
Contributor

Choose a reason for hiding this comment

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

I am not a big fan of this, if we want a streaming interface make it multiple methods, i.e.

  • .ls callback, no streaming
  • .lsStream node stream
  • .lsPull pull stream

or sth like that

Copy link
Contributor

Choose a reason for hiding this comment

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

Removed comment about JS specific things, section is under JavaScript so makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dignifiedquire understood. Right now it is PITA because we have places where 'xStream' is returning a pull-stream, other places where there is an option (really legacy) for buffer: true and a lot of internals that are pull-streams and the 'external' (ie js-ipfs) is Node.js Streams for the sake of not breaking API.

I would be down to just sit, define a language for this different options (or through options object or through different methods) and then apply as a golden rule throughout all the modules.

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, we should try unify this api, agreed

Copy link
Contributor Author

@daviddias daviddias Mar 9, 2017

Choose a reason for hiding this comment

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

Ok, I'll come up with a proposal then based on things we've discussed. I've some cool ideas, I believe :D

Copy link
Contributor Author

Choose a reason for hiding this comment

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

here you go #126


`callback` must follow `function (err, result) {}` signature, where `err` is an error if the operation was not successful and `result` is an Array or a Node.js Stream or a pull-stream, depending on the option passed.

If no `callback` is passed, a [promise][] is returned.

**Example:**

```JavaScript
```

[A great source of examples can be found in the tests for this API.][examples]

#### `dag.tree`

> Enumerate all the entries in a graph

##### `Go` **WIP**

##### `JavaScript` - ipfs.dag.tree(cid [, path, options], callback)

- `cid` - can be one of the following:
- a [CID](https://github.com/ipfs/js-cid) instance.
- a CID in its String format (i.e: zdpuAkxd9KzGwJFGhymCZRkPCXtBmBW7mB2tTuEH11HLbES9Y)
- a CID in its String format concatenated with the path to be resolved
- `path` - the path to be resolved. Optional.
- `options` - a object that might contain the following values:
- `recursive` - bool - if set to true, it will follow the links and continuously run tree on them, returning all the paths in the graph.
- `level`- Number - the level of nestness we want to fetch paths. A level is an hop from one node to another node.

`callback` must follow `function (err, result) {}` signature, where `err` is an error if the operation was not successful and `result` is an Array with the paths passed.

If no `callback` is passed, a [promise][] is returned.

**Example:**

```JavaScript
```

[A great source of examples can be found in the tests for this API.][examples]


[examples](../../src/dag.js)
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"bl": "^1.2.0",
"bs58": "^4.0.0",
"chai": "^3.5.0",
"cids": "^0.4.1",
"concat-stream": "^1.6.0",
"detect-node": "^2.0.3",
"ipfs-block": "^0.5.4",
Expand All @@ -54,4 +55,4 @@
"haad <[email protected]>",
"nginnever <[email protected]>"
]
}
}
85 changes: 67 additions & 18 deletions src/dag.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ const pull = require('pull-stream')
const dagPB = require('ipld-dag-pb')
const DAGNode = dagPB.DAGNode
const dagCBOR = require('ipld-dag-cbor')
const CID = require('cids')

module.exports = (common) => {
describe('.dag', () => {
describe.only('.dag', () => {
let ipfs

before(function (done) {
Expand Down Expand Up @@ -50,7 +51,7 @@ module.exports = (common) => {
}
})

describe('.put', () => {
describe.only('.put', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

please remove

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍

it('dag-pb with default hash func (sha2-256)', (done) => {
ipfs.dag.put(pbNode, {
format: 'dag-pb',
Expand Down Expand Up @@ -100,6 +101,24 @@ module.exports = (common) => {
done()
})
})

it('returns the cid', (done) => {
ipfs.dag.put(cborNode, {
format: 'dag-cbor',
hashAlg: 'sha3-512'
}, (err, cid) => {
expect(err).to.not.exist
expect(cid).to.exist
expect(CID.isCID(cid)).to.be.true
dagCBOR.util.cid(cborNode, (err, _cid) => {
expect(err).to.not.exist
expect(cid.buffer).to.eql(_cid.buffer)
done()
})
})
})

it.skip('pass the cid instead of format and hashAlg', (done) => {})
})

describe('.get', () => {
Expand Down Expand Up @@ -175,16 +194,13 @@ module.exports = (common) => {
ipfs.dag.put(pbNode, {
format: 'dag-pb',
hashAlg: 'sha2-256'
}, (err) => {
}, (err, cid) => {
expect(err).to.not.exist
dagPB.util.cid(pbNode, (err, cid) => {
ipfs.dag.get(cid, (err, result) => {
expect(err).to.not.exist
ipfs.dag.get(cid, (err, result) => {
expect(err).to.not.exist
const node = result.value
expect(pbNode.toJSON()).to.eql(node.toJSON())
done()
})
const node = result.value
expect(pbNode.toJSON()).to.eql(node.toJSON())
done()
})
})
})
Expand All @@ -193,17 +209,14 @@ module.exports = (common) => {
ipfs.dag.put(cborNode, {
format: 'dag-cbor',
hashAlg: 'sha2-256'
}, (err) => {
}, (err, cid) => {
expect(err).to.not.exist
dagCBOR.util.cid(cborNode, (err, cid) => {
ipfs.dag.get(cid, (err, result) => {
expect(err).to.not.exist
ipfs.dag.get(cid, (err, result) => {
expect(err).to.not.exist

const node = result.value
expect(cborNode).to.eql(node)
done()
})
const node = result.value
expect(cborNode).to.eql(node)
done()
})
})
})
Expand Down Expand Up @@ -267,13 +280,49 @@ module.exports = (common) => {
done()
})
})

it('CID String', (done) => {
const cidCborStr = cidCbor.toBaseEncodedString()

ipfs.dag.get(cidCborStr, (err, result) => {
expect(err).to.not.exist

const node = result.value

dagCBOR.util.cid(node, (err, cid) => {
expect(err).to.not.exist
expect(cid).to.eql(cidCbor)
done()
})
})
})

it('CID String + path', (done) => {
const cidCborStr = cidCbor.toBaseEncodedString()

ipfs.dag.get(cidCborStr + '/pb/data', (err, result) => {
expect(err).to.not.exist
expect(result.value).to.eql(new Buffer('I am inside a Protobuf'))
done()
})
})
})
})

describe('.tree', () => {
it.skip('.tree with CID', (done) => {})
it.skip('.tree with CID and path', (done) => {})
it.skip('.tree with CID and path as String', (done) => {})
it.skip('.tree with CID recursive', (done) => {})
it.skip('.tree with CID and path recursive', (done) => {})
})
})

describe('promise API', () => {
describe('.put', () => {})
describe('.get', () => {})
describe('.tree', () => {})
describe('.ls', () => {})
})
})
}