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

Commit 3cbd7e8

Browse files
committed
docs: major API changes
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()` takes an iterable as input now. - `put()`: - 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 `cidVersion` option always defaults to `1`. - `.treeStream()` is renamed to `.tree()` and returns an async iterator. - `.support.add()` is renamed to `.addFormat()`. - `.support.rm()` is renamed to `.removeFormat()`. - `options.loadFormat()` is no longer callback based but is using an async function. - `putMany()` and `removeMany()` are introduced which both take an iterable as input. 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] lazy 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 #70, #175, #182, #183 Closes ipfs-inactive/interface-js-ipfs-core#121 Closes ipfs-inactive/interface-js-ipfs-core#125 Closed ipfs-inactive/interface-js-ipfs-core#137
1 parent af37805 commit 3cbd7e8

File tree

1 file changed

+122
-49
lines changed

1 file changed

+122
-49
lines changed

README.md

+122-49
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,22 @@ Want to get started? Check our examples folder. You can check the development st
3939
- [Install](#install)
4040
- [Usage](#usage)
4141
- [API](#api)
42-
- IPLD Resolver
43-
- [Constructor](#ipld-constructor)
44-
- [`.put(node, options, callback)`](#putnode-options-callback)
45-
- [`.get(cid [, path] [, options], callback)`](#getcid--path--options-callback)
46-
- [`.getStream(cid [, path] [, options])`](#getstreamcid--path--options)
47-
- [`.treeStream(cid [, path] [, options])`](#treestreamcid--path--options)
48-
- [`.remove(cid, callback)`](#removecid-callback)
49-
- [`.support.add(multicodec, formatResolver, formatUtil)`](#supportaddmulticodec-formatresolver-formatutil)
50-
- [`.support.rm(multicodec)`](#supportrmmulticodec)
51-
- [Properties](#properties)
52-
- [`defaultOptions`](#defaultoptions)
42+
- [IPLD constructor](#ipld-constructor)
43+
- [`options.blockService`](#optionsblockservice)
44+
- [`options.formats`](#optionsformats)
45+
- [`options.loadFormat(codec)`](#optionsloadformatcodec)
46+
- [`.put(node, format, options)`](#putnode-format-options)
47+
- [`.putMany(nodes, format, options)`](#putmanynode-format-options)
48+
- [`.resolve(cid, path)`](#resolvecid-path)
49+
- [`.get(cid)`](#getcid)
50+
- [`.getMany(cids)`](#getmanycids)
51+
- [`.remove(cid)`](#removecid)
52+
- [`.removeMany(cids)`](#removemanycids)
53+
- [`.tree(cid, [path], [options])`](#treecid-path-options)
54+
- [`.addFormat(ipldFormatImplementation)`](#addformatipldformatimplementation)
55+
- [`.removeFormat(codec)`](#removeformatcodec)
56+
- [Properties](#properties)
57+
- [`defaultOptions`](#defaultoptions)
5358
- [Packages](#packages)
5459
- [Contribute](#contribute)
5560
- [License](#license)
@@ -91,6 +96,21 @@ initIpld('/tmp/ifpsrepo', (err, ipld) => {
9196

9297
## API
9398

99+
The IPLD API works strictly with CIDs and deserialized IPLD Nodes. Interacting with the binary data happens on lower levels. To access the binary data directly, use the [Block API](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/BLOCK.md).
100+
101+
All methods that return an async iterator return one that got extended with convenience methods:
102+
103+
- `iter.first()`: Return the first item only
104+
- `iter.last()`: Return the last item only
105+
- `iter.all()`: Return all items as array
106+
107+
Example:
108+
109+
```js
110+
const result = ipld.getMany([cid1, cid2])
111+
const node1 = await result.first()
112+
```
113+
94114
### IPLD constructor
95115

96116
> Creates and returns an instance of IPLD.
@@ -131,83 +151,136 @@ const ipld = new Ipld({
131151
})
132152
```
133153

134-
##### `options.loadFormat(codec, callback)`
154+
##### `options.loadFormat(codec)`
135155

136156
| Type | Default |
137157
|------|---------|
138-
| `Function` | `null` |
158+
| `async Function` | `null` |
139159

