Skip to content

Commit

Permalink
feat(bind): returns a promise
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Nov 24, 2017
1 parent 001ff40 commit 4c00b6e
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 44 deletions.
61 changes: 39 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { createSnapshot, extractRefs } from './utils'
function bindCollection ({
vm,
key,
collection
collection,
resolve
}) {
// TODO wait to get all data
const array = vm[key] = []
Expand All @@ -21,13 +22,18 @@ function bindCollection ({
}
}

let ready
return collection.onSnapshot(({ docChanges }) => {
// console.log('pending', metadata.hasPendingWrites)
// docs.forEach(d => console.log('doc', d, '\n', 'data', d.data()))
docChanges.forEach(c => {
// console.log(c)
change[c.type](c)
})
if (!ready) {
ready = true
resolve(array)
}
}, err => {
console.log('onSnapshot ERR', err)
})
Expand All @@ -36,18 +42,24 @@ function bindCollection ({
function bindDocument ({
vm,
key,
document
document,
resolve
}) {
// TODO warning check if key exists?
// TODO create boundRefs object
// const boundRefs = Object.create(null)

let ready
return document.onSnapshot(doc => {
// TODO test doc.exist
// console.log('doc data', doc)
// TODO extract refs
const [data] = extractRefs(createSnapshot(doc))
vm[key] = data
if (doc.exists) {
const [data] = extractRefs(createSnapshot(doc))
vm[key] = data
}
if (!ready) {
ready = true
resolve(vm[key])
}
// TODO bind refs
// const d = doc.data()
// if (!boundRefs[d.path]) {
Expand All @@ -64,21 +76,25 @@ function bindDocument ({
}

function bind ({ vm, key, ref }) {
let unbind
if (ref.where) {
unbind = bindCollection({
vm,
key,
collection: ref
})
} else {
unbind = bindDocument({
vm,
key,
document: ref
})
}
vm._firestoreUnbinds[key] = unbind
return new Promise(resolve => {
let unbind
if (ref.where) {
unbind = bindCollection({
vm,
key,
collection: ref,
resolve
})
} else {
unbind = bindDocument({
vm,
key,
document: ref,
resolve
})
}
vm._firestoreUnbinds[key] = unbind
})
}

function install (Vue, options) {
Expand Down Expand Up @@ -107,12 +123,13 @@ function install (Vue, options) {

// TODO test if $bind exist and warns
Vue.prototype.$bind = function (key, ref) {
bind({
const promise = bind({
vm: this,
key,
ref
})
this.$firestoreRefs[key] = ref
return promise
}

Vue.prototype.$unbind = function (key) {
Expand Down
14 changes: 9 additions & 5 deletions test/bind.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Vue.use(Vuefire)

test.beforeEach(async t => {
t.context.collection = db.collection()
t.context.document = t.context.collection.doc()
t.context.document = db.collection().doc()
t.context.vm = new Vue({
render (h) {
return h('ul', this.items && this.items.map(
Expand All @@ -28,8 +28,7 @@ test.beforeEach(async t => {
})

test('manually binds a collection', async t => {
const vm = t.context.vm
const collection = t.context.collection
const { vm, collection } = t.context
t.deepEqual(vm.items, null)
await vm.$bind('items', collection)
t.deepEqual(vm.items, [])
Expand All @@ -38,11 +37,16 @@ test('manually binds a collection', async t => {
})

test('manually binds a document', async t => {
const vm = t.context.vm
const document = t.context.document
const { vm, document } = t.context
t.deepEqual(vm.item, null)
await vm.$bind('item', document)
t.deepEqual(vm.item, null)
await document.update({ text: 'foo' })
t.deepEqual(vm.item, { text: 'foo' })
})

test('returs a promise', t => {
const { vm, document, collection } = t.context
t.true(vm.$bind('items', collection) instanceof Promise)
t.true(vm.$bind('item', document) instanceof Promise)
})
45 changes: 32 additions & 13 deletions test/helpers/mock.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export class DocumentSnapshot {
constructor (firestore, key, document) {
constructor (firestore, key, document, exists) {
this._firestore = firestore
this._key = key
this._document = document
this.exists = exists
}

data () {
Expand All @@ -16,15 +17,15 @@ export class DocumentSnapshot {

const noop = _ => null

export let id = 0
export let _id = 0
export class Key {
constructor () {
this.id = id++
constructor (v) {
this.v = '' + (v != null ? v : _id++)
}

get path () {
return {
lastSegment: () => this.id
lastSegment: () => this.v
}
}
}
Expand All @@ -35,24 +36,31 @@ class DocumentReference {
this.id = id
this.data = data
this.index = index
this.exists = false
this.cb = this.onError = noop
}

onSnapshot (cb, onError) {
this.cb = cb
this.onError = onError
// TODO timeout a cb
setTimeout(() => {
this.cb(new DocumentSnapshot(null, this.id, this.data, this.exists))
}, 0)
return () => {
this.cb = this.onError = noop
}
}

async delete () {
this.exists = false
return this.collection._remove(this.id)
}

async update (data) {
Object.assign(this.data, data)
this.cb(new DocumentSnapshot(null, this.id, this.data))
this.exists = true
this.cb(new DocumentSnapshot(null, this.id, this.data, true))
return this.collection._modify(this.id, this.data)
}
}
Expand All @@ -66,14 +74,25 @@ class CollectionReference {
onSnapshot (cb, onError) {
this.cb = cb
this.onError = onError
setTimeout(() => {
// Object.keys(this.data).map((k, i) => console.log(k, 'at', i, this.data[k].data))
this.cb({
docChanges: Object.keys(this.data).map((id, newIndex) => ({
type: 'added',
doc: new DocumentSnapshot(null, new Key(id), this.data[id].data),
newIndex,
oldIndex: -1
}))
})
}, 0)
return () => {
this.cb = this.onError = noop
}
}

async add (data) {
const id = new Key()
this.data[id] = new DocumentReference({
this.data[id.v] = new DocumentReference({
collection: this,
id,
data,
Expand All @@ -87,15 +106,15 @@ class CollectionReference {
oldIndex: -1
}]
})
return this.data[id]
return this.data[id.v]
}

// used to check if it's a collection or document ref
where () {}

doc (id) {
id = id || new Key()
return (this.data[id] = this.data[id] || new DocumentReference({
return (this.data[id.v] = this.data[id.v] || new DocumentReference({
collection: this,
id,
data: {},
Expand All @@ -104,8 +123,8 @@ class CollectionReference {
}

async _remove (id) {
const ref = this.data[id]
delete this.data[id]
const ref = this.data[id.v]
delete this.data[id.v]
this.cb({
docChanges: [{
doc: new DocumentSnapshot(null, id, ref.data),
Expand All @@ -121,8 +140,8 @@ class CollectionReference {
docChanges: [{
type: 'modified',
doc: new DocumentSnapshot(null, id, data),
oldIndex: this.data[id].index,
newIndex: this.data[id].index
oldIndex: this.data[id.v].index,
newIndex: this.data[id.v].index
}]
})
}
Expand Down
1 change: 0 additions & 1 deletion test/merging.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import test from 'ava'
import Vuefire from '../src'
import {
db,
tick,
Vue
} from './helpers'

Expand Down
6 changes: 3 additions & 3 deletions test/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {
} from '../src/utils'
import {
Key,
id,
_id,
DocumentSnapshot
} from './helpers'

test.beforeEach(t => {
t.context.id = id
t.context.id = _id
t.context.doc = new DocumentSnapshot(null, new Key(), {
n: 42,
is: true,
Expand All @@ -19,7 +19,7 @@ test.beforeEach(t => {
})

test('createSnapshot adds an id', t => {
t.is(t.context.snapshot.id, t.context.id)
t.is(t.context.snapshot.id, '' + t.context.id)
})

test('id is not enumerable', t => {
Expand Down

0 comments on commit 4c00b6e

Please sign in to comment.