hypercore 9.12.0 → 10.0.0-alpha.11

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.
Files changed (86) hide show
  1. package/.github/workflows/test-node.yml +3 -4
  2. package/README.md +131 -404
  3. package/__snapshots__/test/storage.js.snapshot.cjs +15 -0
  4. package/examples/announce.js +19 -0
  5. package/examples/basic.js +10 -0
  6. package/examples/http.js +123 -0
  7. package/examples/lookup.js +20 -0
  8. package/index.js +365 -1600
  9. package/lib/bitfield.js +113 -285
  10. package/lib/block-encryption.js +68 -0
  11. package/lib/block-store.js +58 -0
  12. package/lib/core.js +468 -0
  13. package/lib/extensions.js +76 -0
  14. package/lib/merkle-tree.js +1110 -0
  15. package/lib/messages.js +571 -0
  16. package/lib/mutex.js +39 -0
  17. package/lib/oplog.js +224 -0
  18. package/lib/protocol.js +525 -0
  19. package/lib/random-iterator.js +46 -0
  20. package/lib/remote-bitfield.js +24 -0
  21. package/lib/replicator.js +857 -0
  22. package/lib/streams.js +39 -0
  23. package/package.json +44 -45
  24. package/test/basic.js +59 -471
  25. package/test/bitfield.js +48 -133
  26. package/test/core.js +290 -0
  27. package/test/encodings.js +18 -0
  28. package/test/encryption.js +123 -0
  29. package/test/extension.js +71 -0
  30. package/test/helpers/index.js +23 -0
  31. package/test/merkle-tree.js +518 -0
  32. package/test/mutex.js +137 -0
  33. package/test/oplog.js +399 -0
  34. package/test/preload.js +72 -0
  35. package/test/replicate.js +227 -824
  36. package/test/sessions.js +173 -0
  37. package/test/storage.js +31 -0
  38. package/test/streams.js +39 -146
  39. package/test/user-data.js +47 -0
  40. package/bench/all.sh +0 -65
  41. package/bench/copy-64kb-blocks.js +0 -51
  42. package/bench/helpers/read-throttled.js +0 -27
  43. package/bench/helpers/read.js +0 -47
  44. package/bench/helpers/write.js +0 -29
  45. package/bench/read-16kb-blocks-proof-throttled.js +0 -1
  46. package/bench/read-16kb-blocks-proof.js +0 -1
  47. package/bench/read-16kb-blocks-throttled.js +0 -1
  48. package/bench/read-16kb-blocks.js +0 -1
  49. package/bench/read-512b-blocks.js +0 -1
  50. package/bench/read-64kb-blocks-linear-batch.js +0 -18
  51. package/bench/read-64kb-blocks-linear.js +0 -18
  52. package/bench/read-64kb-blocks-proof.js +0 -1
  53. package/bench/read-64kb-blocks.js +0 -1
  54. package/bench/replicate-16kb-blocks.js +0 -19
  55. package/bench/replicate-64kb-blocks.js +0 -19
  56. package/bench/write-16kb-blocks.js +0 -1
  57. package/bench/write-512b-blocks.js +0 -1
  58. package/bench/write-64kb-blocks-static.js +0 -1
  59. package/bench/write-64kb-blocks.js +0 -1
  60. package/example.js +0 -23
  61. package/lib/cache.js +0 -26
  62. package/lib/crypto.js +0 -5
  63. package/lib/replicate.js +0 -829
  64. package/lib/safe-buffer-equals.js +0 -6
  65. package/lib/storage.js +0 -421
  66. package/lib/tree-index.js +0 -183
  67. package/test/ack.js +0 -306
  68. package/test/audit.js +0 -36
  69. package/test/cache.js +0 -93
  70. package/test/compat.js +0 -209
  71. package/test/copy.js +0 -377
  72. package/test/default-storage.js +0 -51
  73. package/test/extensions.js +0 -137
  74. package/test/get.js +0 -64
  75. package/test/head.js +0 -65
  76. package/test/helpers/create-tracking-ram.js +0 -27
  77. package/test/helpers/create.js +0 -6
  78. package/test/helpers/replicate.js +0 -4
  79. package/test/seek.js +0 -234
  80. package/test/selections.js +0 -95
  81. package/test/set-uploading-downloading.js +0 -91
  82. package/test/stats.js +0 -77
  83. package/test/timeouts.js +0 -22
  84. package/test/tree-index.js +0 -841
  85. package/test/update.js +0 -156
  86. package/test/value-encoding.js +0 -52
