-
Notifications
You must be signed in to change notification settings - Fork 37
Conversation
The whole IPLD APIs get a review to make them more consistent and easier to use. Changes to compared to the current spec: - No more callbacks, everything is Promises. - `get()`: - Is renamed to `resolve()` to indicate that it also takes a mandatory path argument. - Doesn’t have a `cid` in the return value anymore. That use case is covered by returning all objects that were traversed. Their `value` will always be the CID of the next one to traverse. So if you want to know the CID of the current IPLD Node, just look at the `value` of the previously returned IPLD Node. - Doesn’t return a single value, but an iterator. - `localResolve` option is removed. If you want to resolve a single IPLD Node only, just stop the iterator after the first item. - `getStream()` is removed without replacement. Use `resolve()` which uses async iterators instead. - `getMany()` is renamed to `get()`: - takes an iterable of CIDs as parameter. - `put()`: - takes an iterable of CIDs as parameter. - Doesn’t take `cid` as an option anymore. The CID is always calculated (#175). - The options don’t take the `format` (which is a string), but the `codec` (which is a `multicodec`) (#175). - the `version` option always defaults to `1`. - `.treeStream()` is removed without replacement (the only current user seems to be the IPFS DAG API tree command and the ipld-explorer-cli). IPLD Nodes are just normal JavaScript objects, so you can call `Object.keys()` recursively on a IPLD Node to get all its resolvable paths. If you want to follow all the CIDs, write the tree traversal yourself. This could perhaps be an example bundled with js-ipld. - `remove()`: - takes an iterable of CIDs as parameter. - `.support.add()` is renamed to `.addFormat()`. - `.support.rm()` is renamed to `.removeFormat()`. Almost all open issues in regards to the IPLD API got adressed. One bigger thing is the Patch API, which also isn’t part of the current specification. Here’s an overview of the issues: - #66 - [ ] IPLD Resolver `patch` API: There is no patch API yet - #70 - [x] lazu value lookups: Can be done as IPLD Formats is pure JavaScript - [x] get external / local paths only: @vmx doesn’t know what this is, considers it a “won’t fix” - [x] toJSON + fromJSON - roundtrip: A roundtrip is not a goal anymore => won’t fix - [ ] put + patch api #66: Patch API is still missing - [x] text summary: @vmx doesn’t see a strong use case for this => “won’t fix” - [x] globbing: Out of scope for js-ipld - #175 - [x] Deprecate passing a CID to `ipld.put`?: Current spec doesn’t allow `put()` with a CID - #182 - [x] API Review: Links to many other issues, I list the individual issues below - #183 - [x] getting the merkle proof with resolver.resolve: `resolve()` returns all CIDs along the traversed path - #184 - [ ] Pass down the `options` object to resolver.resolve(): This needs a custom resolver. @vmx isn’t sure if the js-ipld API should make this possible, or of it should just be easy enough to create your own resolver. - https://github.com/ipfs/interface-ipfs-core/issues/81 - [x] The `dag` API - One API to manipulate all the IPLD Format objects: Interesting discussion, but not relevant anymore. - ipfs-inactive/interface-js-ipfs-core#121 - [x] dag api: add {ls, tree}: `tree()` is not part of js-ipld anymore as the IPLD Nodes are just JavaScript objects which you can easily traverse if you like. Though `tree()`-like functionality might be added as an example or separate module. - ipfs-inactive/interface-js-ipfs-core#125 - [x] `dag get --localResolve` vs `dag resolve`: This is solved by the new `resolve()` API - ipfs-inactive/interface-js-ipfs-core#137 - [x] add `level` option to ipfs.dag.tree: `tree()` is not part of js-ipld anymore. It should be considered if `tree()` is implemented (probably as an example or separate module) Closes #182.
Codecov Report
@@ Coverage Diff @@
## master #185 +/- ##
=======================================
Coverage 93.43% 93.43%
=======================================
Files 1 1
Lines 198 198
=======================================
Hits 185 185
Misses 13 13 Continue to review full report at Codecov.
|
Could we please get worked examples to easier understand the proposed API? They should just be on the README.
...and iterators ;)
Is the TLDR that when I do an
I really like this idea!
...and returns? Does it have to accept an iterable? Can it also accept a single CID?
What's the reasoning behind this? I think a string codec name is more user friendly. Perhaps it could be flexible and accept both? Also, I'm fine with It's also consistent with the current IPFS DAG API e.g. https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/DAG.md#dagput and the IPFS block API https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md#blockput
Does it have to accept an iterable? Can it also accept a single CID?
...and could you expand on what they accept? |
Thanks for the feedback!
No. The last element will only contain
It's just an overview so you get an idea if you know the old API/want to upgrade. For details please see the changes on the README itself.
I'm unsure myself. On one hand I'd like to keep the API (and types) as small as possible, on the other hand it should still be nice to use. So I guess changing it to "single item or iterable" might be a good idea. Output from others would be great. About taking the format as string or codec: I'd prefer if all libraries would use the codec instead of a string internally. To pass the right value in you could then import the multicodec table and use something like |
Interesting, I think these changes are pretty good, though like @alanshaw I'd like to see some examples of old vs new api.
Is there ever a case where there wouldn't be a previous node? |
Yes there is. If you only return a single node. But in this case you already know that CID of that node as it is the one you passed into |
Then I'd really like to see some examples of how you see this working in practice 😉 Is it so bad to pass all of the context (e.g. including the CID of the result) to the result handler? That way the handler wouldn't need to know about anything further up the call chain so can limit its scope. |
Most importantly the `tree()` method is added again. It's really needed for backwards compatibility.
Loading a format is no longer callback based but is using an async function.
`doctoc` was used to update the table of contents.
I think this is all fine. The only extra thing I'd like is for |
I had this code, but then I wanted to keep things simple. I didn't really need it for any of the PRs. When it comes up and it helps simplifying code, I'm happy to add it in a later PR. |
Fair enough. We had that feature previously - it made |
- `version` (`number`, default: 1): the CID version to use. | ||
- `onlyHash` (`boolean`, default: false): if true the serialized form of the IPLD Node will not be passed to the underlying block store. | ||
|
||
Returns an async iterator with the CIDs of the serialized IPLD Nodes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not return the full block instances? It doesn’t really cost us anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to expose the serialized form of the nodes like that? I don't think it's needed from the IPFS point of view but are there use cases where this is desirable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's needed from the IPFS point of view but are there use cases where this is desirable?
It's actually a good point. When using IPLD you shouldn't really care about how it is serialized. I'm always in favour having a minimal API :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly - it doesn't feel like an application-level concern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would agree if the API only returned the final value it had resolved, but it doesn’t, it returns all the CID’s it passed through to resolve the path. It’s already exposing the serialization just by giving you the CID’s of the intermediate nodes and in that case, why not just give me the blocks if you already have them? It costs nothing on the consumer side to ignore the content and just use the CID and it saves a BlockService lookup if you do need the data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me it's about abstractions. In js-ipld you only care about the the IPLD Data types. A CID is as low as you go, you don't care about how it is serialized, but only about that it got serialized.
IPLD Formats are the low level building block, which is about serialized data. You should use that level if you have needs to operate on that level.
I think not exposing the serialized data would make IPLD easier to use as it is one less concept to learn.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikeal This discussion is the last outstanding one. Would you be OK with moving forward with the current state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya, it’s fine, go ahead and merge.
The `format` is no longer part of the the options object, but a separate parameter. The `version` option was renamed to `cidVersion`.
I've created a rebased version of this PR at #191. It is now a single commit with an update commit message. Once merged it will close a lot of issues. Hence I'll wait for the merge unti #190 is merged, so that people looking into the README or the closed issue can actually use the new code. Thanks everyone for the review! |
The whole IPLD APIs get a review to make them more consistent and
easier to use.
Changes to compared to the current spec:
get()
:resolve()
to indicate that it also takes a mandatorypath argument.
cid
in the return value anymore. That use case iscovered by returning all objects that were traversed. Their
value
will always be the CID of the next one to traverse. So if you want
to know the CID of the current IPLD Node, just look at the
value
of the previously returned IPLD Node.
localResolve
option is removed. If you want to resolve a single IPLDNode only, just stop the iterator after the first item.
getStream()
is removed without replacement. Useresolve()
which usesasync iterators instead.
getMany()
is renamed toget()
:put()
:cid
as an option anymore. The CID is always calculated(Deprecate passing a CID to
ipld.put
? #175).format
(which is a string), but thecodec
(which is a
multicodec
) (Deprecate passing a CID toipld.put
? #175).version
option always defaults to1
..treeStream()
is removed without replacement (the only current user seemsto be the IPFS DAG API tree command and the ipld-explorer-cli). IPLD Nodes
are just normal JavaScript objects, so you can call
Object.keys()
recursively on a IPLD Node to get all its resolvable paths. If you want to
follow all the CIDs, write the tree traversal yourself. This could perhaps
be an example bundled with js-ipld.
remove()
:.support.add()
is renamed to.addFormat()
..support.rm()
is renamed to.removeFormat()
.Almost all open issues in regards to the IPLD API got adressed. One bigger
thing is the Patch API, which also isn’t part of the current specification.
Here’s an overview of the issues:
patch
API #66patch
API: There is no patch API yetconsiders it a “won’t fix”
=> won’t fix
patch
API #66: Patch API is still missingipld.put
? #175ipld.put
?: Current spec doesn’t allowput()
with a CIDbelow
resolve()
returnsall CIDs along the traversed path
options
object to resolver.resolve() #184options
object to resolver.resolve(): This needs acustom resolver. @vmx isn’t sure if the js-ipld API should make this
possible, or of it should just be easy enough to create your own
resolver.
dag
API - One API to manipulate all the IPLD Format objects:Interesting discussion, but not relevant anymore.
tree()
is not part of js-ipld anymore asthe IPLD Nodes are just JavaScript objects which you can easily traverse
if you like. Though
tree()
-like functionality might be added as anexample or separate module.
dag get --localResolve
vsdag resolve
ipfs-inactive/interface-js-ipfs-core#125dag get --localResolve
vsdag resolve
: This is solved by the newresolve()
APIlevel
option to ipfs.dag.tree ipfs-inactive/interface-js-ipfs-core#137level
option to ipfs.dag.tree:tree()
is not part of js-ipldanymore. It should be considered if
tree()
is implemented (probablyas an example or separate module)
Closes #182.
Others that might be interested: @achingbrain @alanshaw @olizilla