corestore 7.9.2 → 7.10.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.
- package/README.md +43 -0
- package/index.js +58 -4
- package/lib/notify.js +27 -0
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -114,6 +114,42 @@ store.watch(function (core) {
|
|
|
114
114
|
|
|
115
115
|
Unregister a callback used with `store.watch(callback)` so it no longer fires.
|
|
116
116
|
|
|
117
|
+
#### `const handle = store.notifyGroup(topic)`
|
|
118
|
+
|
|
119
|
+
> [!IMPORTANT]
|
|
120
|
+
> This feature is _experimental_. The API is subject to change, and everything may break.
|
|
121
|
+
|
|
122
|
+
Get a `handle` for updates from all `hypercore`s with the group `topic` set.
|
|
123
|
+
|
|
124
|
+
#### `const stream = handle.update(opts = {})`
|
|
125
|
+
|
|
126
|
+
Gets updates for the `topic` the handle is for.
|
|
127
|
+
|
|
128
|
+
`opts` includes:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
{
|
|
132
|
+
since: 0, // What timestamp to start returning updates from. Default `0` returns all updates
|
|
133
|
+
reverse: true, // Flag to return updates in reverse order. Defaults to `true` so latest returned first
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Stream returns the core's `key`:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
for await (const key of handle.updates()) {
|
|
141
|
+
// ...
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### `handle.destroy()`
|
|
146
|
+
|
|
147
|
+
Destroys and unregisters the `handle` from its `store`.
|
|
148
|
+
|
|
149
|
+
#### `handle.on('update', callback)`
|
|
150
|
+
|
|
151
|
+
Calls the callback whenever a core with the `topic` for the `handle` updates.
|
|
152
|
+
|
|
117
153
|
#### `await store.suspend()`
|
|
118
154
|
|
|
119
155
|
Suspend the underlying storage for the Corestore.
|
|
@@ -132,6 +168,13 @@ This is useful for creating deterministic key pairs that are unique to a peer.
|
|
|
132
168
|
|
|
133
169
|
Fully close this Corestore instance.
|
|
134
170
|
|
|
171
|
+
#### `store.on('group-active', (topic) => {})`
|
|
172
|
+
|
|
173
|
+
> [!IMPORTANT]
|
|
174
|
+
> This feature is _experimental_. The API is subject to change, and everything may break.
|
|
175
|
+
|
|
176
|
+
The `group-active` event emits whenever an opened Hypercore in the store updates. The `topic` is the group topic the core belongs to.
|
|
177
|
+
|
|
135
178
|
### License
|
|
136
179
|
|
|
137
180
|
MIT
|
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const { isAndroid } = require('which-runtime')
|
|
|
8
8
|
const { STORAGE_EMPTY, ASSERTION } = require('hypercore-errors')
|
|
9
9
|
|
|
10
10
|
const auditStore = require('./lib/audit.js')
|
|
11
|
+
const GroupNotifyHandle = require('./lib/notify.js')
|
|
11
12
|
|
|
12
13
|
const [NS] = crypto.namespace('corestore', 1)
|
|
13
14
|
const DEFAULT_NAMESPACE = b4a.alloc(32) // This is meant to be 32 0-bytes
|
|
@@ -259,8 +260,10 @@ class Corestore extends ReadyResource {
|
|
|
259
260
|
this.watchers = null
|
|
260
261
|
this.watchIndex = -1
|
|
261
262
|
|
|
263
|
+
this._groupNotifiers = new Map() // group notifications
|
|
262
264
|
this._findingPeers = null // here for legacy
|
|
263
265
|
this._ongcBound = this._ongc.bind(this)
|
|
266
|
+
this._onGroupActiveBound = this._onGroupActive.bind(this)
|
|
264
267
|
|
|
265
268
|
if (opts.primaryKey && !this.root && !opts.unsafe) {
|
|
266
269
|
throw ASSERTION(
|
|
@@ -291,6 +294,44 @@ class Corestore extends ReadyResource {
|
|
|
291
294
|
}
|
|
292
295
|
}
|
|
293
296
|
|
|
297
|
+
_onGroupActive(topic) {
|
|
298
|
+
this.emit('group-active', topic)
|
|
299
|
+
|
|
300
|
+
const topicHex = b4a.toString(topic, 'hex')
|
|
301
|
+
const handles = this._groupNotifiers.get(topicHex)
|
|
302
|
+
if (!handles) return
|
|
303
|
+
for (const handle of handles) handle.emit('update')
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
notifyGroup(topic) {
|
|
307
|
+
const topicHex = b4a.toString(topic, 'hex')
|
|
308
|
+
let handles = this._groupNotifiers.get(topicHex)
|
|
309
|
+
|
|
310
|
+
if (!handles) {
|
|
311
|
+
handles = []
|
|
312
|
+
this._groupNotifiers.set(topicHex, handles)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const handle = new GroupNotifyHandle(this, topic)
|
|
316
|
+
const length = handles.push(handle)
|
|
317
|
+
handle.index = length - 1
|
|
318
|
+
|
|
319
|
+
return handle
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
_removeGroupNotify(handle) {
|
|
323
|
+
if (handle.index === -1) return
|
|
324
|
+
|
|
325
|
+
const topicHex = b4a.toString(handle._topic, 'hex')
|
|
326
|
+
const handles = this._groupNotifiers.get(topicHex)
|
|
327
|
+
if (!handles) return
|
|
328
|
+
|
|
329
|
+
const popped = handles.pop()
|
|
330
|
+
if (popped !== handle) handles[(popped.index = handle.index)] = popped
|
|
331
|
+
if (handles.length === 0) this._groupNotifiers.delete(topicHex)
|
|
332
|
+
handle.index = -1
|
|
333
|
+
}
|
|
334
|
+
|
|
294
335
|
findingPeers() {
|
|
295
336
|
if (this._findingPeers === null) this._findingPeers = new FindingPeers()
|
|
296
337
|
this._findingPeers.inc(this.sessions)
|
|
@@ -309,10 +350,14 @@ class Corestore extends ReadyResource {
|
|
|
309
350
|
async suspend({ log = noop } = {}) {
|
|
310
351
|
await log('Flushing db...')
|
|
311
352
|
// If readOnly we don't need to flush
|
|
312
|
-
if (!this.storage.readOnly)
|
|
353
|
+
if (!this.storage.readOnly) {
|
|
354
|
+
await this.storage.db.flush()
|
|
355
|
+
await log('Flusing db completed')
|
|
356
|
+
}
|
|
313
357
|
if (!this.shouldSuspend) return
|
|
314
358
|
await log('Suspending db...')
|
|
315
|
-
await this.storage.suspend()
|
|
359
|
+
await this.storage.suspend({ log })
|
|
360
|
+
await log('Suspending db completed')
|
|
316
361
|
}
|
|
317
362
|
|
|
318
363
|
resume() {
|
|
@@ -568,6 +613,7 @@ class Corestore extends ReadyResource {
|
|
|
568
613
|
|
|
569
614
|
_makeSession(conf) {
|
|
570
615
|
const session = new Hypercore(null, null, conf)
|
|
616
|
+
|
|
571
617
|
if (this._findingPeers !== null) this._findingPeers.add(session)
|
|
572
618
|
return session
|
|
573
619
|
}
|
|
@@ -610,7 +656,8 @@ class Corestore extends ReadyResource {
|
|
|
610
656
|
keyPair: null,
|
|
611
657
|
key: null,
|
|
612
658
|
discoveryKey,
|
|
613
|
-
manifest: null
|
|
659
|
+
manifest: null,
|
|
660
|
+
group: null
|
|
614
661
|
}
|
|
615
662
|
|
|
616
663
|
if (opts.name) {
|
|
@@ -628,6 +675,10 @@ class Corestore extends ReadyResource {
|
|
|
628
675
|
}
|
|
629
676
|
}
|
|
630
677
|
|
|
678
|
+
if (opts.group) {
|
|
679
|
+
result.group = opts.group
|
|
680
|
+
}
|
|
681
|
+
|
|
631
682
|
if (opts.key) result.key = ID.decode(opts.key)
|
|
632
683
|
else if (result.manifest) result.key = Hypercore.key(result.manifest)
|
|
633
684
|
|
|
@@ -644,7 +695,7 @@ class Corestore extends ReadyResource {
|
|
|
644
695
|
const auth = this._auth(discoveryKey, opts)
|
|
645
696
|
|
|
646
697
|
const id = toHex(auth.discoveryKey)
|
|
647
|
-
const existing = this.cores.resume(id)
|
|
698
|
+
const existing = this.cores.resume(id, auth.group)
|
|
648
699
|
if (existing && !existing.closing) return existing
|
|
649
700
|
|
|
650
701
|
const core = Hypercore.createCore(this.storage, {
|
|
@@ -663,6 +714,7 @@ class Corestore extends ReadyResource {
|
|
|
663
714
|
keyPair: auth.keyPair,
|
|
664
715
|
legacy: opts.legacy,
|
|
665
716
|
manifest: auth.manifest,
|
|
717
|
+
group: auth.group,
|
|
666
718
|
globalCache: opts.globalCache || this.globalCache || null,
|
|
667
719
|
alias: opts.name ? { name: opts.name, namespace: this.ns } : null
|
|
668
720
|
})
|
|
@@ -671,6 +723,8 @@ class Corestore extends ReadyResource {
|
|
|
671
723
|
this.cores.gc(core)
|
|
672
724
|
}
|
|
673
725
|
|
|
726
|
+
core.ongroupupdate = this._onGroupActiveBound
|
|
727
|
+
|
|
674
728
|
core.replicator.ondownloading = () => {
|
|
675
729
|
if (this.active) this.streamTracker.attachAll(core)
|
|
676
730
|
}
|
package/lib/notify.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { EventEmitter } = require('events')
|
|
2
|
+
const { Readable } = require('streamx')
|
|
3
|
+
|
|
4
|
+
class GroupNotifyHandle extends EventEmitter {
|
|
5
|
+
constructor(store, topic) {
|
|
6
|
+
super()
|
|
7
|
+
this._store = store
|
|
8
|
+
this._topic = topic
|
|
9
|
+
this.index = -1
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
updates(opts) {
|
|
13
|
+
return Readable.deferred(async () => {
|
|
14
|
+
const groupId = await this._store.storage.getGroup(this._topic).catch(noop)
|
|
15
|
+
if (groupId === null) return null
|
|
16
|
+
return this._store.storage.createGroupUpdateStream(groupId, opts)
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
destroy() {
|
|
21
|
+
this._store._removeGroupNotify(this)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = GroupNotifyHandle
|
|
26
|
+
|
|
27
|
+
function noop() {}
|
package/package.json
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corestore",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.10.1",
|
|
4
4
|
"description": "A Hypercore factory that simplifies managing collections of cores.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|
|
8
8
|
"lib/*"
|
|
9
9
|
],
|
|
10
|
+
"imports": {
|
|
11
|
+
"events": {
|
|
12
|
+
"bare": "bare-events",
|
|
13
|
+
"default": "events"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
10
16
|
"dependencies": {
|
|
11
17
|
"b4a": "^1.6.7",
|
|
12
|
-
"
|
|
18
|
+
"bare-events": "^2.8.3",
|
|
19
|
+
"hypercore": "^11.32.0",
|
|
13
20
|
"hypercore-crypto": "^3.4.2",
|
|
14
21
|
"hypercore-errors": "^1.4.0",
|
|
15
22
|
"hypercore-id-encoding": "^1.3.0",
|
|
16
23
|
"ready-resource": "^1.1.1",
|
|
17
24
|
"sodium-universal": "^5.0.1",
|
|
25
|
+
"streamx": "^2.26.0",
|
|
18
26
|
"which-runtime": "^1.2.1"
|
|
19
27
|
},
|
|
20
28
|
"devDependencies": {
|
|
@@ -22,15 +30,14 @@
|
|
|
22
30
|
"lunte": "^1.3.0",
|
|
23
31
|
"prettier": "^3.6.2",
|
|
24
32
|
"prettier-config-holepunch": "^2.0.0",
|
|
25
|
-
"rache": "^1.0.0"
|
|
26
|
-
"test-tmp": "^1.3.0"
|
|
33
|
+
"rache": "^1.0.0"
|
|
27
34
|
},
|
|
28
35
|
"scripts": {
|
|
29
36
|
"format": "prettier --write .",
|
|
30
37
|
"test": "npm run test:node && npm run test:bare",
|
|
31
|
-
"test:bare": "brittle-bare --coverage test
|
|
38
|
+
"test:bare": "brittle-bare --coverage test/all.js",
|
|
32
39
|
"lint": "prettier --check . && lunte",
|
|
33
|
-
"test:node": "brittle-node --coverage test
|
|
40
|
+
"test:node": "brittle-node --coverage test/all.js"
|
|
34
41
|
},
|
|
35
42
|
"repository": {
|
|
36
43
|
"type": "git",
|