package/lib/bitfield.js CHANGED
@@ -1,327 +1,155 @@
1
- var flat = require('flat-tree')
2
- var rle = require('bitfield-rle')
3
- var pager = require('memory-pager')
4
- var bitfield = require('sparse-bitfield')
1
+ // TODO: needs massive improvements obvs
5
2
 
6
- var INDEX_UPDATE_MASK = [63, 207, 243, 252]
7
- var INDEX_ITERATE_MASK = [0, 192, 240, 252]
8
- var DATA_ITERATE_MASK = [128, 192, 224, 240, 248, 252, 254, 255]
9
- var DATA_UPDATE_MASK = [127, 191, 223, 239, 247, 251, 253, 254]
10
- var MAP_PARENT_RIGHT = new Array(256)
11
- var MAP_PARENT_LEFT = new Array(256)
12
- var NEXT_DATA_0_BIT = new Array(256)
13
- var NEXT_INDEX_0_BIT = new Array(256)
14
- var TOTAL_1_BITS = new Array(256)
3
+ const BigSparseArray = require('big-sparse-array')
4
+ const b4a = require('b4a')
15
5
 
16
- for (var i = 0; i < 256; i++) {
17
- var a = (i & (15 << 4)) >> 4
18
- var b = i & 15
19
- var nibble = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]
20
- MAP_PARENT_RIGHT[i] = ((a === 15 ? 3 : a === 0 ? 0 : 1) << 2) | (b === 15 ? 3 : b === 0 ? 0 : 1)
21
- MAP_PARENT_LEFT[i] = MAP_PARENT_RIGHT[i] << 4
22
- NEXT_DATA_0_BIT[i] = i === 255 ? -1 : (8 - Math.ceil(Math.log(256 - i) / Math.log(2)))
23
- NEXT_INDEX_0_BIT[i] = i === 255 ? -1 : Math.floor(NEXT_DATA_0_BIT[i] / 2)
24
- TOTAL_1_BITS[i] = nibble[i >> 4] + nibble[i & 0x0F]
25
- }
26
-
27
- module.exports = Bitfield
28
-
29
- function Bitfield (pageSize, pages) {
30
- if (!(this instanceof Bitfield)) return new Bitfield(pageSize, pages)
31
- if (!pageSize) pageSize = 2048 + 1024 + 512
32
-
33
- var deduplicate = Buffer.allocUnsafe(pageSize)
34
- deduplicate.fill(255)
35
-
36
- this.indexSize = pageSize - 2048 - 1024
37
- this.pages = pager(pageSize, { deduplicate })
38
-
39
- if (pages) {
40
- for (var i = 0; i < pages.length; i++) {
41
- this.pages.set(i, pages[i])
42
- }
6
+ class FixedBitfield {
7
+ constructor (index, bitfield) {
8
+ this.dirty = false
9
+ this.index = index
10
+ this.bitfield = bitfield
43
11
  }
44
12
 
45
- this.data = bitfield({
46
- pageSize: 1024,
47
- pageOffset: 0,
48
- pages: this.pages,
49
- trackUpdates: true
50
- })
51
-
52
- this.tree = bitfield({
53
- pageSize: 2048,
54
- pageOffset: 1024,
55
- pages: this.pages,
56
- trackUpdates: true
57
- })
58
-
59
- this.index = bitfield({
60
- pageSize: this.indexSize,
61
- pageOffset: 1024 + 2048,
62
- pages: this.pages,
63
- trackUpdates: true
64
- })
13
+ get (index) {
14
+ const j = index & 31
15
+ const i = (index - j) / 32
65
16
 
66
- this.length = this.data.length
67
- this._iterator = flat.iterator(0)
68
- }
69
-
70
- Bitfield.prototype.set = function (i, value) {
71
- var o = i & 7
72
- i = (i - o) / 8
73
- var v = value ? this.data.getByte(i) | (128 >> o) : this.data.getByte(i) & DATA_UPDATE_MASK[o]
74
-
75
- if (!this.data.setByte(i, v)) return false
76
- this.length = this.data.length
77
- this._setIndex(i, v)
78
- return true
79
- }
80
-
81
- Bitfield.prototype.get = function (i) {
82
- return this.data.get(i)
83
- }
84
-
85
- Bitfield.prototype.total = function (start, end) {
86
- if (!start || start < 0) start = 0
87
- if (!end) end = this.data.length
88
- if (end < start) return 0
89
- if (end > this.data.length) {
90
- this._expand(end)
91
- }
92
- var o = start & 7
93
- var e = end & 7
94
- var pos = (start - o) / 8
95
- var last = (end - e) / 8
96
- var leftMask = (255 - (o ? DATA_ITERATE_MASK[o - 1] : 0))
97
- var rightMask = (e ? DATA_ITERATE_MASK[e - 1] : 0)
98
- var byte = this.data.getByte(pos)
99
- if (pos === last) {
100
- return TOTAL_1_BITS[byte & leftMask & rightMask]
101
- }
102
- var total = TOTAL_1_BITS[byte & leftMask]
103
- for (var i = pos + 1; i < last; i++) {
104
- total += TOTAL_1_BITS[this.data.getByte(i)]
17
+ return i < this.bitfield.length && (this.bitfield[i] & (1 << j)) !== 0
105
18
  }
106
- total += TOTAL_1_BITS[this.data.getByte(last) & rightMask]
107
- return total
108
- }
109
19
 
110
- // TODO: use the index to speed this up *a lot*
111
- Bitfield.prototype.compress = function (start, length) {
112
- if (!start && !length) return rle.encode(this.data.toBuffer())
20
+ set (index, val) {
21
+ const j = index & 31
22
+ const i = (index - j) / 32
23
+ const v = this.bitfield[i]
113
24
 
114
- if (start + length > this.length) length = Math.max(1, this.length - start)
115
- var buf = Buffer.alloc(Math.ceil(length / 8))
25
+ if (val === ((v & (1 << j)) !== 0)) return false
116
26
 
117
- var p = start / this.data.pageSize / 8
118
- var end = p + length / this.data.pageSize / 8
119
- var offset = p * this.data.pageSize
27
+ const u = val
28
+ ? v | (1 << j)
29
+ : v ^ (1 << j)
120
30
 
121
- for (; p < end; p++) {
122
- var page = this.data.pages.get(p, true)
123
- if (!page || !page.buffer) continue
124
- page.buffer.copy(buf, p * this.data.pageSize - offset, this.data.pageOffset, this.data.pageOffset + this.data.pageSize)
125
- }
31
+ if (u === v) return false
126
32
 
127
- return rle.encode(buf)
33
+ this.bitfield[i] = u
34
+ return true
35
+ }
128
36
  }
129
37
 
130
- Bitfield.prototype._setIndex = function (i, value) {
131
- // (a + b | c + d | e + f | g + h)
132
- // -> (a | b | c | d) (e | f | g | h)
133
- //
134
-
135
- var o = i & 3
136
- i = (i - o) / 4
137
-
138
- var bitfield = this.index
139
- var ite = this._iterator
140
- var start = 2 * i
141
- var byte = (bitfield.getByte(start) & INDEX_UPDATE_MASK[o]) | (getIndexValue(value) >> (2 * o))
142
- var len = bitfield.length
143
- var maxLength = this.pages.length * this.indexSize
38
+ module.exports = class Bitfield {
39
+ constructor (storage, buf) {
40
+ this.pageSize = 32768
41
+ this.pages = new BigSparseArray()
42
+ this.unflushed = []
43
+ this.storage = storage
144
44
 
145
- ite.seek(start)
45
+ const all = (buf && buf.byteLength >= 4)
46
+ ? new Uint32Array(buf.buffer, buf.byteOffset, Math.floor(buf.byteLength / 4))
47
+ : new Uint32Array(1024)
146
48
 
147
- while (ite.index < maxLength && bitfield.setByte(ite.index, byte)) {
148
- if (ite.isLeft()) {
149
- byte = MAP_PARENT_LEFT[byte] | MAP_PARENT_RIGHT[bitfield.getByte(ite.sibling())]
150
- } else {
151
- byte = MAP_PARENT_RIGHT[byte] | MAP_PARENT_LEFT[bitfield.getByte(ite.sibling())]
49
+ for (let i = 0; i < all.length; i += 1024) {
50
+ const bitfield = ensureSize(all.subarray(i, i + 1024), 1024)
51
+ const page = new FixedBitfield(i / 1024, bitfield)
52
+ this.pages.set(page.index, page)
152
53
  }
153
- ite.parent()
154
54
  }
155
55
 
156
- if (len !== bitfield.length) this._expand(len)
157
-
158
- return ite.index !== start
159
- }
160
-
161
- Bitfield.prototype._expand = function (len) {
162
- var roots = flat.fullRoots(2 * len)
163
- var bitfield = this.index
164
- var ite = this._iterator
165
- var byte = 0
166
-
167
- for (var i = 0; i < roots.length; i++) {
168
- ite.seek(roots[i])
169
- byte = bitfield.getByte(ite.index)
56
+ get (index) {
57
+ const j = index & 32767
58
+ const i = (index - j) / 32768
59
+ const p = this.pages.get(i)
170
60
 
171
- do {
172
- if (ite.isLeft()) {
173
- byte = MAP_PARENT_LEFT[byte] | MAP_PARENT_RIGHT[bitfield.getByte(ite.sibling())]
174
- } else {
175
- byte = MAP_PARENT_RIGHT[byte] | MAP_PARENT_LEFT[bitfield.getByte(ite.sibling())]
176
- }
177
- } while (setByteNoAlloc(bitfield, ite.parent(), byte))
61
+ return p ? p.get(j) : false
178
62
  }
179
- }
180
-
181
- function setByteNoAlloc (bitfield, i, b) {
182
- if (8 * i >= bitfield.length) return false
183
- return bitfield.setByte(i, b)
184
- }
185
-
186
- Bitfield.prototype.iterator = function (start, end) {
187
- var ite = new Iterator(this)
188
-
189
- ite.range(start || 0, end || this.length)
190
- ite.seek(0)
191
-
192
- return ite
193
- }
194
-
195
- function Iterator (bitfield) {
196
- this.start = 0
197
- this.end = 0
198
63
 
199
- this._indexEnd = 0
200
- this._pos = 0
201
- this._byte = 0
202
- this._bitfield = bitfield
203
- }
204
-
205
- Iterator.prototype.range = function (start, end) {
206
- this.start = start
207
- this.end = end
208
- this._indexEnd = 2 * Math.ceil(end / 32)
64
+ set (index, val) {
65
+ const j = index & 32767
66
+ const i = (index - j) / 32768
209
67
 
210
- if (this.end > this._bitfield.length) {
211
- this._bitfield._expand(this.end)
212
- }
68
+ let p = this.pages.get(i)
213
69
 
214
- return this
215
- }
70
+ if (!p) {
71
+ if (!val) return
72
+ p = this.pages.set(i, new FixedBitfield(i, new Uint32Array(1024)))
73
+ }
216
74
 
217
- Iterator.prototype.seek = function (offset) {
218
- offset += this.start
219
- if (offset < this.start) offset = this.start
75
+ if (!p.set(j, val) || p.dirty) return
220
76
 
221
- if (offset >= this.end) {
222
- this._pos = -1
223
- return this
77
+ p.dirty = true
78
+ this.unflushed.push(p)
224
79
  }
225
80
 
226
- var o = offset & 7
227
-
228
- this._pos = (offset - o) / 8
229
- this._byte = this._bitfield.data.getByte(this._pos) | (o ? DATA_ITERATE_MASK[o - 1] : 0)
230
-
231
- return this
232
- }
233
-
234
- Iterator.prototype.random = function () {
235
- var i = this.seek(Math.floor(Math.random() * (this.end - this.start))).next()
236
- return i === -1 ? this.seek(0).next() : i
237
- }
238
-
239
- Iterator.prototype.next = function () {
240
- if (this._pos === -1) return -1
241
-
242
- var dataBitfield = this._bitfield.data
243
- var free = NEXT_DATA_0_BIT[this._byte]
244
-
245
- while (free === -1) {
246
- this._byte = dataBitfield.getByte(++this._pos)
247
- free = NEXT_DATA_0_BIT[this._byte]
248
-
249
- if (free === -1) {
250
- this._pos = this._skipAhead(this._pos)
251
- if (this._pos === -1) return -1
252
-
253
- this._byte = dataBitfield.getByte(this._pos)
254
- free = NEXT_DATA_0_BIT[this._byte]
81
+ setRange (start, length, val) {
82
+ for (let i = 0; i < length; i++) {
83
+ this.set(start + i, val)
255
84
  }
256
85
  }
257
86
 
258
- this._byte |= DATA_ITERATE_MASK[free]
259
-
260
- var n = 8 * this._pos + free
261
- return n < this.end ? n : -1
262
- }
263
-
264
- Iterator.prototype.peek = function () {
265
- if (this._pos === -1) return -1
266
-
267
- var free = NEXT_DATA_0_BIT[this._byte]
268
- var n = 8 * this._pos + free
269
- return n < this.end ? n : -1
270
- }
271
-
272
- Iterator.prototype._skipAhead = function (start) {
273
- var indexBitfield = this._bitfield.index
274
- var treeEnd = this._indexEnd
275
- var ite = this._bitfield._iterator
276
- var o = start & 3
277
-
278
- ite.seek(2 * ((start - o) / 4))
279
-
280
- var treeByte = indexBitfield.getByte(ite.index) | INDEX_ITERATE_MASK[o]
281
-
282
- while (NEXT_INDEX_0_BIT[treeByte] === -1) {
283
- if (ite.isLeft()) {
284
- ite.next()
285
- } else {
286
- ite.next()
287
- ite.parent()
288
- }
289
-
290
- if (rightSpan(ite) >= treeEnd) {
291
- while (rightSpan(ite) >= treeEnd && isParent(ite)) ite.leftChild()
292
- if (rightSpan(ite) >= treeEnd) return -1
293
- }
294
-
295
- treeByte = indexBitfield.getByte(ite.index)
87
+ // Should prob be removed, when/if we re-add compression
88
+ page (i) {
89
+ const p = this.pages.get(i)
90
+ return p ? p.bitfield : new Uint32Array(1024)
296
91
  }
297
92
 
298
- while (ite.factor > 2) {
299
- if (NEXT_INDEX_0_BIT[treeByte] < 2) ite.leftChild()
300
- else ite.rightChild()
93
+ clear () {
94
+ return new Promise((resolve, reject) => {
95
+ this.storage.del(0, Infinity, (err) => {
96
+ if (err) reject(err)
97
+ else resolve()
98
+ })
99
+ })
100
+ }
301
101
 
302
- treeByte = indexBitfield.getByte(ite.index)
102
+ close () {
103
+ return new Promise((resolve, reject) => {
104
+ this.storage.close((err) => {
105
+ if (err) reject(err)
106
+ else resolve()
107
+ })
108
+ })
303
109
  }
304
110
 
305
- var free = NEXT_INDEX_0_BIT[treeByte]
306
- if (free === -1) free = 4
111
+ flush () {
112
+ return new Promise((resolve, reject) => {
113
+ if (!this.unflushed.length) return resolve()
307
114
 
308
- var next = ite.index * 2 + free
115
+ const self = this
116
+ let missing = this.unflushed.length
117
+ let error = null
309
118
 
310
- return next <= start ? start + 1 : next
311
- }
119
+ for (const page of this.unflushed) {
120
+ const buf = b4a.from(page.bitfield.buffer, page.bitfield.byteOffset, page.bitfield.byteLength)
121
+ page.dirty = false
122
+ this.storage.write(page.index * 4096, buf, done)
123
+ }
312
124
 
313
- function rightSpan (ite) {
314
- return ite.index + ite.factor / 2 - 1
315
- }
125
+ function done (err) {
126
+ if (err) error = err
127
+ if (--missing) return
128
+ if (error) return reject(error)
129
+ self.unflushed = []
130
+ resolve()
131
+ }
132
+ })
133
+ }
316
134
 
317
- function isParent (ite) {
318
- return ite.index & 1
135
+ static open (storage) {
136
+ return new Promise((resolve, reject) => {
137
+ storage.stat((err, st) => {
138
+ if (err) return resolve(new Bitfield(storage, null))
139
+ const size = st.size - (st.size & 3)
140
+ if (!size) return resolve(new Bitfield(storage, null))
141
+ storage.read(0, size, (err, data) => {
142
+ if (err) return reject(err)
143
+ resolve(new Bitfield(storage, data))
144
+ })
145
+ })
146
+ })
147
+ }
319
148
  }
320
149
 
321
- function getIndexValue (n) {
322
- switch (n) {
323
- case 255: return 192
324
- case 0: return 0
325
- default: return 64
326
- }
150
+ function ensureSize (uint32, size) {
151
+ if (uint32.length === size) return uint32
152
+ const a = new Uint32Array(1024)
153
+ a.set(uint32, 0)
154
+ return a
327
155
  }
@@ -0,0 +1,68 @@
1
+ const sodium = require('sodium-universal')
2
+ const c = require('compact-encoding')
3
+ const b4a = require('b4a')
4
+
5
+ const nonce = b4a.alloc(sodium.crypto_stream_NONCEBYTES)
6
+
7
+ module.exports = class BlockEncryption {
8
+ constructor (encryptionKey, hypercoreKey) {
9
+ const subKeys = b4a.alloc(2 * sodium.crypto_stream_KEYBYTES)
10
+
11
+ this.key = encryptionKey
12
+ this.blockKey = subKeys.subarray(0, sodium.crypto_stream_KEYBYTES)
13
+ this.blindingKey = subKeys.subarray(sodium.crypto_stream_KEYBYTES)
14
+ this.padding = 8
15
+
16
+ sodium.crypto_generichash(this.blockKey, encryptionKey, hypercoreKey)
17
+ sodium.crypto_generichash(this.blindingKey, this.blockKey)
18
+ }
19
+
20
+ encrypt (index, block, fork) {
21
+ const padding = block.subarray(0, this.padding)
22
+ block = block.subarray(this.padding)
23
+
24
+ c.uint64.encode({ start: 0, end: 8, buffer: padding }, fork)
25
+ c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
26
+
27
+ // Zero out any previous padding.
28
+ nonce.fill(0, 8, 8 + padding.byteLength)
29
+
30
+ // Blind the fork ID, possibly risking reusing the nonce on a reorg of the
31
+ // Hypercore. This is fine as the blinding is best-effort and the latest
32
+ // fork ID shared on replication anyway.
33
+ sodium.crypto_stream_xor(
34
+ padding,
35
+ padding,
36
+ nonce,
37
+ this.blindingKey
38
+ )
39
+
40
+ nonce.set(padding, 8)
41
+
42
+ // The combination of a (blinded) fork ID and a block index is unique for a
43
+ // given Hypercore and is therefore a valid nonce for encrypting the block.
44
+ sodium.crypto_stream_xor(
45
+ block,
46
+ block,
47
+ nonce,
48
+ this.blockKey
49
+ )
50
+ }
51
+
52
+ decrypt (index, block) {
53
+ const padding = block.subarray(0, this.padding)
54
+ block = block.subarray(this.padding)
55
+
56
+ c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index)
57
+
58
+ nonce.set(padding, 8)
59
+
60
+ // Decrypt the block using the blinded fork ID.
61
+ sodium.crypto_stream_xor(
62
+ block,
63
+ block,
64
+ nonce,
65
+ this.blockKey
66
+ )
67
+ }
68
+ }
@@ -0,0 +1,58 @@
1
+ const b4a = require('b4a')
2
+
3
+ module.exports = class BlockStore {
4
+ constructor (storage, tree) {
5
+ this.storage = storage
6
+ this.tree = tree
7
+ }
8
+
9
+ async get (i) {
10
+ const [offset, size] = await this.tree.byteRange(2 * i)
11
+ return this._read(offset, size)
12
+ }
13
+
14
+ async put (i, data, offset) {
15
+ return this._write(offset, data)
16
+ }
17
+
18
+ putBatch (i, batch, offset) {
19
+ if (batch.length === 0) return Promise.resolve()
20
+ return this.put(i, batch.length === 1 ? batch[0] : b4a.concat(batch), offset)
21
+ }
22
+
23
+ clear () {
24
+ return new Promise((resolve, reject) => {
25
+ this.storage.del(0, Infinity, (err) => {
26
+ if (err) reject(err)
27
+ else resolve()
28
+ })
29
+ })
30
+ }
31
+
32
+ close () {
33
+ return new Promise((resolve, reject) => {
34
+ this.storage.close((err) => {
35
+ if (err) reject(err)
36
+ else resolve()
37
+ })
38
+ })
39
+ }
40
+
41
+ _read (offset, size) {
42
+ return new Promise((resolve, reject) => {
43
+ this.storage.read(offset, size, (err, data) => {
44
+ if (err) reject(err)
45
+ else resolve(data)
46
+ })
47
+ })
48
+ }
49
+
50
+ _write (offset, data) {
51
+ return new Promise((resolve, reject) => {
52
+ this.storage.write(offset, data, (err) => {
53
+ if (err) reject(err)
54
+ else resolve()
55
+ })
56
+ })
57
+ }
58
+ }