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/streams.js ADDED
@@ -0,0 +1,39 @@
1
+ const { Readable } = require('streamx')
2
+
3
+ class ReadStream extends Readable {
4
+ constructor (core, opts = {}) {
5
+ super()
6
+
7
+ this.core = core
8
+ this.start = opts.start || 0
9
+ this.end = typeof opts.end === 'number' ? opts.end : -1
10
+ this.snapshot = !opts.live && opts.snapshot !== false
11
+ this.live = !!opts.live
12
+ }
13
+
14
+ _open (cb) {
15
+ this._openP().then(cb, cb)
16
+ }
17
+
18
+ _read (cb) {
19
+ this._readP().then(cb, cb)
20
+ }
21
+
22
+ async _openP () {
23
+ if (this.end === -1) await this.core.update()
24
+ else await this.core.ready()
25
+ if (this.snapshot && this.end === -1) this.end = this.core.length
26
+ }
27
+
28
+ async _readP () {
29
+ const end = this.live ? -1 : (this.end === -1 ? this.core.length : this.end)
30
+ if (end >= 0 && this.start >= end) {
31
+ this.push(null)
32
+ return
33
+ }
34
+
35
+ this.push(await this.core.get(this.start++))
36
+ }
37
+ }
38
+
39
+ exports.ReadStream = ReadStream
package/package.json CHANGED
@@ -1,57 +1,56 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "9.12.0",
4
- "description": "Hypercore is a secure, distributed append-only log",
3
+ "version": "10.0.0-alpha.11",
4
+ "description": "Hypercore 10",
5
5
  "main": "index.js",
6
- "dependencies": {
7
- "abstract-extension": "^3.0.1",
8
- "atomic-batcher": "^1.0.2",
9
- "bitfield-rle": "^2.2.1",
10
- "codecs": "^2.0.0",
11
- "fast-bitfield": "^1.2.2",
12
- "flat-tree": "^1.6.0",
13
- "hypercore-cache": "^1.0.1",
14
- "hypercore-crypto": "^2.0.0",
15
- "hypercore-default-storage": "^1.1.1",
16
- "hypercore-protocol": "^8.0.5",
17
- "hypercore-streams": "^1.0.1",
18
- "inherits": "^2.0.3",
19
- "inspect-custom-symbol": "^1.1.0",
20
- "last-one-wins": "^1.0.4",
21
- "memory-pager": "^1.0.2",
22
- "merkle-tree-stream": "^4.0.0",
23
- "nanoguard": "^1.2.0",
24
- "nanoresource": "^1.3.0",
25
- "pretty-hash": "^1.0.1",
26
- "sparse-bitfield": "^3.0.0",
27
- "timeout-refresh": "^1.0.3",
28
- "uint64be": "^2.0.1",
29
- "unordered-array-remove": "^1.0.2",
30
- "unordered-set": "^2.0.0"
31
- },
32
- "devDependencies": {
33
- "buffer-from": "^1.1.1",
34
- "nyc": "^14.1.1",
35
- "random-access-memory": "^3.1.0",
36
- "shuffle-array": "^1.0.1",
37
- "speedometer": "^1.0.0",
38
- "standard": "^14.3.4",
39
- "stream-collector": "^1.0.1",
40
- "tape": "^4.6.3"
41
- },
42
6
  "scripts": {
43
- "test": "standard && tape test/*.js",
44
- "cov": "nyc tape test/*.js",
45
- "bench": "cd bench && ./all.sh"
7
+ "test": "standard && brittle test/*.js"
46
8
  },
47
9
  "repository": {
48
10
  "type": "git",
49
- "url": "https://github.com/mafintosh/hypercore.git"
11
+ "url": "git+https://github.com/hypercore-protocol/hypercore.git"
50
12
  },
51
- "author": "Mathias Buus (@mafintosh)",
13
+ "contributors": [
14
+ {
15
+ "name": "Mathias Buus",
16
+ "email": "mathiasbuus@gmail.com",
17
+ "url": "https://mafinto.sh"
18
+ },
19
+ {
20
+ "name": "Andrew Osheroff",
21
+ "email": "andrewosh@gmail.com",
22
+ "url": "https://andrewosh.com"
23
+ }
24
+ ],
52
25
  "license": "MIT",
