Skip to content

Commit c1a1865

Browse files
committed
feat(support document binding):
1 parent 05980a0 commit c1a1865

File tree

6 files changed

+115
-19
lines changed

6 files changed

+115
-19
lines changed

src/index.js

+39-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { createSnapshot } from './utils'
1+
import { createSnapshot, extractRefs } from './utils'
22

3-
function bindCollection({
3+
function bindCollection ({
44
vm,
55
key,
66
collection,
@@ -34,6 +34,38 @@ function bindCollection({
3434

3535
}
3636

37+
function bindDocument ({
38+
vm,
39+
key,
40+
document,
41+
}) {
42+
// TODO warning check if key exists?
43+
const boundRefs = Object.create(null)
44+
45+
const unbind = document.onSnapshot((doc) => {
46+
// TODO test doc.exist
47+
console.log('doc data', doc)
48+
const [data, refs] = extractRefs(createSnapshot(doc))
49+
vm[key] = data
50+
return
51+
// TODO bind refs
52+
const d = doc.data()
53+
if (!boundRefs[d.path]) {
54+
console.log('bound ref', d.path)
55+
boundRefs[d.path] = d.onSnapshot((doc) => {
56+
console.log('ref snap', doc)
57+
}, err => console.log('onSnapshot ref ERR', err))
58+
}
59+
}, err => {
60+
console.log('onSnapshot ERR' ,err)
61+
})
62+
63+
return () => {
64+
// TODO unbind all from boundRefs
65+
return unbind()
66+
}
67+
}
68+
3769
function install (Vue, options) {
3870
Vue.mixin({
3971
created () {
@@ -48,7 +80,11 @@ function install (Vue, options) {
4880
collection: ref,
4981
})
5082
} else {
51-
// TODO
83+
bindDocument({
84+
vm: this,
85+
key,
86+
document: ref,
87+
})
5288
}
5389
})
5490
}

src/utils.js

+15
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,18 @@ export function createSnapshot (doc) {
44
value: doc.id,
55
})
66
}
7+
8+
export function extractRefs (doc) {
9+
return Object.keys(doc).reduce((tot, key) => {
10+
const ref = doc[key]
11+
if (typeof ref.isEqual === 'function') {
12+
tot[0][key] = null
13+
// TODO handle subpathes?
14+
tot[1][key] = ref
15+
} else {
16+
// TODO recursive check
17+
tot[0][key] = ref
18+
}
19+
return tot
20+
}, [{}, {}])
21+
}

test/collection.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ test('delets items', async t => {
4545
})
4646

4747
test('update items', async t => {
48-
const doc = await t.context.collection.add({ text: 'foo' })
48+
const doc = await t.context.collection.add({ text: 'foo', more: true })
4949
await doc.update({ text: 'bar' })
50-
t.deepEqual(t.context.vm.items[0], { text: 'bar' })
50+
t.deepEqual(t.context.vm.items[0], { text: 'bar', more: true })
5151
})
5252

5353
test('add properties', async t => {

test/document.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import test from 'ava'
2+
import Vuefire from '../src'
3+
import {
4+
createSnapshot
5+
} from '../src/utils'
6+
import {
7+
db,
8+
tick,
9+
Vue
10+
} from './helpers'
11+
12+
Vue.use(Vuefire)
13+
14+
test.beforeEach(async t => {
15+
t.context.collection = db.collection()
16+
t.context.document = t.context.collection.doc()
17+
t.context.vm = new Vue({
18+
render (h) {
19+
return h('ul', this.items.map(
20+
item => h('li', [item])
21+
))
22+
},
23+
// purposely set items as null
24+
// but it's a good practice to set it to an empty array
25+
data: () => ({
26+
items: null,
27+
item: null,
28+
}),
29+
firestore: {
30+
items: t.context.collection,
31+
item: t.context.document
32+
}
33+
}).$mount()
34+
await tick()
35+
})
36+
37+
test('binds a document', t => {
38+
t.deepEqual(t.context.vm.item, null)
39+
})
40+
41+
test('updates a document', async t => {
42+
await t.context.document.update({ foo: 'foo' })
43+
t.deepEqual(t.context.vm.item, { foo: 'foo' })
44+
await t.context.document.update({ bar: 'bar' })
45+
t.deepEqual(t.context.vm.item, { foo: 'foo', bar: 'bar' })
46+
})

test/helpers/mock.js

+8
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,22 @@ class DocumentReference {
2727
this.id = id
2828
this.data = data
2929
this.index = index
30+
this.cb = this.onError = noop
3031
}
3132

33+
onSnapshot (cb, onError) {
34+
this.cb = cb
35+
this.onError = onError
36+
}
37+
38+
3239
async delete () {
3340
return this.collection._remove(this.id)
3441
}
3542

3643
async update (data) {
3744
Object.assign(this.data, data)
45+
this.cb(new DocumentSnapshot(null, this.id, this.data))
3846
return this.collection._modify(this.id, this.data)
3947
}
4048
}

test/index.js

+5-14
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ test.beforeEach(async t => {
2222
},
2323
// purposely set items as null
2424
// but it's a good practice to set it to an empty array
25-
data: () => ({ items: null }),
25+
data: () => ({
26+
items: null,
27+
item: null,
28+
}),
2629
firestore: {
2730
items: t.context.collection,
2831
item: t.context.document
@@ -31,22 +34,10 @@ test.beforeEach(async t => {
3134
await tick()
3235
})
3336

34-
test('detects collections', async t => {
35-
await t.context.document.update({ foo: 'foo' })
36-
t.deepEqual(t.context.vm.item, { foo: 'foo' })
37-
})
38-
39-
test('detects documents', async t => {
40-
await t.context.collection.add({ foo: 'foo' })
41-
t.deepEqual(t.context.vm.items, [{ foo: 'foo' }])
42-
})
43-
4437
test('does nothing with no firestore', t => {
4538
const vm = new Vue({
4639
render (h) {
47-
return h('ul', this.items.map(
48-
item => h('li', [item])
49-
))
40+
return h('p', 'eh')
5041
},
5142
data: () => ({ items: null }),
5243
})

0 commit comments

Comments
 (0)