hypercore 10.10.0 → 10.12.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 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
 
@@ -227,7 +228,7 @@ partialStream.pipe(process.stdout)
227
228
  }
228
229
  ```
229
230
 
230
- #### `await core.clear(start, [end])`
231
+ #### `const cleared = await core.clear(start, [end], [options])`
231
232
 
232
233
  Clear stored blocks between `start` and `end`, reclaiming storage when possible.
233
234
 
@@ -238,6 +239,13 @@ await core.clear(0, 10) // clear block 0-10 from your local cache
238
239
 
239
240
  The core will also gossip to peers it is connected to, that is no longer has these blocks.
240
241
 
242
+ `options` include:
243
+ ```js
244
+ {
245
+ diff: false // Returned `cleared` bytes object is null unless you enable this
246
+ }
247
+ ```
248
+
241
249
  #### `await core.truncate(newLength, [forkId])`
242
250
 
243
251
  Truncate the core to a smaller length.
package/index.js CHANGED
@@ -74,6 +74,7 @@ module.exports = class Hypercore extends EventEmitter {
74
74
  this.onwait = opts.onwait || null
75
75
  this.wait = opts.wait !== false
76
76
  this.timeout = opts.timeout || 0
77
+ this._readonly = opts.writable === false
77
78
 
78
79
  this.closing = null
79
80
  this.opening = this._openSession(key, storage, opts)
@@ -201,6 +202,7 @@ module.exports = class Hypercore extends EventEmitter {
201
202
 
202
203
  const sparse = opts.sparse === false ? false : this.sparse
203
204
  const wait = opts.wait === false ? false : this.wait
205
+ const writable = opts.writable === false ? false : !this._readonly
204
206
  const onwait = opts.onwait === undefined ? this.onwait : opts.onwait
205
207
  const timeout = opts.timeout === undefined ? this.timeout : opts.timeout
206
208
  const Clz = opts.class || Hypercore
@@ -210,6 +212,7 @@ module.exports = class Hypercore extends EventEmitter {
210
212
  wait,
211
213
  onwait,
212
214
  timeout,
215
+ writable,
213
216
  _opening: this.opening,
214
217
  _sessions: this.sessions
215
218
  })
@@ -237,7 +240,7 @@ module.exports = class Hypercore extends EventEmitter {
237
240
  this.core = o.core
238
241
  this.replicator = o.replicator
239
242
  this.encryption = o.encryption
240
- this.writable = !!(this.auth && this.auth.sign)
243
+ this.writable = !this._readonly && !!(this.auth && this.auth.sign)
241
244
  this.autoClose = o.autoClose
242
245
 
243
246
  if (this.snapshotted && this.core && !this._snapshot) this._updateSnapshot()
@@ -295,7 +298,7 @@ module.exports = class Hypercore extends EventEmitter {
295
298
  }
296
299
 
297
300
  if (!this.auth) this.auth = this.core.defaultAuth
298
- this.writable = !!this.auth.sign
301
+ this.writable = !this._readonly && !!this.auth.sign
299
302
 
300
303
  if (opts.valueEncoding) {
301
304
  this.valueEncoding = c.from(opts.valueEncoding)
@@ -745,9 +748,13 @@ module.exports = class Hypercore extends EventEmitter {
745
748
  end = start + 1
746
749
  }
747
750
 
748
- if (start >= end) return
751
+ const cleared = (opts && opts.diff) ? { blocks: 0 } : null
749
752
 
750
- await this.core.clear(start, end)
753
+ if (start >= end) return cleared
754
+
755
+ await this.core.clear(start, end, cleared)
756
+
757
+ return cleared
751
758
  }
752
759
 
753
760
  async purge () {
package/lib/core.js CHANGED
@@ -5,6 +5,7 @@ const Mutex = require('./mutex')
5
5
  const MerkleTree = require('./merkle-tree')
6
6
  const BlockStore = require('./block-store')
7
7
  const Bitfield = require('./bitfield')
8
+ const Info = require('./info')
8
9
  const { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_SIGNATURE } = require('./errors')
9
10
  const m = require('./messages')
10
11
 
@@ -238,7 +239,7 @@ module.exports = class Core {
238
239
  }
239
240
  }
240
241
 
241
- async clear (start, end) {
242
+ async clear (start, end, cleared) {
242
243
  await this._mutex.lock()
243
244
 
244
245
  try {
@@ -265,13 +266,20 @@ module.exports = class Core {
265
266
  end = this.bitfield.firstSet(end)
266
267
 
267
268
  if (end === -1) end = this.tree.length
269
+ if (start >= end || start >= this.tree.length) return
268
270
 
269
271
  const offset = await this.tree.byteOffset(start * 2)
270
272
  const [byteEnd, byteEndLength] = await this.tree.byteRange((end - 1) * 2)
271
273
  const length = (byteEnd + byteEndLength) - offset
272
274
 
275
+ const before = cleared ? await Info.bytesUsed(this.blocks.storage) : null
276
+
273
277
  await this.blocks.clear(offset, length)
274
278
 
279
+ const after = cleared ? await Info.bytesUsed(this.blocks.storage) : null
280
+
281
+ if (cleared) cleared.blocks = Math.max(before - after, 0)
282
+
275
283
  this.onupdate(0, entry.bitfield, null, null)
276
284
 
277
285
  if (this._shouldFlush()) await this._flushOplog()
package/lib/info.js CHANGED
@@ -27,27 +27,27 @@ module.exports = class Info {
27
27
  const { oplog, tree, blocks, bitfield } = session.core
28
28
  try {
29
29
  return {
30
- oplog: await bytesUsed(oplog.storage),
31
- tree: await bytesUsed(tree.storage),
32
- blocks: await bytesUsed(blocks.storage),
33
- bitfield: await bytesUsed(bitfield.storage)
30
+ oplog: await Info.bytesUsed(oplog.storage),
31
+ tree: await Info.bytesUsed(tree.storage),
32
+ blocks: await Info.bytesUsed(blocks.storage),
33
+ bitfield: await Info.bytesUsed(bitfield.storage)
34
34
  }
35
35
  } catch {
36
36
  return null
37
37
  }
38
+ }
38
39
 
39
- function bytesUsed (file) {
40
- return new Promise((resolve, reject) => {
41
- file.stat((err, st) => {
42
- if (err) {
43
- resolve(0) // prob just file not found (TODO, improve)
44
- } else if (typeof st.blocks !== 'number') {
45
- reject(new Error('cannot determine bytes used'))
46
- } else {
47
- resolve(st.blocks * 512)
48
- }
49
- })
40
+ static bytesUsed (file) {
41
+ return new Promise((resolve, reject) => {
42
+ file.stat((err, st) => {
43
+ if (err) {
44
+ resolve(0) // prob just file not found (TODO, improve)
45
+ } else if (typeof st.blocks !== 'number') {
46
+ reject(new Error('cannot determine bytes used'))
47
+ } else {
48
+ resolve(st.blocks * 512)
49
+ }
50
50
  })
51
- }
51
+ })
52
52
  }
53
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore",
3
- "version": "10.10.0",
3
+ "version": "10.12.0",
4
4
  "description": "Hypercore is a secure, distributed append-only log",
5
5
  "main": "index.js",
6
6
  "scripts": {