@coboxcoop/space
Version:
a peer-to-peer private and encrypted space
93 lines (78 loc) • 2.49 kB
JavaScript
const Indexer = require('kappa-sparse-indexer')
const Query = require('kappa-view-query')
const sub = require('subleveldown')
const { fromMultifeed } = require('kappa-view-query/util')
const { State } = require('kappa-drive/messages')
const { scopeFeeds, tryDecode } = require('kappa-drive')
const maybe = require('call-me-maybe')
const { EventEmitter } = require('events')
const collect = require('collect-stream')
const crypto = require('@coboxcoop/crypto')
const debug = require('@coboxcoop/logger')('@coboxcoop/space:state-handler')
const INDEXES = [
{ key: 'log', value: [['value', 'timestamp']] },
{ key: 'fil', value: [['value', 'filename'], ['value', 'timestamp']] }
]
class StateHandler extends EventEmitter {
/**
* create a drive state handler
* @constructor
*/
constructor (opts = {}) {
super()
this._id = opts._id || crypto.randomBytes(2).toString('hex')
this.drive = opts.drive
this.core = opts.core
this.feeds = opts.feeds
this.db = opts.db
this._validator = this._validator.bind(this)
this.idx = new Indexer({
db: sub(this.db, 'idx'),
name: this._id
})
this.view = Query(sub(this.db, 'view'), {
indexes: INDEXES,
validator: this._validator,
getMessage: fromMultifeed(this.feeds, {
validator: this._validator
})
})
this.core.use('state', this.idx.source(), this.view)
this.read = this.core.view.state.read
this.feeds.on('feed', (feed) => {
if (this.idx.feed(feed.key)) return
scopeFeeds(feed, (err) => {
if (!err) this.idx.add(feed, { scan: true })
})
})
}
ready (callback) {
return maybe(callback, new Promise((resolve, reject) => {
this.drive.ready((err) => {
if (err) return reject(err)
this._feed = this.drive.metadata
this.core.ready('state', (err) => {
if (err) return reject(err)
return resolve()
})
})
}))
}
query (query, opts = {}) {
if (opts.live) return this.read({ query: [query], live: true, ...opts })
return new Promise((resolve, reject) => {
collect(this.read({ query: [query] }), (err, msgs) => {
if (err) return reject(err)
resolve(msgs)
})
})
}
_validator (msg) {
var value = tryDecode(msg.value)
if (!value) return false
msg.value = value
return msg
}
}
module.exports = (...args) => new StateHandler(...args)
module.exports.StateHandler = StateHandler