Skip to content

Instantly share code, notes, and snippets.

@leontastic
Last active September 14, 2016 14:46
Show Gist options
  • Save leontastic/222a18557c1256bc81c991970966974c to your computer and use it in GitHub Desktop.
Save leontastic/222a18557c1256bc81c991970966974c to your computer and use it in GitHub Desktop.
import { EventEmitter } from 'events'
import { assign, assignIn, forEach, set, unset } from 'lodash'
export default class FirebaseReplicator extends EventEmitter {
static all (replicators) {
const emitter = new EventEmitter()
const start = () => {
return Promise.all(replicators.map((rep) => rep.start()))
}
const stop = () => {
replicators.forEach((rep) => rep.stop())
}
replicators.forEach((rep) => {
rep.on('error', (err) => { emitter.emit('error', err) })
})
return assignIn({ start, stop }, emitter)
}
constructor (firebaseRef, handlers) {
super()
this.replicating = false
this.handlers = {}
this.ref = firebaseRef
forEach(handlers, (fn, key) => {
this.handlers[key] = (snap) => {
this.onUpdate()
this.emit(key, snap)
fn(snap)
}
})
}
onUpdate () {
this.emit('update')
}
onError (err) {
this.emit('error', err)
}
start () {
return new Promise((resolve, reject) => {
if (!this.replicating) {
this.ref.once('value', (snap) => {
this.replicating = true
this.handlers.value(snap) // populate target object with initial data
// TODO: stop 'child_added' events for objects received in the 'value' event
this.ref.on('child_added', this.handlers.child_added, this.onError)
this.ref.on('child_changed', this.handlers.child_changed, this.onError)
this.ref.on('child_removed', this.handlers.child_removed, this.onError)
resolve()
}, (err) => {
this.replicating = false
reject(err)
})
} else {
resolve()
}
})
}
stop () {
if (this.replicating) {
this.ref.off('child_added', this.handlers.child_added)
this.ref.off('child_changed', this.handlers.child_changed)
this.ref.off('child_removed', this.handlers.child_removed)
this.replicating = false
}
}
}
const FirebaseReplicatorFactory = function (createHandlers) {
return class extends FirebaseReplicator {
constructor (firebaseRef, dest) {
const handlers = createHandlers(dest)
super(firebaseRef, handlers)
}
}
}
export const FirebaseMemoryReplicator = FirebaseReplicatorFactory(function (dest) {
return {
value: function (snap) { assign(dest, snap.val()) },
child_added: function (snap) { set(dest, snap.key(), snap.val()) },
child_changed: function (snap) { set(dest, snap.key(), snap.val()) },
child_removed: function (snap) { unset(dest, snap.key()) }
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment