corestore 7.4.8 → 7.5.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 +22 -5
- package/index.js +107 -76
- package/lib/audit.js +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
Corestore is a Hypercore factory that makes it easier to manage large collections of named Hypercores.
|
|
6
6
|
|
|
7
7
|
Corestore provides:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
|
|
9
|
+
1. **Key Derivation** - All writable Hypercore keys are derived from a single master key and a user-provided name.
|
|
10
|
+
2. **Session Handling** - If a single Hypercore is loaded multiple times through the `get` method, the underlying resources will only be opened once (using Hypercore 10's new session feature). Once all sessions are closed, the resources will be released.
|
|
11
|
+
3. **Storage Management** - Hypercores can be stored in any `hypercore-storage` instance, where they will be keyed by their discovery keys.
|
|
12
|
+
4. **Namespacing** - You can share a single Corestore instance between multiple applications or components without worrying about naming collisions by creating "namespaces" (e.g. `corestore.namespace('my-app').get({ name: 'main' })`)
|
|
12
13
|
|
|
13
14
|
### Installation
|
|
15
|
+
|
|
14
16
|
`npm install corestore`
|
|
15
17
|
|
|
16
18
|
> [!NOTE]
|
|
@@ -19,7 +21,9 @@ Corestore provides:
|
|
|
19
21
|
> It will be updated to 11 in a few weeks.
|
|
20
22
|
|
|
21
23
|
### Usage
|
|
24
|
+
|
|
22
25
|
A corestore instance can be constructed with a `hypercore-storage` instance, or a string. If a string is specified, it will be assumed to be a path to a local storage directory:
|
|
26
|
+
|
|
23
27
|
```js
|
|
24
28
|
const Corestore = require('corestore')
|
|
25
29
|
|
|
@@ -46,6 +50,7 @@ Options:
|
|
|
46
50
|
```
|
|
47
51
|
|
|
48
52
|
#### `const core = store.get(key | { name: 'a-name', ...hypercoreOpts})`
|
|
53
|
+
|
|
49
54
|
Loads a Hypercore, either by name (if the `name` option is provided), or from the provided key (if the first argument is a Buffer or String with hex/z32 key, or if the `key` options is set).
|
|
50
55
|
|
|
51
56
|
If that Hypercore has previously been loaded, subsequent calls to `get` will return a new Hypercore session on the existing core.
|
|
@@ -53,6 +58,7 @@ If that Hypercore has previously been loaded, subsequent calls to `get` will ret
|
|
|
53
58
|
All other options besides `name` and `key` will be forwarded to the Hypercore constructor.
|
|
54
59
|
|
|
55
60
|
#### `const stream = store.replicate(optsOrStream)`
|
|
61
|
+
|
|
56
62
|
Creates a replication stream that's capable of replicating all Hypercores that are managed by the Corestore, assuming the remote peer has the correct capabilities.
|
|
57
63
|
|
|
58
64
|
`opts` will be forwarded to Hypercore's `replicate` function.
|
|
@@ -63,7 +69,7 @@ If the remote side dynamically adds a new Hypercore to the replication stream, C
|
|
|
63
69
|
|
|
64
70
|
Using [Hyperswarm](https://github.com/holepunchto/hyperswarm) you can easily replicate corestores
|
|
65
71
|
|
|
66
|
-
```
|
|
72
|
+
```js
|
|
67
73
|
const swarm = new Hyperswarm()
|
|
68
74
|
|
|
69
75
|
// join the relevant topic
|
|
@@ -74,12 +80,15 @@ swarm.on('connection', (connection) => store.replicate(connection))
|
|
|
74
80
|
```
|
|
75
81
|
|
|
76
82
|
#### `const storeB = storeA.session()`
|
|
83
|
+
|
|
77
84
|
Create a new Corestore session. Closing a session will close all cores made from this session.
|
|
78
85
|
|
|
79
86
|
#### `const store = store.namespace(name)`
|
|
87
|
+
|
|
80
88
|
Create a new namespaced Corestore session. Namespacing is useful if you're going to be sharing a single Corestore instance between many applications or components, as it prevents name collisions.
|
|
81
89
|
|
|
82
90
|
Namespaces can be chained:
|
|
91
|
+
|
|
83
92
|
```js
|
|
84
93
|
const ns1 = store.namespace('a')
|
|
85
94
|
const ns2 = ns1.namespace('b')
|
|
@@ -88,9 +97,11 @@ const core2 = ns2.get({ name: 'main' })
|
|
|
88
97
|
```
|
|
89
98
|
|
|
90
99
|
#### `const stream = store.list(namespace)`
|
|
100
|
+
|
|
91
101
|
Creates a discovery key stream of all cores within a namespace or all cores in general if no namespace is provided.
|
|
92
102
|
|
|
93
103
|
#### `store.watch((core) => {})`
|
|
104
|
+
|
|
94
105
|
Register a callback called when new Hypercores are opened. `core` is the internal core for the opened Hypercore. It can be used to create weak references to a Hypercore like so:
|
|
95
106
|
|
|
96
107
|
```
|
|
@@ -100,21 +111,27 @@ store.watch(function (core) {
|
|
|
100
111
|
```
|
|
101
112
|
|
|
102
113
|
#### `store.unwatch(callback)`
|
|
114
|
+
|
|
103
115
|
Unregister a callback used with `store.watch(callback)` so it no longer fires.
|
|
104
116
|
|
|
105
117
|
#### `await store.suspend()`
|
|
118
|
+
|
|
106
119
|
Suspend the underlying storage for the Corestore.
|
|
107
120
|
|
|
108
121
|
#### `await store.resume()`
|
|
122
|
+
|
|
109
123
|
Resume a suspended Corestore.
|
|
110
124
|
|
|
111
125
|
#### `const keypair = await store.createKeyPair(name, ns = this.ns)`
|
|
126
|
+
|
|
112
127
|
Generate a key pair seeded with the Corestore's primary key using a `name` and a `ns` aka namespace. `ns` defaults to the current namespace.
|
|
113
128
|
|
|
114
129
|
This is useful for creating deterministic key pairs that are unique to a peer.
|
|
115
130
|
|
|
116
131
|
#### `await store.close()`
|
|
132
|
+
|
|
117
133
|
Fully close this Corestore instance.
|
|
118
134
|
|
|
119
135
|
### License
|
|
136
|
+
|
|
120
137
|
MIT
|
package/index.js
CHANGED
|
@@ -13,23 +13,23 @@ const [NS] = crypto.namespace('corestore', 1)
|
|
|
13
13
|
const DEFAULT_NAMESPACE = b4a.alloc(32) // This is meant to be 32 0-bytes
|
|
14
14
|
|
|
15
15
|
class StreamTracker {
|
|
16
|
-
constructor
|
|
16
|
+
constructor() {
|
|
17
17
|
this.records = []
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
add
|
|
20
|
+
add(stream, isExternal) {
|
|
21
21
|
const record = { index: 0, stream, isExternal }
|
|
22
22
|
record.index = this.records.push(record) - 1
|
|
23
23
|
return record
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
remove
|
|
26
|
+
remove(record) {
|
|
27
27
|
const popped = this.records.pop()
|
|
28
28
|
if (popped === record) return
|
|
29
29
|
this.records[(popped.index = record.index)] = popped
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
attachAll
|
|
32
|
+
attachAll(core) {
|
|
33
33
|
for (let i = 0; i < this.records.length; i++) {
|
|
34
34
|
const record = this.records[i]
|
|
35
35
|
const muxer = record.stream.noiseStream.userData
|
|
@@ -37,7 +37,7 @@ class StreamTracker {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
destroy
|
|
40
|
+
destroy() {
|
|
41
41
|
// reverse is safer cause we delete mb
|
|
42
42
|
for (let i = this.records.length - 1; i >= 0; i--) {
|
|
43
43
|
const record = this.records[i]
|
|
@@ -47,15 +47,15 @@ class StreamTracker {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
class SessionTracker {
|
|
50
|
-
constructor
|
|
50
|
+
constructor() {
|
|
51
51
|
this.map = new Map()
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
get size
|
|
54
|
+
get size() {
|
|
55
55
|
return this.map.size
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
get
|
|
58
|
+
get(id) {
|
|
59
59
|
const existing = this.map.get(id)
|
|
60
60
|
if (existing !== undefined) return existing
|
|
61
61
|
const fresh = []
|
|
@@ -63,23 +63,23 @@ class SessionTracker {
|
|
|
63
63
|
return fresh
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
gc
|
|
66
|
+
gc(id) {
|
|
67
67
|
this.map.delete(id)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
list
|
|
71
|
-
return id ?
|
|
70
|
+
list(id) {
|
|
71
|
+
return id ? this.map.get(id) || [] : [...this]
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
*
|
|
74
|
+
*[Symbol.iterator]() {
|
|
75
75
|
for (const sessions of this.map.values()) {
|
|
76
|
-
yield
|
|
76
|
+
yield* sessions[Symbol.iterator]()
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
class CoreTracker {
|
|
82
|
-
constructor
|
|
82
|
+
constructor() {
|
|
83
83
|
this.map = new Map()
|
|
84
84
|
this.watching = []
|
|
85
85
|
|
|
@@ -88,23 +88,23 @@ class CoreTracker {
|
|
|
88
88
|
this._gcCycleBound = this._gcCycle.bind(this)
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
get size
|
|
91
|
+
get size() {
|
|
92
92
|
return this.map.size
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
watch
|
|
95
|
+
watch(store) {
|
|
96
96
|
if (store.watchIndex !== -1) return
|
|
97
97
|
store.watchIndex = this.watching.push(store) - 1
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
unwatch
|
|
100
|
+
unwatch(store) {
|
|
101
101
|
if (store.watchIndex === -1) return
|
|
102
102
|
const head = this.watching.pop()
|
|
103
103
|
if (head !== store) this.watching[(head.watchIndex = store.watchIndex)] = head
|
|
104
104
|
store.watchIndex = -1
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
resume
|
|
107
|
+
resume(id) {
|
|
108
108
|
const core = this.map.get(id)
|
|
109
109
|
|
|
110
110
|
if (!core) return null
|
|
@@ -121,12 +121,12 @@ class CoreTracker {
|
|
|
121
121
|
return core
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
opened
|
|
124
|
+
opened(id) {
|
|
125
125
|
const core = this.map.get(id)
|
|
126
126
|
return !!(core && core.opened && !core.closing)
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
get
|
|
129
|
+
get(id) {
|
|
130
130
|
// we allow you do call this from the outside, so support normal buffers also
|
|
131
131
|
if (b4a.isBuffer(id)) id = b4a.toString(id, 'hex')
|
|
132
132
|
const core = this.map.get(id)
|
|
@@ -134,24 +134,24 @@ class CoreTracker {
|
|
|
134
134
|
return core
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
set
|
|
137
|
+
set(id, core) {
|
|
138
138
|
this.map.set(id, core)
|
|
139
139
|
if (this.watching.length > 0) this._emit(core)
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
_emit
|
|
142
|
+
_emit(core) {
|
|
143
143
|
for (let i = this.watching.length - 1; i >= 0; i--) {
|
|
144
144
|
const store = this.watching[i]
|
|
145
145
|
for (const fn of store.watchers) fn(core)
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
_gc
|
|
149
|
+
_gc(core) {
|
|
150
150
|
const id = toHex(core.discoveryKey)
|
|
151
151
|
if (this.map.get(id) === core) this.map.delete(id)
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
_gcCycle
|
|
154
|
+
_gcCycle() {
|
|
155
155
|
for (const core of this._gcing) {
|
|
156
156
|
if (++core.gc < 4) continue
|
|
157
157
|
const gc = this._gc.bind(this, core)
|
|
@@ -162,24 +162,24 @@ class CoreTracker {
|
|
|
162
162
|
if (this._gcing.size === 0) this._stopGC()
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
gc
|
|
165
|
+
gc(core) {
|
|
166
166
|
core.gc = 1 // first strike
|
|
167
167
|
this._gcing.add(core)
|
|
168
168
|
if (this._gcing.size === 1) this._startGC()
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
_stopGC
|
|
171
|
+
_stopGC() {
|
|
172
172
|
clearInterval(this._gcInterval)
|
|
173
173
|
this._gcInterval = null
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
_startGC
|
|
176
|
+
_startGC() {
|
|
177
177
|
if (this._gcInterval) return
|
|
178
178
|
this._gcInterval = setInterval(this._gcCycleBound, 2000)
|
|
179
179
|
if (this._gcInterval.unref) this._gcInterval.unref()
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
close
|
|
182
|
+
close() {
|
|
183
183
|
this._stopGC()
|
|
184
184
|
this._gcing.clear()
|
|
185
185
|
|
|
@@ -193,7 +193,7 @@ class CoreTracker {
|
|
|
193
193
|
return Promise.all(all)
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
*
|
|
196
|
+
*[Symbol.iterator]() {
|
|
197
197
|
for (const core of this.map.values()) {
|
|
198
198
|
if (!core.closing) yield core
|
|
199
199
|
}
|
|
@@ -201,17 +201,17 @@ class CoreTracker {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
class FindingPeers {
|
|
204
|
-
constructor
|
|
204
|
+
constructor() {
|
|
205
205
|
this.count = 0
|
|
206
206
|
this.pending = []
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
add
|
|
209
|
+
add(core) {
|
|
210
210
|
if (this.count === 0) return
|
|
211
211
|
this.pending.push(core.findingPeers())
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
inc
|
|
214
|
+
inc(sessions) {
|
|
215
215
|
if (++this.count !== 1) return
|
|
216
216
|
|
|
217
217
|
for (const core of sessions) {
|
|
@@ -219,25 +219,31 @@ class FindingPeers {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
dec
|
|
222
|
+
dec(sessions) {
|
|
223
223
|
if (--this.count !== 0) return
|
|
224
224
|
while (this.pending.length > 0) this.pending.pop()()
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
class Corestore extends ReadyResource {
|
|
229
|
-
constructor
|
|
229
|
+
constructor(storage, opts = {}) {
|
|
230
230
|
super()
|
|
231
231
|
|
|
232
232
|
this.root = opts.root || null
|
|
233
|
-
this.storage = this.root
|
|
233
|
+
this.storage = this.root
|
|
234
|
+
? this.root.storage
|
|
235
|
+
: Hypercore.defaultStorage(storage, {
|
|
236
|
+
id: opts.id,
|
|
237
|
+
allowBackup: opts.allowBackup,
|
|
238
|
+
readOnly: opts.readOnly
|
|
239
|
+
})
|
|
234
240
|
this.streamTracker = this.root ? this.root.streamTracker : new StreamTracker()
|
|
235
241
|
this.cores = this.root ? this.root.cores : new CoreTracker()
|
|
236
242
|
this.sessions = new SessionTracker()
|
|
237
243
|
this.corestores = this.root ? this.root.corestores : new Set()
|
|
238
244
|
this.readOnly = opts.writable === false || !!opts.readOnly
|
|
239
|
-
this.globalCache = this.root ? this.root.globalCache :
|
|
240
|
-
this.primaryKey = this.root ? this.root.primaryKey :
|
|
245
|
+
this.globalCache = this.root ? this.root.globalCache : opts.globalCache || null
|
|
246
|
+
this.primaryKey = this.root ? this.root.primaryKey : opts.primaryKey || null
|
|
241
247
|
this.ns = opts.namespace || DEFAULT_NAMESPACE
|
|
242
248
|
this.manifestVersion = opts.manifestVersion || 1
|
|
243
249
|
this.shouldSuspend = isAndroid ? !!opts.suspend : opts.suspend !== false
|
|
@@ -254,7 +260,7 @@ class Corestore extends ReadyResource {
|
|
|
254
260
|
this.ready().catch(noop)
|
|
255
261
|
}
|
|
256
262
|
|
|
257
|
-
watch
|
|
263
|
+
watch(fn) {
|
|
258
264
|
if (this.watchers === null) {
|
|
259
265
|
this.watchers = new Set()
|
|
260
266
|
this.cores.watch(this)
|
|
@@ -263,7 +269,7 @@ class Corestore extends ReadyResource {
|
|
|
263
269
|
this.watchers.add(fn)
|
|
264
270
|
}
|
|
265
271
|
|
|
266
|
-
unwatch
|
|
272
|
+
unwatch(fn) {
|
|
267
273
|
if (this.watchers === null) return
|
|
268
274
|
|
|
269
275
|
this.watchers.delete(fn)
|
|
@@ -274,7 +280,7 @@ class Corestore extends ReadyResource {
|
|
|
274
280
|
}
|
|
275
281
|
}
|
|
276
282
|
|
|
277
|
-
findingPeers
|
|
283
|
+
findingPeers() {
|
|
278
284
|
if (this._findingPeers === null) this._findingPeers = new FindingPeers()
|
|
279
285
|
this._findingPeers.inc(this.sessions)
|
|
280
286
|
let done = false
|
|
@@ -285,51 +291,59 @@ class Corestore extends ReadyResource {
|
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
293
|
|
|
288
|
-
audit
|
|
294
|
+
audit(opts = {}) {
|
|
289
295
|
return auditStore(this, opts)
|
|
290
296
|
}
|
|
291
297
|
|
|
292
|
-
async suspend
|
|
298
|
+
async suspend({ log = noop } = {}) {
|
|
293
299
|
await log('Flushing db...')
|
|
294
|
-
|
|
300
|
+
// If readOnly we don't need to flush
|
|
301
|
+
if (!this.storage.readOnly) await this.storage.db.flush()
|
|
295
302
|
if (!this.shouldSuspend) return
|
|
296
303
|
await log('Suspending db...')
|
|
297
304
|
await this.storage.db.suspend()
|
|
298
305
|
}
|
|
299
306
|
|
|
300
|
-
resume
|
|
307
|
+
resume() {
|
|
301
308
|
return this.storage.db.resume()
|
|
302
309
|
}
|
|
303
310
|
|
|
304
|
-
session
|
|
311
|
+
session(opts) {
|
|
305
312
|
this._maybeClosed()
|
|
306
313
|
const root = this.root || this
|
|
307
|
-
return new Corestore(null, {
|
|
314
|
+
return new Corestore(null, {
|
|
315
|
+
manifestVersion: this.manifestVersion,
|
|
316
|
+
...opts,
|
|
317
|
+
root
|
|
318
|
+
})
|
|
308
319
|
}
|
|
309
320
|
|
|
310
|
-
namespace
|
|
311
|
-
return this.session({
|
|
321
|
+
namespace(name, opts) {
|
|
322
|
+
return this.session({
|
|
323
|
+
...opts,
|
|
324
|
+
namespace: generateNamespace(this.ns, name)
|
|
325
|
+
})
|
|
312
326
|
}
|
|
313
327
|
|
|
314
|
-
list
|
|
328
|
+
list(namespace) {
|
|
315
329
|
return this.storage.createDiscoveryKeyStream(namespace)
|
|
316
330
|
}
|
|
317
331
|
|
|
318
|
-
getAuth
|
|
332
|
+
getAuth(discoveryKey) {
|
|
319
333
|
return this.storage.getAuth(discoveryKey)
|
|
320
334
|
}
|
|
321
335
|
|
|
322
|
-
_ongc
|
|
336
|
+
_ongc(session) {
|
|
323
337
|
if (session.sessions.length === 0) this.sessions.gc(session.id)
|
|
324
338
|
}
|
|
325
339
|
|
|
326
|
-
async _getOrSetSeed
|
|
340
|
+
async _getOrSetSeed() {
|
|
327
341
|
const seed = await this.storage.getSeed()
|
|
328
342
|
if (seed !== null) return seed
|
|
329
343
|
return await this.storage.setSeed(this.primaryKey || crypto.randomBytes(32))
|
|
330
344
|
}
|
|
331
345
|
|
|
332
|
-
async _open
|
|
346
|
+
async _open() {
|
|
333
347
|
if (this.root !== null) {
|
|
334
348
|
if (this.root.opened === false) await this.root.ready()
|
|
335
349
|
this.primaryKey = this.root.primaryKey
|
|
@@ -348,7 +362,7 @@ class Corestore extends ReadyResource {
|
|
|
348
362
|
}
|
|
349
363
|
}
|
|
350
364
|
|
|
351
|
-
async _close
|
|
365
|
+
async _close() {
|
|
352
366
|
const closing = []
|
|
353
367
|
const hanging = [...this.sessions]
|
|
354
368
|
for (const sess of hanging) closing.push(sess.close())
|
|
@@ -370,9 +384,13 @@ class Corestore extends ReadyResource {
|
|
|
370
384
|
await this.storage.close()
|
|
371
385
|
}
|
|
372
386
|
|
|
373
|
-
async _attachMaybe
|
|
387
|
+
async _attachMaybe(muxer, discoveryKey) {
|
|
374
388
|
if (this.opened === false) await this.ready()
|
|
375
|
-
if (
|
|
389
|
+
if (
|
|
390
|
+
!this.cores.opened(toHex(discoveryKey)) &&
|
|
391
|
+
!(await this.storage.has(discoveryKey, { ifMigrated: true }))
|
|
392
|
+
)
|
|
393
|
+
return
|
|
376
394
|
if (this.closing) return
|
|
377
395
|
|
|
378
396
|
const core = this._openCore(discoveryKey, { createIfMissing: false })
|
|
@@ -387,13 +405,19 @@ class Corestore extends ReadyResource {
|
|
|
387
405
|
core.checkIfIdle()
|
|
388
406
|
}
|
|
389
407
|
|
|
390
|
-
|
|
408
|
+
_shouldReplicate(core, muxer) {
|
|
409
|
+
return (
|
|
410
|
+
core.replicator.downloading && !core.replicator.attached(muxer) && core.opened && this.active
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
replicate(isInitiator, opts) {
|
|
391
415
|
this._maybeClosed()
|
|
392
416
|
|
|
393
417
|
const isExternal = isStream(isInitiator)
|
|
394
418
|
const stream = Hypercore.createProtocolStream(isInitiator, {
|
|
395
419
|
...opts,
|
|
396
|
-
ondiscoverykey: discoveryKey => {
|
|
420
|
+
ondiscoverykey: (discoveryKey) => {
|
|
397
421
|
if (this.closing) return
|
|
398
422
|
const muxer = stream.noiseStream.userData
|
|
399
423
|
return this._attachMaybe(muxer, discoveryKey)
|
|
@@ -406,7 +430,9 @@ class Corestore extends ReadyResource {
|
|
|
406
430
|
muxer.cork()
|
|
407
431
|
|
|
408
432
|
for (const core of this.cores) {
|
|
409
|
-
if (!
|
|
433
|
+
if (!this._shouldReplicate(core, muxer)) {
|
|
434
|
+
continue
|
|
435
|
+
}
|
|
410
436
|
core.replicator.attachTo(muxer)
|
|
411
437
|
}
|
|
412
438
|
|
|
@@ -418,13 +444,13 @@ class Corestore extends ReadyResource {
|
|
|
418
444
|
return stream
|
|
419
445
|
}
|
|
420
446
|
|
|
421
|
-
_maybeClosed
|
|
447
|
+
_maybeClosed() {
|
|
422
448
|
if (this.closing || (this.root !== null && this.root.closing)) {
|
|
423
449
|
throw new Error('Corestore is closed')
|
|
424
450
|
}
|
|
425
451
|
}
|
|
426
452
|
|
|
427
|
-
get
|
|
453
|
+
get(opts) {
|
|
428
454
|
this._maybeClosed()
|
|
429
455
|
|
|
430
456
|
if (b4a.isBuffer(opts) || typeof opts === 'string') opts = { key: opts }
|
|
@@ -473,28 +499,30 @@ class Corestore extends ReadyResource {
|
|
|
473
499
|
return this._makeSession(conf)
|
|
474
500
|
}
|
|
475
501
|
|
|
476
|
-
_makeSession
|
|
502
|
+
_makeSession(conf) {
|
|
477
503
|
const session = new Hypercore(null, null, conf)
|
|
478
504
|
if (this._findingPeers !== null) this._findingPeers.add(session)
|
|
479
505
|
return session
|
|
480
506
|
}
|
|
481
507
|
|
|
482
|
-
async createKeyPair
|
|
508
|
+
async createKeyPair(name, ns = this.ns) {
|
|
483
509
|
if (this.opened === false) await this.ready()
|
|
484
510
|
return createKeyPair(this.primaryKey, ns, name)
|
|
485
511
|
}
|
|
486
512
|
|
|
487
|
-
async _preloadCheckIfExists
|
|
513
|
+
async _preloadCheckIfExists(opts) {
|
|
488
514
|
const has = await this.storage.has(opts.discoveryKey)
|
|
489
515
|
if (!has) throw STORAGE_EMPTY('No Hypercore is stored here')
|
|
490
516
|
return this._preload(opts)
|
|
491
517
|
}
|
|
492
518
|
|
|
493
|
-
async _preload
|
|
519
|
+
async _preload(opts) {
|
|
494
520
|
if (opts.preload) opts = { ...opts, ...(await opts.preload) }
|
|
495
521
|
if (this.opened === false) await this.ready()
|
|
496
522
|
|
|
497
|
-
const discoveryKey = opts.name
|
|
523
|
+
const discoveryKey = opts.name
|
|
524
|
+
? await this.storage.getAlias({ name: opts.name, namespace: this.ns })
|
|
525
|
+
: null
|
|
498
526
|
this._maybeClosed()
|
|
499
527
|
|
|
500
528
|
const core = this._openCore(discoveryKey, opts)
|
|
@@ -509,7 +537,7 @@ class Corestore extends ReadyResource {
|
|
|
509
537
|
}
|
|
510
538
|
}
|
|
511
539
|
|
|
512
|
-
_auth
|
|
540
|
+
_auth(discoveryKey, opts) {
|
|
513
541
|
const result = {
|
|
514
542
|
keyPair: null,
|
|
515
543
|
key: null,
|
|
@@ -526,7 +554,10 @@ class Corestore extends ReadyResource {
|
|
|
526
554
|
if (opts.manifest) {
|
|
527
555
|
result.manifest = opts.manifest
|
|
528
556
|
} else if (result.keyPair && !result.discoveryKey) {
|
|
529
|
-
result.manifest = {
|
|
557
|
+
result.manifest = {
|
|
558
|
+
version: this.manifestVersion,
|
|
559
|
+
signers: [{ publicKey: result.keyPair.publicKey }]
|
|
560
|
+
}
|
|
530
561
|
}
|
|
531
562
|
|
|
532
563
|
if (opts.key) result.key = ID.decode(opts.key)
|
|
@@ -541,7 +572,7 @@ class Corestore extends ReadyResource {
|
|
|
541
572
|
return result
|
|
542
573
|
}
|
|
543
574
|
|
|
544
|
-
_openCore
|
|
575
|
+
_openCore(discoveryKey, opts) {
|
|
545
576
|
const auth = this._auth(discoveryKey, opts)
|
|
546
577
|
|
|
547
578
|
const id = toHex(auth.discoveryKey)
|
|
@@ -549,7 +580,7 @@ class Corestore extends ReadyResource {
|
|
|
549
580
|
if (existing && !existing.closing) return existing
|
|
550
581
|
|
|
551
582
|
const core = Hypercore.createCore(this.storage, {
|
|
552
|
-
preopen:
|
|
583
|
+
preopen: existing && existing.opened ? existing.closing : null, // always wait for the prev one to close first in any case...
|
|
553
584
|
eagerUpgrade: true,
|
|
554
585
|
notDownloadingLinger: opts.notDownloadingLinger,
|
|
555
586
|
allowFork: opts.allowFork !== false,
|
|
@@ -582,25 +613,25 @@ class Corestore extends ReadyResource {
|
|
|
582
613
|
|
|
583
614
|
module.exports = Corestore
|
|
584
615
|
|
|
585
|
-
function isStream
|
|
616
|
+
function isStream(s) {
|
|
586
617
|
return typeof s === 'object' && s && typeof s.pipe === 'function'
|
|
587
618
|
}
|
|
588
619
|
|
|
589
|
-
function generateNamespace
|
|
620
|
+
function generateNamespace(namespace, name) {
|
|
590
621
|
if (!b4a.isBuffer(name)) name = b4a.from(name)
|
|
591
622
|
const out = b4a.allocUnsafeSlow(32)
|
|
592
623
|
sodium.crypto_generichash_batch(out, [namespace, name])
|
|
593
624
|
return out
|
|
594
625
|
}
|
|
595
626
|
|
|
596
|
-
function deriveSeed
|
|
627
|
+
function deriveSeed(primaryKey, namespace, name) {
|
|
597
628
|
if (!b4a.isBuffer(name)) name = b4a.from(name)
|
|
598
629
|
const out = b4a.alloc(32)
|
|
599
630
|
sodium.crypto_generichash_batch(out, [NS, namespace, name], primaryKey)
|
|
600
631
|
return out
|
|
601
632
|
}
|
|
602
633
|
|
|
603
|
-
function createKeyPair
|
|
634
|
+
function createKeyPair(primaryKey, namespace, name) {
|
|
604
635
|
const seed = deriveSeed(primaryKey, namespace, name)
|
|
605
636
|
const buf = b4a.alloc(sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_sign_SECRETKEYBYTES)
|
|
606
637
|
const keyPair = {
|
|
@@ -611,8 +642,8 @@ function createKeyPair (primaryKey, namespace, name) {
|
|
|
611
642
|
return keyPair
|
|
612
643
|
}
|
|
613
644
|
|
|
614
|
-
function noop
|
|
645
|
+
function noop() {}
|
|
615
646
|
|
|
616
|
-
function toHex
|
|
647
|
+
function toHex(discoveryKey) {
|
|
617
648
|
return b4a.toString(discoveryKey, 'hex')
|
|
618
649
|
}
|
package/lib/audit.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
module.exports = async function
|
|
1
|
+
module.exports = async function* audit(store, { dryRun = false } = {}) {
|
|
2
2
|
for await (const { discoveryKey, core } of store.storage.createCoreStream()) {
|
|
3
3
|
if (core.version < 1) continue // not migrated, ignore
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corestore",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.5.0",
|
|
4
4
|
"description": "A Hypercore factory that simplifies managing collections of cores.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"brittle": "^3.7.0",
|
|
22
|
+
"prettier": "^3.6.2",
|
|
23
|
+
"prettier-config-holepunch": "^2.0.0",
|
|
22
24
|
"rache": "^1.0.0",
|
|
23
|
-
"standard": "^17.1.2",
|
|
24
25
|
"test-tmp": "^1.3.0"
|
|
25
26
|
},
|
|
26
27
|
"scripts": {
|
|
27
|
-
"
|
|
28
|
+
"format": "prettier --write .",
|
|
29
|
+
"test": "prettier --check . && brittle test/*.js",
|
|
28
30
|
"test:bare": "bare test/basic.js"
|
|
29
31
|
},
|
|
30
32
|
"repository": {
|