Skip to content

Commit 4c00b6e

Browse files
committed
feat(bind): returns a promise
1 parent 001ff40 commit 4c00b6e

File tree

5 files changed

+83
-44
lines changed

5 files changed

+83
-44
lines changed

src/index.js

+39-22
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { createSnapshot, extractRefs } from './utils'
33
function bindCollection ({
44
vm,
55
key,
6-
collection
6+
collection,
7+
resolve
78
}) {
89
// TODO wait to get all data
910
const array = vm[key] = []
@@ -21,13 +22,18 @@ function bindCollection ({
2122
}
2223
}
2324

25+
let ready
2426
return collection.onSnapshot(({ docChanges }) => {
2527
// console.log('pending', metadata.hasPendingWrites)
2628
// docs.forEach(d => console.log('doc', d, '\n', 'data', d.data()))
2729
docChanges.forEach(c => {
2830
// console.log(c)
2931
change[c.type](c)
3032
})
33+
if (!ready) {
34+
ready = true
35+
resolve(array)
36+
}
3137
}, err => {
3238
console.log('onSnapshot ERR', err)
3339
})
@@ -36,18 +42,24 @@ function bindCollection ({
3642
function bindDocument ({
3743
vm,
3844
key,
39-
document
45+
document,
46+
resolve
4047
}) {
4148
// TODO warning check if key exists?
4249
// TODO create boundRefs object
4350
// const boundRefs = Object.create(null)
4451

52+
let ready
4553
return document.onSnapshot(doc => {
46-
// TODO test doc.exist
47-
// console.log('doc data', doc)
4854
// TODO extract refs
49-
const [data] = extractRefs(createSnapshot(doc))
50-
vm[key] = data
55+
if (doc.exists) {
56+
const [data] = extractRefs(createSnapshot(doc))
57+
vm[key] = data
58+
}
59+
if (!ready) {
60+
ready = true
61+
resolve(vm[key])
62+
}
5163
// TODO bind refs
5264
// const d = doc.data()
5365
// if (!boundRefs[d.path]) {
@@ -64,21 +76,25 @@ function bindDocument ({
6476
}
6577

6678
function bind ({ vm, key, ref }) {
67-
let unbind
68-
if (ref.where) {
69-
unbind = bindCollection({
70-
vm,
71-
key,
72-
collection: ref
73-
})
74-
} else {
75-
unbind = bindDocument({
76-
vm,
77-
key,
78-
document: ref
79-
})
80-
}
81-
vm._firestoreUnbinds[key] = unbind
79+
return new Promise(resolve => {
80+
let unbind
81+
if (ref.where) {
82+
unbind = bindCollection({
83+
vm,
84+
key,
85+
collection: ref,
86+
resolve
87+
})
88+
} else {
89+
unbind = bindDocument({
90+
vm,
91+
key,
92+
document: ref,
93+
resolve
94+
})
95+
}
96+
vm._firestoreUnbinds[key] = unbind
97+
})
8298
}
8399

84100
function install (Vue, options) {
@@ -107,12 +123,13 @@ function install (Vue, options) {
107123

108124
// TODO test if $bind exist and warns
109125
Vue.prototype.$bind = function (key, ref) {
110-
bind({
126+
const promise = bind({
111127
vm: this,
112128
key,
113129
ref
114130
})
115131
this.$firestoreRefs[key] = ref
132+
return promise
116133
}
117134

118135
Vue.prototype.$unbind = function (key) {

test/bind.spec.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Vue.use(Vuefire)
1010

1111
test.beforeEach(async t => {
1212
t.context.collection = db.collection()
13-
t.context.document = t.context.collection.doc()
13+
t.context.document = db.collection().doc()
1414
t.context.vm = new Vue({
1515
render (h) {
1616
return h('ul', this.items && this.items.map(
@@ -28,8 +28,7 @@ test.beforeEach(async t => {
2828
})
2929

3030
test('manually binds a collection', async t => {
31-
const vm = t.context.vm
32-
const collection = t.context.collection
31+
const { vm, collection } = t.context
3332
t.deepEqual(vm.items, null)
3433
await vm.$bind('items', collection)
3534
t.deepEqual(vm.items, [])
@@ -38,11 +37,16 @@ test('manually binds a collection', async t => {
3837
})
3938

4039
test('manually binds a document', async t => {
41-
const vm = t.context.vm
42-
const document = t.context.document
40+
const { vm, document } = t.context
4341
t.deepEqual(vm.item, null)
4442
await vm.$bind('item', document)
4543
t.deepEqual(vm.item, null)
4644
await document.update({ text: 'foo' })
4745
t.deepEqual(vm.item, { text: 'foo' })
4846
})
47+
48+
test('returs a promise', t => {
49+
const { vm, document, collection } = t.context
50+
t.true(vm.$bind('items', collection) instanceof Promise)
51+
t.true(vm.$bind('item', document) instanceof Promise)
52+
})

test/helpers/mock.js

+32-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
export class DocumentSnapshot {
2-
constructor (firestore, key, document) {
2+
constructor (firestore, key, document, exists) {
33
this._firestore = firestore
44
this._key = key
55
this._document = document
6+
this.exists = exists
67
}
78

89
data () {
@@ -16,15 +17,15 @@ export class DocumentSnapshot {
1617

1718
const noop = _ => null
1819

19-
export let id = 0
20+
export let _id = 0
2021
export class Key {
21-
constructor () {
22-
this.id = id++
22+
constructor (v) {
23+
this.v = '' + (v != null ? v : _id++)
2324
}
2425

2526
get path () {
2627
return {
27-
lastSegment: () => this.id
28+
lastSegment: () => this.v
2829
}
2930
}
3031
}
@@ -35,24 +36,31 @@ class DocumentReference {
3536
this.id = id
3637
this.data = data
3738
this.index = index
39+
this.exists = false
3840
this.cb = this.onError = noop
3941
}
4042

4143
onSnapshot (cb, onError) {
4244
this.cb = cb
4345
this.onError = onError
46+
// TODO timeout a cb
47+
setTimeout(() => {
48+
this.cb(new DocumentSnapshot(null, this.id, this.data, this.exists))
49+
}, 0)
4450
return () => {
4551
this.cb = this.onError = noop
4652
}
4753
}
4854

4955
async delete () {
56+
this.exists = false
5057
return this.collection._remove(this.id)
5158
}
5259

5360
async update (data) {
5461
Object.assign(this.data, data)
55-
this.cb(new DocumentSnapshot(null, this.id, this.data))
62+
this.exists = true
63+
this.cb(new DocumentSnapshot(null, this.id, this.data, true))
5664
return this.collection._modify(this.id, this.data)
5765
}
5866
}
@@ -66,14 +74,25 @@ class CollectionReference {
6674
onSnapshot (cb, onError) {
6775
this.cb = cb
6876
this.onError = onError
77+
setTimeout(() => {
78+
// Object.keys(this.data).map((k, i) => console.log(k, 'at', i, this.data[k].data))
79+
this.cb({
80+
docChanges: Object.keys(this.data).map((id, newIndex) => ({
81+
type: 'added',
82+
doc: new DocumentSnapshot(null, new Key(id), this.data[id].data),
83+
newIndex,
84+
oldIndex: -1
85+
}))
86+
})
87+
}, 0)
6988
return () => {
7089
this.cb = this.onError = noop
7190
}
7291
}
7392

7493
async add (data) {
7594
const id = new Key()
76-
this.data[id] = new DocumentReference({
95+
this.data[id.v] = new DocumentReference({
7796
collection: this,
7897
id,
7998
data,
@@ -87,15 +106,15 @@ class CollectionReference {
87106
oldIndex: -1
88107
}]
89108
})
90-
return this.data[id]
109+
return this.data[id.v]
91110
}
92111

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

96115
doc (id) {
97116
id = id || new Key()
98-
return (this.data[id] = this.data[id] || new DocumentReference({
117+
return (this.data[id.v] = this.data[id.v] || new DocumentReference({
99118
collection: this,
100119
id,
101120
data: {},
@@ -104,8 +123,8 @@ class CollectionReference {
104123
}
105124

106125
async _remove (id) {
107-
const ref = this.data[id]
108-
delete this.data[id]
126+
const ref = this.data[id.v]
127+
delete this.data[id.v]
109128
this.cb({
110129
docChanges: [{
111130
doc: new DocumentSnapshot(null, id, ref.data),
@@ -121,8 +140,8 @@ class CollectionReference {
121140
docChanges: [{
122141
type: 'modified',
123142
doc: new DocumentSnapshot(null, id, data),
124-
oldIndex: this.data[id].index,
125-
newIndex: this.data[id].index
143+
oldIndex: this.data[id.v].index,
144+
newIndex: this.data[id.v].index
126145
}]
127146
})
128147
}

test/merging.spec.js

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import test from 'ava'
22
import Vuefire from '../src'
33
import {
44
db,
5-
tick,
65
Vue
76
} from './helpers'
87

test/utils.spec.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import {
44
} from '../src/utils'
55
import {
66
Key,
7-
id,
7+
_id,
88
DocumentSnapshot
99
} from './helpers'
1010

1111
test.beforeEach(t => {
12-
t.context.id = id
12+
t.context.id = _id
1313
t.context.doc = new DocumentSnapshot(null, new Key(), {
1414
n: 42,
1515
is: true,
@@ -19,7 +19,7 @@ test.beforeEach(t => {
1919
})
2020

2121
test('createSnapshot adds an id', t => {
22-
t.is(t.context.snapshot.id, t.context.id)
22+
t.is(t.context.snapshot.id, '' + t.context.id)
2323
})
2424

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

0 commit comments

Comments
 (0)