Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 1c8247c

Browse files
committed
refactor: ipfs.add only works on single items, ipfs.addAll works on multiple
`ipfs.add` returns single items only. Where a source would result in multiple items returned, only the last item is returned. `ipfs.addAll` retains the previous behaviour of `ipfs.add`. Examples: ```javascript const { cid, path, mode, mtime } = await ipfs.add('Hello world') ``` ```javascript const { cid } = await ipfs.add(Uint16Array.from([0, 1, 2])) ``` ```javascript const { cid } = await ipfs.add({ path: '/foo/bar/baz.txt', content: 'File content' }) // cid is the CID for the root directory /foo for await (const buf of ipfs.cat(`/ipfs/${cid}/bar/baz.txt`)) { ... } ``` BREAKING CHANGES: - `ipfs.add` only works on single items - a Uint8Array, a String, an AsyncIterable<Uint8Array> etc - `ipfs.addAll` works on multiple items
1 parent 1c91feb commit 1c8247c

File tree

64 files changed

+872
-612
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+872
-612
lines changed

docs/core-api/FILES.md

+161-44
Original file line numberDiff line numberDiff line change
@@ -9,85 +9,89 @@ _Explore the Mutable File System through interactive coding challenges in our [P
99
- [Parameters](#parameters)
1010
- [Options](#options)
1111
- [Returns](#returns)
12+
- [`ipfs.addAll(source, [options])`](#ipfsaddallsource-options)
13+
- [Parameters](#parameters-1)
14+
- [Options](#options-1)
15+
- [Returns](#returns-1)
1216
- [Notes](#notes)
1317
- [Chunking options](#chunking-options)
1418
- [Hash algorithms](#hash-algorithms)
1519
- [Importing files from the file system](#importing-files-from-the-file-system)
1620
- [Importing a file from a URL](#importing-a-file-from-a-url)
1721
- [`ipfs.cat(ipfsPath, [options])`](#ipfscatipfspath-options)
18-
- [Parameters](#parameters-1)
19-
- [Options](#options-1)
20-
- [Returns](#returns-1)
21-
- [Example](#example)
22-
- [`ipfs.get(ipfsPath, [options])`](#ipfsgetipfspath-options)
2322
- [Parameters](#parameters-2)
2423
- [Options](#options-2)
2524
- [Returns](#returns-2)
26-
- [`ipfs.ls(ipfsPath)`](#ipfslsipfspath)
25+
- [Example](#example)
26+
- [`ipfs.get(ipfsPath, [options])`](#ipfsgetipfspath-options)
2727
- [Parameters](#parameters-3)
2828
- [Options](#options-3)
2929
- [Returns](#returns-3)
30-
- [Example](#example-1)
31-
- [The Mutable Files API](#the-mutable-files-api)
32-
- [`ipfs.files.chmod(path, mode, [options])`](#ipfsfileschmodpath-mode-options)
30+
- [`ipfs.ls(ipfsPath)`](#ipfslsipfspath)
3331
- [Parameters](#parameters-4)
3432
- [Options](#options-4)
3533
- [Returns](#returns-4)
36-
- [Example](#example-2)
37-
- [`ipfs.files.cp(...from, to, [options])`](#ipfsfilescpfrom-to-options)
34+
- [Example](#example-1)
35+
- [The Mutable Files API](#the-mutable-files-api)
36+
- [`ipfs.files.chmod(path, mode, [options])`](#ipfsfileschmodpath-mode-options)
3837
- [Parameters](#parameters-5)
3938
- [Options](#options-5)
4039
- [Returns](#returns-5)
41-
- [Example](#example-3)
42-
- [Notes](#notes-1)
43-
- [`ipfs.files.mkdir(path, [options])`](#ipfsfilesmkdirpath-options)
40+
- [Example](#example-2)
41+
- [`ipfs.files.cp(...from, to, [options])`](#ipfsfilescpfrom-to-options)
4442
- [Parameters](#parameters-6)
4543
- [Options](#options-6)
4644
- [Returns](#returns-6)
47-
- [Example](#example-4)
48-
- [`ipfs.files.stat(path, [options])`](#ipfsfilesstatpath-options)
45+
- [Example](#example-3)
46+
- [Notes](#notes-1)
47+
- [`ipfs.files.mkdir(path, [options])`](#ipfsfilesmkdirpath-options)
4948
- [Parameters](#parameters-7)
5049
- [Options](#options-7)
5150
- [Returns](#returns-7)
52-
- [Example](#example-5)
53-
- [`ipfs.files.touch(path, [options])`](#ipfsfilestouchpath-options)
51+
- [Example](#example-4)
52+
- [`ipfs.files.stat(path, [options])`](#ipfsfilesstatpath-options)
5453
- [Parameters](#parameters-8)
5554
- [Options](#options-8)
5655
- [Returns](#returns-8)
57-
- [Example](#example-6)
58-
- [`ipfs.files.rm(...paths, [options])`](#ipfsfilesrmpaths-options)
56+
- [Example](#example-5)
57+
- [`ipfs.files.touch(path, [options])`](#ipfsfilestouchpath-options)
5958
- [Parameters](#parameters-9)
6059
- [Options](#options-9)
61-
- [Example](#example-7)
62-
- [`ipfs.files.read(path, [options])`](#ipfsfilesreadpath-options)
60+
- [Returns](#returns-9)
61+
- [Example](#example-6)
62+
- [`ipfs.files.rm(...paths, [options])`](#ipfsfilesrmpaths-options)
6363
- [Parameters](#parameters-10)
6464
- [Options](#options-10)
65-
- [Returns](#returns-9)
66-
- [`ipfs.files.write(path, content, [options])`](#ipfsfileswritepath-content-options)
65+
- [Example](#example-7)
66+
- [`ipfs.files.read(path, [options])`](#ipfsfilesreadpath-options)
6767
- [Parameters](#parameters-11)
6868
- [Options](#options-11)
6969
- [Returns](#returns-10)
70-
- [`ipfs.files.mv(...from, to, [options])`](#ipfsfilesmvfrom-to-options)
70+
- [`ipfs.files.write(path, content, [options])`](#ipfsfileswritepath-content-options)
7171
- [Parameters](#parameters-12)
7272
- [Options](#options-12)
7373
- [Returns](#returns-11)
74-
- [Example](#example-8)
75-
- [`ipfs.files.flush(path, [options])`](#ipfsfilesflushpath-options)
74+
- [`ipfs.files.mv(...from, to, [options])`](#ipfsfilesmvfrom-to-options)
7675
- [Parameters](#parameters-13)
7776
- [Options](#options-13)
7877
- [Returns](#returns-12)
79-
- [`ipfs.files.ls(path, [options])`](#ipfsfileslspath-options)
78+
- [Example](#example-8)
79+
- [`ipfs.files.flush(path, [options])`](#ipfsfilesflushpath-options)
8080
- [Parameters](#parameters-14)
8181
- [Options](#options-14)
8282
- [Returns](#returns-13)
83+
- [`ipfs.files.ls(path, [options])`](#ipfsfileslspath-options)
84+
- [Parameters](#parameters-15)
85+
- [Options](#options-15)
86+
- [Returns](#returns-14)
8387
- [Example](#example-9)
8488

8589
## The Regular API
8690
The regular, top-level API for add, cat, get and ls Files on IPFS
8791

8892
### `ipfs.add(data, [options])`
8993

90-
> Import files and data into IPFS.
94+
> Import a file or data into IPFS.
9195
9296
#### Parameters
9397

@@ -97,19 +101,132 @@ The regular, top-level API for add, cat, get and ls Files on IPFS
97101

98102
`data` may be:
99103

100-
* `Bytes` (alias for `Buffer`|`ArrayBuffer`|`TypedArray`) [single file]
101-
* `Bloby` (alias for: `Blob`|`File`) [single file]
102-
* `string` [single file]
103-
* `FileObject` (see below for definition) [single file]
104-
* `Iterable<number>` [single file]
105-
* `Iterable<Bytes>` [single file]
106-
* `Iterable<Bloby>` [multiple files]
107-
* `Iterable<string>` [multiple files]
108-
* `Iterable<FileObject>` [multiple files]
109-
* `AsyncIterable<Bytes>` [single file]
110-
* `AsyncIterable<Bloby>` [multiple files]
111-
* `AsyncIterable<String>` [multiple files]
112-
* `AsyncIterable<FileObject>` [multiple files]
104+
* `Blob`
105+
* `String`
106+
* `Uint8Array`
107+
* `FileObject` (see below for definition)
108+
* `Iterable<Uint8Array>`
109+
* `AsyncIterable<Uint8Array>`
110+
111+
`FileObject` is a plain JS object of the following form:
112+
113+
```js
114+
{
115+
// The path you want to the file to be accessible at from the root CID _after_ it has been added
116+
path?: string
117+
// The contents of the file (see below for definition)
118+
content?: FileContent
119+
// File mode to store the entry with (see https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation)
120+
mode?: number | string
121+
// The modification time of the entry (see below for definition)
122+
mtime?: UnixTime
123+
}
124+
```
125+
126+
If no `path` is specified, then the item will be added to the root level and will be given a name according to it's CID.
127+
128+
If no `content` is passed, then the item is treated as an empty directory.
129+
130+
One of `path` or `content` _must_ be passed.
131+
132+
`FileContent` is one of the following types:
133+
134+
```js
135+
Uint8Array | Blob | String | Iterable<Uint8Array> | AsyncIterable<Uint8Array>
136+
```
137+
138+
`UnixTime` is one of the following types:
139+
140+
```js
141+
Date | { secs: number, nsecs?: number } | number[]
142+
```
143+
144+
As an object, `secs` is the number of seconds since (positive) or before (negative) the Unix Epoch began and `nsecs` is the number of nanoseconds since the last full second.
145+
146+
As an array of numbers, it must have two elements, as per the output of [`process.hrtime()`](https://nodejs.org/dist/latest/docs/api/process.html#process_process_hrtime_time).
147+
148+
#### Options
149+
150+
An optional object which may have the following keys:
151+
152+
| Name | Type | Default | Description |
153+
| ---- | ---- | ------- | ----------- |
154+
| chunker | `String` | `'size-262144` | chunking algorithm used to build ipfs DAGs |
155+
| cidVersion | `Number` | `0` | the CID version to use when storing the data |
156+
| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use |
157+
| onlyHash | `boolean` | `false` | If true, will not add blocks to the blockstore |
158+
| pin | `boolean` | `true` | pin this object when adding |
159+
| progress | function | `undefined` | a function that will be called with the byte length of chunks as a file is added to ipfs |
160+
| rawLeaves | `boolean` | `false` | if true, DAG leaves will contain raw file data and not be wrapped in a protobuf |
161+
| trickle | `boolean` | `false` | if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation |
162+
| wrapWithDirectory | `boolean` | `false` | Adds a wrapping node around the content |
163+
| timeout | `Number` | `undefined` | A timeout in ms |
164+
| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call |
165+
166+
#### Returns
167+
168+
| Type | Description |
169+
| -------- | -------- |
170+
| `UnixFSEntry` | A object describing the added data |
171+
172+
Each yielded object is of the form:
173+
174+
```JavaScript
175+
{
176+
path: '/tmp/myfile.txt',
177+
cid: CID('QmHash'),
178+
mode: Number,
179+
mtime: { secs: Number, nsecs: Number },
180+
size: 123
181+
}
182+
```
183+
184+
#### Example
185+
186+
```js
187+
const file = {
188+
path: '/tmp/myfile.txt',
189+
content: 'ABC'
190+
}
191+
192+
const result of await ipfs.add(content)
193+
194+
console.info(result)
195+
196+
/*
197+
Prints:
198+
{
199+
"path": "tmp",
200+
"cid": CID("QmWXdjNC362aPDtwHPUE9o2VMqPeNeCQuTBTv1NsKtwypg"),
201+
"mode": 493,
202+
"mtime": { secs: Number, nsecs: Number },
203+
"size": 67
204+
}
205+
*/
206+
```
207+
208+
Now [ipfs.io/ipfs/Qm..pg/myfile.txt](https://ipfs.io/ipfs/QmWXdjNC362aPDtwHPUE9o2VMqPeNeCQuTBTv1NsKtwypg/myfile.txt) returns the "ABC" string.
209+
210+
### `ipfs.addAll(source, [options])`
211+
212+
> Import multiple files and data into IPFS.
213+
214+
#### Parameters
215+
216+
| Name | Type | Description |
217+
| ---- | ---- | ----------- |
218+
| source | Object | Data to import (see below) |
219+
220+
`source` may be:
221+
222+
* `Iterable<Blob>`
223+
* `Iterable<String>`
224+
* `Iterable<Uint8Array>`
225+
* `Iterable<FileObject>`
226+
* `AsyncIterable<Blob>`
227+
* `AsyncIterable<String>`
228+
* `AsyncIterable<Uint8Array>`
229+
* `AsyncIterable<FileObject>`
113230

114231
`FileObject` is a plain JS object of the following form:
115232

@@ -135,7 +252,7 @@ One of `path` or `content` _must_ be passed.
135252
`FileContent` is one of the following types:
136253

137254
```js
138-
Bytes | Bloby | string | Iterable<number> | Iterable<Bytes> | AsyncIterable<Bytes>
255+
Uint8Array | Blob | String | Iterable<Uint8Array> | AsyncIterable<Uint8Array>
139256
```
140257

141258
`UnixTime` is one of the following types:
@@ -172,7 +289,7 @@ An optional object which may have the following keys:
172289

173290
| Type | Description |
174291
| -------- | -------- |
175-
| `AsyncIterable<Object>` | An async iterable that yields objects describing the added data |
292+
| `AsyncIterable<UnixFSEntry>` | An async iterable that yields objects describing the added data |
176293

177294
Each yielded object is of the form:
178295

examples/browser-add-readable-stream/index.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ const streamFiles = async (ipfs, directory, files) => {
5252
}
5353
})
5454

55-
for await (const data of ipfs.add(stream)) {
56-
log(`Added ${data.path} hash: ${data.hash}`)
55+
const data = await ipfs.add(stream)
5756

58-
// The last data event will contain the directory hash
59-
if (data.path === directory) {
60-
return data.cid
61-
}
57+
log(`Added ${data.path} hash: ${data.hash}`)
58+
59+
// The last data event will contain the directory hash
60+
if (data.path === directory) {
61+
return data.cid
6262
}
6363
}
6464

examples/browser-browserify/src/index.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ document.addEventListener('DOMContentLoaded', async () => {
1010
async function store () {
1111
const toStore = document.getElementById('source').value
1212

13-
for await (const file of node.add(toStore)) {
14-
if (file && file.cid) {
15-
console.log('successfully stored', file.cid)
13+
const file = await node.add(toStore)
1614

17-
await display(file.cid)
18-
}
19-
}
15+
console.log('successfully stored', file.cid)
16+
17+
await display(file.cid)
2018
}
2119

2220
async function display (cid) {

examples/browser-parceljs/public/index.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,17 @@ document.addEventListener('DOMContentLoaded', async () => {
2222

2323
log(`The IPFS node version is ${version.version}`)
2424

25-
for await (const entry of node.add({
25+
const entry = await node.add({
2626
path: 'hello-parcel.txt',
2727
content: 'Hello from parcel.js bundled ipfs example'
28-
})) {
29-
log(`This page deployed ${entry.path} to IPFS and its CID is ${entry.cid}`)
28+
})
29+
log(`This page deployed ${entry.path} to IPFS and its CID is ${entry.cid}`)
3030

31-
const buffers = []
31+
const buffers = []
3232

33-
for await (const buf of node.cat(entry.cid)) {
34-
buffers.push(buf)
35-
}
36-
37-
log(`The contents of the file was: ${Buffer.concat(buffers).toString()}`)
33+
for await (const buf of node.cat(entry.cid)) {
34+
buffers.push(buf)
3835
}
36+
37+
log(`The contents of the file was: ${Buffer.concat(buffers).toString()}`)
3938
})

examples/browser-readablestream/utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const dragDrop = (ipfs) => {
4545

4646
const progress = log(`IPFS: Adding...`)
4747

48-
for await (const added of ipfs.add(files, {
48+
for await (const added of ipfs.addAll(files, {
4949
progress: (addedBytes) => {
5050
progress.textContent = `IPFS: Adding ${addedBytes} bytes\r\n`
5151
}

examples/browser-script-tag/index.html

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ <h2>Some suggestions</h2>
3131

3232
<code style="display:block; white-space:pre-wrap; background-color:#d7d6d6">
3333
async function addFile () {
34-
for await (const { cid } of node.add('Hello world!')) {
35-
console.log('successfully stored', cid)
36-
}
34+
const { cid } = await node.add('Hello world!'))
35+
console.log('successfully stored', cid)
3736
}
3837

3938
addFile()

examples/browser-webpack/src/components/app.js

+8-9
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,17 @@ class App extends React.Component {
3030

3131
this.setState({ id, agentVersion, protocolVersion })
3232

33-
for await (const { cid } of node.add(stringToUse)) {
34-
this.setState({ addedFileHash: cid.toString() })
33+
const { cid } = await node.add(stringToUse)
34+
this.setState({ addedFileHash: cid.toString() })
3535

36-
let bufs = []
36+
let bufs = []
3737

38-
for await (const buf of node.cat(cid)) {
39-
bufs.push(buf)
40-
}
41-
42-
const data = Buffer.concat(bufs)
43-
this.setState({ addedFileContents: data.toString('utf8') })
38+
for await (const buf of node.cat(cid)) {
39+
bufs.push(buf)
4440
}
41+
42+
const data = Buffer.concat(bufs)
43+
this.setState({ addedFileContents: data.toString('utf8') })
4544
}
4645

4746
render () {

0 commit comments

Comments
 (0)