key-collection
Version:
Hyperdb-based collection of 32-byte keys
101 lines (80 loc) • 2.19 kB
JavaScript
const ReadyResource = require('ready-resource')
const HyperDB = require('hyperdb')
const IdEnc = require('hypercore-id-encoding')
const spec = require('./spec/hyperdb')
class KeyCollection extends ReadyResource {
constructor (core) {
super()
this.db = HyperDB.bee(core, spec, { autoUpdate: true }) // TODO: needed? (we only update through this class)
}
get key () {
return this.db.core.key
}
get discoveryKey () {
return this.db.core.discoveryKey
}
async _open () {
await this.db.ready()
}
async _close () {
await this.db.close()
}
async toMap () {
if (!this.opened) await this.ready()
const res = new Map()
for await (const entry of this.db.find('@key-collection/key-entries')) {
res.set(normKey(entry.key), { name: entry.name })
}
return res
}
// WARNING: not safe to call multiple times in parallel
async sync (desiredState) {
if (!this.opened) await this.ready()
desiredState = normKeys(desiredState)
const desiredKeys = new Set([...desiredState.keys()])
const existingEntries = await this.toMap()
const toDel = new Set()
const toAdd = new Set()
for (const key of existingEntries.keys()) {
if (!desiredKeys.has(key)) toDel.add(key)
}
for (const key of desiredState.keys()) {
if (!existingEntries.has(key)) toAdd.add(key)
}
const tx = this.db.transaction()
const proms = []
for (const key of toAdd) {
proms.push(
tx.insert(
'@key-collection/key-entries',
{ key: IdEnc.decode(key), ...desiredState.get(key) }
)
)
}
for (const key of toDel) {
proms.push(
tx.delete(
'@key-collection/key-entries',
{ key: IdEnc.decode(key) }
)
)
}
await Promise.all(proms)
await tx.flush()
}
static normKey (key) {
return normKey(key)
}
}
function normKey (key) {
return IdEnc.normalize(key)
}
function normKeys (desiredState) {
const res = new Map()
for (const [key, value] of desiredState) {
const name = value.name || ''
res.set(normKey(key), { name })
}
return res
}
module.exports = KeyCollection