53
26
  "bugs": {
54
- "url": "https://github.com/mafintosh/hypercore/issues"
27
+ "url": "https://github.com/hypercore-protocol/hypercore/issues"
28
+ },
29
+ "homepage": "https://github.com/hypercore-protocol/hypercore#readme",
30
+ "dependencies": {
31
+ "@hyperswarm/secret-stream": "^5.0.0",
32
+ "b4a": "^1.1.0",
33
+ "big-sparse-array": "^1.0.2",
34
+ "codecs": "^2.2.0",
35
+ "compact-encoding": "^2.5.0",
36
+ "crc32-universal": "^1.0.1",
37
+ "flat-tree": "^1.9.0",
38
+ "hypercore-crypto": "^2.1.1",
39
+ "is-options": "^1.0.1",
40
+ "random-access-file": "^2.1.4",
41
+ "random-array-iterator": "^1.0.0",
42
+ "safety-catch": "^1.0.1",
43
+ "sodium-universal": "^3.0.4",
44
+ "xache": "^1.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "brittle": "^1.4.1",
48
+ "hyperswarm": "next",
49
+ "random-access-memory": "^3.1.2",
50
+ "standard": "^16.0.3",
51
+ "tmp-promise": "^3.0.2"
55
52
  },
56
- "homepage": "https://github.com/mafintosh/hypercore"
53
+ "optionalDependencies": {
54
+ "fsctl": "^1.0.0"
55
+ }
57
56
  }
package/test/basic.js CHANGED
@@ -1,502 +1,90 @@
1
- var create = require('./helpers/create')
2
- var createTrackingRam = require('./helpers/create-tracking-ram')
3
- var crypto = require('hypercore-crypto')
4
- var tape = require('tape')
5
- var hypercore = require('../')
6
- var ram = require('random-access-memory')
7
- var bufferAlloc = require('buffer-alloc-unsafe')
1
+ const test = require('brittle')
2
+ const ram = require('random-access-memory')
8
3
 
