hypercore 10.11.0 → 10.13.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 +2 -1
- package/index.js +26 -4
- package/lib/batch.js +114 -0
- package/lib/errors.js +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,7 +72,8 @@ Note that `tree`, `data`, and `bitfield` are normally heavily sparse files.
|
|
|
72
72
|
encodeBatch: batch => { ... }, // optionally apply an encoding to complete batches
|
|
73
73
|
keyPair: kp, // optionally pass the public key and secret key as a key pair
|
|
74
74
|
encryptionKey: k, // optionally pass an encryption key to enable block encryption
|
|
75
|
-
onwait: () => {} // hook that is called if gets are waiting for download
|
|
75
|
+
onwait: () => {}, // hook that is called if gets are waiting for download
|
|
76
|
+
writable: true // disable appends and truncates
|
|
76
77
|
}
|
|
77
78
|
```
|
|
78
79
|
|
package/index.js
CHANGED
|
@@ -14,8 +14,16 @@ 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 Batch = require('./lib/batch')
|
|
17
18
|
const { ReadStream, WriteStream, ByteStream } = require('./lib/streams')
|
|
18
|
-
const {
|
|
19
|
+
const {
|
|
20
|
+
BAD_ARGUMENT,
|
|
21
|
+
BATCH_ALREADY_EXISTS,
|
|
22
|
+
BATCH_UNFLUSHED,
|
|
23
|
+
SESSION_CLOSED,
|
|
24
|
+
SESSION_NOT_WRITABLE,
|
|
25
|
+
SNAPSHOT_NOT_AVAILABLE
|
|
26
|
+
} = require('./lib/errors')
|
|
19
27
|
|
|
20
28
|
const promises = Symbol.for('hypercore.promises')
|
|
21
29
|
const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
@@ -74,6 +82,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
74
82
|
this.onwait = opts.onwait || null
|
|
75
83
|
this.wait = opts.wait !== false
|
|
76
84
|
this.timeout = opts.timeout || 0
|
|
85
|
+
this._readonly = opts.writable === false
|
|
77
86
|
|
|
78
87
|
this.closing = null
|
|
79
88
|
this.opening = this._openSession(key, storage, opts)
|
|
@@ -81,6 +90,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
81
90
|
|
|
82
91
|
this._preappend = preappend.bind(this)
|
|
83
92
|
this._snapshot = null
|
|
93
|
+
this._batch = opts._batch || null
|
|
84
94
|
this._findingPeers = 0
|
|
85
95
|
}
|
|
86
96
|
|
|
@@ -201,6 +211,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
201
211
|
|
|
202
212
|
const sparse = opts.sparse === false ? false : this.sparse
|
|
203
213
|
const wait = opts.wait === false ? false : this.wait
|
|
214
|
+
const writable = opts.writable === false ? false : !this._readonly
|
|
204
215
|
const onwait = opts.onwait === undefined ? this.onwait : opts.onwait
|
|
205
216
|
const timeout = opts.timeout === undefined ? this.timeout : opts.timeout
|
|
206
217
|
const Clz = opts.class || Hypercore
|
|
@@ -210,8 +221,10 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
210
221
|
wait,
|
|
211
222
|
onwait,
|
|
212
223
|
timeout,
|
|
224
|
+
writable,
|
|
213
225
|
_opening: this.opening,
|
|
214
|
-
_sessions: this.sessions
|
|
226
|
+
_sessions: this.sessions,
|
|
227
|
+
_batch: this._batch
|
|
215
228
|
})
|
|
216
229
|
|
|
217
230
|
s._passCapabilities(this)
|
|
@@ -237,7 +250,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
237
250
|
this.core = o.core
|
|
238
251
|
this.replicator = o.replicator
|
|
239
252
|
this.encryption = o.encryption
|
|
240
|
-
this.writable = !!(this.auth && this.auth.sign)
|
|
253
|
+
this.writable = !this._readonly && !!(this.auth && this.auth.sign)
|
|
241
254
|
this.autoClose = o.autoClose
|
|
242
255
|
|
|
243
256
|
if (this.snapshotted && this.core && !this._snapshot) this._updateSnapshot()
|
|
@@ -295,7 +308,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
295
308
|
}
|
|
296
309
|
|
|
297
310
|
if (!this.auth) this.auth = this.core.defaultAuth
|
|
298
|
-
this.writable = !!this.auth.sign
|
|
311
|
+
this.writable = !this._readonly && !!this.auth.sign
|
|
299
312
|
|
|
300
313
|
if (opts.valueEncoding) {
|
|
301
314
|
this.valueEncoding = c.from(opts.valueEncoding)
|
|
@@ -681,6 +694,13 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
681
694
|
return true
|
|
682
695
|
}
|
|
683
696
|
|
|
697
|
+
batch () {
|
|
698
|
+
if (this._batch !== null) throw BATCH_ALREADY_EXISTS()
|
|
699
|
+
const batch = new Batch(this)
|
|
700
|
+
for (const session of this.sessions) session._batch = batch
|
|
701
|
+
return batch
|
|
702
|
+
}
|
|
703
|
+
|
|
684
704
|
async seek (bytes, opts) {
|
|
685
705
|
if (this.opened === false) await this.opening
|
|
686
706
|
|
|
@@ -843,6 +863,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
843
863
|
}
|
|
844
864
|
|
|
845
865
|
async truncate (newLength = 0, fork = -1) {
|
|
866
|
+
if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
|
|
846
867
|
if (this.opened === false) await this.opening
|
|
847
868
|
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
848
869
|
|
|
@@ -854,6 +875,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
854
875
|
}
|
|
855
876
|
|
|
856
877
|
async append (blocks) {
|
|
878
|
+
if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
|
|
857
879
|
if (this.opened === false) await this.opening
|
|
858
880
|
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
859
881
|
|
package/lib/batch.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const { SESSION_NOT_WRITABLE, BATCH_ALREADY_FLUSHED } = require('./errors')
|
|
2
|
+
|
|
3
|
+
module.exports = class Batch {
|
|
4
|
+
constructor (session) {
|
|
5
|
+
this.session = session
|
|
6
|
+
this.flushed = false
|
|
7
|
+
|
|
8
|
+
this._appends = []
|
|
9
|
+
this._byteLength = 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get length () {
|
|
13
|
+
return this.session.length + this._appends.length
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ready () {
|
|
17
|
+
return this.session.ready()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async info (opts) {
|
|
21
|
+
const session = this.session
|
|
22
|
+
const info = await session.info(opts)
|
|
23
|
+
|
|
24
|
+
if (info.contiguousLength === info.length) {
|
|
25
|
+
info.contiguousLength = info.length += this._appends.length
|
|
26
|
+
} else {
|
|
27
|
+
info.length += this._appends.length
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
info.byteLength += this._byteLength
|
|
31
|
+
|
|
32
|
+
return info
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async get (index, opts) {
|
|
36
|
+
const session = this.session
|
|
37
|
+
if (session.opened === false) await session.opening
|
|
38
|
+
|
|
39
|
+
const length = this.session.length
|
|
40
|
+
if (index < length) return this.session.get(index, opts)
|
|
41
|
+
|
|
42
|
+
return this._appends[index - length] || null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async truncate (newLength) {
|
|
46
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
47
|
+
|
|
48
|
+
const session = this.session
|
|
49
|
+
if (session.opened === false) await session.opening
|
|
50
|
+
if (session.writable === false) throw SESSION_NOT_WRITABLE()
|
|
51
|
+
|
|
52
|
+
const length = session.length
|
|
53
|
+
if (newLength < length) throw new Error('Cannot truncate committed blocks')
|
|
54
|
+
|
|
55
|
+
this._appends.length = newLength - length
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async append (blocks) {
|
|
59
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
60
|
+
|
|
61
|
+
const session = this.session
|
|
62
|
+
if (session.opened === false) await session.opening
|
|
63
|
+
if (session.writable === false) throw SESSION_NOT_WRITABLE()
|
|
64
|
+
|
|
65
|
+
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
66
|
+
|
|
67
|
+
const buffers = session.encodeBatch !== null
|
|
68
|
+
? session.encodeBatch(blocks)
|
|
69
|
+
: new Array(blocks.length)
|
|
70
|
+
|
|
71
|
+
if (session.encodeBatch === null) {
|
|
72
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
73
|
+
const buffer = session._encode(session.valueEncoding, blocks[i])
|
|
74
|
+
buffers[i] = buffer
|
|
75
|
+
this._byteLength += buffer.byteLength
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this._appends.push(...buffers)
|
|
80
|
+
|
|
81
|
+
const byteLength = session.byteLength + this._byteLength
|
|
82
|
+
|
|
83
|
+
return { length: this.length, byteLength }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async flush () {
|
|
87
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
88
|
+
this.flushed = true
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
if (this._appends.length) await this.session.append(this._appends)
|
|
92
|
+
} finally {
|
|
93
|
+
this._clearBatch()
|
|
94
|
+
this._clearAppends()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async close () {
|
|
99
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
100
|
+
this.flushed = true
|
|
101
|
+
|
|
102
|
+
this._clearBatch()
|
|
103
|
+
this._clearAppends()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_clearAppends () {
|
|
107
|
+
this._appends = []
|
|
108
|
+
this._byteLength = 0
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_clearBatch () {
|
|
112
|
+
for (const session of this.session.sessions) session._batch = null
|
|
113
|
+
}
|
|
114
|
+
}
|
package/lib/errors.js
CHANGED
|
@@ -64,6 +64,18 @@ module.exports = class HypercoreError extends Error {
|
|
|
64
64
|
return new HypercoreError(msg, 'SESSION_CLOSED', HypercoreError.SESSION_CLOSED)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
static BATCH_UNFLUSHED (msg = 'Batch not yet flushed') {
|
|
68
|
+
return new HypercoreError(msg, 'BATCH_UNFLUSHED', HypercoreError.BATCH_UNFLUSHED)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static BATCH_ALREADY_EXISTS (msg = 'Batch already exists') {
|
|
72
|
+
return new HypercoreError(msg, 'BATCH_ALREADY_EXISTS', HypercoreError.BATCH_ALREADY_EXISTS)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static BATCH_ALREADY_FLUSHED (msg = 'Batch has already been flushed') {
|
|
76
|
+
return new HypercoreError(msg, 'BATCH_ALREADY_FLUSHED', HypercoreError.BATCH_ALREADY_FLUSHED)
|
|
77
|
+
}
|
|
78
|
+
|
|
67
79
|
static OPLOG_CORRUPT (msg = 'Oplog file appears corrupt or out of date') {
|
|
68
80
|
return new HypercoreError(msg, 'OPLOG_CORRUPT', HypercoreError.OPLOG_CORRUPT)
|
|
69
81
|
}
|