-
Notifications
You must be signed in to change notification settings - Fork 37
docs: major API changes #191
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,17 +39,22 @@ Want to get started? Check our examples folder. You can check the development st | |
- [Install](#install) | ||
- [Usage](#usage) | ||
- [API](#api) | ||
- IPLD Resolver | ||
- [Constructor](#ipld-constructor) | ||
- [`.put(node, options, callback)`](#putnode-options-callback) | ||
- [`.get(cid [, path] [, options], callback)`](#getcid--path--options-callback) | ||
- [`.getStream(cid [, path] [, options])`](#getstreamcid--path--options) | ||
- [`.treeStream(cid [, path] [, options])`](#treestreamcid--path--options) | ||
- [`.remove(cid, callback)`](#removecid-callback) | ||
- [`.support.add(multicodec, formatResolver, formatUtil)`](#supportaddmulticodec-formatresolver-formatutil) | ||
- [`.support.rm(multicodec)`](#supportrmmulticodec) | ||
- [Properties](#properties) | ||
- [`defaultOptions`](#defaultoptions) | ||
- [IPLD constructor](#ipld-constructor) | ||
- [`options.blockService`](#optionsblockservice) | ||
- [`options.formats`](#optionsformats) | ||
- [`options.loadFormat(codec)`](#optionsloadformatcodec) | ||
- [`.put(node, format, options)`](#putnode-format-options) | ||
- [`.putMany(nodes, format, options)`](#putmanynode-format-options) | ||
- [`.resolve(cid, path)`](#resolvecid-path) | ||
- [`.get(cid)`](#getcid) | ||
- [`.getMany(cids)`](#getmanycids) | ||
- [`.remove(cid)`](#removecid) | ||
- [`.removeMany(cids)`](#removemanycids) | ||
- [`.tree(cid, [path], [options])`](#treecid-path-options) | ||
- [`.addFormat(ipldFormatImplementation)`](#addformatipldformatimplementation) | ||
- [`.removeFormat(codec)`](#removeformatcodec) | ||
- [Properties](#properties) | ||
- [`defaultOptions`](#defaultoptions) | ||
- [Packages](#packages) | ||
- [Contribute](#contribute) | ||
- [License](#license) | ||
|
@@ -91,6 +96,21 @@ initIpld('/tmp/ifpsrepo', (err, ipld) => { | |
|
||
## API | ||
|
||
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). | ||
|
||
All methods that return an async iterator return one that got extended with convenience methods: | ||
|
||
- `iter.first()`: Return the first item only | ||
- `iter.last()`: Return the last item only | ||
- `iter.all()`: Return all items as array | ||
|
||
Example: | ||
|
||
```js | ||
const result = ipld.getMany([cid1, cid2]) | ||
const node1 = await result.first() | ||
``` | ||
|
||
### IPLD constructor | ||
|
||
> Creates and returns an instance of IPLD. | ||
|
@@ -131,83 +151,136 @@ const ipld = new Ipld({ | |
}) | ||
``` | ||
|
||
##### `options.loadFormat(codec, callback)` | ||
##### `options.loadFormat(codec)` | ||
|
||
| Type | Default | | ||
|------|---------| | ||
| `Function` | `null` | | ||
| `async Function` | `null` | | ||
|
||
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. | ||
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: | ||
|
||
```js | ||
const multicodec = require('multicodec') | ||
const ipld = new Ipld({ | ||
loadFormat (codec, callback) { | ||
if (codec === 'git-raw') { | ||
callback(null, require('ipld-git')) | ||
async loadFormat (codec) { | ||
if (codec === multicodec.GIT_RAW) { | ||
return require('ipld-git') | ||
} else { | ||
callback(new Error('unable to load format ' + codec)) | ||
throw new Error('unable to load format ' + multicodec.print[codec]) | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
### `.put(node, options, callback)` | ||
### `.put(node, format, options)` | ||
|
||
> Stores the given IPLD Node of a recognized IPLD Format. | ||
|
||
- `node` (`Object`): the deserialized IPLD node that should be inserted. | ||
- `format` (`multicodec`, required): the multicodec of the format that IPLD Node should be encoded in. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is general question / feedback: I find passing name / code of the codec counter intuitive & I think just providing a codec instance might be better for following reasons:
I understand that without installing a codec / format Not a big deal, just in my code I find it more convenient to pass actual codecs than names. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've opened #197 so that we don't lose that idea. |
||
- `options` is an object with the following properties: | ||
- `hashAlg` (`multicodec`, default: hash algorithm of the given multicodec): the hashing algorithm that is used to calculate the CID. | ||
- `cidVersion` (`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 a Promise with the CID of the serialized IPLD Node. | ||
|
||
|
||
### `.putMany(nodes, format, options)` | ||
|
||
> Stores the given IPLD Nodes of a recognized IPLD Format. | ||
|
||
- `nodes` (`AsyncIterable<Object>`): deserialized IPLD nodes that should be inserted. | ||
- `format` (`multicodec`, required): the multicodec of the format that IPLD Node should be encoded in. | ||
- `options` is applied to any of the `nodes` and is an object with the following properties: | ||
- `hashAlg` (`multicodec`, default: hash algorithm of the given multicodec): the hashing algorithm that is used to calculate the CID. | ||
- `cidVersion` (`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. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth specifying what happens if error occurs in the middle of the iteration. |
||
Returns an async iterator with the CIDs of the serialized IPLD Nodes. The iterator will throw an exception on the first error that occurs. | ||
|
||
|
||
### `.resolve(cid, path)` | ||
|
||
> Retrieves IPLD Nodes along the `path` that is rooted at `cid`. | ||
|
||
- `cid` (`CID`, required): the CID the resolving starts. | ||
- `path` (`IPLD Path`, required): the path that should be resolved. | ||
|
||
Returns an async iterator of all the IPLD Nodes that were traversed during the path resolving. Every element is an object with these fields: | ||
- `remainderPath` (`string`): the part of the path that wasn’t resolved yet. | ||
- `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. | ||
|
||
|
||
### `.get(cid)` | ||
|
||
> Retrieve an IPLD Node. | ||
|
||
- `cid` (`CID`): the CID of the IPLD Node that should be retrieved. | ||
|
||
Returns a Promise with the IPLD Node that correspond to the given `cid`. | ||
|
||
Throws an error if the IPLD Node can’t be retrieved. | ||
|
||
|
||
### `.getMany(cids)` | ||
|
||
> Retrieve several IPLD Nodes at once. | ||
|
||
- `cids` (`AsyncIterable<CID>`): the CIDs of the IPLD Nodes that should be retrieved. | ||
|
||
Returns an async iterator with the IPLD Nodes that correspond to the given `cids`. | ||
|
||
Throws an error if a IPLD Node can’t be retrieved. | ||
|
||
> Store the given node of a recognized IPLD Format. | ||
|
||
`options` is an object that must contain one of the following combinations: | ||
- `cid` - the CID of the node | ||
- `[hashAlg]`, `[version]` and `format` - the hashAlg, version and the format that should be used to create the CID of the node. The | ||
`hashAlg` and `version` defaults to the default values for the `format`. | ||
### `.remove(cid)` | ||
|
||
It may contain any of the following: | ||
> Remove an IPLD Node by the given `cid` | ||
|
||
- `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 | ||
- `cid` (`CID`): the CIDs of the IPLD Node that should be removed. | ||
|
||
`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. | ||
Throws an error if the IPLD Node can’t be removed. | ||
|
||
### `.get(cid [, path] [, options], callback)` | ||
|
||
> Retrieve a node by the given `cid` or `cid + path` | ||
### `.removeMany(cids)` | ||
|
||
`options` is an optional object containing: | ||
> Remove IPLD Nodes by the given `cids` | ||
|
||
- `localResolve: bool` - if true, get will only attempt to resolve the path locally | ||
- `cids` (`AsyncIterable<CID>`): the CIDs of the IPLD Nodes that should be removed. | ||
|
||
`callback` should be a function with the signature `function (err, result)`, the result being an object with: | ||
Throws an error if any of the Blocks can’t be removed. This operation is not atomic, some Blocks might have already been removed. | ||
|
||
- `value` - the value that resulted from the get | ||
- `remainderPath` - If it didn't manage to successfully resolve the whole path through or if simply the `localResolve` option was passed. | ||
- `cid` - Where the graph traversal finished - if `remainderPath` has a value, this will be where it has its root | ||
|
||
### `.getMany(cids, callback)` | ||
### `.tree(cid, [path], [options])` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sidenote: I find I also kind of wish there was a way to traverse without following every branch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extracted into #198. |
||
|
||
> Retrieve several nodes at once | ||
> Returns all the paths that can be resolved into. | ||
|
||
`callback` should be a function with the signature `function (err, result)`, the result is an array with the nodes corresponding to the CIDs. | ||
- `cid` (`CID`, required): the CID to get the paths from. | ||
- `path` (`IPLD Path`, default: ''): the path to start to retrieve the other paths from. | ||
- `options`: | ||
- `recursive` (`bool`, default: false): whether to get the paths recursively or not. `false` resolves only the paths of the given CID. | ||
|
||
Returns an async iterator of all the paths (as Strings) you could resolve into. | ||
|
||
### `.getStream(cid [, path] [, options])` | ||
|
||
> Same as get, but returns a source pull-stream that is used to pass the fetched node. | ||
### `.addFormat(ipldFormatImplementation)` | ||
|
||
### `.treeStream(cid [, path] [, options])` | ||
> Add support for an IPLD Format | ||
|
||
> Returns all the paths under a cid + path through a pull-stream. Accepts the following options: | ||
- `ipldFormatImplementation` (`IPLD Format`, required): the implementation of an IPLD Format. | ||
|
||
- `recursive` - bool - traverse through links to complete the graph. | ||
Returns the IPLD instance. This way you can chain `addFormat()` calls. | ||
|
||
### `.remove(cid, callback)` | ||
|
||
> Remove a node by the given `cid` | ||
### `.removeFormat(codec)` | ||
|
||
### `.support.add(multicodec, formatResolver, formatUtil)` | ||
> Remove support for an IPLD Format | ||
|
||
> Add support to another IPLD Format | ||
- `codec` (`multicodec`, required): the codec of the IPLD Format to remove. | ||
|
||
### `.support.rm(multicodec)` | ||
Returns the IPLD instance. This way you can chain `removeFormat()` calls. | ||
|
||
> Removes support of an IPLD Format | ||
|
||
### Properties | ||
|
||
|
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 think that it this is confusing way to communicate. I would suggest to just define a type / class e.g
Batch
and say that it implements async iteration interface along with methodsfirst
,last
,all
.That would make communication clear:
putMany
takes async iterable, while it does returnBatch
, otherwise it leaves reader wondering if whetherputMany
should also be provided async iterable that has those extensions.Batch
could be exposed and could haveBatch.from(asyncIterable)
in case users need to create own API compatible instances without needing to do it on their own.Batch
API can be further extended with other methods.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've opened #196 as kind of a "catch all" issue for batch API related things.