hypercore 10.12.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/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 { BAD_ARGUMENT, SESSION_CLOSED, SESSION_NOT_WRITABLE, SNAPSHOT_NOT_AVAILABLE } = require('./lib/errors')
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')
@@ -82,6 +90,7 @@ module.exports = class Hypercore extends EventEmitter {
82
90
 
83
91
  this._preappend = preappend.bind(this)
84
92
  this._snapshot = null
93
+ this._batch = opts._batch || null
85
94
  this._findingPeers = 0
86
95
  }
87
96
 
@@ -214,7 +223,8 @@ module.exports = class Hypercore extends EventEmitter {
214
223
  timeout,
215
224
  writable,
216
225
  _opening: this.opening,
217
- _sessions: this.sessions
226
+ _sessions: this.sessions,
227
+ _batch: this._batch
218
228
  })
219
229
 
220
230
  s._passCapabilities(this)
@@ -684,6 +694,13 @@ module.exports = class Hypercore extends EventEmitter {
684
694
  return true
685
695
  }
686
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
+
687
704
  async seek (bytes, opts) {
688
705
  if (this.opened === false) await this.opening
689
706
 
@@ -846,6 +863,7 @@ module.exports = class Hypercore extends EventEmitter {
846
863
  }
847
864
 
848
865
  async truncate (newLength = 0, fork = -1) {
866
+ if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
849
867
  if (this.opened === false) await this.opening
850
868
  if (this.writable === false) throw SESSION_NOT_WRITABLE()
851
869
 
@@ -857,6 +875,7 @@ module.exports = class Hypercore extends EventEmitter {
857
875
  }
858
876
 
859
877
  async append (blocks) {
878
+ if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
860
879
  if (this.opened === false) await this.opening
861
880
  if (this.writable === false) throw SESSION_NOT_WRITABLE()
862
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.12.0",
3
+ "version": "10.13.0",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {