hypercore 10.0.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -32
- package/index.js +6 -15
- package/lib/bitfield.js +1 -1
- package/lib/block-store.js +6 -3
- package/lib/core.js +23 -12
- package/lib/download.js +22 -0
- package/lib/info.js +1 -0
- package/lib/merkle-tree.js +1 -1
- package/lib/oplog.js +2 -2
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -83,12 +83,31 @@ valueEncodings will be applied to individually blocks, even if you append batche
|
|
|
83
83
|
Append a block of data (or an array of blocks) to the core.
|
|
84
84
|
Returns the new length and byte length of the core.
|
|
85
85
|
|
|
86
|
+
``` js
|
|
87
|
+
// simple call append with a new block of data
|
|
88
|
+
await core.append(Buffer.from('I am a block of data'))
|
|
89
|
+
|
|
90
|
+
// pass an array to append multiple blocks as a batch
|
|
91
|
+
await core.append([Buffer.from('batch block 1'), Buffer.from('batch block 2')])
|
|
92
|
+
```
|
|
93
|
+
|
|
86
94
|
#### `const block = await core.get(index, [options])`
|
|
87
95
|
|
|
88
96
|
Get a block of data.
|
|
89
97
|
If the data is not available locally this method will prioritize and wait for the data to be downloaded.
|
|
90
98
|
|
|
91
|
-
|
|
99
|
+
``` js
|
|
100
|
+
// get block #42
|
|
101
|
+
const block = await core.get(42)
|
|
102
|
+
|
|
103
|
+
// get block #43, but only wait 5s
|
|
104
|
+
const blockIfFast = await core.get(43, { timeout: 5000 })
|
|
105
|
+
|
|
106
|
+
// get block #44, but only if we have it locally
|
|
107
|
+
const blockLocal = await core.get(44, { wait: false })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Additional options include
|
|
92
111
|
|
|
93
112
|
``` js
|
|
94
113
|
{
|
|
@@ -99,20 +118,52 @@ Options include
|
|
|
99
118
|
}
|
|
100
119
|
```
|
|
101
120
|
|
|
102
|
-
#### `await core.
|
|
121
|
+
#### `const updated = await core.update()`
|
|
103
122
|
|
|
104
|
-
|
|
123
|
+
Wait for the core to try and find a signed update to it's length.
|
|
124
|
+
Does not download any data from peers except for a proof of the new core length.
|
|
105
125
|
|
|
106
|
-
|
|
107
|
-
|
|
126
|
+
``` js
|
|
127
|
+
const updated = await core.update()
|
|
108
128
|
|
|
109
|
-
|
|
129
|
+
console.log('core was updated?', updated, 'length is', core.length)
|
|
130
|
+
```
|
|
110
131
|
|
|
111
|
-
|
|
132
|
+
#### `const [index, relativeOffset] = await core.seek(byteOffset)`
|
|
133
|
+
|
|
134
|
+
Seek to a byte offset.
|
|
135
|
+
|
|
136
|
+
Returns `[index, relativeOffset]`, where `index` is the data block the byteOffset is contained in and `relativeOffset` is
|
|
137
|
+
the relative byte offset in the data block.
|
|
138
|
+
|
|
139
|
+
``` js
|
|
140
|
+
await core.append([Buffer.from('abc'), Buffer.from('d'), Buffer.from('efg')])
|
|
141
|
+
|
|
142
|
+
const first = await core.seek(1) // returns [0, 1]
|
|
143
|
+
const second = await core.seek(3) // returns [1, 0]
|
|
144
|
+
const third = await core.seek(5) // returns [2, 1]
|
|
145
|
+
```
|
|
112
146
|
|
|
113
147
|
#### `const stream = core.createReadStream([options])`
|
|
114
148
|
|
|
115
|
-
Make a read stream
|
|
149
|
+
Make a read stream to read a range of data out at once.
|
|
150
|
+
|
|
151
|
+
``` js
|
|
152
|
+
// read the full core
|
|
153
|
+
const fullStream = core.createReadStream()
|
|
154
|
+
|
|
155
|
+
// read from block 10-15
|
|
156
|
+
const partialStream = core.createReadStream({ start: 10, end: 15 })
|
|
157
|
+
|
|
158
|
+
// pipe the stream somewhere using the .pipe method on Node.js or consume it as
|
|
159
|
+
// an async iterator
|
|
160
|
+
|
|
161
|
+
for await (const data of fullStream) {
|
|
162
|
+
console.log('data:', data)
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Additional options include:
|
|
116
167
|
|
|
117
168
|
``` js
|
|
118
169
|
{
|
|
@@ -123,6 +174,28 @@ Make a read stream. Options include:
|
|
|
123
174
|
}
|
|
124
175
|
```
|
|
125
176
|
|
|
177
|
+
#### `await core.clear(start, [end])`
|
|
178
|
+
|
|
179
|
+
Clear stored blocks between `start` and `end`, reclaiming storage when possible.
|
|
180
|
+
|
|
181
|
+
``` js
|
|
182
|
+
await core.clear(4) // clear block 4 from your local cache
|
|
183
|
+
await core.clear(0, 10) // clear block 0-10 from your local cache
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The core will also gossip to peers it is connected to, that is no longer has these blocks.
|
|
187
|
+
|
|
188
|
+
#### `await core.truncate(newLength, [forkId])`
|
|
189
|
+
|
|
190
|
+
Truncate the core to a smaller length.
|
|
191
|
+
|
|
192
|
+
Per default this will update the fork id of the core to `+ 1`, but you can set the fork id you prefer with the option.
|
|
193
|
+
Note that the fork id should be monotonely incrementing.
|
|
194
|
+
|
|
195
|
+
#### `const hash = await core.treeHash([length])`
|
|
196
|
+
|
|
197
|
+
Get the Merkle Tree hash of the core at a given length, defaulting to the current length of the core.
|
|
198
|
+
|
|
126
199
|
#### `const range = core.download([range])`
|
|
127
200
|
|
|
128
201
|
Download a range of data.
|
|
@@ -130,7 +203,7 @@ Download a range of data.
|
|
|
130
203
|
You can await when the range has been fully downloaded by doing:
|
|
131
204
|
|
|
132
205
|
```js
|
|
133
|
-
await range.
|
|
206
|
+
await range.done()
|
|
134
207
|
```
|
|
135
208
|
|
|
136
209
|
A range can have the following properties:
|
|
@@ -165,23 +238,6 @@ To cancel downloading a range simply destroy the range instance.
|
|
|
165
238
|
range.destroy()
|
|
166
239
|
```
|
|
167
240
|
|
|
168
|
-
#### `const [index, relativeOffset] = await core.seek(byteOffset)`
|
|
169
|
-
|
|
170
|
-
Seek to a byte offset.
|
|
171
|
-
|
|
172
|
-
Returns `(index, relativeOffset)`, where `index` is the data block the byteOffset is contained in and `relativeOffset` is
|
|
173
|
-
the relative byte offset in the data block.
|
|
174
|
-
|
|
175
|
-
#### `const updated = await core.update()`
|
|
176
|
-
|
|
177
|
-
Wait for the core to try and find a signed update to it's length.
|
|
178
|
-
Does not download any data from peers except for a proof of the new core length.
|
|
179
|
-
|
|
180
|
-
``` js
|
|
181
|
-
const updated = await core.update()
|
|
182
|
-
console.log('core was updated?', updated, 'length is', core.length)
|
|
183
|
-
```
|
|
184
|
-
|
|
185
241
|
#### `const info = await core.info()`
|
|
186
242
|
|
|
187
243
|
Get information about this core, such as its total size in bytes.
|
|
@@ -191,6 +247,7 @@ The object will look like this:
|
|
|
191
247
|
```js
|
|
192
248
|
Info {
|
|
193
249
|
key: Buffer(...),
|
|
250
|
+
discoveryKey: Buffer(...),
|
|
194
251
|
length: 18,
|
|
195
252
|
contiguousLength: 16,
|
|
196
253
|
byteLength: 742,
|
|
@@ -267,12 +324,6 @@ How many blocks are contiguously available starting from the first block of this
|
|
|
267
324
|
|
|
268
325
|
Populated after `ready` has been emitted. Will be `0` before the event.
|
|
269
326
|
|
|
270
|
-
#### `core.contiguousByteLength`
|
|
271
|
-
|
|
272
|
-
How much data is contiguously available starting from the first block of this core?
|
|
273
|
-
|
|
274
|
-
Populated after `ready` has been emitted. Will be `0` before the event.
|
|
275
|
-
|
|
276
327
|
#### `core.fork`
|
|
277
328
|
|
|
278
329
|
What is the current fork id of this core?
|
package/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const Replicator = require('./lib/replicator')
|
|
|
12
12
|
const Core = require('./lib/core')
|
|
13
13
|
const BlockEncryption = require('./lib/block-encryption')
|
|
14
14
|
const Info = require('./lib/info')
|
|
15
|
+
const Download = require('./lib/download')
|
|
15
16
|
const { ReadStream, WriteStream } = require('./lib/streams')
|
|
16
17
|
const { BAD_ARGUMENT, SESSION_CLOSED, SESSION_NOT_WRITABLE, SNAPSHOT_NOT_AVAILABLE } = require('./lib/errors')
|
|
17
18
|
|
|
@@ -612,8 +613,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
612
613
|
if (this.opened === false) await this.opening
|
|
613
614
|
if (this.closing !== null) return false
|
|
614
615
|
|
|
615
|
-
|
|
616
|
-
if (this.writable) {
|
|
616
|
+
if (this.writable && (!opts || opts.force !== true)) {
|
|
617
617
|
if (!this.snapshotted) return false
|
|
618
618
|
return this._updateSnapshot()
|
|
619
619
|
}
|
|
@@ -629,7 +629,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
629
629
|
const end = this.core.tree.length
|
|
630
630
|
const contig = this.contiguousLength
|
|
631
631
|
|
|
632
|
-
await this.download({ start, end, ifAvailable: true }).
|
|
632
|
+
await this.download({ start, end, ifAvailable: true }).done()
|
|
633
633
|
|
|
634
634
|
if (!upgraded) upgraded = this.contiguousLength !== contig
|
|
635
635
|
}
|
|
@@ -740,21 +740,12 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
740
740
|
}
|
|
741
741
|
|
|
742
742
|
download (range) {
|
|
743
|
-
const
|
|
743
|
+
const req = this._download(range)
|
|
744
744
|
|
|
745
745
|
// do not crash in the background...
|
|
746
|
-
|
|
746
|
+
req.catch(noop)
|
|
747
747
|
|
|
748
|
-
|
|
749
|
-
return {
|
|
750
|
-
async downloaded () {
|
|
751
|
-
const req = await reqP
|
|
752
|
-
return req.promise
|
|
753
|
-
},
|
|
754
|
-
destroy () {
|
|
755
|
-
reqP.then(req => req.context && req.context.detach(req), noop)
|
|
756
|
-
}
|
|
757
|
-
}
|
|
748
|
+
return new Download(req)
|
|
758
749
|
}
|
|
759
750
|
|
|
760
751
|
async _download (range) {
|
package/lib/bitfield.js
CHANGED
|
@@ -152,7 +152,7 @@ module.exports = class Bitfield {
|
|
|
152
152
|
|
|
153
153
|
clear () {
|
|
154
154
|
return new Promise((resolve, reject) => {
|
|
155
|
-
this.storage.
|
|
155
|
+
this.storage.truncate(0, (err) => {
|
|
156
156
|
if (err) return reject(err)
|
|
157
157
|
this.pages = new BigSparseArray()
|
|
158
158
|
this.unflushed = []
|
package/lib/block-store.js
CHANGED
|
@@ -20,12 +20,15 @@ module.exports = class BlockStore {
|
|
|
20
20
|
return this.put(i, batch.length === 1 ? batch[0] : b4a.concat(batch), offset)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
clear (offset = 0, length =
|
|
23
|
+
clear (offset = 0, length = -1) {
|
|
24
24
|
return new Promise((resolve, reject) => {
|
|
25
|
-
this.storage.
|
|
25
|
+
if (length === -1) this.storage.truncate(offset, done)
|
|
26
|
+
else this.storage.del(offset, length, done)
|
|
27
|
+
|
|
28
|
+
function done (err) {
|
|
26
29
|
if (err) reject(err)
|
|
27
30
|
else resolve()
|
|
28
|
-
}
|
|
31
|
+
}
|
|
29
32
|
})
|
|
30
33
|
}
|
|
31
34
|
|
package/lib/core.js
CHANGED
|
@@ -37,18 +37,8 @@ module.exports = class Core {
|
|
|
37
37
|
try {
|
|
38
38
|
return await this.resume(oplogFile, treeFile, bitfieldFile, dataFile, opts)
|
|
39
39
|
} catch (err) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
oplogFile.close(done)
|
|
44
|
-
treeFile.close(done)
|
|
45
|
-
bitfieldFile.close(done)
|
|
46
|
-
dataFile.close(done)
|
|
47
|
-
|
|
48
|
-
function done () {
|
|
49
|
-
if (--missing === 0) reject(err)
|
|
50
|
-
}
|
|
51
|
-
})
|
|
40
|
+
await closeAll(oplogFile, treeFile, bitfieldFile, dataFile)
|
|
41
|
+
throw err
|
|
52
42
|
}
|
|
53
43
|
}
|
|
54
44
|
|
|
@@ -596,4 +586,25 @@ function updateUserData (list, key, value) {
|
|
|
596
586
|
if (value) list.push({ key, value })
|
|
597
587
|
}
|
|
598
588
|
|
|
589
|
+
function closeAll (...storages) {
|
|
590
|
+
let missing = 1
|
|
591
|
+
let error = null
|
|
592
|
+
|
|
593
|
+
return new Promise((resolve, reject) => {
|
|
594
|
+
for (const s of storages) {
|
|
595
|
+
missing++
|
|
596
|
+
s.close(done)
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
done(null)
|
|
600
|
+
|
|
601
|
+
function done (err) {
|
|
602
|
+
if (err) error = err
|
|
603
|
+
if (--missing) return
|
|
604
|
+
if (error) reject(error)
|
|
605
|
+
else resolve()
|
|
606
|
+
}
|
|
607
|
+
})
|
|
608
|
+
}
|
|
609
|
+
|
|
599
610
|
function noop () {}
|
package/lib/download.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module.exports = class Download {
|
|
2
|
+
constructor (req) {
|
|
3
|
+
this.req = req
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async done () {
|
|
7
|
+
return (await this.req).promise
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Deprecated. Use `range.done()`.
|
|
12
|
+
*/
|
|
13
|
+
downloaded () {
|
|
14
|
+
return this.done()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
destroy () {
|
|
18
|
+
this.req.then(req => req.context && req.context.detach(req), noop)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function noop () {}
|
package/lib/info.js
CHANGED
package/lib/merkle-tree.js
CHANGED
|
@@ -454,7 +454,7 @@ module.exports = class MerkleTree {
|
|
|
454
454
|
const t = this.truncateTo
|
|
455
455
|
const offset = t === 0 ? 0 : (t - 1) * 80 + 40
|
|
456
456
|
|
|
457
|
-
this.storage.
|
|
457
|
+
this.storage.truncate(offset, (err) => {
|
|
458
458
|
if (err) return reject(err)
|
|
459
459
|
|
|
460
460
|
if (this.truncateTo === t) {
|
package/lib/oplog.js
CHANGED
|
@@ -121,7 +121,7 @@ module.exports = class Oplog {
|
|
|
121
121
|
if (size === buffer.byteLength) return result
|
|
122
122
|
|
|
123
123
|
await new Promise((resolve, reject) => {
|
|
124
|
-
this.storage.
|
|
124
|
+
this.storage.truncate(size, err => {
|
|
125
125
|
if (err) return reject(err)
|
|
126
126
|
resolve()
|
|
127
127
|
})
|
|
@@ -164,7 +164,7 @@ module.exports = class Oplog {
|
|
|
164
164
|
this.storage.write(i === 0 ? 0 : this._pageSize, buf, err => {
|
|
165
165
|
if (err) return reject(err)
|
|
166
166
|
|
|
167
|
-
this.storage.
|
|
167
|
+
this.storage.truncate(this._entryOffset, err => {
|
|
168
168
|
if (err) return reject(err)
|
|
169
169
|
|
|
170
170
|
this._headers[i] = bit
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.0",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "standard &&
|
|
7
|
+
"test": "standard && node test/all.js",
|
|
8
|
+
"test:generate": "brittle -r test/all.js test/*.js"
|
|
8
9
|
},
|
|
9
10
|
"repository": {
|
|
10
11
|
"type": "git",
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
"hypercore-crypto": "^3.2.1",
|
|
44
45
|
"is-options": "^1.0.1",
|
|
45
46
|
"protomux": "^3.2.0",
|
|
46
|
-
"random-access-file": "^3.
|
|
47
|
+
"random-access-file": "^3.2.2",
|
|
47
48
|
"random-array-iterator": "^1.0.0",
|
|
48
49
|
"safety-catch": "^1.0.1",
|
|
49
50
|
"sodium-universal": "^3.0.4",
|
|
@@ -51,9 +52,9 @@
|
|
|
51
52
|
"xache": "^1.1.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
|
-
"brittle": "^
|
|
55
|
+
"brittle": "^3.0.0",
|
|
55
56
|
"hyperswarm": "^4.1.1",
|
|
56
|
-
"random-access-memory": "^5.0.
|
|
57
|
+
"random-access-memory": "^5.0.1",
|
|
57
58
|
"random-access-memory-overlay": "^2.0.0",
|
|
58
59
|
"standard": "^16.0.3",
|
|
59
60
|
"tmp-promise": "^3.0.2"
|