140-
Function to dynamically load an [IPLD Format](https://github.com/ipld/interface-ipld-format). It is passed a string `codec`, the multicodec of the IPLD format to load and a callback function to call when the format has been loaded. e.g.
160+
Function to dynamically load an [IPLD Format](https://github.com/ipld/interface-ipld-format). It is passed a `codec`, the multicodec code of the IPLD format to load and returns an IPLD Format implementation. For example:
141161

142162
```js
163+
const multicodec = require('multicodec')
143164
const ipld = new Ipld({
144-
loadFormat (codec, callback) {
145-
if (codec === 'git-raw') {
146-
callback(null, require('ipld-git'))
165+
async loadFormat (codec) {
166+
if (codec === multicodec.GIT_RAW) {
167+
return require('ipld-git')
147168
} else {
148-
callback(new Error('unable to load format ' + codec))
169+
throw new Error('unable to load format ' + multicodec.print[codec])
149170
}
150171
}
151172
})
152173
```
153174

154-
### `.put(node, options, callback)`
175+
### `.put(node, format, options)`
176+
177+
> Stores the given IPLD Node of a recognized IPLD Format.
178+
179+
- `node` (`Object`): the deserialized IPLD node that should be inserted.
180+
- `format` (`multicodec`, required): the multicodec of the format that IPLD Node should be encoded in.
181+
- `options` is an object with the following properties:
182+
- `hashAlg` (`multicodec`, default: hash algorithm of the given multicodec): the hashing algorithm that is used to calculate the CID.
183+
- `cidVersion` (`number`, default: 1): the CID version to use.
184+
- `onlyHash` (`boolean`, default: false): if true the serialized form of the IPLD Node will not be passed to the underlying block store.
185+
186+
Returns a Promise with the CID of the serialized IPLD Node.
187+
188+
189+
### `.putMany(nodes, format, options)`
190+
191+
> Stores the given IPLD Nodes of a recognized IPLD Format.
192+
193+
- `nodes` (`AsyncIterable<Object>`): deserialized IPLD nodes that should be inserted.
194+
- `format` (`multicodec`, required): the multicodec of the format that IPLD Node should be encoded in.
195+
- `options` is applied to any of the `nodes` and is an object with the following properties:
196+
- `hashAlg` (`multicodec`, default: hash algorithm of the given multicodec): the hashing algorithm that is used to calculate the CID.
197+
- `cidVersion` (`number`, default: 1): the CID version to use.
198+
- `onlyHash` (`boolean`, default: false): if true the serialized form of the IPLD Node will not be passed to the underlying block store.
199+
200+
Returns an async iterator with the CIDs of the serialized IPLD Nodes. The iterator will throw an exception on the first error that occurs.
201+
202+
203+
### `.resolve(cid, path)`
204+
205+
> Retrieves IPLD Nodes along the `path` that is rooted at `cid`.
206+
207+
- `cid` (`CID`, required): the CID the resolving starts.
208+
- `path` (`IPLD Path`, required): the path that should be resolved.
209+
210+
Returns an async iterator of all the IPLD Nodes that were traversed during the path resolving. Every element is an object with these fields:
211+
- `remainderPath` (`string`): the part of the path that wasn’t resolved yet.
212+
- `value` (`*`): the value where the resolved path points to. If further traversing is possible, then the value is a CID object linking to another IPLD Node. If it was possible to fully resolve the path, `value` is the value the `path` points to. So if you need the CID of the IPLD Node you’re currently at, just take the `value` of the previously returned IPLD Node.
213+
214+
215+
### `.get(cid)`
216+
217+
> Retrieve an IPLD Node.
218+
219+
- `cid` (`CID`): the CID of the IPLD Node that should be retrieved.
220+
221+
Returns a Promise with the IPLD Node that correspond to the given `cid`.
222+
223+
Throws an error if the IPLD Node can’t be retrieved.
224+
225+
226+
### `.getMany(cids)`
227+
228+
> Retrieve several IPLD Nodes at once.
229+
230+
- `cids` (`AsyncIterable<CID>`): the CIDs of the IPLD Nodes that should be retrieved.
231+
232+
Returns an async iterator with the IPLD Nodes that correspond to the given `cids`.
233+
234+
Throws an error if a IPLD Node can’t be retrieved.
155235

156-
> Store the given node of a recognized IPLD Format.
157236

158-
`options` is an object that must contain one of the following combinations:
159-
- `cid` - the CID of the node
160-
- `[hashAlg]`, `[version]` and `format` - the hashAlg, version and the format that should be used to create the CID of the node. The
161-
`hashAlg` and `version` defaults to the default values for the `format`.
237+
### `.remove(cid)`
162238

163-
It may contain any of the following:
239+
> Remove an IPLD Node by the given `cid`
164240
165-
- `onlyHash` - If true the serialized form of the node will not be passed to the underlying block store but the passed callback will be invoked as if it had been
241+
- `cid` (`CID`): the CIDs of the IPLD Node that should be removed.
166242

167-
`callback` is a function that should have the signature as following: `function (err, cid) {}`, where `err` is an Error object in case of error and `cid` is the cid of the stored object.
243+
Throws an error if the IPLD Node can’t be removed.
168244

169-
### `.get(cid [, path] [, options], callback)`
170245

171-
> Retrieve a node by the given `cid` or `cid + path`
246+
### `.removeMany(cids)`
172247

173-
`options` is an optional object containing:
248+
> Remove IPLD Nodes by the given `cids`
174249
175-
- `localResolve: bool` - if true, get will only attempt to resolve the path locally
250+
- `cids` (`AsyncIterable<CID>`): the CIDs of the IPLD Nodes that should be removed.
176251

177-
`callback` should be a function with the signature `function (err, result)`, the result being an object with:
252+
Throws an error if any of the Blocks can’t be removed. This operation is not atomic, some Blocks might have already been removed.
178253

179-
- `value` - the value that resulted from the get
180-
- `remainderPath` - If it didn't manage to successfully resolve the whole path through or if simply the `localResolve` option was passed.
181-
- `cid` - Where the graph traversal finished - if `remainderPath` has a value, this will be where it has its root
182254

183-
### `.getMany(cids, callback)`
255+
### `.tree(cid, [path], [options])`
184256

185-
> Retrieve several nodes at once
257+
> Returns all the paths that can be resolved into.
186258
187-
`callback` should be a function with the signature `function (err, result)`, the result is an array with the nodes corresponding to the CIDs.
259+
- `cid` (`CID`, required): the CID to get the paths from.
260+
- `path` (`IPLD Path`, default: ''): the path to start to retrieve the other paths from.
261+
- `options`:
262+
- `recursive` (`bool`, default: false): whether to get the paths recursively or not. `false` resolves only the paths of the given CID.
188263

264+
Returns an async iterator of all the paths (as Strings) you could resolve into.
189265

190-
### `.getStream(cid [, path] [, options])`
191266

192-
> Same as get, but returns a source pull-stream that is used to pass the fetched node.
267+
### `.addFormat(ipldFormatImplementation)`
193268

194-
### `.treeStream(cid [, path] [, options])`
269+
> Add support for an IPLD Format
195270
196-
> Returns all the paths under a cid + path through a pull-stream. Accepts the following options:
271+
- `ipldFormatImplementation` (`IPLD Format`, required): the implementation of an IPLD Format.
197272

198-
- `recursive` - bool - traverse through links to complete the graph.
273+
Returns the IPLD instance. This way you can chain `addFormat()` calls.
199274

200-
### `.remove(cid, callback)`
201275

202-
> Remove a node by the given `cid`
276+
### `.removeFormat(codec)`
203277

204-
### `.support.add(multicodec, formatResolver, formatUtil)`
278+
> Remove support for an IPLD Format
205279
206-
> Add support to another IPLD Format
280+
- `codec` (`multicodec`, required): the codec of the IPLD Format to remove.
207281

208-
### `.support.rm(multicodec)`
282+
Returns the IPLD instance. This way you can chain `removeFormat()` calls.
209283

210-
> Removes support of an IPLD Format
211284

212285
### Properties
213286

0 commit comments

Comments
 (0)