Skip to content

Commit 3bcc74b

Browse files
Switch to Hyperdb (#2)
* Switch to Hyperdb * Update schemas * standard * Use correct naming in Schema * Change ops naming
1 parent 94310ab commit 3bcc74b

File tree

11 files changed

+1298
-85
lines changed

11 files changed

+1298
-85
lines changed

index.js

Lines changed: 75 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
const Autobase = require('autobase')
44
const BlindPairing = require('blind-pairing')
5-
const Hyperbee = require('hyperbee')
5+
const HyperDB = require('hyperdb')
66
const Hyperswarm = require('hyperswarm')
77
const ReadyResource = require('ready-resource')
88
const z32 = require('z32')
99
const b4a = require('b4a')
10+
const { Router, dispatch } = require('./spec/hyperdispatch')
11+
const db = require('./spec/db/index.js')
1012

1113
class AutopassPairer extends ReadyResource {
1214
constructor (store, invite, opts = {}) {
1315
super()
14-
1516
this.store = store
1617
this.invite = invite
1718
this.swarm = null
@@ -27,24 +28,21 @@ class AutopassPairer extends ReadyResource {
2728

2829
async _open () {
2930
await this.store.ready()
30-
3131
this.swarm = new Hyperswarm({
3232
keyPair: await this.store.createKeyPair('hyperswarm'),
3333
bootstrap: this.bootstrap
3434
})
3535

36-
const store = this.store // we null this when passing it on, so avoid a nullptr
36+
const store = this.store
3737
this.swarm.on('connection', (connection, peerInfo) => {
3838
store.replicate(connection)
3939
})
4040

4141
this.pairing = new BlindPairing(this.swarm)
42-
4342
const core = Autobase.getLocalCore(this.store)
4443
await core.ready()
4544
const key = core.key
4645
await core.close()
47-
4846
this.candidate = this.pairing.addCandidate({
4947
invite: z32.decode(this.invite),
5048
userData: key,
@@ -59,12 +57,23 @@ class AutopassPairer extends ReadyResource {
5957
}
6058
this.swarm = null
6159
this.store = null
62-
if (this.onresolve) this.onresolve(this.pass)
60+
if (this.onresolve) this._whenWritable()
6361
this.candidate.close().catch(noop)
6462
}
6563
})
6664
}
6765

66+
_whenWritable () {
67+
if (this.pass.base.writable) return
68+
const check = () => {
69+
if (this.pass.base.writable) {
70+
this.pass.base.off('update', check)
71+
this.onresolve(this.pass)
72+
}
73+
}
74+
this.pass.base.on('update', check)
75+
}
76+
6877
async _close () {
6978
if (this.candidate !== null) {
7079
await this.candidate.close()
@@ -96,7 +105,7 @@ class AutopassPairer extends ReadyResource {
96105
class Autopass extends ReadyResource {
97106
constructor (corestore, opts = {}) {
98107
super()
99-
108+
this.router = new Router()
100109
this.store = corestore
101110
this.swarm = opts.swarm || null
102111
this.base = null
@@ -105,6 +114,26 @@ class Autopass extends ReadyResource {
105114
this.pairing = null
106115
this.replicate = opts.replicate !== false
107116
this.debug = !!opts.key
117+
// Register handlers for commands
118+
this.router.add('@autopass/remove-writer', async (data, context) => {
119+
await context.base.removeWriter(data.key)
120+
})
121+
122+
this.router.add('@autopass/add-writer', async (data, context) => {
123+
await context.base.addWriter(data.key)
124+
})
125+
126+
this.router.add('@autopass/put', async (data, context) => {
127+
await context.view.insert('@autopass/records', data)
128+
})
129+
130+
this.router.add('@autopass/del', async (data, context) => {
131+
await context.view.delete('@autopass/records', { key: data.key })
132+
})
133+
134+
this.router.add('@autopass/add-invite', async (data, context) => {
135+
await context.view.insert('@autopass/invite', data)
136+
})
108137

109138
this._boot(opts)
110139
this.ready().catch(noop)
@@ -117,44 +146,33 @@ class Autopass extends ReadyResource {
117146
this.base = new Autobase(this.store, key, {
118147
encrypt: true,
119148
encryptionKey,
120-
valueEncoding: 'json',
121149
open (store) {
122-
return new Hyperbee(store.get('view'), {
150+
return HyperDB.bee(store.get('view'), db, {
123151
extension: false,
124-
keyEncoding: 'utf-8',
125-
valueEncoding: 'json'
152+
autoUpdate: true
126153
})
127154
},
128155
// New data blocks will be added using the apply function
129-
async apply (nodes, view, base) {
130-
for (const node of nodes) {
131-
const op = node.value
132-
133-
// Add support for adding other peers as a writer to the base
134-
if (op.type === 'addWriter') {
135-
await base.addWriter(z32.decode(op.key))
136-
} else if (op.type === 'removeWriter') {
137-
await base.removeWriter(z32.decode(op.key))
138-
} else if (op.type === 'addRecord') {
139-
// This adds a new record
140-
await view.put(op.key, op.value)
141-
} else if (op.type === 'removeRecord') {
142-
// Remove an existing record
143-
await view.del(op.key)
144-
}
145-
}
146-
}
156+
apply: this._apply.bind(this)
147157
})
148158

149-
this.base.on('update', () => this.emit('update'))
159+
this.base.on('update', () => {
160+
this.emit('update')
161+
})
162+
}
163+
164+
async _apply (nodes, view, base) {
165+
for (const node of nodes) {
166+
await this.router.dispatch(node.value, { view, base })
167+
}
168+
await view.flush()
150169
}
151170

152171
async _open () {
153172
await this.base.ready()
154173
if (this.replicate) await this._replicate()
155174
}
156175

157-
// Close the base
158176
async _close () {
159177
if (this.swarm) {
160178
await this.member.close()
@@ -164,23 +182,18 @@ class Autopass extends ReadyResource {
164182
await this.base.close()
165183
}
166184

167-
// Need this key to become a writer
168185
get writerKey () {
169186
return this.base.local.key
170187
}
171188

172-
// Return bootstrap key of the base
173-
// This is what other peers should use to bootstrap the base from
174189
get key () {
175190
return this.base.key
176191
}
177192

178-
// Find peers in Hyperswarm using this
179193
get discoveryKey () {
180194
return this.base.discoveryKey
181195
}
182196

183-
// Encryption key for the base
184197
get encryptionKey () {
185198
return this.base.encryptionKey
186199
}
@@ -191,101 +204,79 @@ class Autopass extends ReadyResource {
191204

192205
async createInvite (opts) {
193206
if (this.opened === false) await this.ready()
194-
const existing = await this.get('autopass/invite')
195-
if (existing) return existing.invite
207+
const existing = await this.base.view.findOne('@autopass/invite', {})
208+
if (existing) {
209+
return z32.encode(existing.invite)
210+
}
196211
const { id, invite, publicKey, expires } = BlindPairing.createInvite(this.base.key)
197-
const record = { id: z32.encode(id), invite: z32.encode(invite), publicKey: z32.encode(publicKey), expires }
198-
await this.add('autopass/invite', record)
199-
return record.invite
212+
213+
const record = { id, invite, publicKey, expires }
214+
await this.base.append(dispatch('@autopass/add-invite', record))
215+
return z32.encode(record.invite)
200216
}
201217

202-
// Get data of all indexes in the base
203218
list (opts) {
204-
return this.base.view.createReadStream(opts)
219+
return this.base.view.find('@autopass/records', {})
205220
}
206221

207-
// Get data stored in a specific key
208222
async get (key) {
209-
const node = await this.base.view.get(key)
210-
if (node === null) return null
211-
return node.value
223+
const data = await this.base.view.get('@autopass/records', { key })
224+
if (data === null) {
225+
return null
226+
}
227+
return data.value
212228
}
213229

214-
// Add a peer as a writer
215230
async addWriter (key) {
216-
await this.base.append({
217-
type: 'addWriter',
218-
key: b4a.isBuffer(key) ? z32.encode(key) : key
219-
})
220-
231+
await this.base.append(dispatch('@autopass/add-writer', { key: b4a.isBuffer(key) ? key : b4a.from(key) }))
221232
return true
222233
}
223234

224-
// To later add removeWriter
225235
async removeWriter (key) {
226-
await this.base.append({
227-
type: 'removeWriter',
228-
key: b4a.isBuffer(key) ? z32.encode(key) : key
229-
})
236+
await this.base.append(dispatch('@autopass/remove-writer', { key: b4a.isBuffer(key) ? key : b4a.from(key) }))
230237
}
231238

232-
// Check if the base is writable
233239
get writable () {
234240
return this.base.writable
235241
}
236242

237-
// Start Replicating the base across peers
238243
async _replicate () {
244+
await this.base.ready()
239245
if (this.swarm === null) {
240246
this.swarm = new Hyperswarm({
241247
keyPair: await this.store.createKeyPair('hyperswarm'),
242248
bootstrap: this.bootstrap
243249
})
244-
245250
this.swarm.on('connection', (connection, peerInfo) => {
246251
this.store.replicate(connection)
247252
})
248253
}
249254
this.pairing = new BlindPairing(this.swarm)
250-
251255
this.member = this.pairing.addMember({
252256
discoveryKey: this.base.discoveryKey,
253257
onadd: async (candidate) => {
254-
const id = z32.encode(candidate.inviteId)
255-
const inv = await this.get('autopass/invite')
256-
257-
if (inv.id !== id) return
258-
259-
candidate.open(z32.decode(inv.publicKey))
260-
258+
const id = candidate.inviteId
259+
const inv = await this.base.view.findOne('@autopass/invite', {})
260+
if (!b4a.equals(inv.id, id)) {
261+
return
262+
}
263+
candidate.open(inv.publicKey)
261264
await this.addWriter(candidate.userData)
262-
263265
candidate.confirm({
264266
key: this.base.key,
265267
encryptionKey: this.base.encryptionKey
266268
})
267269
}
268270
})
269-
270271
this.swarm.join(this.base.discoveryKey)
271272
}
272273

273-
// Append a key/value to the base
274274
async add (key, value) {
275-
await this.base.append({
276-
type: 'addRecord',
277-
key,
278-
value
279-
})
275+
await this.base.append(dispatch('@autopass/put', { key, value }))
280276
}
281277

282-
// Remove a key pair
283278
async remove (key) {
284-
await this.base.append({
285-
type: 'removeRecord',
286-
key,
287-
value: null
288-
})
279+
await this.base.append(dispatch('@autopass/del', { key }))
289280
}
290281
} // end class
291282

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
"autobase": "^6.5.12",
2020
"b4a": "^1.6.7",
2121
"blind-pairing": "^2.3.1",
22-
"hyperbee": "^2.20.7",
22+
"compact-encoding": "^2.16.0",
23+
"hyperbee": "^2.21.2",
24+
"hypercore": "^10.38.2",
25+
"hyperdb": "^4.8.0",
26+
"hyperdispatch": "^1.0.2",
27+
"hyperschema": "^1.7.2",
2328
"hyperswarm": "^4.8.4",
2429
"ready-resource": "^1.1.1"
2530
}

0 commit comments

Comments
 (0)