corestore 6.0.1-alpha.8 → 6.0.1-alpha.9
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/index.js +31 -25
- package/package.json +2 -1
- package/test/all.js +40 -0
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const { EventEmitter } = require('events')
|
|
2
|
+
const safetyCatch = require('safety-catch')
|
|
2
3
|
const crypto = require('hypercore-crypto')
|
|
3
4
|
const sodium = require('sodium-universal')
|
|
4
5
|
const Hypercore = require('hypercore')
|
|
@@ -37,11 +38,11 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
async _generateKeys (opts) {
|
|
40
|
-
if (opts.
|
|
41
|
+
if (opts._discoveryKey) {
|
|
41
42
|
return {
|
|
42
43
|
keyPair: null,
|
|
43
44
|
sign: null,
|
|
44
|
-
discoveryKey: opts.
|
|
45
|
+
discoveryKey: opts._discoveryKey
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
if (!opts.name) {
|
|
@@ -94,8 +95,10 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
94
95
|
|
|
95
96
|
while (this.cores.has(id)) {
|
|
96
97
|
const existing = this.cores.get(id)
|
|
97
|
-
if (existing) {
|
|
98
|
-
|
|
98
|
+
if (existing.opened && !existing.closing) return { from: existing, keyPair, sign }
|
|
99
|
+
if (!existing.opened) {
|
|
100
|
+
await existing.ready().catch(safetyCatch)
|
|
101
|
+
} else if (existing.closing) {
|
|
99
102
|
await existing.close()
|
|
100
103
|
}
|
|
101
104
|
}
|
|
@@ -110,22 +113,28 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
110
113
|
|
|
111
114
|
const storageRoot = [CORES_DIR, id.slice(0, 2), id.slice(2, 4), id].join('/')
|
|
112
115
|
const core = new Hypercore(p => this.storage(storageRoot + '/' + p), {
|
|
116
|
+
_preready: this._preready.bind(this),
|
|
113
117
|
autoClose: true,
|
|
114
118
|
encryptionKey: opts.encryptionKey || null,
|
|
115
|
-
keyPair: {
|
|
116
|
-
publicKey: keyPair.publicKey,
|
|
117
|
-
secretKey: null
|
|
118
|
-
},
|
|
119
119
|
userData,
|
|
120
120
|
sign: null,
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
createIfMissing: !opts._discoveryKey,
|
|
122
|
+
keyPair: keyPair && keyPair.publicKey
|
|
123
|
+
? {
|
|
124
|
+
publicKey: keyPair.publicKey,
|
|
125
|
+
secretKey: null
|
|
126
|
+
}
|
|
127
|
+
: null
|
|
123
128
|
})
|
|
124
129
|
|
|
125
130
|
this.cores.set(id, core)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
core.ready().then(() => {
|
|
132
|
+
for (const { stream } of this._replicationStreams) {
|
|
133
|
+
core.replicate(stream)
|
|
134
|
+
}
|
|
135
|
+
}, () => {
|
|
136
|
+
this.cores.delete(id)
|
|
137
|
+
})
|
|
129
138
|
core.once('close', () => {
|
|
130
139
|
this.cores.delete(id)
|
|
131
140
|
})
|
|
@@ -145,18 +154,16 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
145
154
|
|
|
146
155
|
replicate (isInitiator, opts) {
|
|
147
156
|
const isExternal = isStream(isInitiator) || !!(opts && opts.stream)
|
|
148
|
-
const stream = Hypercore.createProtocolStream(isInitiator,
|
|
157
|
+
const stream = Hypercore.createProtocolStream(isInitiator, {
|
|
158
|
+
...opts,
|
|
159
|
+
ondiscoverykey: discoveryKey => {
|
|
160
|
+
const core = this.get({ _discoveryKey: discoveryKey })
|
|
161
|
+
return core.ready().catch(safetyCatch)
|
|
162
|
+
}
|
|
163
|
+
})
|
|
149
164
|
for (const core of this.cores.values()) {
|
|
150
|
-
core.replicate(stream)
|
|
165
|
+
if (core.opened) core.replicate(stream) // If the core is not opened, it will be replicated in preload.
|
|
151
166
|
}
|
|
152
|
-
stream.on('discovery-key', discoveryKey => {
|
|
153
|
-
const core = this.get({ discoveryKey })
|
|
154
|
-
core.ready().then(() => {
|
|
155
|
-
core.replicate(stream)
|
|
156
|
-
}, () => {
|
|
157
|
-
stream.close(discoveryKey)
|
|
158
|
-
})
|
|
159
|
-
})
|
|
160
167
|
const streamRecord = { stream, isExternal }
|
|
161
168
|
this._replicationStreams.push(streamRecord)
|
|
162
169
|
stream.once('close', () => {
|
|
@@ -216,8 +223,7 @@ function validateGetOptions (opts) {
|
|
|
216
223
|
if (opts.name && opts.secretKey) throw new Error('Cannot provide both a name and a secret key')
|
|
217
224
|
if (opts.publicKey && !Buffer.isBuffer(opts.publicKey)) throw new Error('publicKey option must be a Buffer')
|
|
218
225
|
if (opts.secretKey && !Buffer.isBuffer(opts.secretKey)) throw new Error('secretKey option must be a Buffer')
|
|
219
|
-
if (opts.
|
|
220
|
-
if (!opts.name && !opts.publicKey) throw new Error('Must provide either a name or a publicKey')
|
|
226
|
+
if (!opts._discoveryKey && (!opts.name && !opts.publicKey)) throw new Error('Must provide either a name or a publicKey')
|
|
221
227
|
return opts
|
|
222
228
|
}
|
|
223
229
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corestore",
|
|
3
|
-
"version": "6.0.1-alpha.
|
|
3
|
+
"version": "6.0.1-alpha.9",
|
|
4
4
|
"description": "A Hypercore factory that simplifies managing collections of cores.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"derive-key": "^1.0.1",
|
|
32
32
|
"hypercore": "next",
|
|
33
33
|
"hypercore-crypto": "^2.3.0",
|
|
34
|
+
"safety-catch": "^1.0.1",
|
|
34
35
|
"sodium-universal": "^3.0.4"
|
|
35
36
|
}
|
|
36
37
|
}
|
package/test/all.js
CHANGED
|
@@ -77,6 +77,46 @@ test('basic replication', async function (t) {
|
|
|
77
77
|
t.alike(await core4.get(0), Buffer.from('world'))
|
|
78
78
|
})
|
|
79
79
|
|
|
80
|
+
test('replicating cores created after replication begins', async function (t) {
|
|
81
|
+
const store1 = new Corestore(ram)
|
|
82
|
+
const store2 = new Corestore(ram)
|
|
83
|
+
|
|
84
|
+
const s = store1.replicate(true, { live: true })
|
|
85
|
+
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
86
|
+
|
|
87
|
+
const core1 = store1.get({ name: 'core-1' })
|
|
88
|
+
const core2 = store1.get({ name: 'core-2' })
|
|
89
|
+
await core1.append('hello')
|
|
90
|
+
await core2.append('world')
|
|
91
|
+
|
|
92
|
+
const core3 = store2.get({ key: core1.key })
|
|
93
|
+
const core4 = store2.get({ key: core2.key })
|
|
94
|
+
|
|
95
|
+
t.alike(await core3.get(0), Buffer.from('hello'))
|
|
96
|
+
t.alike(await core4.get(0), Buffer.from('world'))
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('replicating cores using discovery key hook', async function (t) {
|
|
100
|
+
const dir = await tmp.dir({ unsafeCleanup: true })
|
|
101
|
+
let store1 = new Corestore(dir.path)
|
|
102
|
+
const store2 = new Corestore(ram)
|
|
103
|
+
|
|
104
|
+
const core = store1.get({ name: 'main' })
|
|
105
|
+
await core.append('hello')
|
|
106
|
+
const key = core.key
|
|
107
|
+
|
|
108
|
+
await store1.close()
|
|
109
|
+
store1 = new Corestore(dir.path)
|
|
110
|
+
|
|
111
|
+
const s = store1.replicate(true, { live: true })
|
|
112
|
+
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
113
|
+
|
|
114
|
+
const core2 = store2.get(key)
|
|
115
|
+
t.alike(await core2.get(0), Buffer.from('hello'))
|
|
116
|
+
|
|
117
|
+
await dir.cleanup()
|
|
118
|
+
})
|
|
119
|
+
|
|
80
120
|
test('nested namespaces', async function (t) {
|
|
81
121
|
const store = new Corestore(ram)
|
|
82
122
|
const ns1a = store.namespace('ns1').namespace('a')
|