9
- tape('append', function (t) {
10
- t.plan(8)
4
+ const Hypercore = require('../')
5
+ const { create } = require('./helpers')
11
6
 
12
- var feed = create({ valueEncoding: 'json' })
7
+ test('basic', async function (t) {
8
+ const core = await create()
9
+ let appends = 0
13
10
 
14
- feed.append({
15
- hello: 'world'
16
- })
17
-
18
- feed.append([{
19
- hello: 'verden'
20
- }, {
21
- hello: 'welt'
22
- }])
23
-
24
- feed.flush(function () {
25
- t.same(feed.length, 3, '3 blocks')
26
- t.same(feed.byteLength, 54, '54 bytes')
27
-
28
- feed.get(0, function (err, value) {
29
- t.error(err, 'no error')
30
- t.same(value, { hello: 'world' })
31
- })
32
-
33
- feed.get(1, function (err, value) {
34
- t.error(err, 'no error')
35
- t.same(value, { hello: 'verden' })
36
- })
37
-
38
- feed.get(2, function (err, value) {
39
- t.error(err, 'no error')
40
- t.same(value, { hello: 'welt' })
41
- })
42
- })
43
- })
44
-
45
- tape('flush', function (t) {
46
- var feed = create()
47
-
48
- feed.append('hello')
49
-
50
- feed.flush(function (err) {
51
- t.error(err, 'no error')
52
- t.same(feed.length, 1, '1 block')
53
- t.end()
54
- })
55
- })
56
-
57
- tape('verify', function (t) {
58
- t.plan(9)
59
-
60
- var feed = create()
61
- var evilfeed = create(feed.key, { secretKey: feed.secretKey })
62
-
63
- feed.append('test', function (err) {
64
- t.error(err, 'no error')
65
-
66
- evilfeed.append('t\0st', function (err) {
67
- t.error(err, 'no error')
68
-
69
- feed.signature(0, function (err, sig) {
70
- t.error(err, 'no error')
71
- t.same(sig.index, 0, '0 signed at 0')
72
-
73
- feed.verify(0, sig.signature, function (err, success) {
74
- t.error(err, 'no error')
75
- t.ok(success)
76
- })
77
-
78
- evilfeed.verify(0, sig.signature, function (err, success) {
79
- t.ok(!!err)
80
- t.ok(err instanceof Error)
81
- t.ok(!success, 'fake verify failed')
82
- })
83
- })
84
- })
85
- })
86
- })
87
-
88
- tape('rootHashes', function (t) {
89
- t.plan(9)
90
-
91
- var feed = create()
92
- var evilfeed = create(feed.key, { secretKey: feed.secretKey })
93
-
94
- feed.append('test', function (err) {
95
- t.error(err, 'no error')
96
-
97
- evilfeed.append('t\0st', function (err) {
98
- t.error(err, 'no error')
99
-
100
- var result = []
11
+ t.is(core.length, 0)
12
+ t.is(core.byteLength, 0)
13
+ t.is(core.writable, true)
14
+ t.is(core.readable, true)
101
15
 
102
- feed.rootHashes(0, onroots)
103
- evilfeed.rootHashes(0, onroots)
104
-
105
- function onroots (err, roots) {
106
- t.error(err, 'no error')
107
- t.ok(roots instanceof Array)
108
- result.push(roots)
109
- if (result.length < 2) return
110
- t.notEqual(result[0], result[1])
111
- t.equal(result[0].length, result[1].length)
112
- t.notEqual(Buffer.compare(result[0][0].hash, result[1][0].hash), 0)
113
- }
114
- })
16
+ core.on('append', function () {
17
+ appends++
115
18
  })
116
- })
117
19
 
118
- tape('pass in secret key', function (t) {
119
- var keyPair = crypto.keyPair()
120
- var secretKey = keyPair.secretKey
121
- var key = keyPair.publicKey
20
+ await core.append('hello')
21
+ await core.append('world')
122
22
 
123
- var feed = create(key, { secretKey: secretKey })
23
+ t.is(core.length, 2)
24
+ t.is(core.byteLength, 10)
25
+ t.is(appends, 2)
124
26
 
125
- feed.on('ready', function () {
126
- t.same(feed.key, key)
127
- t.same(feed.secretKey, secretKey)
128
- t.ok(feed.writable)
129
- t.end()
130
- })
27
+ t.end()
131
28
  })
132
29
 
133
- tape('check existing key', function (t) {
134
- var feed = hypercore(storage)
30
+ test('session', async function (t) {
31
+ const core = await create()
135
32
 
136
- feed.append('hi', function () {
137
- var key = bufferAlloc(32)
138
- key.fill(0)
139
- var otherFeed = hypercore(storage, key)
140
- otherFeed.on('error', function () {
141
- t.pass('should error')
142
- t.end()
143
- })
144
- })
33
+ const session = core.session()
145
34
 
146
- function storage (name) {
147
- if (storage[name]) return storage[name]
148
- storage[name] = ram()
149
- return storage[name]
150
- }
35
+ await session.append('test')
36
+ t.alike(await core.get(0), Buffer.from('test'))
37
+ t.alike(await session.get(0), Buffer.from('test'))
38
+ t.end()
151
39
  })
152
40
 
153
- tape('create from existing keys', function (t) {
154
- t.plan(3)
155
-
156
- var storage1 = storage.bind(null, '1')
157
- var storage2 = storage.bind(null, '2')
158
-
159
- var feed = hypercore(storage1)
41
+ test('close', async function (t) {
42
+ const core = await create()
43
+ await core.append('hello world')
160
44
 
161
- feed.append('hi', function () {
162
- var otherFeed = hypercore(storage2, feed.key, { secretKey: feed.secretKey })
163
- var store = otherFeed._storage
164
- otherFeed.ready(function () {
165
- store.open({ key: feed.key }, function (err, data) {
166
- t.error(err)
167
- t.equals(data.key.toString('hex'), feed.key.toString('hex'))
168
- t.equals(data.secretKey.toString('hex'), feed.secretKey.toString('hex'))
169
- })
170
- })
171
- })
45
+ await core.close()
172
46
 
173
- function storage (prefix, name) {
174
- var fullname = prefix + '_' + name
175
- if (storage[fullname]) return storage[fullname]
176
- storage[fullname] = ram()
177
- return storage[fullname]
47
+ try {
48
+ await core.get(0)
49
+ t.fail('core should be closed')
50
+ } catch {
51
+ t.pass('get threw correctly when core was closed')
178
52
  }
179
53
  })
180
54
 
181
- tape('head', function (t) {
182
- t.plan(8)
183
-
184
- var feed = create({ valueEncoding: 'json' })
185
-
186
- feed.head(function (err, head) {
187
- t.ok(!!err)
188
- t.ok(err instanceof Error)
189
- step2()
190
- })
191
-
192
- function step2 () {
193
- feed.append({
194
- hello: 'world'
195
- }, function () {
196
- feed.head(function (err, head) {
197
- t.error(err)
198
- t.same(head, { hello: 'world' })
199
- step3()
200
- })
201
- })
202
- }
203
-
204
- function step3 () {
205
- feed.append([{
206
- hello: 'verden'
207
- }, {
208
- hello: 'welt'
209
- }], function () {
210
- feed.head({}, function (err, head) {
211
- t.error(err)
212
- t.same(head, { hello: 'welt' })
213
- step4()
214
- })
215
- })
216
- }
217
-
218
- function step4 () {
219
- feed.append('blender', function () {
220
- feed.head({ valueEncoding: 'utf-8' }, function (err, head) {
221
- t.error(err)
222
- t.same(head, '"blender"\n')
223
- })
224
- })
225
- }
226
- })
227
-
228
- tape('append, no cache', function (t) {
229
- t.plan(8)
230
-
231
- var feed = create({ valueEncoding: 'json', storageCacheSize: 0 })
232
-
233
- feed.append({
234
- hello: 'world'
235
- })
236
-
237
- feed.append([{
238
- hello: 'verden'
239
- }, {
240
- hello: 'welt'
241
- }])
242
-
243
- feed.flush(function () {
244
- t.same(feed.length, 3, '3 blocks')
245
- t.same(feed.byteLength, 54, '54 bytes')
246
-
247
- feed.get(0, function (err, value) {
248
- t.error(err, 'no error')
249
- t.same(value, { hello: 'world' })
250
- })
251
-
252
- feed.get(1, function (err, value) {
253
- t.error(err, 'no error')
254
- t.same(value, { hello: 'verden' })
255
- })
256
-
257
- feed.get(2, function (err, value) {
258
- t.error(err, 'no error')
259
- t.same(value, { hello: 'welt' })
260
- })
261
- })
262
- })
263
-
264
- tape('onwrite', function (t) {
265
- var expected = [
266
- { index: 0, data: 'hello', peer: null },
267
- { index: 1, data: 'world', peer: null }
268
- ]
55
+ test('close multiple', async function (t) {
56
+ const core = await create()
57
+ await core.append('hello world')
269
58
 
270
- var feed = create({
271
- onwrite: function (index, data, peer, cb) {
272
- t.same({ index: index, data: data.toString(), peer: peer }, expected.shift())
273
- cb()
274
- }
275
- })
276
-
277
- feed.append(['hello', 'world'], function (err) {
278
- t.error(err, 'no error')
279
- t.same(expected.length, 0)
280
- t.end()
281
- })
282
- })
59
+ const ev = t.test('events')
283
60
 
284
- tape('close, emitter and callback', function (t) {
285
- t.plan(3)
286
- var feed = create()
61
+ ev.plan(4)
287
62
 
288
- feed.on('close', function () {
289
- t.pass('close emitted')
290
- })
63
+ let i = 0
291
64
 
292
- feed.close(function (err) {
293
- t.error(err, 'closed without error')
294
- t.pass('callback invoked')
295
- })
65
+ core.on('close', () => ev.is(i++, 0, 'on close'))
66
+ core.close().then(() => ev.is(i++, 1, 'first close'))
67
+ core.close().then(() => ev.is(i++, 2, 'second close'))
68
+ core.close().then(() => ev.is(i++, 3, 'third close'))
296
69
 
297
- feed.close(function () {
298
- t.end()
299
- })
70
+ await ev
300
71
  })
301
72
 
302
- tape('close calls pending callbacks', function (t) {
303
- t.plan(5)
304
-
305
- var feed = create()
306
-
307
- feed.createReadStream({ live: true })
308
- .once('error', function (err) {
309
- t.ok(err, 'read stream errors')
310
- })
311
- .resume()
312
-
313
- feed.get(0, function (err) {
314
- t.ok(err, 'get errors')
315
- })
316
-
317
- feed.once('close', function () {
318
- t.pass('close emitted')
319
- })
320
-
321
- feed.ready(function () {
322
- feed.close(function () {
323
- feed.createReadStream({ live: true })
324
- .once('error', function (err) {
325
- t.ok(err, 'read stream still errors')
326
- })
327
- .resume()
328
-
329
- feed.get(0, function (err) {
330
- t.ok(err, 'get still errors')
331
- })
332
- })
333
- })
73
+ test('storage options', async function (t) {
74
+ const core = new Hypercore({ storage: ram })
75
+ await core.append('hello')
76
+ t.alike(await core.get(0), Buffer.from('hello'))
77
+ t.end()
334
78
  })
335
79
 
336
- tape('get batch', function (t) {
337
- t.plan(2 * 3)
80
+ test(
81
+ 'allow publicKeys with different byteLength that 32, if opts.crypto were passed',
82
+ function (t) {
83
+ const key = Buffer.alloc(33).fill('a')
338
84
 
339
- var feed = create({ valueEncoding: 'utf-8' })
85
+ const core = new Hypercore(ram, key, { crypto: {} })
340
86
 
341
- feed.append(['a', 'be', 'cee', 'd'], function () {
342
- feed.getBatch(0, 4, function (err, batch) {
343
- t.error(err)
344
- t.same(batch, ['a', 'be', 'cee', 'd'])
345
- })
346
- feed.getBatch(1, 3, function (err, batch) {
347
- t.error(err)
348
- t.same(batch, ['be', 'cee'])
349
- })
350
- feed.getBatch(2, 4, function (err, batch) {
351
- t.error(err)
352
- t.same(batch, ['cee', 'd'])
353
- })
354
- })
355
- })
356
-
357
- tape('append returns the seq', function (t) {
358
- var feed = hypercore(storage)
359
-
360
- feed.append('a', function (err, seq) {
361
- t.error(err)
362
- t.same(seq, 0)
363
- feed.append(['b', 'c'], function (err, seq) {
364
- t.error(err)
365
- t.same(seq, 1)
366
- feed.append(['d'], function (err, seq) {
367
- t.error(err)
368
- t.same(seq, 3)
369
-
370
- var reloaded = hypercore(storage)
371
- reloaded.append(['e'], function (err, seq) {
372
- t.error(err)
373
- t.same(seq, 4)
374
- t.same(reloaded.length, 5)
375
- t.end()
376
- })
377
- })
378
- })
379
- })
380
-
381
- function storage (name) {
382
- if (storage[name]) return storage[name]
383
- storage[name] = ram()
384
- return storage[name]
87
+ t.is(core.key, key)
88
+ t.pass('creating a core with more than 32 byteLength key did not throw')
385
89
  }
386
- })
387
-
388
- tape('append and createWriteStreams preserve seq', function (t) {
389
- var feed = create()
390
-
391
- var ws = feed.createWriteStream()
392
-
393
- ws.write('a')
394
- ws.write('b')
395
- ws.write('c')
396
- ws.end(function () {
397
- t.same(feed.length, 3)
398
- feed.append('d', function (err, seq) {
399
- t.error(err)
400
- t.same(seq, 3)
401
- t.same(feed.length, 4)
402
-
403
- var ws1 = feed.createWriteStream()
404
-
405
- ws1.write('e')
406
- ws1.write('f')
407
- ws1.end(function () {
408
- feed.append('g', function (err, seq) {
409
- t.error(err)
410
- t.same(seq, 6)
411
- t.same(feed.length, 7)
412
- t.end()
413
- })
414
- })
415
- })
416
- })
417
- })
418
-
419
- tape('closing all streams on close', function (t) {
420
- var memories = {}
421
- var feed = hypercore(function (filename) {
422
- var memory = memories[filename]
423
- if (!memory) {
424
- memory = ram()
425
- memories[filename] = memory
426
- }
427
- return memory
428
- })
429
- var expectedFiles = ['key', 'secret_key', 'tree', 'data', 'bitfield', 'signatures']
430
- feed.ready(function () {
431
- t.deepEquals(Object.keys(memories), expectedFiles, 'all files are open')
432
- feed.close(function () {
433
- expectedFiles.forEach(function (filename) {
434
- var memory = memories[filename]
435
- t.ok(memory.closed, filename + ' is closed')
436
- })
437
- t.end()
438
- })
439
- })
440
- })
441
-
442
- tape('writes are batched', function (t) {
443
- var trackingRam = createTrackingRam()
444
- var feed = hypercore(trackingRam)
445
- var ws = feed.createWriteStream()
446
-
447
- ws.write('ab')
448
- ws.write('cd')
449
- setImmediate(function () {
450
- ws.write('ef')
451
- ws.write('gh')
452
- ws.end(function () {
453
- t.deepEquals(trackingRam.log.data, [
454
- { write: [0, Buffer.from('abcd')] },
455
- { write: [4, Buffer.from('efgh')] }
456
- ])
457
- feed.close(function () {
458
- t.end()
459
- })
460
- })
461
- })
462
- })
463
-
464
- tape('cancel get', function (t) {
465
- var feed = create()
466
- var cancelled = false
467
-
468
- const get = feed.get(42, function (err) {
469
- t.ok(cancelled, 'was cancelled')
470
- t.ok(err, 'had error')
471
- t.end()
472
- })
473
-
474
- setImmediate(function () {
475
- cancelled = true
476
- feed.cancel(get)
477
- })
478
- })
479
-
480
- tape('onwait', function (t) {
481
- t.plan(2)
482
-
483
- var feed = create()
484
-
485
- feed.append('a', function () {
486
- feed.get(0, {
487
- onwait () {
488
- t.fail('no onwait')
489
- }
490
- }, function () {
491
- t.ok('should call cb')
492
- })
493
-
494
- feed.get(42, {
495
- onwait () {
496
- t.ok('should wait')
497
- }
498
- }, function () {
499
- t.fail('no cb')
500
- })
501
- })
502
- })
90
+ )