corestore 5.8.0 → 6.0.0-alpha.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/.github/workflows/test-node.yml +24 -0
- package/README.md +31 -90
- package/index.js +160 -369
- package/lib/keys.js +120 -0
- package/package.json +15 -19
- package/test/all.js +108 -437
- package/test/helpers/index.js +3 -35
- package/test/keys.js +94 -0
- package/.travis.yml +0 -5
- package/CHANGELOG.md +0 -5
- package/LICENSE +0 -21
package/index.js
CHANGED
|
@@ -1,432 +1,223 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const datEncoding = require('dat-encoding')
|
|
6
|
-
const maybe = require('call-me-maybe')
|
|
1
|
+
const { EventEmitter } = require('events')
|
|
2
|
+
const crypto = require('hypercore-crypto')
|
|
3
|
+
const sodium = require('sodium-universal')
|
|
4
|
+
const Hypercore = require('hypercore')
|
|
7
5
|
|
|
8
|
-
const
|
|
9
|
-
const deriveSeed = require('derive-key')
|
|
10
|
-
const derivedStorage = require('derived-key-storage')
|
|
11
|
-
const raf = require('random-access-file')
|
|
6
|
+
const KeyManager = require('./lib/keys')
|
|
12
7
|
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
8
|
+
const CORES_DIR = 'cores'
|
|
9
|
+
const KEYS_DIR = 'keys'
|
|
10
|
+
const USERDATA_NAME_KEY = '@corestore/name'
|
|
11
|
+
const USERDATA_NAMESPACE_KEY = '@corestore/namespace'
|
|
12
|
+
const DEFAULT_NAMESPACE = generateNamespace('@corestore/default')
|
|
16
13
|
|
|
17
|
-
class
|
|
14
|
+
module.exports = class Corestore extends EventEmitter {
|
|
18
15
|
constructor (storage, opts = {}) {
|
|
19
16
|
super()
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
if (typeof storage !== 'function') throw new Error('Storage should be a function or string')
|
|
23
|
-
this.storage = storage
|
|
18
|
+
this.storage = Hypercore.defaultStorage(storage, { lock: KEYS_DIR + '/profile' })
|
|
24
19
|
|
|
25
|
-
this.
|
|
20
|
+
this.cores = opts._cores || new Map()
|
|
21
|
+
this.keys = opts.keys
|
|
26
22
|
|
|
27
|
-
this.
|
|
28
|
-
this.
|
|
29
|
-
maxSize: opts.cacheSize || 1000,
|
|
30
|
-
close: core => {
|
|
31
|
-
core.close(err => {
|
|
32
|
-
if (err) this.emit('error', err)
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
// Generated in _open
|
|
38
|
-
this._masterKey = opts.masterKey || null
|
|
39
|
-
this._id = hypercoreCrypto.randomBytes(8)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Nanoresource Methods
|
|
43
|
-
|
|
44
|
-
_open (cb) {
|
|
45
|
-
if (this._masterKey) return cb()
|
|
46
|
-
const keyStorage = this.storage(MASTER_KEY_FILENAME)
|
|
47
|
-
keyStorage.read(0, 32, (err, key) => {
|
|
48
|
-
if (err) {
|
|
49
|
-
this._masterKey = hypercoreCrypto.randomBytes(32)
|
|
50
|
-
return keyStorage.write(0, this._masterKey, err => {
|
|
51
|
-
if (err) return cb(err)
|
|
52
|
-
keyStorage.close(cb)
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
this._masterKey = key
|
|
56
|
-
keyStorage.close(cb)
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
_close (cb) {
|
|
61
|
-
let error = null
|
|
62
|
-
for (const { stream } of this._replicationStreams) {
|
|
63
|
-
stream.destroy()
|
|
64
|
-
}
|
|
65
|
-
if (!this.cache.size) return process.nextTick(cb, null)
|
|
66
|
-
let remaining = this.cache.size
|
|
67
|
-
for (const { value: core } of this.cache.entries.values()) {
|
|
68
|
-
core.close(err => {
|
|
69
|
-
if (err) error = err
|
|
70
|
-
if (!--remaining) {
|
|
71
|
-
if (error) return cb(error)
|
|
72
|
-
return cb(null)
|
|
73
|
-
}
|
|
74
|
-
})
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Private Methods
|
|
79
|
-
|
|
80
|
-
_checkIfExists (dkey, cb) {
|
|
81
|
-
dkey = encodeKey(dkey)
|
|
82
|
-
if (this.cache.has(dkey)) return process.nextTick(cb, null, true)
|
|
23
|
+
this._namespace = opts._namespace || DEFAULT_NAMESPACE
|
|
24
|
+
this._replicationStreams = opts._streams || []
|
|
83
25
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (err) return cb(err)
|
|
88
|
-
coreStorage.close(err => {
|
|
89
|
-
if (err) return cb(err)
|
|
90
|
-
if (!key) return cb(null, false)
|
|
91
|
-
return cb(null, true)
|
|
92
|
-
})
|
|
93
|
-
})
|
|
26
|
+
this._opening = opts._opening ? opts._opening.then(() => this._open()) : this._open()
|
|
27
|
+
this._opening.catch(noop)
|
|
28
|
+
this.ready = () => this._opening
|
|
94
29
|
}
|
|
95
30
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.
|
|
31
|
+
async _open () {
|
|
32
|
+
if (this.keys) {
|
|
33
|
+
this.keys = await this.keys // opts.keys can be a Promise that resolves to a KeyManager
|
|
34
|
+
} else {
|
|
35
|
+
this.keys = await KeyManager.fromStorage(p => this.storage(KEYS_DIR + '/' + p))
|
|
99
36
|
}
|
|
100
37
|
}
|
|
101
38
|
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
core.ready(function (err) {
|
|
105
|
-
if (err) return
|
|
106
|
-
core.replicate(isInitiator, {
|
|
107
|
-
...opts,
|
|
108
|
-
stream: mainStream
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
_deriveSecret (namespace, name) {
|
|
114
|
-
return deriveSeed(namespace, this._masterKey, name)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
_generateKeyPair (name) {
|
|
118
|
-
if (typeof name === 'string') name = Buffer.from(name)
|
|
119
|
-
else if (!name) name = hypercoreCrypto.randomBytes(32)
|
|
120
|
-
|
|
121
|
-
const seed = this._deriveSecret(NAMESPACE, name)
|
|
122
|
-
|
|
123
|
-
const keyPair = hypercoreCrypto.keyPair(seed)
|
|
124
|
-
const discoveryKey = hypercoreCrypto.discoveryKey(keyPair.publicKey)
|
|
125
|
-
return { name, publicKey: keyPair.publicKey, secretKey: keyPair.secretKey, discoveryKey }
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
_generateKeys (coreOpts) {
|
|
129
|
-
if (!coreOpts) coreOpts = {}
|
|
130
|
-
if (typeof coreOpts === 'string') coreOpts = Buffer.from(coreOpts, 'hex')
|
|
131
|
-
if (Buffer.isBuffer(coreOpts)) coreOpts = { key: coreOpts }
|
|
132
|
-
|
|
133
|
-
if (coreOpts.keyPair) {
|
|
134
|
-
const publicKey = coreOpts.keyPair.publicKey
|
|
135
|
-
const secretKey = coreOpts.keyPair.secretKey
|
|
39
|
+
async _generateKeys (opts) {
|
|
40
|
+
if (opts.discoveryKey) {
|
|
136
41
|
return {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
discoveryKey:
|
|
140
|
-
name: null
|
|
42
|
+
keyPair: null,
|
|
43
|
+
sign: null,
|
|
44
|
+
discoveryKey: opts.discoveryKey
|
|
141
45
|
}
|
|
142
46
|
}
|
|
143
|
-
if (
|
|
144
|
-
const publicKey = decodeKey(coreOpts.key)
|
|
47
|
+
if (!opts.name) {
|
|
145
48
|
return {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
49
|
+
keyPair: {
|
|
50
|
+
publicKey: opts.publicKey,
|
|
51
|
+
secretKey: opts.secretKey
|
|
52
|
+
},
|
|
53
|
+
sign: opts.sign,
|
|
54
|
+
discoveryKey: crypto.discoveryKey(opts.publicKey)
|
|
150
55
|
}
|
|
151
56
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
secretKey: null,
|
|
161
|
-
discoveryKey,
|
|
162
|
-
name: null
|
|
163
|
-
}
|
|
57
|
+
const { publicKey, sign } = await this.keys.createHypercoreKeyPair(opts.name, this._namespace)
|
|
58
|
+
return {
|
|
59
|
+
keyPair: {
|
|
60
|
+
publicKey,
|
|
61
|
+
secretKey: null
|
|
62
|
+
},
|
|
63
|
+
sign,
|
|
64
|
+
discoveryKey: crypto.discoveryKey(publicKey)
|
|
164
65
|
}
|
|
165
|
-
return this._generateKeyPair(null)
|
|
166
66
|
}
|
|
167
67
|
|
|
168
|
-
|
|
68
|
+
async _postload (core) {
|
|
69
|
+
const name = await core.getUserData(USERDATA_NAME_KEY)
|
|
70
|
+
if (!name) return
|
|
169
71
|
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
}
|
|
72
|
+
const namespace = await core.getUserData(USERDATA_NAMESPACE_KEY)
|
|
73
|
+
const { publicKey, sign } = await this.keys.createHypercoreKeyPair(name.toString(), namespace)
|
|
74
|
+
if (!publicKey.equals(core.key)) throw new Error('Stored core key does not match the provided name')
|
|
174
75
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return entry.refs !== 0
|
|
76
|
+
// TODO: Should Hypercore expose a helper for this, or should postload return keypair/sign?
|
|
77
|
+
core.sign = sign
|
|
78
|
+
core.key = publicKey
|
|
79
|
+
core.writable = true
|
|
180
80
|
}
|
|
181
81
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const self = this
|
|
82
|
+
async _preload (opts) {
|
|
83
|
+
await this.ready()
|
|
186
84
|
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const id = encodeKey(discoveryKey)
|
|
85
|
+
const { discoveryKey, keyPair, sign } = await this._generateKeys(opts)
|
|
86
|
+
const id = discoveryKey.toString('hex')
|
|
190
87
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const keyStorage = derivedStorage(createStorage, (name, cb) => {
|
|
197
|
-
if (name) {
|
|
198
|
-
const res = this._generateKeyPair(name)
|
|
199
|
-
if (discoveryKey && (!discoveryKey.equals((res.discoveryKey)))) {
|
|
200
|
-
return cb(new Error('Stored an incorrect name.'))
|
|
201
|
-
}
|
|
202
|
-
return cb(null, res)
|
|
88
|
+
while (this.cores.has(id)) {
|
|
89
|
+
const existing = this.cores.get(id)
|
|
90
|
+
if (existing) {
|
|
91
|
+
if (!existing.closing) return { from: existing, keyPair, sign }
|
|
92
|
+
await existing.close()
|
|
203
93
|
}
|
|
204
|
-
if (secretKey) return cb(null, generatedKeys)
|
|
205
|
-
if (publicKey) return cb(null, { name: null, publicKey, secretKey: null })
|
|
206
|
-
const err = new Error('Unknown key pair.')
|
|
207
|
-
err.unknownKeyPair = true
|
|
208
|
-
return cb(err)
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
const cacheOpts = { ...this.opts.cache }
|
|
212
|
-
if (coreOpts.cache) {
|
|
213
|
-
if (coreOpts.cache.data === false) delete cacheOpts.data
|
|
214
|
-
if (coreOpts.cache.tree === false) delete cacheOpts.tree
|
|
215
94
|
}
|
|
216
|
-
if (cacheOpts.data) cacheOpts.data = cacheOpts.data.namespace()
|
|
217
|
-
if (cacheOpts.tree) cacheOpts.tree = cacheOpts.tree.namespace()
|
|
218
|
-
|
|
219
|
-
const core = hypercore(name => {
|
|
220
|
-
if (name === 'key') return keyStorage.key
|
|
221
|
-
if (name === 'secret_key') return keyStorage.secretKey
|
|
222
|
-
return createStorage(name)
|
|
223
|
-
}, publicKey, {
|
|
224
|
-
...this.opts,
|
|
225
|
-
...coreOpts,
|
|
226
|
-
cache: cacheOpts,
|
|
227
|
-
createIfMissing: !!publicKey
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
this.cache.set(id, core)
|
|
231
|
-
core.ifAvailable.wait()
|
|
232
95
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
return core
|
|
239
|
-
|
|
240
|
-
function onready () {
|
|
241
|
-
if (errored) return
|
|
242
|
-
self.emit('feed', core, coreOpts)
|
|
243
|
-
core.removeListener('error', onerror)
|
|
244
|
-
self._injectIntoReplicationStreams(core)
|
|
245
|
-
// TODO: nexttick here needed? prob not, just legacy
|
|
246
|
-
process.nextTick(() => core.ifAvailable.continue())
|
|
96
|
+
const userData = {}
|
|
97
|
+
if (opts.name) {
|
|
98
|
+
userData[USERDATA_NAME_KEY] = Buffer.from(opts.name)
|
|
99
|
+
userData[USERDATA_NAMESPACE_KEY] = this._namespace
|
|
247
100
|
}
|
|
248
101
|
|
|
249
|
-
|
|
250
|
-
errored = true
|
|
251
|
-
core.ifAvailable.continue()
|
|
252
|
-
self.cache.delete(id)
|
|
253
|
-
if (err.unknownKeyPair) {
|
|
254
|
-
// If an error occurs during creation by discovery key, then that core does not exist on disk.
|
|
255
|
-
// TODO: This should not throw, but should propagate somehow.
|
|
256
|
-
}
|
|
257
|
-
}
|
|
102
|
+
// No more async ticks allowed after this point -- necessary for caching
|
|
258
103
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const finalOpts = { ...this.opts, ...replicationOpts }
|
|
272
|
-
const mainStream = replicationOpts.stream || new HypercoreProtocol(isInitiator, { ...finalOpts })
|
|
273
|
-
var closed = false
|
|
274
|
-
|
|
275
|
-
for (const core of cores) {
|
|
276
|
-
this._replicateCore(isInitiator, core, mainStream, { ...finalOpts })
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
mainStream.on('discovery-key', ondiscoverykey)
|
|
280
|
-
mainStream.on('finish', onclose)
|
|
281
|
-
mainStream.on('end', onclose)
|
|
282
|
-
mainStream.on('close', onclose)
|
|
283
|
-
|
|
284
|
-
const streamState = { stream: mainStream, opts: finalOpts }
|
|
285
|
-
this._replicationStreams.push(streamState)
|
|
286
|
-
|
|
287
|
-
return mainStream
|
|
288
|
-
|
|
289
|
-
function ondiscoverykey (dkey) {
|
|
290
|
-
// Get will automatically add the core to all replication streams.
|
|
291
|
-
self._checkIfExists(dkey, (err, exists) => {
|
|
292
|
-
if (closed) return
|
|
293
|
-
if (err || !exists) return mainStream.close(dkey)
|
|
294
|
-
const passiveCore = self.get({ discoveryKey: dkey })
|
|
295
|
-
self._replicateCore(false, passiveCore, mainStream, { ...finalOpts })
|
|
296
|
-
})
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function onclose () {
|
|
300
|
-
if (!closed) {
|
|
301
|
-
self._replicationStreams.splice(self._replicationStreams.indexOf(streamState), 1)
|
|
302
|
-
closed = true
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
class Corestore extends Nanoresource {
|
|
309
|
-
constructor (storage, opts = {}) {
|
|
310
|
-
super()
|
|
311
|
-
|
|
312
|
-
this.storage = storage
|
|
313
|
-
this.name = opts.name || 'default'
|
|
314
|
-
this.inner = opts.inner || new InnerCorestore(storage, opts)
|
|
315
|
-
this.cache = this.inner.cache
|
|
316
|
-
this.store = this // Backwards-compat for NamespacedCorestore
|
|
317
|
-
|
|
318
|
-
this._parent = opts.parent
|
|
319
|
-
this._isNamespaced = !!opts.name
|
|
320
|
-
this._openedCores = new Map()
|
|
321
|
-
|
|
322
|
-
const onfeed = feed => this.emit('feed', feed)
|
|
323
|
-
const onerror = err => this.emit('error', err)
|
|
324
|
-
this.inner.on('feed', onfeed)
|
|
325
|
-
this.inner.on('error', onerror)
|
|
326
|
-
this._unlisten = () => {
|
|
327
|
-
this.inner.removeListener('feed', onfeed)
|
|
328
|
-
this.inner.removeListener('error', onerror)
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
ready (cb) {
|
|
333
|
-
return maybe(cb, new Promise((resolve, reject) => {
|
|
334
|
-
this.open(err => {
|
|
335
|
-
if (err) return reject(err)
|
|
336
|
-
return resolve()
|
|
337
|
-
})
|
|
338
|
-
}))
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Nanoresource Methods
|
|
342
|
-
|
|
343
|
-
_open (cb) {
|
|
344
|
-
return this.inner.open(cb)
|
|
345
|
-
}
|
|
104
|
+
const storageRoot = [CORES_DIR, id.slice(0, 2), id.slice(2, 4), id].join('/')
|
|
105
|
+
const core = new Hypercore(p => this.storage(storageRoot + '/' + p), {
|
|
106
|
+
autoClose: true,
|
|
107
|
+
keyPair: {
|
|
108
|
+
publicKey: keyPair.publicKey,
|
|
109
|
+
secretKey: null
|
|
110
|
+
},
|
|
111
|
+
userData,
|
|
112
|
+
sign: null,
|
|
113
|
+
postload: this._postload.bind(this),
|
|
114
|
+
createIfMissing: !!opts.keyPair
|
|
115
|
+
})
|
|
346
116
|
|
|
347
|
-
|
|
348
|
-
this.
|
|
349
|
-
|
|
350
|
-
for (const dkey of this._openedCores) {
|
|
351
|
-
this.cache.decrement(dkey)
|
|
117
|
+
this.cores.set(id, core)
|
|
118
|
+
for (const stream of this._replicationStreams) {
|
|
119
|
+
core.replicate(stream)
|
|
352
120
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// Private Methods
|
|
121
|
+
core.once('close', () => {
|
|
122
|
+
this.cores.delete(id)
|
|
123
|
+
})
|
|
357
124
|
|
|
358
|
-
|
|
359
|
-
const id = encodeKey(core.discoveryKey)
|
|
360
|
-
if (this._openedCores.has(id)) return
|
|
361
|
-
this._openedCores.set(id, core)
|
|
362
|
-
this.cache.increment(id)
|
|
125
|
+
return { from: core, keyPair, sign }
|
|
363
126
|
}
|
|
364
127
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
128
|
+
get (opts = {}) {
|
|
129
|
+
opts = validateGetOptions(opts)
|
|
130
|
+
const core = new Hypercore(null, {
|
|
131
|
+
...opts,
|
|
132
|
+
name: null,
|
|
133
|
+
preload: () => this._preload(opts)
|
|
134
|
+
})
|
|
371
135
|
return core
|
|
372
136
|
}
|
|
373
137
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
138
|
+
replicate (opts = {}) {
|
|
139
|
+
const stream = isStream(opts) ? opts : (opts.stream || Hypercore.createProtocolStream(opts))
|
|
140
|
+
for (const core of this.cores.values()) {
|
|
141
|
+
core.replicate(stream)
|
|
142
|
+
}
|
|
143
|
+
stream.on('discovery-key', discoveryKey => {
|
|
144
|
+
const core = this.get({ discoveryKey })
|
|
145
|
+
core.ready().then(() => {
|
|
146
|
+
core.replicate(stream)
|
|
147
|
+
}, () => {
|
|
148
|
+
stream.close(discoveryKey)
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
this._replicationStreams.push(stream)
|
|
152
|
+
stream.once('close', () => {
|
|
153
|
+
this._replicationStreams.splice(this._replicationStreams.indexOf(stream), 1)
|
|
154
|
+
})
|
|
155
|
+
return stream
|
|
377
156
|
}
|
|
378
157
|
|
|
379
158
|
namespace (name) {
|
|
380
|
-
if (!name) name =
|
|
381
|
-
if (Buffer.isBuffer(name)) name = name.toString('hex')
|
|
382
|
-
name = this._isNamespaced ? this.name + NAMESPACE_SEPERATOR + name : name
|
|
159
|
+
if (!Buffer.isBuffer(name)) name = Buffer.from(name)
|
|
383
160
|
return new Corestore(this.storage, {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
161
|
+
_namespace: generateNamespace(this._namespace, name),
|
|
162
|
+
_opening: this._opening,
|
|
163
|
+
_cores: this.cores,
|
|
164
|
+
_streams: this._replicationStreams,
|
|
165
|
+
keys: this._opening.then(() => this.keys)
|
|
387
166
|
})
|
|
388
167
|
}
|
|
389
168
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return this.inner.isExternal(coreOpts)
|
|
169
|
+
async _close () {
|
|
170
|
+
if (this._closing) return this._closing
|
|
171
|
+
const closePromises = []
|
|
172
|
+
for (const core of this.cores.values()) {
|
|
173
|
+
closePromises.push(core.close())
|
|
174
|
+
}
|
|
175
|
+
await Promise.allSettled(closePromises)
|
|
176
|
+
for (const stream of this._replicationStreams) {
|
|
177
|
+
stream.destroy()
|
|
178
|
+
}
|
|
401
179
|
}
|
|
402
180
|
|
|
403
|
-
|
|
404
|
-
|
|
181
|
+
close () {
|
|
182
|
+
if (this._closing) return this._closing
|
|
183
|
+
this._closing = this._close()
|
|
184
|
+
this._closing.catch(noop)
|
|
185
|
+
return this._closing
|
|
405
186
|
}
|
|
406
|
-
}
|
|
407
187
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (entry.refs > 0) yield entry.value
|
|
411
|
-
continue
|
|
188
|
+
static createToken () {
|
|
189
|
+
return KeyManager.createToken()
|
|
412
190
|
}
|
|
413
191
|
}
|
|
414
192
|
|
|
415
|
-
function
|
|
416
|
-
|
|
193
|
+
function validateGetOptions (opts) {
|
|
194
|
+
if (Buffer.isBuffer(opts)) return { key: opts, publicKey: opts }
|
|
195
|
+
if (opts.key) {
|
|
196
|
+
opts.publicKey = opts.key
|
|
197
|
+
}
|
|
198
|
+
if (opts.keyPair) {
|
|
199
|
+
opts.publicKey = opts.keyPair.publicKey
|
|
200
|
+
opts.secretKey = opts.keyPair.secretKey
|
|
201
|
+
}
|
|
202
|
+
if (opts.name && typeof opts.name !== 'string') throw new Error('name option must be a String')
|
|
203
|
+
if (opts.name && opts.secretKey) throw new Error('Cannot provide both a name and a secret key')
|
|
204
|
+
if (opts.publicKey && !Buffer.isBuffer(opts.publicKey)) throw new Error('publicKey option must be a Buffer')
|
|
205
|
+
if (opts.secretKey && !Buffer.isBuffer(opts.secretKey)) throw new Error('secretKey option must be a Buffer')
|
|
206
|
+
if (opts.discoveryKey && !Buffer.isBuffer(opts.discoveryKey)) throw new Error('discoveryKey option must be a Buffer')
|
|
207
|
+
if (!opts.name && !opts.publicKey) throw new Error('Must provide either a name or a publicKey')
|
|
208
|
+
return opts
|
|
417
209
|
}
|
|
418
210
|
|
|
419
|
-
function
|
|
420
|
-
|
|
211
|
+
function generateNamespace (first, second) {
|
|
212
|
+
if (!Buffer.isBuffer(first)) first = Buffer.from(first)
|
|
213
|
+
if (second && !Buffer.isBuffer(second)) second = Buffer.from(second)
|
|
214
|
+
const out = Buffer.allocUnsafe(32)
|
|
215
|
+
sodium.crypto_generichash(out, second ? Buffer.concat([first, second]) : first)
|
|
216
|
+
return out
|
|
421
217
|
}
|
|
422
218
|
|
|
423
|
-
function
|
|
424
|
-
return
|
|
425
|
-
try {
|
|
426
|
-
var lock = name.endsWith('/bitfield') ? require('fd-lock') : null
|
|
427
|
-
} catch (err) {}
|
|
428
|
-
return raf(name, { directory: dir, lock: lock })
|
|
429
|
-
}
|
|
219
|
+
function isStream (s) {
|
|
220
|
+
return typeof s === 'object' && s && typeof s.pipe === 'function'
|
|
430
221
|
}
|
|
431
222
|
|
|
432
|
-
|
|
223
|
+
function noop () {}
|