corestore 6.18.3 → 7.0.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 +12 -38
- package/index.js +299 -459
- package/package.json +29 -30
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -13,6 +13,11 @@ Corestore provides:
|
|
|
13
13
|
### Installation
|
|
14
14
|
`npm install corestore`
|
|
15
15
|
|
|
16
|
+
> [!NOTE]
|
|
17
|
+
> This readme reflects Corestore 7, our latest major version that is backed by RocksDB for storage and atomicity.
|
|
18
|
+
> Whilst we are fully validating that, the npm dist-tag for latest is set to latest version of Corestore 7, the previous major, to avoid too much disruption.
|
|
19
|
+
> It will be updated to 11 in a few weeks.
|
|
20
|
+
|
|
16
21
|
### Usage
|
|
17
22
|
A corestore instance can be constructed with a random-access-storage module, a function that returns a random-access-storage module given a path, or a string. If a string is specified, it will be assumed to be a path to a local storage directory:
|
|
18
23
|
```js
|
|
@@ -24,27 +29,17 @@ const core2 = store.get({ name: 'core-2' })
|
|
|
24
29
|
```
|
|
25
30
|
|
|
26
31
|
### API
|
|
27
|
-
#### `const store = new Corestore(storage
|
|
32
|
+
#### `const store = new Corestore(storage)`
|
|
28
33
|
Create a new Corestore instance.
|
|
29
34
|
|
|
30
35
|
`storage` can be either a random-access-storage module, a string, or a function that takes a path and returns an random-access-storage instance.
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
{
|
|
35
|
-
inflightRange: null // Advanced option. Forwarded to the Hypercores created by corestore.get(...)
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
#### `const core = store.get(key | { name: 'a-name', exclusive, ...hypercoreOpts})`
|
|
37
|
+
#### `const core = store.get(key | { name: 'a-name', ...hypercoreOpts})`
|
|
40
38
|
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).
|
|
41
39
|
|
|
42
40
|
If that Hypercore has previously been loaded, subsequent calls to `get` will return a new Hypercore session on the existing core.
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
opening the Hypercore effectively meaning any op on the core will wait until its exclusive.
|
|
46
|
-
|
|
47
|
-
All other options besides `name` and `key` and `exclusive` will be forwarded to the Hypercore constructor.
|
|
42
|
+
All other options besides `name` and `key` will be forwarded to the Hypercore constructor.
|
|
48
43
|
|
|
49
44
|
#### `const stream = store.replicate(optsOrStream)`
|
|
50
45
|
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.
|
|
@@ -67,8 +62,11 @@ swarm.join(...)
|
|
|
67
62
|
swarm.on('connection', (connection) => store.replicate(connection))
|
|
68
63
|
```
|
|
69
64
|
|
|
65
|
+
#### `const storeB = storeA.session()`
|
|
66
|
+
Create a new Corestore session. Closing a session will close all cores made from this session.
|
|
67
|
+
|
|
70
68
|
#### `const store = store.namespace(name)`
|
|
71
|
-
Create a new namespaced Corestore. Namespacing is useful if you're going to be sharing a single Corestore instance between many applications or components, as it prevents name collisions.
|
|
69
|
+
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.
|
|
72
70
|
|
|
73
71
|
Namespaces can be chained:
|
|
74
72
|
```js
|
|
@@ -78,32 +76,8 @@ const core1 = ns1.get({ name: 'main' }) // These will load different Hypercores
|
|
|
78
76
|
const core2 = ns2.get({ name: 'main' })
|
|
79
77
|
```
|
|
80
78
|
|
|
81
|
-
#### `const storeB = storeA.session(opts)`
|
|
82
|
-
Create a new Corestore that shares resources with the original, like cache, cores, replication streams, and storage, while optionally resetting the namespace, overriding `primaryKey`.
|
|
83
|
-
Useful when an application wants to accept an optional Corestore, but needs to maintain a predictable key derivation.
|
|
84
|
-
|
|
85
|
-
`opts` are the same as the constructor options:
|
|
86
|
-
|
|
87
|
-
```js
|
|
88
|
-
{
|
|
89
|
-
primaryKey, // Overrides the primaryKey for this session
|
|
90
|
-
namespace, // If set to null it will reset to the DEFAULT_NAMESPACE
|
|
91
|
-
detach: true, // By disabling this, closing the session will also close the store that created the session
|
|
92
|
-
inflightRange: null // Advanced option. Forwarded to the Hypercores created by `session.get(...)
|
|
93
|
-
}
|
|
94
|
-
```
|
|
95
|
-
|
|
96
79
|
#### `await store.close()`
|
|
97
80
|
Fully close this Corestore instance.
|
|
98
81
|
|
|
99
|
-
#### `store.on('core-open', core)`
|
|
100
|
-
Emitted when the first session for a core is opened.
|
|
101
|
-
|
|
102
|
-
*Note: This core may close at any time, so treat it as a weak reference*
|
|
103
|
-
|
|
104
|
-
#### `store.on('core-close', core)`
|
|
105
|
-
Emitted when the last session for a core is closed.
|
|
106
|
-
|
|
107
82
|
### License
|
|
108
83
|
MIT
|
|
109
|
-
|
package/index.js
CHANGED
|
@@ -1,567 +1,407 @@
|
|
|
1
|
-
const safetyCatch = require('safety-catch')
|
|
2
|
-
const crypto = require('hypercore-crypto')
|
|
3
|
-
const sodium = require('sodium-universal')
|
|
4
|
-
const Hypercore = require('hypercore')
|
|
5
|
-
const hypercoreId = require('hypercore-id-encoding')
|
|
6
|
-
const Xache = require('xache')
|
|
7
1
|
const b4a = require('b4a')
|
|
2
|
+
const Hypercore = require('hypercore')
|
|
8
3
|
const ReadyResource = require('ready-resource')
|
|
9
|
-
const
|
|
4
|
+
const EventEmitter = require('events')
|
|
5
|
+
const sodium = require('sodium-universal')
|
|
6
|
+
const crypto = require('hypercore-crypto')
|
|
7
|
+
const ID = require('hypercore-id-encoding')
|
|
10
8
|
|
|
11
9
|
const [NS] = crypto.namespace('corestore', 1)
|
|
12
10
|
const DEFAULT_NAMESPACE = b4a.alloc(32) // This is meant to be 32 0-bytes
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const USERDATA_NAMESPACE_KEY = 'corestore/namespace'
|
|
18
|
-
const POOL_SIZE = 512 // how many open fds to aim for before cycling them
|
|
19
|
-
const DEFAULT_MANIFEST = 0 // bump to 1 when this is more widely deployed
|
|
20
|
-
const DEFAULT_COMPAT = true
|
|
21
|
-
|
|
22
|
-
module.exports = class Corestore extends ReadyResource {
|
|
23
|
-
constructor (storage, opts = {}) {
|
|
24
|
-
super()
|
|
25
|
-
|
|
26
|
-
const root = opts._root
|
|
27
|
-
|
|
28
|
-
this.storage = Hypercore.defaultStorage(storage, { lock: PRIMARY_KEY_FILE_NAME, poolSize: opts.poolSize || POOL_SIZE, rmdir: true })
|
|
29
|
-
this.cores = root ? root.cores : new Map()
|
|
30
|
-
this.cache = !!opts.cache
|
|
31
|
-
this.primaryKey = opts.primaryKey || null
|
|
32
|
-
this.passive = !!opts.passive
|
|
33
|
-
this.manifestVersion = typeof opts.manifestVersion === 'number' ? opts.manifestVersion : (root ? root.manifestVersion : DEFAULT_MANIFEST)
|
|
34
|
-
this.compat = typeof opts.compat === 'boolean' ? opts.compat : (root ? root.compat : DEFAULT_COMPAT)
|
|
35
|
-
this.inflightRange = opts.inflightRange || null
|
|
36
|
-
this.globalCache = opts.globalCache || null
|
|
37
|
-
|
|
38
|
-
this._keyStorage = null
|
|
39
|
-
this._bootstrap = opts._bootstrap || null
|
|
40
|
-
this._namespace = opts.namespace || DEFAULT_NAMESPACE
|
|
41
|
-
this._noCoreCache = root ? root._noCoreCache : new Xache({ maxSize: 65536 })
|
|
42
|
-
|
|
43
|
-
this._root = root || this
|
|
44
|
-
this._replicationStreams = root ? root._replicationStreams : []
|
|
45
|
-
this._overwrite = opts.overwrite === true
|
|
46
|
-
this._readonly = opts.writable === false
|
|
47
|
-
this._attached = opts._attached || null
|
|
48
|
-
this._notDownloadingLinger = opts.notDownloadingLinger
|
|
49
|
-
|
|
50
|
-
this._sessions = new Set() // sessions for THIS namespace
|
|
51
|
-
this._rootStoreSessions = new Set()
|
|
52
|
-
this._locks = root ? root._locks : new Map()
|
|
53
|
-
|
|
54
|
-
this._findingPeersCount = 0
|
|
55
|
-
this._findingPeers = []
|
|
56
|
-
this._isCorestore = true
|
|
57
|
-
|
|
58
|
-
if (this._namespace.byteLength !== 32) throw new Error('Namespace must be a 32-byte Buffer or Uint8Array')
|
|
59
|
-
this.ready().catch(safetyCatch)
|
|
12
|
+
class StreamTracker {
|
|
13
|
+
constructor () {
|
|
14
|
+
this.records = []
|
|
60
15
|
}
|
|
61
16
|
|
|
62
|
-
|
|
63
|
-
|
|
17
|
+
add (stream, isExternal) {
|
|
18
|
+
const record = { index: 0, stream, isExternal }
|
|
19
|
+
this.records.push(record)
|
|
20
|
+
return record
|
|
64
21
|
}
|
|
65
22
|
|
|
66
|
-
|
|
67
|
-
|
|
23
|
+
remove (record) {
|
|
24
|
+
const popped = this.records.pop()
|
|
25
|
+
if (popped === record) return
|
|
26
|
+
this.records[popped.index = record.index] = popped
|
|
68
27
|
}
|
|
69
28
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (this._keyStorage !== null) {
|
|
77
|
-
await new Promise((resolve, reject) => {
|
|
78
|
-
this._keyStorage.suspend((err) => {
|
|
79
|
-
if (err) return reject(err)
|
|
80
|
-
resolve()
|
|
81
|
-
})
|
|
82
|
-
})
|
|
29
|
+
attachAll (core) {
|
|
30
|
+
for (let i = 0; i < this.records.length; i++) {
|
|
31
|
+
const record = this.records[i]
|
|
32
|
+
const muxer = record.stream.noiseStream.userData
|
|
33
|
+
if (!core.replicator.attached(muxer)) core.replicator.attachTo(muxer)
|
|
83
34
|
}
|
|
84
35
|
}
|
|
85
36
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (this._keyStorage !== null) {
|
|
92
|
-
await new Promise((resolve, reject) => {
|
|
93
|
-
this._keyStorage.open((err) => {
|
|
94
|
-
if (err) return reject(err)
|
|
95
|
-
resolve()
|
|
96
|
-
})
|
|
97
|
-
})
|
|
37
|
+
destroy () {
|
|
38
|
+
// reverse is safer cause we delete mb
|
|
39
|
+
for (let i = this.records.length - 1; i >= 0; i--) {
|
|
40
|
+
const record = this.records[i]
|
|
41
|
+
if (!record.isExternal) record.stream.destroy()
|
|
98
42
|
}
|
|
99
43
|
}
|
|
44
|
+
}
|
|
100
45
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
|
|
105
|
-
return () => {
|
|
106
|
-
if (done) return
|
|
107
|
-
done = true
|
|
108
|
-
this._decFindingPeers()
|
|
109
|
-
}
|
|
46
|
+
class SessionTracker {
|
|
47
|
+
constructor () {
|
|
48
|
+
this.map = new Map()
|
|
110
49
|
}
|
|
111
50
|
|
|
112
|
-
|
|
113
|
-
this.
|
|
114
|
-
for (const session of this._root._rootStoreSessions) {
|
|
115
|
-
if (session !== this) {
|
|
116
|
-
session.emit(name, core)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (this !== this._root) this._root.emit(name, core)
|
|
51
|
+
get size () {
|
|
52
|
+
return this.map.size
|
|
120
53
|
}
|
|
121
54
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
55
|
+
get (id) {
|
|
56
|
+
const existing = this.map.get(id)
|
|
57
|
+
if (existing !== undefined) return existing
|
|
58
|
+
const fresh = []
|
|
59
|
+
this.map.set(id, fresh)
|
|
60
|
+
return fresh
|
|
128
61
|
}
|
|
129
62
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
while (this._findingPeers.length > 0) {
|
|
134
|
-
this._findingPeers.pop()()
|
|
135
|
-
}
|
|
63
|
+
gc (id) {
|
|
64
|
+
this.map.delete(id)
|
|
136
65
|
}
|
|
137
66
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (ns) {
|
|
141
|
-
this._namespace = ns
|
|
142
|
-
}
|
|
67
|
+
list (id) {
|
|
68
|
+
return id ? (this.map.get(id) || []) : [...this]
|
|
143
69
|
}
|
|
144
70
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (!this.primaryKey) this.primaryKey = this._root.primaryKey
|
|
149
|
-
if (this._bootstrap) await this._openNamespaceFromBootstrap()
|
|
150
|
-
return
|
|
71
|
+
* [Symbol.iterator] () {
|
|
72
|
+
for (const sessions of this.map.values()) {
|
|
73
|
+
yield * sessions[Symbol.iterator]()
|
|
151
74
|
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
152
77
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const key = this.primaryKey || crypto.randomBytes(32)
|
|
160
|
-
return this._keyStorage.write(0, key, err => {
|
|
161
|
-
if (err) return reject(err)
|
|
162
|
-
return resolve(key)
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
this._keyStorage.read(0, 32, (err, key) => {
|
|
166
|
-
if (err) return reject(err)
|
|
167
|
-
if (this.primaryKey) return resolve(this.primaryKey)
|
|
168
|
-
return resolve(key)
|
|
169
|
-
})
|
|
170
|
-
})
|
|
171
|
-
})
|
|
78
|
+
class CoreTracker extends EventEmitter {
|
|
79
|
+
constructor () {
|
|
80
|
+
super()
|
|
81
|
+
this.map = new Map()
|
|
82
|
+
this.watching = []
|
|
83
|
+
}
|
|
172
84
|
|
|
173
|
-
|
|
85
|
+
get size () {
|
|
86
|
+
return this.map.size
|
|
174
87
|
}
|
|
175
88
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
89
|
+
watch (store) {
|
|
90
|
+
if (store.watchIndex !== -1) return
|
|
91
|
+
store.watchIndex = this.watching.push(store) - 1
|
|
92
|
+
}
|
|
179
93
|
|
|
180
|
-
|
|
94
|
+
unwatch (store) {
|
|
95
|
+
if (store.watchIndex === -1) return
|
|
96
|
+
const head = this.watching.pop()
|
|
97
|
+
if (head !== store) this.watching[(head.watchIndex = store.watchIndex)] = head
|
|
98
|
+
store.watchIndex = -1
|
|
99
|
+
}
|
|
181
100
|
|
|
182
|
-
|
|
183
|
-
|
|
101
|
+
get (id) {
|
|
102
|
+
// we allow you do call this from the outside, so support normal buffers also
|
|
103
|
+
if (b4a.isBuffer(id)) id = b4a.toString(id, 'hex')
|
|
104
|
+
return this.map.get(id) || null
|
|
105
|
+
}
|
|
184
106
|
|
|
185
|
-
|
|
107
|
+
set (id, core) {
|
|
108
|
+
this.map.set(id, core)
|
|
109
|
+
this.emit('add', core) // TODO: will be removed
|
|
110
|
+
if (this.watching.length > 0) this._emit(core)
|
|
186
111
|
}
|
|
187
112
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
keyPair: null,
|
|
193
|
-
key: null,
|
|
194
|
-
discoveryKey: opts._discoveryKey
|
|
195
|
-
}
|
|
113
|
+
_emit (core) {
|
|
114
|
+
for (let i = this.watching.length - 1; i >= 0; i--) {
|
|
115
|
+
const store = this.watching[i]
|
|
116
|
+
for (const fn of store.watchers) fn(core)
|
|
196
117
|
}
|
|
118
|
+
}
|
|
197
119
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
: null
|
|
120
|
+
delete (id, core) {
|
|
121
|
+
this.map.delete(id)
|
|
122
|
+
this.emit('remove', core) // TODO: will be removed
|
|
123
|
+
}
|
|
203
124
|
|
|
204
|
-
|
|
205
|
-
|
|
125
|
+
[Symbol.iterator] () {
|
|
126
|
+
return this.map.values()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
206
129
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
key,
|
|
211
|
-
discoveryKey: crypto.discoveryKey(key)
|
|
212
|
-
}
|
|
213
|
-
}
|
|
130
|
+
class Corestore extends ReadyResource {
|
|
131
|
+
constructor (storage, opts = {}) {
|
|
132
|
+
super()
|
|
214
133
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
134
|
+
this.root = opts.root || null
|
|
135
|
+
this.storage = this.root ? this.root.storage : Hypercore.defaultStorage(storage)
|
|
136
|
+
this.streamTracker = this.root ? this.root.streamTracker : new StreamTracker()
|
|
137
|
+
this.cores = this.root ? this.root.cores : new CoreTracker()
|
|
138
|
+
this.sessions = new SessionTracker()
|
|
139
|
+
this.globalCache = this.root ? this.root.globalCache : (opts.globalCache || null)
|
|
140
|
+
this.primaryKey = this.root ? this.root.primaryKey : (opts.primaryKey || null)
|
|
141
|
+
this.ns = opts.namespace || DEFAULT_NAMESPACE
|
|
223
142
|
|
|
224
|
-
|
|
143
|
+
this.watchers = null
|
|
144
|
+
this.watchIndex = -1
|
|
225
145
|
|
|
226
|
-
|
|
227
|
-
let manifest = { version: this.manifestVersion, signers: [{ publicKey }] } // default manifest
|
|
228
|
-
let key = Hypercore.key(manifest)
|
|
229
|
-
let discoveryKey = crypto.discoveryKey(key)
|
|
146
|
+
this.manifestVersion = 1 // just compat
|
|
230
147
|
|
|
231
|
-
|
|
232
|
-
const manifestV0 = { version: 0, signers: [{ publicKey }] }
|
|
233
|
-
const keyV0 = Hypercore.key(manifestV0)
|
|
234
|
-
const discoveryKeyV0 = crypto.discoveryKey(keyV0)
|
|
148
|
+
this._ongcBound = this._ongc.bind(this)
|
|
235
149
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
key = keyV0
|
|
239
|
-
discoveryKey = discoveryKeyV0
|
|
240
|
-
}
|
|
241
|
-
}
|
|
150
|
+
this.ready().catch(noop)
|
|
151
|
+
}
|
|
242
152
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
discoveryKey
|
|
248
|
-
}
|
|
153
|
+
watch (fn) {
|
|
154
|
+
if (this.watchers === null) {
|
|
155
|
+
this.watchers = new Set()
|
|
156
|
+
this.cores.watch(this)
|
|
249
157
|
}
|
|
250
158
|
|
|
251
|
-
|
|
252
|
-
manifest: null,
|
|
253
|
-
keyPair,
|
|
254
|
-
key: publicKey,
|
|
255
|
-
discoveryKey: crypto.discoveryKey(publicKey)
|
|
256
|
-
}
|
|
159
|
+
this.watchers.add(fn)
|
|
257
160
|
}
|
|
258
161
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
for (const { key: savedKey, value } of core.core.header.userData) {
|
|
262
|
-
if (key === savedKey) return value
|
|
263
|
-
}
|
|
264
|
-
return null
|
|
265
|
-
}
|
|
162
|
+
unwatch (fn) {
|
|
163
|
+
if (this.watchers === null) return
|
|
266
164
|
|
|
267
|
-
|
|
268
|
-
const name = this._getPrereadyUserData(core, USERDATA_NAME_KEY)
|
|
269
|
-
if (!name) return
|
|
165
|
+
this.watchers.delete(fn)
|
|
270
166
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
167
|
+
if (this.watchers.size === 0) {
|
|
168
|
+
this.watchers = null
|
|
169
|
+
this.cores.unwatch(this)
|
|
170
|
+
}
|
|
274
171
|
}
|
|
275
172
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
rw = new RW()
|
|
281
|
-
this._locks.set(id, rw)
|
|
282
|
-
}
|
|
173
|
+
session (opts) {
|
|
174
|
+
const root = this.root || this
|
|
175
|
+
return new Corestore(null, { ...opts, root })
|
|
176
|
+
}
|
|
283
177
|
|
|
284
|
-
|
|
178
|
+
namespace (name, opts) {
|
|
179
|
+
return this.session({ ...opts, namespace: generateNamespace(this.ns, name) })
|
|
285
180
|
}
|
|
286
181
|
|
|
287
|
-
|
|
288
|
-
|
|
182
|
+
_ongc (session) {
|
|
183
|
+
if (session.sessions.length === 0) this.sessions.gc(session.id)
|
|
184
|
+
}
|
|
289
185
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} else {
|
|
296
|
-
await existing.ready().catch(safetyCatch)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
186
|
+
async _getOrSetSeed () {
|
|
187
|
+
const seed = await this.storage.getSeed()
|
|
188
|
+
if (seed !== null) return seed
|
|
189
|
+
return await this.storage.setSeed(this.primaryKey || crypto.randomBytes(32))
|
|
190
|
+
}
|
|
299
191
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
192
|
+
async _open () {
|
|
193
|
+
if (this.root !== null) {
|
|
194
|
+
if (this.root.opened === false) await this.root.ready()
|
|
195
|
+
this.primaryKey = this.root.primaryKey
|
|
196
|
+
return
|
|
305
197
|
}
|
|
306
198
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const storageRoot = getStorageRoot(id)
|
|
310
|
-
const core = new Hypercore(p => this.storage(storageRoot + '/' + p), {
|
|
311
|
-
_preready: this._preready.bind(this),
|
|
312
|
-
notDownloadingLinger: this._notDownloadingLinger,
|
|
313
|
-
inflightRange: this.inflightRange,
|
|
314
|
-
autoClose: true,
|
|
315
|
-
active: false,
|
|
316
|
-
encryptionKey: opts.encryptionKey || null,
|
|
317
|
-
isBlockKey: !!opts.isBlockKey,
|
|
318
|
-
userData,
|
|
319
|
-
manifest,
|
|
320
|
-
key,
|
|
321
|
-
compat: opts.compat,
|
|
322
|
-
cache: opts.cache,
|
|
323
|
-
globalCache: this.globalCache,
|
|
324
|
-
createIfMissing: opts.createIfMissing === false ? false : !opts._discoveryKey,
|
|
325
|
-
keyPair: hasKeyPair ? keyPair : null
|
|
326
|
-
})
|
|
199
|
+
const primaryKey = await this._getOrSetSeed()
|
|
327
200
|
|
|
328
|
-
if (this.
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
} catch {}
|
|
332
|
-
throw new Error('The corestore is closed')
|
|
201
|
+
if (this.primaryKey === null) {
|
|
202
|
+
this.primaryKey = primaryKey
|
|
203
|
+
return
|
|
333
204
|
}
|
|
334
205
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
core.ready().then(() => {
|
|
338
|
-
if (core.closing) return // extra safety here as ready is a tick after open
|
|
339
|
-
if (hasKeyPair) core.setKeyPair(keyPair)
|
|
340
|
-
this._emitCore('core-open', core)
|
|
341
|
-
if (this.passive) return
|
|
342
|
-
|
|
343
|
-
const ondownloading = () => {
|
|
344
|
-
for (const { stream } of this._replicationStreams) {
|
|
345
|
-
core.replicate(stream, { session: true })
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
// when the replicator says we are downloading, answer the call
|
|
349
|
-
core.replicator.ondownloading = ondownloading
|
|
350
|
-
// trigger once if the condition is already true
|
|
351
|
-
if (core.replicator.downloading) ondownloading()
|
|
352
|
-
}, () => {
|
|
353
|
-
this._noCoreCache.set(id, true)
|
|
354
|
-
this.cores.delete(id)
|
|
355
|
-
})
|
|
356
|
-
core.once('close', () => {
|
|
357
|
-
this._emitCore('core-close', core)
|
|
358
|
-
this.cores.delete(id)
|
|
359
|
-
})
|
|
360
|
-
core.on('conflict', (len, fork, proof) => {
|
|
361
|
-
this.emit('conflict', core, len, fork, proof)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
return { from: core, keyPair, manifest, cache: !!opts.cache }
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
async createKeyPair (name, namespace = this._namespace) {
|
|
368
|
-
if (!this.opened) await this.ready()
|
|
369
|
-
|
|
370
|
-
const keyPair = {
|
|
371
|
-
publicKey: b4a.allocUnsafe(sodium.crypto_sign_PUBLICKEYBYTES),
|
|
372
|
-
secretKey: b4a.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
|
206
|
+
if (!b4a.equals(primaryKey, this.primaryKey)) {
|
|
207
|
+
throw new Error('Another corestore is stored here')
|
|
373
208
|
}
|
|
374
|
-
|
|
375
|
-
const seed = deriveSeed(this.primaryKey, namespace, name)
|
|
376
|
-
sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
|
|
377
|
-
|
|
378
|
-
return keyPair
|
|
379
209
|
}
|
|
380
210
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if (opts.cache !== false) {
|
|
386
|
-
opts.cache = opts.cache === true || (this.cache && !opts.cache) ? defaultCache() : opts.cache
|
|
387
|
-
}
|
|
388
|
-
if (this._readonly && opts.writable !== false) {
|
|
389
|
-
opts.writable = false
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
let rw = null
|
|
393
|
-
let id = null
|
|
211
|
+
async _close () {
|
|
212
|
+
const sessions = []
|
|
213
|
+
const hanging = [...this.sessions]
|
|
214
|
+
for (const sess of hanging) sessions.push(sess.close())
|
|
394
215
|
|
|
395
|
-
|
|
396
|
-
...opts,
|
|
397
|
-
globalCache: this.globalCache,
|
|
398
|
-
name: null,
|
|
399
|
-
preload: async () => {
|
|
400
|
-
if (opts.preload) opts = { ...opts, ...(await opts.preload()) }
|
|
401
|
-
if (!this.opened) await this.ready()
|
|
216
|
+
if (this.watchers !== null) this.cores.unwatch(this)
|
|
402
217
|
|
|
403
|
-
|
|
218
|
+
await Promise.all(sessions)
|
|
219
|
+
if (this.root !== null) return
|
|
404
220
|
|
|
405
|
-
|
|
406
|
-
|
|
221
|
+
const cores = []
|
|
222
|
+
for (const core of this.cores) cores.push(core.close())
|
|
223
|
+
await Promise.all(cores)
|
|
224
|
+
await this.storage.close()
|
|
225
|
+
}
|
|
407
226
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
})
|
|
227
|
+
async _attachMaybe (muxer, discoveryKey) {
|
|
228
|
+
if (this.opened === false) await this.ready()
|
|
229
|
+
if (this.cores.get(toHex(discoveryKey)) === null && !(await this.storage.has(discoveryKey))) return
|
|
412
230
|
|
|
413
|
-
this.
|
|
414
|
-
if (this._findingPeersCount > 0) {
|
|
415
|
-
this._findingPeers.push(core.findingPeers())
|
|
416
|
-
}
|
|
231
|
+
const core = this._getCore(discoveryKey, { createIfMissing: false })
|
|
417
232
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
// but the lifecycle for those are pretty short so prob not worth the complexity
|
|
421
|
-
// as _decFindingPeers clear them all.
|
|
422
|
-
this._sessions.delete(core)
|
|
233
|
+
if (!core) return
|
|
234
|
+
if (!core.opened) await core.ready()
|
|
423
235
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (!rw.write.locked) this._locks.delete(id)
|
|
236
|
+
if (!core.replicator.attached(muxer)) {
|
|
237
|
+
core.replicator.attachTo(muxer)
|
|
427
238
|
}
|
|
428
|
-
|
|
429
|
-
core.ready().catch(gc)
|
|
430
|
-
core.once('close', gc)
|
|
431
|
-
|
|
432
|
-
return core
|
|
433
239
|
}
|
|
434
240
|
|
|
435
241
|
replicate (isInitiator, opts) {
|
|
436
|
-
const isExternal = isStream(isInitiator)
|
|
242
|
+
const isExternal = isStream(isInitiator)
|
|
437
243
|
const stream = Hypercore.createProtocolStream(isInitiator, {
|
|
438
244
|
...opts,
|
|
439
|
-
ondiscoverykey:
|
|
245
|
+
ondiscoverykey: discoveryKey => {
|
|
440
246
|
if (this.closing) return
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
if (this._noCoreCache.get(id)) return
|
|
444
|
-
|
|
445
|
-
const core = this.get({ _discoveryKey: discoveryKey, active: false })
|
|
446
|
-
|
|
447
|
-
try {
|
|
448
|
-
await core.ready()
|
|
449
|
-
} catch {
|
|
450
|
-
return
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// remote is asking for the core so we HAVE to answer even if not downloading
|
|
454
|
-
if (!core.closing) core.replicate(stream, { session: true })
|
|
455
|
-
await core.close()
|
|
247
|
+
const muxer = stream.noiseStream.userData
|
|
248
|
+
return this._attachMaybe(muxer, discoveryKey)
|
|
456
249
|
}
|
|
457
250
|
})
|
|
458
251
|
|
|
459
|
-
if (
|
|
252
|
+
if (this.cores.size > 0) {
|
|
460
253
|
const muxer = stream.noiseStream.userData
|
|
254
|
+
const uncork = muxer.uncork.bind(muxer)
|
|
461
255
|
muxer.cork()
|
|
462
|
-
for (const core of this.cores.values()) {
|
|
463
|
-
// If the core is not opened, it will be replicated in preload.
|
|
464
|
-
if (!core.opened || core.closing || !core.replicator.downloading) continue
|
|
465
|
-
core.replicate(stream, { session: true })
|
|
466
|
-
}
|
|
467
|
-
stream.noiseStream.opened.then(() => muxer.uncork())
|
|
468
|
-
}
|
|
469
256
|
|
|
470
|
-
|
|
471
|
-
|
|
257
|
+
for (const core of this.cores) {
|
|
258
|
+
if (!core.replicator.downloading || core.replicator.attached(muxer) || !core.opened) continue
|
|
259
|
+
core.replicator.attachTo(muxer)
|
|
260
|
+
}
|
|
472
261
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
})
|
|
262
|
+
stream.noiseStream.opened.then(uncork)
|
|
263
|
+
}
|
|
476
264
|
|
|
265
|
+
const record = this.streamTracker.add(stream, isExternal)
|
|
266
|
+
stream.once('close', () => this.streamTracker.remove(record))
|
|
477
267
|
return stream
|
|
478
268
|
}
|
|
479
269
|
|
|
480
|
-
|
|
481
|
-
if (
|
|
482
|
-
|
|
270
|
+
get (opts) {
|
|
271
|
+
if (b4a.isBuffer(opts) || typeof opts === 'string') opts = { key: opts }
|
|
272
|
+
if (!opts) opts = {}
|
|
273
|
+
|
|
274
|
+
const conf = {
|
|
275
|
+
preload: null,
|
|
276
|
+
parent: null,
|
|
277
|
+
sessions: null,
|
|
278
|
+
ongc: null,
|
|
279
|
+
core: null,
|
|
280
|
+
active: opts.active !== false,
|
|
281
|
+
encryptionKey: opts.encryptionKey || null,
|
|
282
|
+
isBlockKey: false,
|
|
283
|
+
valueEncoding: opts.valueEncoding || null,
|
|
284
|
+
exclusive: !!opts.exclusive,
|
|
285
|
+
manifest: opts.manifest || null,
|
|
286
|
+
keyPair: opts.keyPair || null,
|
|
287
|
+
onwait: opts.onwait || null,
|
|
288
|
+
wait: opts.wait !== false,
|
|
289
|
+
timeout: opts.timeout || 0,
|
|
290
|
+
draft: !!opts.draft,
|
|
291
|
+
writable: opts.writable
|
|
483
292
|
}
|
|
484
|
-
|
|
293
|
+
|
|
294
|
+
conf.preload = this._preload(opts)
|
|
295
|
+
|
|
296
|
+
return new Hypercore(null, null, conf)
|
|
485
297
|
}
|
|
486
298
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
cache: this.cache,
|
|
491
|
-
writable: !this._readonly,
|
|
492
|
-
_attached: opts && opts.detach === false ? this : null,
|
|
493
|
-
_root: this._root,
|
|
494
|
-
inflightRange: this.inflightRange,
|
|
495
|
-
globalCache: this.globalCache,
|
|
496
|
-
...opts
|
|
497
|
-
})
|
|
498
|
-
if (this === this._root) this._rootStoreSessions.add(session)
|
|
499
|
-
return session
|
|
299
|
+
async createKeyPair (name, ns = this.ns) {
|
|
300
|
+
if (this.opened === false) await this.ready()
|
|
301
|
+
return createKeyPair(this.primaryKey, ns, name)
|
|
500
302
|
}
|
|
501
303
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
304
|
+
async _preload (opts) {
|
|
305
|
+
if (opts.preload) opts = { ...opts, ...(await opts.preload) }
|
|
306
|
+
if (this.opened === false) await this.ready()
|
|
307
|
+
|
|
308
|
+
const discoveryKey = opts.name ? await this.storage.getAlias({ name: opts.name, namespace: this.ns }) : null
|
|
309
|
+
const core = this._getCore(discoveryKey, opts)
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
parent: opts.parent || null,
|
|
313
|
+
sessions: this.sessions.get(core.id),
|
|
314
|
+
ongc: this._ongcBound,
|
|
315
|
+
core,
|
|
316
|
+
encryptionKey: opts.encryptionKey || null,
|
|
317
|
+
isBlockKey: !!opts.isBlockKey
|
|
506
318
|
}
|
|
507
|
-
return Promise.allSettled(closePromises)
|
|
508
319
|
}
|
|
509
320
|
|
|
510
|
-
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
321
|
+
_auth (discoveryKey, opts) {
|
|
322
|
+
const result = {
|
|
323
|
+
keyPair: null,
|
|
324
|
+
key: null,
|
|
325
|
+
discoveryKey,
|
|
326
|
+
manifest: null
|
|
516
327
|
}
|
|
517
|
-
|
|
518
|
-
|
|
328
|
+
|
|
329
|
+
if (opts.name) {
|
|
330
|
+
result.keyPair = createKeyPair(this.primaryKey, this.ns, opts.name)
|
|
331
|
+
} else if (opts.keyPair) {
|
|
332
|
+
result.keyPair = opts.keyPair
|
|
519
333
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
334
|
+
|
|
335
|
+
if (opts.manifest) {
|
|
336
|
+
result.manifest = opts.manifest
|
|
337
|
+
} else if (result.keyPair && !result.discoveryKey) {
|
|
338
|
+
result.manifest = { version: 1, signers: [{ publicKey: result.keyPair.publicKey }] }
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (opts.key) result.key = ID.decode(opts.key)
|
|
342
|
+
else if (result.manifest) result.key = Hypercore.key(result.manifest)
|
|
343
|
+
|
|
344
|
+
if (result.discoveryKey) return result
|
|
345
|
+
|
|
346
|
+
if (opts.discoveryKey) result.discoveryKey = ID.decode(opts.discoveryKey)
|
|
347
|
+
else if (result.key) result.discoveryKey = crypto.discoveryKey(result.key)
|
|
348
|
+
else throw new Error('Could not derive discovery from input')
|
|
349
|
+
|
|
350
|
+
return result
|
|
527
351
|
}
|
|
528
352
|
|
|
529
|
-
|
|
530
|
-
this.
|
|
353
|
+
_hasCore (discoveryKey) {
|
|
354
|
+
return this.cores.get(toHex(discoveryKey)) !== null
|
|
355
|
+
}
|
|
531
356
|
|
|
532
|
-
|
|
357
|
+
_getCore (discoveryKey, opts) {
|
|
358
|
+
const auth = this._auth(discoveryKey, opts)
|
|
359
|
+
|
|
360
|
+
const id = toHex(auth.discoveryKey)
|
|
361
|
+
const existing = this.cores.get(id)
|
|
362
|
+
if (existing) return existing
|
|
363
|
+
|
|
364
|
+
const core = Hypercore.createCore(this.storage, {
|
|
365
|
+
eagerUpgrade: true,
|
|
366
|
+
notDownloadingLinger: opts.notDownloadingLinger,
|
|
367
|
+
allowFork: opts.allowFork !== false,
|
|
368
|
+
inflightRange: opts.inflightRange,
|
|
369
|
+
compat: false, // no compat for now :)
|
|
370
|
+
force: opts.force,
|
|
371
|
+
createIfMissing: opts.createIfMissing,
|
|
372
|
+
discoveryKey: auth.discoveryKey,
|
|
373
|
+
overwrite: opts.overwrite,
|
|
374
|
+
key: auth.key,
|
|
375
|
+
keyPair: auth.keyPair,
|
|
376
|
+
legacy: opts.legacy,
|
|
377
|
+
manifest: auth.manifest,
|
|
378
|
+
globalCache: opts.globalCache || this.globalCache || null,
|
|
379
|
+
alias: opts.name ? { name: opts.name, namespace: this.ns } : null
|
|
380
|
+
})
|
|
533
381
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
await this._attached.close()
|
|
382
|
+
core.onidle = () => {
|
|
383
|
+
core.destroy()
|
|
384
|
+
this.cores.delete(id, core)
|
|
538
385
|
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
386
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
387
|
+
core.replicator.ondownloading = () => {
|
|
388
|
+
this.streamTracker.attachAll(core)
|
|
389
|
+
}
|
|
545
390
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
549
|
-
if (opts.keyPair) {
|
|
550
|
-
opts.publicKey = opts.keyPair.publicKey
|
|
551
|
-
opts.secretKey = opts.keyPair.secretKey
|
|
391
|
+
this.cores.set(id, core)
|
|
392
|
+
return core
|
|
552
393
|
}
|
|
394
|
+
}
|
|
553
395
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (!opts._discoveryKey && (!opts.name && !opts.publicKey && !opts.manifest && !opts.key && !opts.preload)) throw new Error('Must provide either a name or a publicKey')
|
|
559
|
-
return opts
|
|
396
|
+
module.exports = Corestore
|
|
397
|
+
|
|
398
|
+
function isStream (s) {
|
|
399
|
+
return typeof s === 'object' && s && typeof s.pipe === 'function'
|
|
560
400
|
}
|
|
561
401
|
|
|
562
402
|
function generateNamespace (namespace, name) {
|
|
563
403
|
if (!b4a.isBuffer(name)) name = b4a.from(name)
|
|
564
|
-
const out = b4a.
|
|
404
|
+
const out = b4a.allocUnsafeSlow(32)
|
|
565
405
|
sodium.crypto_generichash_batch(out, [namespace, name])
|
|
566
406
|
return out
|
|
567
407
|
}
|
|
@@ -573,19 +413,19 @@ function deriveSeed (primaryKey, namespace, name) {
|
|
|
573
413
|
return out
|
|
574
414
|
}
|
|
575
415
|
|
|
576
|
-
function
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
416
|
+
function createKeyPair (primaryKey, namespace, name) {
|
|
417
|
+
const seed = deriveSeed(primaryKey, namespace, name)
|
|
418
|
+
const buf = b4a.alloc(sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_sign_SECRETKEYBYTES)
|
|
419
|
+
const keyPair = {
|
|
420
|
+
publicKey: buf.subarray(0, sodium.crypto_sign_PUBLICKEYBYTES),
|
|
421
|
+
secretKey: buf.subarray(sodium.crypto_sign_PUBLICKEYBYTES)
|
|
422
|
+
}
|
|
423
|
+
sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed)
|
|
424
|
+
return keyPair
|
|
582
425
|
}
|
|
583
426
|
|
|
584
|
-
|
|
585
|
-
await core.ready()
|
|
586
|
-
return Promise.all(core.sessions.map(s => s.close()))
|
|
587
|
-
}
|
|
427
|
+
function noop () {}
|
|
588
428
|
|
|
589
|
-
function
|
|
590
|
-
return
|
|
429
|
+
function toHex (discoveryKey) {
|
|
430
|
+
return b4a.toString(discoveryKey, 'hex')
|
|
591
431
|
}
|
package/package.json
CHANGED
|
@@ -1,44 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corestore",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "A Hypercore factory that simplifies managing collections of cores.",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js"
|
|
8
|
+
],
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"b4a": "^1.6.7",
|
|
11
|
+
"bare-events": "^2.5.0",
|
|
12
|
+
"hypercore": "^11.0.0",
|
|
13
|
+
"hypercore-crypto": "^3.4.2",
|
|
14
|
+
"hypercore-id-encoding": "^1.3.0",
|
|
15
|
+
"ready-resource": "^1.1.1",
|
|
16
|
+
"sodium-universal": "^4.0.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"brittle": "^3.7.0",
|
|
20
|
+
"rache": "^1.0.0",
|
|
21
|
+
"standard": "^17.1.2",
|
|
22
|
+
"test-tmp": "^1.3.0"
|
|
23
|
+
},
|
|
6
24
|
"scripts": {
|
|
7
25
|
"test": "standard && brittle test/*.js"
|
|
8
26
|
},
|
|
27
|
+
"imports": {
|
|
28
|
+
"events": {
|
|
29
|
+
"bare": "bare-events",
|
|
30
|
+
"default": "events"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
9
33
|
"repository": {
|
|
10
34
|
"type": "git",
|
|
11
|
-
"url": "
|
|
35
|
+
"url": "https://github.com/holepunchto/corestore2.git"
|
|
12
36
|
},
|
|
13
|
-
"
|
|
14
|
-
"corestore"
|
|
15
|
-
],
|
|
16
|
-
"author": "Andrew Osheroff <andrewosh@gmail.com>",
|
|
37
|
+
"author": "Holepunch Inc",
|
|
17
38
|
"license": "MIT",
|
|
18
39
|
"bugs": {
|
|
19
|
-
"url": "https://github.com/holepunchto/
|
|
20
|
-
},
|
|
21
|
-
"homepage": "https://github.com/holepunchto/corestore#readme",
|
|
22
|
-
"files": [
|
|
23
|
-
"index.js",
|
|
24
|
-
"lib/**.js"
|
|
25
|
-
],
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"brittle": "^3.2.2",
|
|
28
|
-
"random-access-memory": "^6.2.0",
|
|
29
|
-
"standard": "^17.1.0",
|
|
30
|
-
"test-tmp": "^1.0.2",
|
|
31
|
-
"rache": "^1.0.0"
|
|
40
|
+
"url": "https://github.com/holepunchto/corestore2/issues"
|
|
32
41
|
},
|
|
33
|
-
"
|
|
34
|
-
"b4a": "^1.6.4",
|
|
35
|
-
"hypercore": "^10.37.10",
|
|
36
|
-
"hypercore-crypto": "^3.4.0",
|
|
37
|
-
"hypercore-id-encoding": "^1.2.0",
|
|
38
|
-
"read-write-mutexify": "^2.1.0",
|
|
39
|
-
"ready-resource": "^1.0.0",
|
|
40
|
-
"safety-catch": "^1.0.1",
|
|
41
|
-
"sodium-universal": "^4.0.0",
|
|
42
|
-
"xache": "^1.1.0"
|
|
43
|
-
}
|
|
42
|
+
"homepage": "https://github.com/holepunchto/corestore2"
|
|
44
43
|
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Holepunch Inc
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
all copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
THE SOFTWARE.
|