hypercore 11.16.2 → 11.18.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
@@ -10,6 +10,7 @@ const id = require('hypercore-id-encoding')
10
10
  const safetyCatch = require('safety-catch')
11
11
  const unslab = require('unslab')
12
12
 
13
+ const inspect = require('./lib/inspect')
13
14
  const Core = require('./lib/core')
14
15
  const Info = require('./lib/info')
15
16
  const Download = require('./lib/download')
@@ -29,14 +30,14 @@ const {
29
30
  DECODING_ERROR
30
31
  } = require('hypercore-errors')
31
32
 
32
- const inspect = Symbol.for('nodejs.util.inspect.custom')
33
+ const inspectSymbol = Symbol.for('nodejs.util.inspect.custom')
33
34
 
34
35
  // Hypercore actually does not have any notion of max/min block sizes
35
36
  // but we enforce 15mb to ensure smooth replication (each block is transmitted atomically)
36
37
  const MAX_SUGGESTED_BLOCK_SIZE = 15 * 1024 * 1024
37
38
 
38
39
  class Hypercore extends EventEmitter {
39
- constructor (storage, key, opts) {
40
+ constructor(storage, key, opts) {
40
41
  super()
41
42
 
42
43
  if (isOptions(storage) && !storage.db) {
@@ -96,75 +97,37 @@ class Hypercore extends EventEmitter {
96
97
  this.on('newListener', maybeAddMonitor)
97
98
  }
98
99
 
99
- [inspect] (depth, opts) {
100
- let indent = ''
101
- if (typeof opts.indentationLvl === 'number') {
102
- while (indent.length < opts.indentationLvl) indent += ' '
103
- }
104
-
105
- let peers = ''
106
- const min = Math.min(this.peers.length, 5)
107
-
108
- for (let i = 0; i < min; i++) {
109
- const peer = this.peers[i]
110
-
111
- peers += indent + ' Peer(\n'
112
- peers += indent + ' remotePublicKey: ' + opts.stylize(toHex(peer.remotePublicKey), 'string') + '\n'
113
- peers += indent + ' remoteLength: ' + opts.stylize(peer.remoteLength, 'number') + '\n'
114
- peers += indent + ' remoteFork: ' + opts.stylize(peer.remoteFork, 'number') + '\n'
115
- peers += indent + ' remoteCanUpgrade: ' + opts.stylize(peer.remoteCanUpgrade, 'boolean') + '\n'
116
- peers += indent + ' )' + '\n'
117
- }
118
-
119
- if (this.peers.length > 5) {
120
- peers += indent + ' ... and ' + (this.peers.length - 5) + ' more\n'
121
- }
122
-
123
- if (peers) peers = '[\n' + peers + indent + ' ]'
124
- else peers = '[ ' + opts.stylize(0, 'number') + ' ]'
125
-
126
- return this.constructor.name + '(\n' +
127
- indent + ' id: ' + opts.stylize(this.id, 'string') + '\n' +
128
- indent + ' key: ' + opts.stylize(toHex(this.key), 'string') + '\n' +
129
- indent + ' discoveryKey: ' + opts.stylize(toHex(this.discoveryKey), 'string') + '\n' +
130
- indent + ' opened: ' + opts.stylize(this.opened, 'boolean') + '\n' +
131
- indent + ' closed: ' + opts.stylize(this.closed, 'boolean') + '\n' +
132
- indent + ' snapshotted: ' + opts.stylize(this.snapshotted, 'boolean') + '\n' +
133
- indent + ' writable: ' + opts.stylize(this.writable, 'boolean') + '\n' +
134
- indent + ' length: ' + opts.stylize(this.length, 'number') + '\n' +
135
- indent + ' fork: ' + opts.stylize(this.fork, 'number') + '\n' +
136
- indent + ' sessions: [ ' + opts.stylize(this.sessions.length, 'number') + ' ]\n' +
137
- indent + ' activeRequests: [ ' + opts.stylize(this.activeRequests.length, 'number') + ' ]\n' +
138
- indent + ' peers: ' + peers + '\n' +
139
- indent + ')'
100
+ [inspectSymbol](depth, opts) {
101
+ return inspect(this, depth, opts)
140
102
  }
141
103
 
142
104
  static MAX_SUGGESTED_BLOCK_SIZE = MAX_SUGGESTED_BLOCK_SIZE
143
105
 
144
106
  static DefaultEncryption = DefaultEncryption
145
107
 
146
- static key (manifest, { compat, version, namespace } = {}) {
147
- if (b4a.isBuffer(manifest)) manifest = { version, signers: [{ publicKey: manifest, namespace }] }
108
+ static key(manifest, { compat, version, namespace } = {}) {
109
+ if (b4a.isBuffer(manifest))
110
+ manifest = { version, signers: [{ publicKey: manifest, namespace }] }
148
111
  return compat ? manifest.signers[0].publicKey : manifestHash(createManifest(manifest))
149
112
  }
150
113
 
151
- static discoveryKey (key) {
114
+ static discoveryKey(key) {
152
115
  return crypto.discoveryKey(key)
153
116
  }
154
117
 
155
- static blockEncryptionKey (key, encryptionKey) {
118
+ static blockEncryptionKey(key, encryptionKey) {
156
119
  return DefaultEncryption.blockEncryptionKey(key, encryptionKey)
157
120
  }
158
121
 
159
- static getProtocolMuxer (stream) {
122
+ static getProtocolMuxer(stream) {
160
123
  return stream.noiseStream.userData
161
124
  }
162
125
 
163
- static createCore (storage, opts) {
126
+ static createCore(storage, opts) {
164
127
  return new Core(Hypercore.defaultStorage(storage), { autoClose: false, ...opts })
165
128
  }
166
129
 
167
- static createProtocolStream (isInitiator, opts = {}) {
130
+ static createProtocolStream(isInitiator, opts = {}) {
168
131
  let outerStream = Protomux.isProtomux(isInitiator)
169
132
  ? isInitiator.stream
170
133
  : isStream(isInitiator)
@@ -197,22 +160,26 @@ class Hypercore extends EventEmitter {
197
160
  return outerStream
198
161
  }
199
162
 
200
- static defaultStorage (storage, opts = {}) {
163
+ static defaultStorage(storage, opts = {}) {
201
164
  if (CoreStorage.isCoreStorage(storage)) return storage
202
165
 
203
166
  const directory = storage
204
167
  return new CoreStorage(directory, opts)
205
168
  }
206
169
 
207
- static clearRequests (session, err) {
170
+ static clearRequests(session, err) {
208
171
  return Replicator.clearRequests(session, err)
209
172
  }
210
173
 
211
- snapshot (opts) {
174
+ snapshot(opts) {
212
175
  return this.session({ ...opts, snapshot: true })
213
176
  }
214
177
 
215
- session (opts = {}) {
178
+ compact() {
179
+ return this.core.compact()
180
+ }
181
+
182
+ session(opts = {}) {
216
183
  if (this.closing) {
217
184
  // This makes the closing logic a lot easier. If this turns out to be a problem
218
185
  // in practice, open an issue and we'll try to make a solution for it.
@@ -243,13 +210,13 @@ class Hypercore extends EventEmitter {
243
210
  return s
244
211
  }
245
212
 
246
- async setEncryptionKey (key, opts) {
213
+ async setEncryptionKey(key, opts) {
247
214
  if (!this.opened) await this.opening
248
215
  const encryption = this._getEncryptionProvider({ key, block: !!(opts && opts.block) })
249
216
  return this.setEncryption(encryption)
250
217
  }
251
218
 
252
- async setEncryption (encryption) {
219
+ async setEncryption(encryption) {
253
220
  if (!this.opened) await this.opening
254
221
 
255
222
  if (encryption === null) {
@@ -264,11 +231,11 @@ class Hypercore extends EventEmitter {
264
231
  this.encryption = encryption
265
232
  }
266
233
 
267
- setKeyPair (keyPair) {
234
+ setKeyPair(keyPair) {
268
235
  this.keyPair = keyPair
269
236
  }
270
237
 
271
- setActive (bool) {
238
+ setActive(bool) {
272
239
  const active = !!bool
273
240
  if (active === this._active || this.closing) return
274
241
  this._active = active
@@ -276,7 +243,7 @@ class Hypercore extends EventEmitter {
276
243
  this.core.replicator.updateActivity(this._active ? 1 : -1)
277
244
  }
278
245
 
279
- async _open (storage, key, opts) {
246
+ async _open(storage, key, opts) {
280
247
  const preload = opts.preload || (opts.parent && opts.parent.preload)
281
248
 
282
249
  if (preload) {
@@ -324,7 +291,7 @@ class Hypercore extends EventEmitter {
324
291
  if (this.core.closing) this.close().catch(safetyCatch)
325
292
  }
326
293
 
327
- _removeSession () {
294
+ _removeSession() {
328
295
  if (this._sessionIndex === -1) return
329
296
  const head = this.sessions.pop()
330
297
  if (head !== this) this.sessions[(head._sessionIndex = this._sessionIndex)] = head
@@ -332,7 +299,7 @@ class Hypercore extends EventEmitter {
332
299
  if (this.ongc !== null) this.ongc(this)
333
300
  }
334
301
 
335
- async _openSession (opts) {
302
+ async _openSession(opts) {
336
303
  if (this.core.opened === false) await this.core.ready()
337
304
 
338
305
  if (this.keyPair === null) this.keyPair = opts.keyPair || this.core.header.keyPair
@@ -388,10 +355,18 @@ class Hypercore extends EventEmitter {
388
355
  }
389
356
 
390
357
  if (this.state && checkout !== -1) {
391
- if (!opts.name && !opts.atom) throw ASSERTION('Checkouts must be named or atomized', this.discoveryKey)
392
- if (checkout > this.state.length) throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', length is ' + this.state.length, this.discoveryKey)
358
+ if (!opts.name && !opts.atom)
359
+ throw ASSERTION('Checkouts must be named or atomized', this.discoveryKey)
360
+ if (checkout > this.state.length)
361
+ throw ASSERTION(
362
+ `Invalid checkout ${checkout} for ${opts.name}, length is ${this.state.length}`,
363
+ this.discoveryKey
364
+ )
393
365
  if (this.state.prologue && checkout < this.state.prologue.length) {
394
- throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', prologue length is ' + this.state.prologue.length, this.discoveryKey)
366
+ throw ASSERTION(
367
+ `Invalid checkout ${checkout} for ${opts.name}, prologue length is ${this.state.prologue.length}`,
368
+ this.discoveryKey
369
+ )
395
370
  }
396
371
  if (checkout < this.state.length) await this.state.truncate(checkout, this.fork)
397
372
  }
@@ -425,11 +400,11 @@ class Hypercore extends EventEmitter {
425
400
  this.opened = true
426
401
  }
427
402
 
428
- get replicator () {
403
+ get replicator() {
429
404
  return this.core === null ? null : this.core.replicator
430
405
  }
431
406
 
432
- _getSnapshot () {
407
+ _getSnapshot() {
433
408
  return {
434
409
  length: this.state.length,
435
410
  byteLength: this.state.byteLength,
@@ -437,33 +412,33 @@ class Hypercore extends EventEmitter {
437
412
  }
438
413
  }
439
414
 
440
- _updateSnapshot () {
415
+ _updateSnapshot() {
441
416
  const prev = this._snapshot
442
- const next = this._snapshot = this._getSnapshot()
417
+ const next = (this._snapshot = this._getSnapshot())
443
418
 
444
419
  if (!prev) return true
445
420
  return prev.length !== next.length || prev.fork !== next.fork
446
421
  }
447
422
 
448
- _isWritable () {
423
+ _isWritable() {
449
424
  if (this._readonly) return false
450
425
  if (this.state && !this.state.isDefault()) return true
451
426
  return !!(this.keyPair && this.keyPair.secretKey)
452
427
  }
453
428
 
454
- close ({ error } = {}) {
429
+ close({ error } = {}) {
455
430
  if (this.closing) return this.closing
456
431
 
457
432
  this.closing = this._close(error || null)
458
433
  return this.closing
459
434
  }
460
435
 
461
- clearRequests (activeRequests, error) {
436
+ clearRequests(activeRequests, error) {
462
437
  if (!activeRequests.length) return
463
438
  if (this.core) this.core.replicator.clearRequests(activeRequests, error)
464
439
  }
465
440
 
466
- async _close (error) {
441
+ async _close(error) {
467
442
  if (this.opened === false) {
468
443
  try {
469
444
  await this.opening
@@ -511,14 +486,14 @@ class Hypercore extends EventEmitter {
511
486
  this.emit('close')
512
487
  }
513
488
 
514
- async commit (session, opts) {
489
+ async commit(session, opts) {
515
490
  await this.ready()
516
491
  await session.ready()
517
492
 
518
493
  return this.state.commit(session.state, { keyPair: this.keyPair, ...opts })
519
494
  }
520
495
 
521
- replicate (isInitiator, opts = {}) {
496
+ replicate(isInitiator, opts = {}) {
522
497
  // Only limitation here is that ondiscoverykey doesn't work atm when passing a muxer directly,
523
498
  // because it doesn't really make a lot of sense.
524
499
  if (Protomux.isProtomux(isInitiator)) return this._attachToMuxer(isInitiator)
@@ -535,11 +510,16 @@ class Hypercore extends EventEmitter {
535
510
  return protocolStream
536
511
  }
537
512
 
538
- _isAttached (stream) {
539
- return stream.userData && this.core && this.core.replicator && this.core.replicator.attached(stream.userData)
513
+ _isAttached(stream) {
514
+ return (
515
+ stream.userData &&
516
+ this.core &&
517
+ this.core.replicator &&
518
+ this.core.replicator.attached(stream.userData)
519
+ )
540
520
  }
541
521
 
542
- _attachToMuxer (mux) {
522
+ _attachToMuxer(mux) {
543
523
  if (this.opened) {
544
524
  this.core.replicator.attachTo(mux)
545
525
  } else {
@@ -549,55 +529,55 @@ class Hypercore extends EventEmitter {
549
529
  return mux
550
530
  }
551
531
 
552
- get id () {
532
+ get id() {
553
533
  return this.core === null ? null : this.core.id
554
534
  }
555
535
 
556
- get key () {
536
+ get key() {
557
537
  return this.core === null ? null : this.core.key
558
538
  }
559
539
 
560
- get discoveryKey () {
540
+ get discoveryKey() {
561
541
  return this.core === null ? null : this.core.discoveryKey
562
542
  }
563
543
 
564
- get manifest () {
544
+ get manifest() {
565
545
  return this.core === null ? null : this.core.manifest
566
546
  }
567
547
 
568
- get length () {
548
+ get length() {
569
549
  if (this._snapshot) return this._snapshot.length
570
550
  return this.opened === false ? 0 : this.state.length
571
551
  }
572
552
 
573
- get signedLength () {
553
+ get signedLength() {
574
554
  return this.opened === false ? 0 : this.state.signedLength()
575
555
  }
576
556
 
577
557
  /**
578
558
  * Deprecated. Use `const { byteLength } = await core.info()`.
579
559
  */
580
- get byteLength () {
560
+ get byteLength() {
581
561
  if (this.opened === false) return 0
582
562
  if (this._snapshot) return this._snapshot.byteLength
583
- return this.state.byteLength - (this.state.length * this.padding)
563
+ return this.state.byteLength - this.state.length * this.padding
584
564
  }
585
565
 
586
- get contiguousLength () {
566
+ get contiguousLength() {
587
567
  if (this.opened === false) return 0
588
568
  return Math.min(this.core.state.length, this.core.header.hints.contiguousLength)
589
569
  }
590
570
 
591
- get contiguousByteLength () {
571
+ get contiguousByteLength() {
592
572
  return 0
593
573
  }
594
574
 
595
- get fork () {
575
+ get fork() {
596
576
  if (this.opened === false) return 0
597
577
  return this.state.fork
598
578
  }
599
579
 
600
- get padding () {
580
+ get padding() {
601
581
  if (this.encryption && this.key && this.manifest) {
602
582
  return this.encryption.padding(this.core, this.length)
603
583
  }
@@ -605,24 +585,24 @@ class Hypercore extends EventEmitter {
605
585
  return 0
606
586
  }
607
587
 
608
- get peers () {
588
+ get peers() {
609
589
  return this.opened === false ? [] : this.core.replicator.peers
610
590
  }
611
591
 
612
- get globalCache () {
592
+ get globalCache() {
613
593
  return this.opened === false ? null : this.core.globalCache
614
594
  }
615
595
 
616
- ready () {
596
+ ready() {
617
597
  return this.opening
618
598
  }
619
599
 
620
- async setUserData (key, value) {
600
+ async setUserData(key, value) {
621
601
  if (this.opened === false) await this.opening
622
602
  await this.state.setUserData(key, value)
623
603
  }
624
604
 
625
- async getUserData (key) {
605
+ async getUserData(key) {
626
606
  if (this.opened === false) await this.opening
627
607
  const batch = this.state.storage.read()
628
608
  const p = batch.getUserData(key)
@@ -630,7 +610,7 @@ class Hypercore extends EventEmitter {
630
610
  return p
631
611
  }
632
612
 
633
- transferSession (core) {
613
+ transferSession(core) {
634
614
  // todo: validate we can move
635
615
 
636
616
  if (this.weak === false) {
@@ -652,7 +632,7 @@ class Hypercore extends EventEmitter {
652
632
  this.emit('migrate', this.key)
653
633
  }
654
634
 
655
- findingPeers () {
635
+ findingPeers() {
656
636
  this._findingPeers++
657
637
  if (this.core !== null && !this.closing) this.core.replicator.findingPeers++
658
638
 
@@ -668,13 +648,13 @@ class Hypercore extends EventEmitter {
668
648
  }
669
649
  }
670
650
 
671
- async info (opts) {
651
+ async info(opts) {
672
652
  if (this.opened === false) await this.opening
673
653
 
674
654
  return Info.from(this, opts)
675
655
  }
676
656
 
677
- async update (opts) {
657
+ async update(opts) {
678
658
  if (this.opened === false) await this.opening
679
659
  if (this.closing !== null) return false
680
660
  if (this.snapshotted) return false
@@ -705,7 +685,7 @@ class Hypercore extends EventEmitter {
705
685
  return true
706
686
  }
707
687
 
708
- async seek (bytes, opts) {
688
+ async seek(bytes, opts) {
709
689
  if (this.opened === false) await this.opening
710
690
  if (!isValidIndex(bytes)) throw ASSERTION('seek is invalid', this.discoveryKey)
711
691
 
@@ -726,7 +706,8 @@ class Hypercore extends EventEmitter {
726
706
  const offset = await s.update()
727
707
  if (offset) return offset
728
708
 
729
- if (this.closing !== null) throw SESSION_CLOSED('cannot seek on a closed session', this.discoveryKey)
709
+ if (this.closing !== null)
710
+ throw SESSION_CLOSED('cannot seek on a closed session', this.discoveryKey)
730
711
 
731
712
  if (!this._shouldWait(opts, this.wait)) return null
732
713
 
@@ -743,9 +724,10 @@ class Hypercore extends EventEmitter {
743
724
  }
744
725
  }
745
726
 
746
- async has (start, end = start + 1) {
727
+ async has(start, end = start + 1) {
747
728
  if (this.opened === false) await this.opening
748
- if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('has range is invalid', this.discoveryKey)
729
+ if (!isValidIndex(start) || !isValidIndex(end))
730
+ throw ASSERTION('has range is invalid', this.discoveryKey)
749
731
 
750
732
  if (this.state.isDefault()) {
751
733
  if (end === start + 1) return this.core.bitfield.get(start)
@@ -770,16 +752,18 @@ class Hypercore extends EventEmitter {
770
752
  count++
771
753
  }
772
754
 
773
- return count === (end - start)
755
+ return count === end - start
774
756
  }
775
757
 
776
- async get (index, opts) {
758
+ async get(index, opts) {
777
759
  if (this.opened === false) await this.opening
778
760
  if (!isValidIndex(index)) throw ASSERTION('block index is invalid', this.discoveryKey)
779
761
 
780
- if (this.closing !== null) throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
762
+ if (this.closing !== null)
763
+ throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
781
764
 
782
- const encoding = (opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.valueEncoding
765
+ const encoding =
766
+ (opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.valueEncoding
783
767
 
784
768
  if (this.onseq !== null) this.onseq(index, this)
785
769
 
@@ -800,18 +784,20 @@ class Hypercore extends EventEmitter {
800
784
  return this._decode(encoding, block, index)
801
785
  }
802
786
 
803
- async clear (start, end = start + 1, opts) {
787
+ async clear(start, end = start + 1, opts) {
804
788
  if (this.opened === false) await this.opening
805
- if (this.closing !== null) throw SESSION_CLOSED('cannot clear on a closed session', this.discoveryKey)
789
+ if (this.closing !== null)
790
+ throw SESSION_CLOSED('cannot clear on a closed session', this.discoveryKey)
806
791
 
807
792
  if (typeof end === 'object') {
808
793
  opts = end
809
794
  end = start + 1
810
795
  }
811
796
 
812
- if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('clear range is invalid', this.discoveryKey)
797
+ if (!isValidIndex(start) || !isValidIndex(end))
798
+ throw ASSERTION('clear range is invalid', this.discoveryKey)
813
799
 
814
- const cleared = (opts && opts.diff) ? { blocks: 0 } : null
800
+ const cleared = opts && opts.diff ? { blocks: 0 } : null
815
801
 
816
802
  if (start >= end) return cleared
817
803
  if (start >= this.length) return cleared
@@ -821,17 +807,18 @@ class Hypercore extends EventEmitter {
821
807
  return cleared
822
808
  }
823
809
 
824
- async purge () {
810
+ async purge() {
825
811
  await this._closeAllSessions(null)
826
812
  await this.core.purge()
827
813
  }
828
814
 
829
- async _get (index, opts) {
815
+ async _get(index, opts) {
830
816
  const block = await readBlock(this.state.storage.read(), index)
831
817
 
832
818
  if (block !== null) return block
833
819
 
834
- if (this.closing !== null) throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
820
+ if (this.closing !== null)
821
+ throw SESSION_CLOSED('cannot get on a closed session', this.discoveryKey)
835
822
 
836
823
  // snapshot should check if core has block
837
824
  if (this._snapshot !== null) {
@@ -876,7 +863,7 @@ class Hypercore extends EventEmitter {
876
863
  return maybeUnslab(replicatedBlock)
877
864
  }
878
865
 
879
- _shouldWait (opts, defaultValue) {
866
+ _shouldWait(opts, defaultValue) {
880
867
  if (opts) {
881
868
  if (opts.wait === false) return false
882
869
  if (opts.wait === true) return true
@@ -884,33 +871,33 @@ class Hypercore extends EventEmitter {
884
871
  return defaultValue
885
872
  }
886
873
 
887
- createReadStream (opts) {
874
+ createReadStream(opts) {
888
875
  return new ReadStream(this, opts)
889
876
  }
890
877
 
891
- createWriteStream () {
878
+ createWriteStream() {
892
879
  return new WriteStream(this)
893
880
  }
894
881
 
895
- createByteStream (opts) {
882
+ createByteStream(opts) {
896
883
  return new ByteStream(this, opts)
897
884
  }
898
885
 
899
- download (range) {
886
+ download(range) {
900
887
  return new Download(this, range)
901
888
  }
902
889
 
903
890
  // TODO: get rid of this / deprecate it?
904
- undownload (range) {
891
+ undownload(range) {
905
892
  range.destroy(null)
906
893
  }
907
894
 
908
895
  // TODO: get rid of this / deprecate it?
909
- cancel (request) {
896
+ cancel(request) {
910
897
  // Do nothing for now
911
898
  }
912
899
 
913
- async truncate (newLength = 0, opts = {}) {
900
+ async truncate(newLength = 0, opts = {}) {
914
901
  if (this.opened === false) await this.opening
915
902
 
916
903
  const {
@@ -921,7 +908,8 @@ class Hypercore extends EventEmitter {
921
908
 
922
909
  const isDefault = this.state === this.core.state
923
910
  const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
924
- if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork)) throw SESSION_NOT_WRITABLE('cannot append to a non-writable core', this.discoveryKey)
911
+ if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork))
912
+ throw SESSION_NOT_WRITABLE('cannot append to a non-writable core', this.discoveryKey)
925
913
 
926
914
  await this.state.truncate(newLength, fork, { keyPair, signature })
927
915
 
@@ -929,16 +917,18 @@ class Hypercore extends EventEmitter {
929
917
  if (this.state === this.core.state) this.core.replicator.updateAll()
930
918
  }
931
919
 
932
- async append (blocks, opts = {}) {
920
+ async append(blocks, opts = {}) {
933
921
  if (this.opened === false) await this.opening
934
922
 
935
923
  const isDefault = this.state === this.core.state
936
924
  const defaultKeyPair = this.state.name === null ? this.keyPair : null
937
925
 
938
926
  const { keyPair = defaultKeyPair, signature = null, maxLength } = opts
939
- const writable = !isDefault || !!signature || !!(keyPair && keyPair.secretKey) || opts.writable === true
927
+ const writable =
928
+ !isDefault || !!signature || !!(keyPair && keyPair.secretKey) || opts.writable === true
940
929
 
941
- if (this._readonly || writable === false) throw SESSION_NOT_WRITABLE('cannot append to a readonly core', this.discoveryKey)
930
+ if (this._readonly || writable === false)
931
+ throw SESSION_NOT_WRITABLE('cannot append to a readonly core', this.discoveryKey)
942
932
 
943
933
  blocks = Array.isArray(blocks) ? blocks : [blocks]
944
934
 
@@ -953,14 +943,17 @@ class Hypercore extends EventEmitter {
953
943
  }
954
944
  for (const b of buffers) {
955
945
  if (b.byteLength > MAX_SUGGESTED_BLOCK_SIZE) {
956
- throw BAD_ARGUMENT('Appended block exceeds the maximum suggested block size', this.discoveryKey)
946
+ throw BAD_ARGUMENT(
947
+ 'Appended block exceeds the maximum suggested block size',
948
+ this.discoveryKey
949
+ )
957
950
  }
958
951
  }
959
952
 
960
953
  return this.state.append(buffers, { keyPair, signature, preappend, maxLength })
961
954
  }
962
955
 
963
- async signable (length = -1, fork = -1) {
956
+ async signable(length = -1, fork = -1) {
964
957
  if (this.opened === false) await this.opening
965
958
  if (length === -1) length = this.length
966
959
  if (fork === -1) fork = this.fork
@@ -968,7 +961,7 @@ class Hypercore extends EventEmitter {
968
961
  return caps.treeSignable(this.key, await this.treeHash(length), length, fork)
969
962
  }
970
963
 
971
- async treeHash (length = -1) {
964
+ async treeHash(length = -1) {
972
965
  if (this.opened === false) await this.opening
973
966
  if (length === -1) length = this.length
974
967
 
@@ -976,7 +969,12 @@ class Hypercore extends EventEmitter {
976
969
  return crypto.tree(roots)
977
970
  }
978
971
 
979
- async proof (opts) {
972
+ async missingNodes(index) {
973
+ if (this.opened === false) await this.opening
974
+ return await MerkleTree.missingNodes(this.core.state, 2 * index, this.core.state.length)
975
+ }
976
+
977
+ async proof(opts) {
980
978
  if (this.opened === false) await this.opening
981
979
  const rx = this.state.storage.read()
982
980
  const promise = MerkleTree.proof(this.state, rx, opts)
@@ -984,14 +982,14 @@ class Hypercore extends EventEmitter {
984
982
  return promise
985
983
  }
986
984
 
987
- async verifyFullyRemote (proof) {
985
+ async verifyFullyRemote(proof) {
988
986
  if (this.opened === false) await this.opening
989
987
  const batch = await MerkleTree.verifyFullyRemote(this.state, proof)
990
988
  await this.core._verifyBatchUpgrade(batch, proof.manifest)
991
989
  return batch
992
990
  }
993
991
 
994
- registerExtension (name, handlers = {}) {
992
+ registerExtension(name, handlers = {}) {
995
993
  if (this.extensions.has(name)) {
996
994
  const ext = this.extensions.get(name)
997
995
  ext.handlers = handlers
@@ -1005,23 +1003,23 @@ class Hypercore extends EventEmitter {
1005
1003
  handlers,
1006
1004
  encoding: c.from(handlers.encoding || c.buffer),
1007
1005
  session: this,
1008
- send (message, peer) {
1006
+ send(message, peer) {
1009
1007
  const buffer = c.encode(this.encoding, message)
1010
1008
  peer.extension(name, buffer)
1011
1009
  },
1012
- broadcast (message) {
1010
+ broadcast(message) {
1013
1011
  const buffer = c.encode(this.encoding, message)
1014
1012
  for (const peer of this.session.peers) {
1015
1013
  peer.extension(name, buffer)
1016
1014
  }
1017
1015
  },
1018
- destroy () {
1016
+ destroy() {
1019
1017
  for (const peer of this.session.peers) {
1020
1018
  if (peer.extensions.get(name) === ext) peer.extensions.delete(name)
1021
1019
  }
1022
1020
  this.session.extensions.delete(name)
1023
1021
  },
1024
- _onmessage (state, peer) {
1022
+ _onmessage(state, peer) {
1025
1023
  const m = this.encoding.decode(state)
1026
1024
  if (this.handlers.onmessage) this.handlers.onmessage(m, peer)
1027
1025
  }
@@ -1039,7 +1037,7 @@ class Hypercore extends EventEmitter {
1039
1037
  return ext
1040
1038
  }
1041
1039
 
1042
- _encode (enc, val) {
1040
+ _encode(enc, val) {
1043
1041
  const state = { start: this.padding, end: this.padding, buffer: null }
1044
1042
 
1045
1043
  if (b4a.isBuffer(val)) {
@@ -1061,7 +1059,7 @@ class Hypercore extends EventEmitter {
1061
1059
  return state.buffer
1062
1060
  }
1063
1061
 
1064
- _decode (enc, block, index) {
1062
+ _decode(enc, block, index) {
1065
1063
  if (this.encryption) block = block.subarray(this.encryption.padding(this.core, index))
1066
1064
  try {
1067
1065
  if (enc) return c.decode(enc, block)
@@ -1071,7 +1069,7 @@ class Hypercore extends EventEmitter {
1071
1069
  return block
1072
1070
  }
1073
1071
 
1074
- _getEncryptionProvider (e) {
1072
+ _getEncryptionProvider(e) {
1075
1073
  if (isEncryptionProvider(e)) return e
1076
1074
  if (!e || !e.key) return null
1077
1075
  return new DefaultEncryption(e.key, this.key, { block: e.block, compat: this.core.compat })
@@ -1080,15 +1078,11 @@ class Hypercore extends EventEmitter {
1080
1078
 
1081
1079
  module.exports = Hypercore
1082
1080
 
1083
- function isStream (s) {
1081
+ function isStream(s) {
1084
1082
  return typeof s === 'object' && s && typeof s.pipe === 'function'
1085
1083
  }
1086
1084
 
1087
- function toHex (buf) {
1088
- return buf && b4a.toString(buf, 'hex')
1089
- }
1090
-
1091
- async function preappend (blocks) {
1085
+ async function preappend(blocks) {
1092
1086
  const offset = this.state.length
1093
1087
  const fork = this.state.encryptionFork
1094
1088
 
@@ -1097,26 +1091,30 @@ async function preappend (blocks) {
1097
1091
  }
1098
1092
  }
1099
1093
 
1100
- function isValidIndex (index) {
1094
+ function isValidIndex(index) {
1101
1095
  return index === 0 || index > 0
1102
1096
  }
1103
1097
 
1104
- function maybeUnslab (block) {
1098
+ function maybeUnslab(block) {
1105
1099
  // Unslab only when it takes up less then half the slab
1106
1100
  return block !== null && 2 * block.byteLength < block.buffer.byteLength ? unslab(block) : block
1107
1101
  }
1108
1102
 
1109
- function checkSnapshot (snapshot, index) {
1110
- if (index >= snapshot.state.snapshotCompatLength) throw SNAPSHOT_NOT_AVAILABLE(`snapshot at index ${index} not available (max compat length ${snapshot.state.snapshotCompatLength})`, snapshot.discoveryKey)
1103
+ function checkSnapshot(snapshot, index) {
1104
+ if (index >= snapshot.state.snapshotCompatLength)
1105
+ throw SNAPSHOT_NOT_AVAILABLE(
1106
+ `snapshot at index ${index} not available (max compat length ${snapshot.state.snapshotCompatLength})`,
1107
+ snapshot.discoveryKey
1108
+ )
1111
1109
  }
1112
1110
 
1113
- function readBlock (rx, index) {
1111
+ function readBlock(rx, index) {
1114
1112
  const promise = rx.getBlock(index)
1115
1113
  rx.tryFlush()
1116
1114
  return promise
1117
1115
  }
1118
1116
 
1119
- function initOnce (session, storage, key, opts) {
1117
+ function initOnce(session, storage, key, opts) {
1120
1118
  if (storage === null) storage = opts.storage || null
1121
1119
  if (key === null) key = opts.key || null
1122
1120
 
@@ -1139,7 +1137,7 @@ function initOnce (session, storage, key, opts) {
1139
1137
  })
1140
1138
  }
1141
1139
 
1142
- function maybeAddMonitor (name) {
1140
+ function maybeAddMonitor(name) {
1143
1141
  if (name === 'append' || name === 'truncate') return
1144
1142
  if (this._monitorIndex >= 0 || this.closing) return
1145
1143
 
@@ -1150,21 +1148,21 @@ function maybeAddMonitor (name) {
1150
1148
  }
1151
1149
  }
1152
1150
 
1153
- function isSessionMoved (err) {
1151
+ function isSessionMoved(err) {
1154
1152
  return err.code === 'SESSION_MOVED'
1155
1153
  }
1156
1154
 
1157
- function getEncryptionOption (opts) {
1155
+ function getEncryptionOption(opts) {
1158
1156
  // old style, supported for now but will go away
1159
1157
  if (opts.encryptionKey) return { key: opts.encryptionKey, block: !!opts.isBlockKey }
1160
1158
  if (!opts.encryption) return null
1161
1159
  return b4a.isBuffer(opts.encryption) ? { key: opts.encryption } : opts.encryption
1162
1160
  }
1163
1161
 
1164
- function isEncryptionProvider (e) {
1162
+ function isEncryptionProvider(e) {
1165
1163
  return e && isFunction(e.padding) && isFunction(e.encrypt) && isFunction(e.decrypt)
1166
1164
  }
1167
1165
 
1168
- function isFunction (fn) {
1166
+ function isFunction(fn) {
1169
1167
  return !!fn && typeof fn === 'function'
1170
1168
  }