corestore 6.0.5 → 6.1.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/index.js +26 -32
- package/package.json +7 -3
- package/.github/workflows/test-node.yml +0 -23
- package/test/all.js +0 -411
- package/test/cache.js +0 -46
- package/test/helpers/index.js +0 -19
package/index.js
CHANGED
|
@@ -13,25 +13,26 @@ const CORES_DIR = 'cores'
|
|
|
13
13
|
const PRIMARY_KEY_FILE_NAME = 'primary-key'
|
|
14
14
|
const USERDATA_NAME_KEY = 'corestore/name'
|
|
15
15
|
const USERDATA_NAMESPACE_KEY = 'corestore/namespace'
|
|
16
|
+
const POOL_SIZE = 512 // how many open fds to aim for before cycling them
|
|
16
17
|
|
|
17
18
|
module.exports = class Corestore extends EventEmitter {
|
|
18
19
|
constructor (storage, opts = {}) {
|
|
19
20
|
super()
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.
|
|
22
|
+
const root = opts._root
|
|
23
|
+
|
|
24
|
+
this.storage = Hypercore.defaultStorage(storage, { lock: PRIMARY_KEY_FILE_NAME, poolSize: opts.poolSize || POOL_SIZE })
|
|
25
|
+
this.cores = root ? root.cores : new Map()
|
|
24
26
|
this.cache = !!opts.cache
|
|
27
|
+
this.primaryKey = opts.primaryKey || null
|
|
25
28
|
|
|
26
29
|
this._keyStorage = null
|
|
27
|
-
this._primaryKey = opts.primaryKey
|
|
28
30
|
this._namespace = opts.namespace || DEFAULT_NAMESPACE
|
|
29
31
|
|
|
30
|
-
this._root =
|
|
31
|
-
this._replicationStreams =
|
|
32
|
+
this._root = root || this
|
|
33
|
+
this._replicationStreams = root ? root._replicationStreams : []
|
|
32
34
|
this._overwrite = opts.overwrite === true
|
|
33
35
|
|
|
34
|
-
this._streamSessions = opts._streamSessions || new Map()
|
|
35
36
|
this._sessions = new Set() // sessions for THIS namespace
|
|
36
37
|
|
|
37
38
|
this._findingPeersCount = 0
|
|
@@ -40,9 +41,12 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
40
41
|
if (this._namespace.byteLength !== 32) throw new Error('Namespace must be a 32-byte Buffer or Uint8Array')
|
|
41
42
|
|
|
42
43
|
this._closing = null
|
|
43
|
-
this._opening =
|
|
44
|
+
this._opening = this._open()
|
|
44
45
|
this._opening.catch(safetyCatch)
|
|
45
|
-
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ready () {
|
|
49
|
+
return this._opening
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
findingPeers () {
|
|
@@ -73,16 +77,19 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
async _open () {
|
|
76
|
-
if (this.
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
if (this._root !== this) {
|
|
81
|
+
await this._root._opening
|
|
82
|
+
this.primaryKey = this._root.primaryKey
|
|
83
|
+
return
|
|
79
84
|
}
|
|
85
|
+
|
|
80
86
|
this._keyStorage = this.storage(PRIMARY_KEY_FILE_NAME)
|
|
87
|
+
|
|
81
88
|
this.primaryKey = await new Promise((resolve, reject) => {
|
|
82
89
|
this._keyStorage.stat((err, st) => {
|
|
83
90
|
if (err && err.code !== 'ENOENT') return reject(err)
|
|
84
91
|
if (err || st.size < 32 || this._overwrite) {
|
|
85
|
-
const key = crypto.randomBytes(32)
|
|
92
|
+
const key = this.primaryKey || crypto.randomBytes(32)
|
|
86
93
|
return this._keyStorage.write(0, key, err => {
|
|
87
94
|
if (err) return reject(err)
|
|
88
95
|
return resolve(key)
|
|
@@ -90,11 +97,11 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
90
97
|
}
|
|
91
98
|
this._keyStorage.read(0, 32, (err, key) => {
|
|
92
99
|
if (err) return reject(err)
|
|
100
|
+
if (this.primaryKey) return resolve(this.primaryKey)
|
|
93
101
|
return resolve(key)
|
|
94
102
|
})
|
|
95
103
|
})
|
|
96
104
|
})
|
|
97
|
-
return this.primaryKey
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
async _generateKeys (opts) {
|
|
@@ -150,7 +157,7 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
async _preload (opts) {
|
|
153
|
-
await this.
|
|
160
|
+
if (!this.primaryKey) await this._opening
|
|
154
161
|
|
|
155
162
|
const { discoveryKey, keyPair, auth } = await this._generateKeys(opts)
|
|
156
163
|
const id = b4a.toString(discoveryKey, 'hex')
|
|
@@ -194,10 +201,7 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
194
201
|
this.cores.set(id, core)
|
|
195
202
|
core.ready().then(() => {
|
|
196
203
|
for (const { stream } of this._replicationStreams) {
|
|
197
|
-
|
|
198
|
-
const session = core.session()
|
|
199
|
-
sessions.push(session)
|
|
200
|
-
core.replicate(stream)
|
|
204
|
+
core.replicate(stream, { session: true })
|
|
201
205
|
}
|
|
202
206
|
}, () => {
|
|
203
207
|
this.cores.delete(id)
|
|
@@ -268,36 +272,26 @@ module.exports = class Corestore extends EventEmitter {
|
|
|
268
272
|
}
|
|
269
273
|
})
|
|
270
274
|
|
|
271
|
-
const sessions = []
|
|
272
275
|
for (const core of this.cores.values()) {
|
|
273
276
|
if (!core.opened) continue // If the core is not opened, it will be replicated in preload.
|
|
274
|
-
|
|
275
|
-
sessions.push(session)
|
|
276
|
-
core.replicate(stream)
|
|
277
|
+
core.replicate(stream, { session: true })
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
const streamRecord = { stream, isExternal }
|
|
280
281
|
this._replicationStreams.push(streamRecord)
|
|
281
|
-
this._streamSessions.set(stream, sessions)
|
|
282
282
|
|
|
283
283
|
stream.once('close', () => {
|
|
284
284
|
this._replicationStreams.splice(this._replicationStreams.indexOf(streamRecord), 1)
|
|
285
|
-
this._streamSessions.delete(stream)
|
|
286
|
-
Promise.all(sessions.map(s => s.close())).catch(safetyCatch)
|
|
287
285
|
})
|
|
286
|
+
|
|
288
287
|
return stream
|
|
289
288
|
}
|
|
290
289
|
|
|
291
290
|
namespace (name) {
|
|
292
291
|
return new Corestore(this.storage, {
|
|
293
|
-
primaryKey: this._opening.then(() => this.primaryKey),
|
|
294
292
|
namespace: generateNamespace(this._namespace, name),
|
|
295
293
|
cache: this.cache,
|
|
296
|
-
_root: this._root
|
|
297
|
-
_opening: this._opening,
|
|
298
|
-
_cores: this.cores,
|
|
299
|
-
_streams: this._replicationStreams,
|
|
300
|
-
_streamSessions: this._streamSessions
|
|
294
|
+
_root: this._root
|
|
301
295
|
})
|
|
302
296
|
}
|
|
303
297
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corestore",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "A Hypercore factory that simplifies managing collections of cores.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,14 +19,18 @@
|
|
|
19
19
|
"url": "https://github.com/hypercore-protocol/corestore/issues"
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/hypercore-protocol/corestore#readme",
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"lib/**.js"
|
|
25
|
+
],
|
|
22
26
|
"devDependencies": {
|
|
23
27
|
"brittle": "^3.0.0",
|
|
24
|
-
"random-access-memory": "^
|
|
28
|
+
"random-access-memory": "^6.0.0",
|
|
25
29
|
"standardx": "^7.0.0"
|
|
26
30
|
},
|
|
27
31
|
"dependencies": {
|
|
28
32
|
"b4a": "^1.3.1",
|
|
29
|
-
"hypercore": "^10.
|
|
33
|
+
"hypercore": "^10.3.1",
|
|
30
34
|
"hypercore-crypto": "^3.2.1",
|
|
31
35
|
"safety-catch": "^1.0.1",
|
|
32
36
|
"sodium-universal": "^3.0.4",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
name: Build Status
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- master
|
|
6
|
-
pull_request:
|
|
7
|
-
branches:
|
|
8
|
-
- master
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
strategy:
|
|
12
|
-
matrix:
|
|
13
|
-
node-version: [lts/*]
|
|
14
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
15
|
-
runs-on: ${{ matrix.os }}
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v2
|
|
18
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
19
|
-
uses: actions/setup-node@v2
|
|
20
|
-
with:
|
|
21
|
-
node-version: ${{ matrix.node-version }}
|
|
22
|
-
- run: npm install
|
|
23
|
-
- run: npm test
|
package/test/all.js
DELETED
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
const test = require('brittle')
|
|
2
|
-
const crypto = require('hypercore-crypto')
|
|
3
|
-
const ram = require('random-access-memory')
|
|
4
|
-
const os = require('os')
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const b4a = require('b4a')
|
|
7
|
-
const sodium = require('sodium-universal')
|
|
8
|
-
|
|
9
|
-
const Corestore = require('..')
|
|
10
|
-
|
|
11
|
-
test('basic get with caching', async function (t) {
|
|
12
|
-
const store = new Corestore(ram)
|
|
13
|
-
const core1a = store.get({ name: 'core-1' })
|
|
14
|
-
const core1b = store.get({ name: 'core-1' })
|
|
15
|
-
const core2 = store.get({ name: 'core-2' })
|
|
16
|
-
|
|
17
|
-
await Promise.all([core1a.ready(), core1b.ready(), core2.ready()])
|
|
18
|
-
|
|
19
|
-
t.alike(core1a.key, core1b.key)
|
|
20
|
-
t.unlike(core1a.key, core2.key)
|
|
21
|
-
|
|
22
|
-
t.ok(core1a.writable)
|
|
23
|
-
t.ok(core1b.writable)
|
|
24
|
-
|
|
25
|
-
t.is(store.cores.size, 2)
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
test('basic get with custom keypair', async function (t) {
|
|
29
|
-
const store = new Corestore(ram)
|
|
30
|
-
const kp1 = crypto.keyPair()
|
|
31
|
-
const kp2 = crypto.keyPair()
|
|
32
|
-
|
|
33
|
-
const core1 = store.get(kp1)
|
|
34
|
-
const core2 = store.get(kp2)
|
|
35
|
-
await Promise.all([core1.ready(), core2.ready()])
|
|
36
|
-
|
|
37
|
-
t.alike(core1.key, kp1.publicKey)
|
|
38
|
-
t.alike(core2.key, kp2.publicKey)
|
|
39
|
-
t.ok(core1.writable)
|
|
40
|
-
t.ok(core2.writable)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
test('get with createIfMissing=false throws if new core', async function (t) {
|
|
44
|
-
const store = new Corestore(ram)
|
|
45
|
-
const core1a = store.get({ name: 'core-1', createIfMissing: false })
|
|
46
|
-
|
|
47
|
-
await t.exception(core1a.ready(), 'No Hypercore is stored here')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
test('get with createIfMissing=false works if no new core', async function (t) {
|
|
51
|
-
const store = new Corestore(ram)
|
|
52
|
-
const name = 'core-1'
|
|
53
|
-
|
|
54
|
-
const core1 = store.get({ name })
|
|
55
|
-
await core1.ready()
|
|
56
|
-
|
|
57
|
-
const core1Too = store.get({ name, createIfMissing: false })
|
|
58
|
-
await t.execution(core1Too.ready())
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('basic namespaces', async function (t) {
|
|
62
|
-
const store = new Corestore(ram)
|
|
63
|
-
const ns1 = store.namespace('ns1')
|
|
64
|
-
const ns2 = store.namespace('ns2')
|
|
65
|
-
const ns3 = store.namespace('ns1') // Duplicate namespace
|
|
66
|
-
|
|
67
|
-
const core1 = ns1.get({ name: 'main' })
|
|
68
|
-
const core2 = ns2.get({ name: 'main' })
|
|
69
|
-
const core3 = ns3.get({ name: 'main' })
|
|
70
|
-
await Promise.all([core1.ready(), core2.ready(), core3.ready()])
|
|
71
|
-
|
|
72
|
-
t.absent(core1.key.equals(core2.key))
|
|
73
|
-
t.ok(core1.key.equals(core3.key))
|
|
74
|
-
t.ok(core1.writable)
|
|
75
|
-
t.ok(core2.writable)
|
|
76
|
-
t.ok(core3.writable)
|
|
77
|
-
t.is(store.cores.size, 2)
|
|
78
|
-
|
|
79
|
-
t.end()
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
test('basic replication', async function (t) {
|
|
83
|
-
const store1 = new Corestore(ram)
|
|
84
|
-
const store2 = new Corestore(ram)
|
|
85
|
-
|
|
86
|
-
const core1 = store1.get({ name: 'core-1' })
|
|
87
|
-
const core2 = store1.get({ name: 'core-2' })
|
|
88
|
-
await core1.append('hello')
|
|
89
|
-
await core2.append('world')
|
|
90
|
-
|
|
91
|
-
const core3 = store2.get({ key: core1.key })
|
|
92
|
-
const core4 = store2.get({ key: core2.key })
|
|
93
|
-
|
|
94
|
-
const s = store1.replicate(true)
|
|
95
|
-
s.pipe(store2.replicate(false)).pipe(s)
|
|
96
|
-
|
|
97
|
-
t.alike(await core3.get(0), Buffer.from('hello'))
|
|
98
|
-
t.alike(await core4.get(0), Buffer.from('world'))
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test('replicating cores created after replication begins', async function (t) {
|
|
102
|
-
const store1 = new Corestore(ram)
|
|
103
|
-
const store2 = new Corestore(ram)
|
|
104
|
-
|
|
105
|
-
const s = store1.replicate(true, { live: true })
|
|
106
|
-
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
107
|
-
|
|
108
|
-
const core1 = store1.get({ name: 'core-1' })
|
|
109
|
-
const core2 = store1.get({ name: 'core-2' })
|
|
110
|
-
await core1.append('hello')
|
|
111
|
-
await core2.append('world')
|
|
112
|
-
|
|
113
|
-
const core3 = store2.get({ key: core1.key })
|
|
114
|
-
const core4 = store2.get({ key: core2.key })
|
|
115
|
-
|
|
116
|
-
t.alike(await core3.get(0), Buffer.from('hello'))
|
|
117
|
-
t.alike(await core4.get(0), Buffer.from('world'))
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
test('replicating cores using discovery key hook', async function (t) {
|
|
121
|
-
const dir = tmpdir()
|
|
122
|
-
let store1 = new Corestore(dir)
|
|
123
|
-
const store2 = new Corestore(ram)
|
|
124
|
-
|
|
125
|
-
const core = store1.get({ name: 'main' })
|
|
126
|
-
await core.append('hello')
|
|
127
|
-
const key = core.key
|
|
128
|
-
|
|
129
|
-
await store1.close()
|
|
130
|
-
store1 = new Corestore(dir)
|
|
131
|
-
|
|
132
|
-
const s = store1.replicate(true, { live: true })
|
|
133
|
-
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
134
|
-
|
|
135
|
-
const core2 = store2.get(key)
|
|
136
|
-
t.alike(await core2.get(0), Buffer.from('hello'))
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
test('nested namespaces', async function (t) {
|
|
140
|
-
const store = new Corestore(ram)
|
|
141
|
-
const ns1a = store.namespace('ns1').namespace('a')
|
|
142
|
-
const ns1b = store.namespace('ns1').namespace('b')
|
|
143
|
-
|
|
144
|
-
const core1 = ns1a.get({ name: 'main' })
|
|
145
|
-
const core2 = ns1b.get({ name: 'main' })
|
|
146
|
-
await Promise.all([core1.ready(), core2.ready()])
|
|
147
|
-
|
|
148
|
-
t.not(core1.key.equals(core2.key))
|
|
149
|
-
t.ok(core1.writable)
|
|
150
|
-
t.ok(core2.writable)
|
|
151
|
-
t.is(store.cores.size, 2)
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('core uncached when all sessions close', async function (t) {
|
|
155
|
-
const store = new Corestore(ram)
|
|
156
|
-
const core1 = store.get({ name: 'main' })
|
|
157
|
-
await core1.ready()
|
|
158
|
-
t.is(store.cores.size, 1)
|
|
159
|
-
await core1.close()
|
|
160
|
-
t.is(store.cores.size, 0)
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
test('writable core loaded from name userData', async function (t) {
|
|
164
|
-
const dir = tmpdir()
|
|
165
|
-
|
|
166
|
-
let store = new Corestore(dir)
|
|
167
|
-
let core = store.get({ name: 'main' })
|
|
168
|
-
await core.ready()
|
|
169
|
-
const key = core.key
|
|
170
|
-
|
|
171
|
-
t.ok(core.writable)
|
|
172
|
-
await core.append('hello')
|
|
173
|
-
t.is(core.length, 1)
|
|
174
|
-
|
|
175
|
-
await store.close()
|
|
176
|
-
store = new Corestore(dir)
|
|
177
|
-
core = store.get(key)
|
|
178
|
-
await core.ready()
|
|
179
|
-
|
|
180
|
-
t.ok(core.writable)
|
|
181
|
-
await core.append('world')
|
|
182
|
-
t.is(core.length, 2)
|
|
183
|
-
t.alike(await core.get(0), Buffer.from('hello'))
|
|
184
|
-
t.alike(await core.get(1), Buffer.from('world'))
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
test('writable core loaded from name and namespace userData', async function (t) {
|
|
188
|
-
const dir = tmpdir()
|
|
189
|
-
|
|
190
|
-
let store = new Corestore(dir)
|
|
191
|
-
let core = store.namespace('ns1').get({ name: 'main' })
|
|
192
|
-
await core.ready()
|
|
193
|
-
const key = core.key
|
|
194
|
-
|
|
195
|
-
t.ok(core.writable)
|
|
196
|
-
await core.append('hello')
|
|
197
|
-
t.is(core.length, 1)
|
|
198
|
-
|
|
199
|
-
await store.close()
|
|
200
|
-
store = new Corestore(dir)
|
|
201
|
-
core = store.get(key)
|
|
202
|
-
await core.ready()
|
|
203
|
-
|
|
204
|
-
t.ok(core.writable)
|
|
205
|
-
await core.append('world')
|
|
206
|
-
t.is(core.length, 2)
|
|
207
|
-
t.alike(await core.get(0), Buffer.from('hello'))
|
|
208
|
-
t.alike(await core.get(1), Buffer.from('world'))
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
test('storage locking', async function (t) {
|
|
212
|
-
const dir = tmpdir()
|
|
213
|
-
|
|
214
|
-
const store1 = new Corestore(dir)
|
|
215
|
-
await store1.ready()
|
|
216
|
-
|
|
217
|
-
const store2 = new Corestore(dir)
|
|
218
|
-
try {
|
|
219
|
-
await store2.ready()
|
|
220
|
-
t.fail('dir should have been locked')
|
|
221
|
-
} catch {
|
|
222
|
-
t.pass('dir was locked')
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
test('cores close when their last referencing namespace closes', async function (t) {
|
|
227
|
-
const store = new Corestore(ram)
|
|
228
|
-
const ns1 = store.namespace('ns1')
|
|
229
|
-
const core1 = ns1.get({ name: 'core-1' })
|
|
230
|
-
const core2 = ns1.get({ name: 'core-2' })
|
|
231
|
-
await Promise.all([core1.ready(), core2.ready()])
|
|
232
|
-
|
|
233
|
-
const core3 = store.get(core1.key)
|
|
234
|
-
const core4 = store.get(core2.key)
|
|
235
|
-
await Promise.all([core3.ready(), core4.ready()])
|
|
236
|
-
|
|
237
|
-
await ns1.close()
|
|
238
|
-
|
|
239
|
-
t.is(store.cores.size, 2)
|
|
240
|
-
t.not(core1.closed)
|
|
241
|
-
t.not(core1.closed)
|
|
242
|
-
|
|
243
|
-
await store.close()
|
|
244
|
-
|
|
245
|
-
t.is(store.cores.size, 0)
|
|
246
|
-
t.ok(core1.closed)
|
|
247
|
-
t.ok(core2.closed)
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
test('findingPeers', async function (t) {
|
|
251
|
-
t.plan(6)
|
|
252
|
-
|
|
253
|
-
const store = new Corestore(ram)
|
|
254
|
-
|
|
255
|
-
const ns1 = store.namespace('ns1')
|
|
256
|
-
const ns2 = store.namespace('ns2')
|
|
257
|
-
|
|
258
|
-
const a = ns1.get(Buffer.alloc(32).fill('a'))
|
|
259
|
-
const b = ns2.get(Buffer.alloc(32).fill('b'))
|
|
260
|
-
|
|
261
|
-
const done = ns1.findingPeers()
|
|
262
|
-
|
|
263
|
-
let aUpdated = false
|
|
264
|
-
let bUpdated = false
|
|
265
|
-
let cUpdated = false
|
|
266
|
-
|
|
267
|
-
const c = ns1.get(Buffer.alloc(32).fill('c'))
|
|
268
|
-
|
|
269
|
-
a.update().then(function (bool) {
|
|
270
|
-
aUpdated = true
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
b.update().then(function (bool) {
|
|
274
|
-
bUpdated = true
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
c.update().then(function (bool) {
|
|
278
|
-
cUpdated = true
|
|
279
|
-
})
|
|
280
|
-
|
|
281
|
-
await new Promise(resolve => setImmediate(resolve))
|
|
282
|
-
|
|
283
|
-
t.is(aUpdated, false)
|
|
284
|
-
t.is(bUpdated, true)
|
|
285
|
-
t.is(cUpdated, false)
|
|
286
|
-
|
|
287
|
-
done()
|
|
288
|
-
|
|
289
|
-
await new Promise(resolve => setImmediate(resolve))
|
|
290
|
-
|
|
291
|
-
t.is(aUpdated, true)
|
|
292
|
-
t.is(bUpdated, true)
|
|
293
|
-
t.is(cUpdated, true)
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
test('different primary keys yield different keypairs', async function (t) {
|
|
297
|
-
const pk1 = randomBytes(32)
|
|
298
|
-
const pk2 = randomBytes(32)
|
|
299
|
-
t.unlike(pk1, pk2)
|
|
300
|
-
|
|
301
|
-
const store1 = new Corestore(ram, { primaryKey: pk1 })
|
|
302
|
-
const store2 = new Corestore(ram, { primaryKey: pk2 })
|
|
303
|
-
|
|
304
|
-
const kp1 = await store1.createKeyPair('hello')
|
|
305
|
-
const kp2 = await store2.createKeyPair('hello')
|
|
306
|
-
|
|
307
|
-
t.unlike(kp1.publicKey, kp2.publicKey)
|
|
308
|
-
})
|
|
309
|
-
|
|
310
|
-
test('keypair auth sign', async function (t) {
|
|
311
|
-
const store = new Corestore(ram)
|
|
312
|
-
const keyPair = await store.createKeyPair('foo')
|
|
313
|
-
const message = b4a.from('hello world')
|
|
314
|
-
|
|
315
|
-
const sig = keyPair.auth.sign(message)
|
|
316
|
-
|
|
317
|
-
t.is(sig.length, 64)
|
|
318
|
-
t.ok(crypto.verify(message, sig, keyPair.publicKey))
|
|
319
|
-
t.absent(crypto.verify(message, b4a.alloc(64), keyPair.publicKey))
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
test('keypair auth verify', async function (t) {
|
|
323
|
-
const store = new Corestore(ram)
|
|
324
|
-
const keyPair = await store.createKeyPair('foo')
|
|
325
|
-
const message = b4a.from('hello world')
|
|
326
|
-
|
|
327
|
-
const sig = crypto.sign(message, keyPair.secretKey)
|
|
328
|
-
|
|
329
|
-
t.is(sig.length, 64)
|
|
330
|
-
t.ok(keyPair.auth.verify(message, sig))
|
|
331
|
-
t.absent(keyPair.auth.verify(message, b4a.alloc(64)))
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
test('core caching after reopen regression', async function (t) {
|
|
335
|
-
const store = new Corestore(ram)
|
|
336
|
-
const core = store.get({ name: 'test-core' })
|
|
337
|
-
await core.ready()
|
|
338
|
-
|
|
339
|
-
core.close()
|
|
340
|
-
await core.opening
|
|
341
|
-
|
|
342
|
-
const core2 = store.get({ name: 'test-core' })
|
|
343
|
-
await core2.ready()
|
|
344
|
-
|
|
345
|
-
t.pass('did not infinite loop')
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
test('closing a namespace does not close the root corestore', async function (t) {
|
|
349
|
-
const store = new Corestore(ram)
|
|
350
|
-
const core1 = store.get({ name: 'core-1' })
|
|
351
|
-
await core1.ready()
|
|
352
|
-
|
|
353
|
-
const ns = store.namespace('test-namespace')
|
|
354
|
-
const core2 = ns.get(core1.key)
|
|
355
|
-
await core2.ready()
|
|
356
|
-
|
|
357
|
-
await ns.close()
|
|
358
|
-
t.is(core1.closed, false)
|
|
359
|
-
t.is(core2.closed, true)
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
test('open a new session concurrently with a close should throw', async function (t) {
|
|
363
|
-
const store = new Corestore(ram)
|
|
364
|
-
const ns = store.namespace('test-namespace')
|
|
365
|
-
|
|
366
|
-
const core1 = ns.get({ name: 'core-1' })
|
|
367
|
-
store.close()
|
|
368
|
-
|
|
369
|
-
try {
|
|
370
|
-
await core1.ready()
|
|
371
|
-
t.fail('core1 should not have opened')
|
|
372
|
-
} catch {
|
|
373
|
-
t.pass('core1 did not open after corestore close')
|
|
374
|
-
}
|
|
375
|
-
})
|
|
376
|
-
|
|
377
|
-
test('closing the root corestore closes all sessions', async function (t) {
|
|
378
|
-
const store = new Corestore(ram)
|
|
379
|
-
const ns = store.namespace('test-namespace')
|
|
380
|
-
|
|
381
|
-
const core1 = store.get({ name: 'core-1' })
|
|
382
|
-
const core2 = store.get({ name: 'core-2' })
|
|
383
|
-
await Promise.all([core1.ready(), core2.ready()])
|
|
384
|
-
|
|
385
|
-
const core3 = ns.get(core1.key)
|
|
386
|
-
const core4 = ns.get(core2.key)
|
|
387
|
-
await Promise.all([core3.ready(), core4.ready()])
|
|
388
|
-
|
|
389
|
-
await store.close()
|
|
390
|
-
|
|
391
|
-
t.is(core1.closed, true)
|
|
392
|
-
t.is(core2.closed, true)
|
|
393
|
-
|
|
394
|
-
try {
|
|
395
|
-
const core5 = ns.get({ name: 'core-3' })
|
|
396
|
-
await core5.ready()
|
|
397
|
-
t.fail('core5 should not have opened after corestore close')
|
|
398
|
-
} catch (err) {
|
|
399
|
-
t.pass('core5 did not open after corestore close')
|
|
400
|
-
}
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
function tmpdir () {
|
|
404
|
-
return path.join(os.tmpdir(), 'corestore-' + Math.random().toString(16).slice(2))
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
function randomBytes (n) {
|
|
408
|
-
const buf = b4a.allocUnsafe(n)
|
|
409
|
-
sodium.randombytes_buf(buf)
|
|
410
|
-
return buf
|
|
411
|
-
}
|
package/test/cache.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const test = require('brittle')
|
|
2
|
-
const RAM = require('random-access-memory')
|
|
3
|
-
|
|
4
|
-
const Corestore = require('..')
|
|
5
|
-
|
|
6
|
-
test('core cache', async function (t) {
|
|
7
|
-
const store = new Corestore(RAM, { cache: true })
|
|
8
|
-
|
|
9
|
-
const core = store.get({ name: 'core' })
|
|
10
|
-
await core.append(['a', 'b', 'c'])
|
|
11
|
-
|
|
12
|
-
const p = core.get(0)
|
|
13
|
-
const q = core.get(0)
|
|
14
|
-
|
|
15
|
-
t.is(await p, await q)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
test('clear cache on truncate', async function (t) {
|
|
19
|
-
const store = new Corestore(RAM, { cache: true })
|
|
20
|
-
|
|
21
|
-
const core = store.get({ name: 'core' })
|
|
22
|
-
await core.append(['a', 'b', 'c'])
|
|
23
|
-
|
|
24
|
-
const p = core.get(0)
|
|
25
|
-
|
|
26
|
-
await core.truncate(0)
|
|
27
|
-
await core.append('d')
|
|
28
|
-
|
|
29
|
-
const q = core.get(0)
|
|
30
|
-
|
|
31
|
-
t.alike(await p, Buffer.from('a'))
|
|
32
|
-
t.alike(await q, Buffer.from('d'))
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
test('core cache on namespace', async function (t) {
|
|
36
|
-
const store = new Corestore(RAM, { cache: true })
|
|
37
|
-
const ns1 = store.namespace('test-namespace-1')
|
|
38
|
-
|
|
39
|
-
const c1 = store.get({ name: 'test-core' })
|
|
40
|
-
const c2 = ns1.get({ name: 'test-core' })
|
|
41
|
-
|
|
42
|
-
await Promise.all([c1.ready(), c2.ready()])
|
|
43
|
-
|
|
44
|
-
t.ok(c1.cache)
|
|
45
|
-
t.ok(c2.cache)
|
|
46
|
-
})
|
package/test/helpers/index.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
const fs = require('fs').promises
|
|
2
|
-
|
|
3
|
-
async function cleanup (dirs) {
|
|
4
|
-
return Promise.allSettled(dirs.map(dir => fs.rmdir(dir, { recursive: true })))
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function delay (ms, cb) {
|
|
8
|
-
return new Promise(resolve => {
|
|
9
|
-
setTimeout(() => {
|
|
10
|
-
if (cb) cb()
|
|
11
|
-
resolve()
|
|
12
|
-
}, ms)
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = {
|
|
17
|
-
delay,
|
|
18
|
-
cleanup
|
|
19
|
-
}
|