hypercore-storage 1.13.0 → 1.14.1

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 (3) hide show
  1. package/README.md +14 -4
  2. package/index.js +96 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -85,7 +85,7 @@ Return a bitfield page.
85
85
 
86
86
  #### `await rx.getUserData(key)`
87
87
 
88
- Return a user stored buffer.
88
+ Return a user stored buffer. `key` is a string.
89
89
 
90
90
  #### `rx.tryFlush()`
91
91
 
@@ -155,11 +155,11 @@ Delete bitfield pages between two indexes.
155
155
 
156
156
  #### `tx.putUserData(key, value)`
157
157
 
158
- Put a user provided buffer at a user provided key.
158
+ Put a user provided buffer at a user provided `key`. `key` is a string.
159
159
 
160
160
  #### `tx.deleteUserData(key)`
161
161
 
162
- Delete a user provided key.
162
+ Delete a user provided `key`. `key` is a string.
163
163
 
164
164
  #### `await tx.flush()`
165
165
 
@@ -179,7 +179,17 @@ Create a stream of all bitfield pages.
179
179
 
180
180
  #### `stream = core.createUserDataStream(opts)`
181
181
 
182
- Create a stream of all user data.
182
+ Create a stream of all user data. `opts` is a query object with the following possible properties:
183
+
184
+ ```
185
+ {
186
+ gt: 'only return keys > than this', // Not currently supported
187
+ gte: 'only return keys >= than this',
188
+ lt: 'only return keys < than this',
189
+ lte: 'only return keys <= than this', // Not currently supported
190
+ reverse: false // reverse results. Not currently supported
191
+ }
192
+ ```
183
193
 
184
194
  #### `await core.close()`
185
195
 
package/index.js CHANGED
@@ -347,6 +347,47 @@ class HypercoreStorage {
347
347
 
348
348
  return this.db.close()
349
349
  }
350
+
351
+ static async export (ptr, db, { batches = false } = {}) {
352
+ const rx = new CoreRX(ptr, db, EMPTY)
353
+
354
+ const core = {
355
+ head: null,
356
+ auth: null,
357
+ sessions: [],
358
+ data: null
359
+ }
360
+
361
+ const sessionsPromise = rx.getSessions()
362
+ const headPromise = rx.getHead()
363
+ const authPromise = rx.getAuth()
364
+
365
+ rx.tryFlush()
366
+
367
+ const [sessions, head, auth] = await Promise.all([
368
+ sessionsPromise,
369
+ headPromise,
370
+ authPromise
371
+ ])
372
+
373
+ core.head = head
374
+ core.auth = { ...auth, keyPair: null }
375
+ if (sessions) core.sessions = sessions.map(s => s.name)
376
+
377
+ const data = []
378
+
379
+ data.push(exportData(ptr, db))
380
+
381
+ if (batches) {
382
+ for (const { dataPointer } of sessions) {
383
+ data.push(exportData({ dataPointer, dependencies: [] }, db))
384
+ }
385
+ }
386
+
387
+ core.data = await Promise.all(data)
388
+
389
+ return core
390
+ }
350
391
  }
351
392
 
352
393
  class CorestoreStorage {
@@ -356,6 +397,7 @@ class CorestoreStorage {
356
397
  this.bootstrap = storage !== null
357
398
  this.path = storage !== null ? storage : path.join(db.path, '..')
358
399
  this.readOnly = !!opts.readOnly
400
+ this.allowBackup = !!opts.allowBackup
359
401
 
360
402
  // tmp sync fix for simplicty since not super deployed yet
361
403
  if (this.bootstrap && !this.readOnly) tmpFixStorage(this.path)
@@ -462,7 +504,7 @@ class CorestoreStorage {
462
504
 
463
505
  await this.db.ready()
464
506
 
465
- if (this.bootstrap && !this.readOnly) {
507
+ if (this.bootstrap && !this.readOnly && !this.allowBackup) {
466
508
  const corestoreFile = path.join(this.path, 'CORESTORE')
467
509
 
468
510
  if (!(await DeviceFile.resume(corestoreFile, { id: this.id }))) {
@@ -772,6 +814,36 @@ class CorestoreStorage {
772
814
  return this._resumeFromPointers(EMPTY, discoveryKey, false, core)
773
815
  }
774
816
 
817
+ async export (discoveryKey, opts) {
818
+ const rx = new CorestoreRX(this.db, EMPTY)
819
+ const corePromise = rx.getCore(discoveryKey)
820
+
821
+ rx.tryFlush()
822
+ const core = await corePromise
823
+ if (core === null) return null
824
+
825
+ let { dataPointer, corePointer } = core
826
+
827
+ const ptr = { corePointer, dataPointer, dependencies: [] }
828
+
829
+ while (true) {
830
+ const rx = new CoreRX({ dataPointer, corePointer: 0, dependencies: [] }, this.db, EMPTY)
831
+ const dependencyPromise = rx.getDependency()
832
+ rx.tryFlush()
833
+ const dependency = await dependencyPromise
834
+ if (!dependency) break
835
+ ptr.dependencies.push(dependency)
836
+ dataPointer = dependency.dataPointer
837
+ }
838
+
839
+ const session = this.db.session()
840
+ try {
841
+ return await HypercoreStorage.export(ptr, session, opts)
842
+ } finally {
843
+ await session.close()
844
+ }
845
+ }
846
+
775
847
  async _resumeFromPointers (view, discoveryKey, create, { version, corePointer, dataPointer }) {
776
848
  const core = { corePointer, dataPointer, dependencies: [] }
777
849
 
@@ -926,3 +998,26 @@ function tmpFixStorage (p) {
926
998
  fs.renameSync(path.join(p, f), path.join(p, 'db', f))
927
999
  }
928
1000
  }
1001
+
1002
+ async function exportData (ptr, db, opts) {
1003
+ // just need dataPointer
1004
+ const reads = [
1005
+ toArray(createBlockStream(ptr, db, EMPTY, opts)),
1006
+ toArray(createTreeNodeStream(ptr, db, EMPTY, opts)),
1007
+ toArray(createBitfieldStream(ptr, db, EMPTY, opts))
1008
+ ]
1009
+
1010
+ const [blocks, tree, bitfield] = await Promise.all(reads)
1011
+
1012
+ return {
1013
+ blocks,
1014
+ tree,
1015
+ bitfield
1016
+ }
1017
+ }
1018
+
1019
+ async function toArray (stream) {
1020
+ const all = []
1021
+ for await (const e of stream) all.push(e)
1022
+ return all
1023
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore-storage",
3
- "version": "1.13.0",
3
+ "version": "1.14.1",
4
4
  "main": "index.js",
5
5
  "files": [
6
6
  "index.js",