hypercore 10.9.2 → 10.10.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 +34 -0
- package/index.js +20 -3
- package/lib/core.js +19 -0
- package/lib/streams.js +74 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -197,6 +197,36 @@ for await (const data of fullStream) {
|
|
|
197
197
|
}
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
#### `const bs = core.createByteStream([options])`
|
|
201
|
+
|
|
202
|
+
Make a byte stream to read a range of bytes.
|
|
203
|
+
|
|
204
|
+
``` js
|
|
205
|
+
// Read the full core
|
|
206
|
+
const fullStream = core.createByteStream()
|
|
207
|
+
|
|
208
|
+
// Read from byte 3, and from there read 50 bytes
|
|
209
|
+
const partialStream = core.createByteStream({ byteOffset: 3, byteLength: 50 })
|
|
210
|
+
|
|
211
|
+
// Consume it as an async iterator
|
|
212
|
+
for await (const data of fullStream) {
|
|
213
|
+
console.log('data:', data)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Or pipe it somewhere like any stream:
|
|
217
|
+
partialStream.pipe(process.stdout)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`options` include:
|
|
221
|
+
|
|
222
|
+
``` js
|
|
223
|
+
{
|
|
224
|
+
byteOffset: 0,
|
|
225
|
+
byteLength: core.byteLength - options.byteOffset,
|
|
226
|
+
prefetch: 32
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
200
230
|
#### `await core.clear(start, [end])`
|
|
201
231
|
|
|
202
232
|
Clear stored blocks between `start` and `end`, reclaiming storage when possible.
|
|
@@ -215,6 +245,10 @@ Truncate the core to a smaller length.
|
|
|
215
245
|
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.
|
|
216
246
|
Note that the fork id should be monotonely incrementing.
|
|
217
247
|
|
|
248
|
+
#### `await core.purge()`
|
|
249
|
+
|
|
250
|
+
Purge the hypercore from your storage, completely removing all data.
|
|
251
|
+
|
|
218
252
|
#### `const hash = await core.treeHash([length])`
|
|
219
253
|
|
|
220
254
|
Get the Merkle Tree hash of the core at a given length, defaulting to the current length of the core.
|
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const Core = require('./lib/core')
|
|
|
14
14
|
const BlockEncryption = require('./lib/block-encryption')
|
|
15
15
|
const Info = require('./lib/info')
|
|
16
16
|
const Download = require('./lib/download')
|
|
17
|
-
const { ReadStream, WriteStream } = require('./lib/streams')
|
|
17
|
+
const { ReadStream, WriteStream, ByteStream } = require('./lib/streams')
|
|
18
18
|
const { BAD_ARGUMENT, SESSION_CLOSED, SESSION_NOT_WRITABLE, SNAPSHOT_NOT_AVAILABLE } = require('./lib/errors')
|
|
19
19
|
|
|
20
20
|
const promises = Symbol.for('hypercore.promises')
|
|
@@ -173,13 +173,14 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
173
173
|
const directory = storage
|
|
174
174
|
const toLock = opts.unlocked ? null : (opts.lock || 'oplog')
|
|
175
175
|
const pool = opts.pool || (opts.poolSize ? RAF.createPool(opts.poolSize) : null)
|
|
176
|
+
const rmdir = !!opts.rmdir
|
|
176
177
|
|
|
177
178
|
return createFile
|
|
178
179
|
|
|
179
180
|
function createFile (name) {
|
|
180
181
|
const lock = toLock === null ? false : isFile(name, toLock)
|
|
181
182
|
const sparse = isFile(name, 'data') || isFile(name, 'bitfield') || isFile(name, 'tree')
|
|
182
|
-
return new RAF(name, { directory, lock, sparse, pool: lock ? null : pool })
|
|
183
|
+
return new RAF(name, { directory, lock, sparse, pool: lock ? null : pool, rmdir })
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
function isFile (name, n) {
|
|
@@ -528,9 +529,16 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
528
529
|
for (const s of this.sessions) s.emit('conflict', proof.upgrade.length, proof.fork, proof)
|
|
529
530
|
|
|
530
531
|
const err = new Error('Two conflicting signatures exist for length ' + proof.upgrade.length)
|
|
532
|
+
await this._closeAllSessions(err)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
async _closeAllSessions (err) {
|
|
536
|
+
// this.sessions modifies itself when a session closes
|
|
537
|
+
// This way we ensure we indeed iterate over all sessions
|
|
538
|
+
const sessions = [...this.sessions]
|
|
531
539
|
|
|
532
540
|
const all = []
|
|
533
|
-
for (const s of
|
|
541
|
+
for (const s of sessions) all.push(s.close(err))
|
|
534
542
|
await Promise.allSettled(all)
|
|
535
543
|
}
|
|
536
544
|
|
|
@@ -742,6 +750,11 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
742
750
|
await this.core.clear(start, end)
|
|
743
751
|
}
|
|
744
752
|
|
|
753
|
+
async purge () {
|
|
754
|
+
await this._closeAllSessions(null)
|
|
755
|
+
await this.core.purge()
|
|
756
|
+
}
|
|
757
|
+
|
|
745
758
|
async _get (index, opts) {
|
|
746
759
|
let block
|
|
747
760
|
|
|
@@ -794,6 +807,10 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
794
807
|
return new WriteStream(this, opts)
|
|
795
808
|
}
|
|
796
809
|
|
|
810
|
+
createByteStream (opts) {
|
|
811
|
+
return new ByteStream(this, opts)
|
|
812
|
+
}
|
|
813
|
+
|
|
797
814
|
download (range) {
|
|
798
815
|
const req = this._download(range)
|
|
799
816
|
|
package/lib/core.js
CHANGED
|
@@ -280,6 +280,25 @@ module.exports = class Core {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
async purge () {
|
|
284
|
+
return new Promise((resolve, reject) => {
|
|
285
|
+
let missing = 4
|
|
286
|
+
let error = null
|
|
287
|
+
|
|
288
|
+
this.oplog.storage.unlink(done)
|
|
289
|
+
this.tree.storage.unlink(done)
|
|
290
|
+
this.bitfield.storage.unlink(done)
|
|
291
|
+
this.blocks.storage.unlink(done)
|
|
292
|
+
|
|
293
|
+
function done (err) {
|
|
294
|
+
if (err) error = err
|
|
295
|
+
if (--missing) return
|
|
296
|
+
if (error) reject(error)
|
|
297
|
+
else resolve()
|
|
298
|
+
}
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
|
|
283
302
|
async append (values, auth = this.defaultAuth, hooks = {}) {
|
|
284
303
|
await this._mutex.lock()
|
|
285
304
|
|
package/lib/streams.js
CHANGED
|
@@ -54,3 +54,77 @@ class WriteStream extends Writable {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
exports.WriteStream = WriteStream
|
|
57
|
+
|
|
58
|
+
class ByteStream extends Readable {
|
|
59
|
+
constructor (core, opts = {}) {
|
|
60
|
+
super()
|
|
61
|
+
|
|
62
|
+
this._core = core
|
|
63
|
+
this._index = 0
|
|
64
|
+
this._range = null
|
|
65
|
+
|
|
66
|
+
this._byteOffset = opts.byteOffset || 0
|
|
67
|
+
this._byteLength = typeof opts.byteLength === 'number' ? opts.byteLength : -1
|
|
68
|
+
this._prefetch = typeof opts.prefetch === 'number' ? opts.prefetch : 32
|
|
69
|
+
|
|
70
|
+
this._applyOffset = this._byteOffset > 0
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
_open (cb) {
|
|
74
|
+
this._openp().then(cb, cb)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_read (cb) {
|
|
78
|
+
this._readp().then(cb, cb)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async _openp () {
|
|
82
|
+
if (this._byteLength === -1) {
|
|
83
|
+
await this._core.update()
|
|
84
|
+
this._byteLength = Math.max(this._core.byteLength - this._byteOffset, 0)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async _readp () {
|
|
89
|
+
let data = null
|
|
90
|
+
|
|
91
|
+
if (this._byteLength === 0) {
|
|
92
|
+
this.push(null)
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let relativeOffset = 0
|
|
97
|
+
|
|
98
|
+
if (this._applyOffset) {
|
|
99
|
+
this._applyOffset = false
|
|
100
|
+
|
|
101
|
+
const [block, byteOffset] = await this._core.seek(this._byteOffset)
|
|
102
|
+
|
|
103
|
+
this._index = block
|
|
104
|
+
relativeOffset = byteOffset
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this._predownload(this._index + 1)
|
|
108
|
+
data = await this._core.get(this._index++)
|
|
109
|
+
|
|
110
|
+
if (relativeOffset > 0) data = data.subarray(relativeOffset)
|
|
111
|
+
|
|
112
|
+
if (data.byteLength > this._byteLength) data = data.subarray(0, this._byteLength)
|
|
113
|
+
this._byteLength -= data.byteLength
|
|
114
|
+
|
|
115
|
+
this.push(data)
|
|
116
|
+
if (this._byteLength === 0) this.push(null)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
_predownload (index) {
|
|
120
|
+
if (this._range) this._range.destroy()
|
|
121
|
+
this._range = this._core.download({ start: index, end: index + this._prefetch, linear: true })
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_destroy (cb) {
|
|
125
|
+
if (this._range) this._range.destroy()
|
|
126
|
+
cb(null)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
exports.ByteStream = ByteStream
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hypercore",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.10.0",
|
|
4
4
|
"description": "Hypercore is a secure, distributed append-only log",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"hyperswarm": "^4.3.6",
|
|
58
58
|
"random-access-memory": "^6.1.0",
|
|
59
59
|
"random-access-memory-overlay": "^3.0.0",
|
|
60
|
+
"range-parser": "^1.2.1",
|
|
60
61
|
"standard": "^17.0.0",
|
|
61
62
|
"tmp-promise": "^3.0.2"
|
|
62
63
|
}
|