Skip to content

Commit

Permalink
feat(refs): wait for refs when resolving $bind promise
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Dec 11, 2017
1 parent e963e54 commit 5d37389
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 22 deletions.
39 changes: 17 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createSnapshot, extractRefs } from './utils'
import { createSnapshot, extractRefs, callOnceWithArg } from './utils'

function bindCollection ({
vm,
Expand Down Expand Up @@ -38,12 +38,14 @@ function bindCollection ({
}, reject)
}

function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }) {
function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0, resolve }) {
// TODO extract refs
const [data, refs] = extractRefs(snapshot)
obj[key] = data
const refKeys = Object.keys(refs)
if (!refKeys.length) resolve()
// TODO check if no ref is missing
Object.keys(refs).forEach(refKey => {
refKeys.forEach(refKey => {
// check if already bound to the same ref -> skip
const sub = subs[refKey]
const ref = refs[refKey]
Expand All @@ -56,7 +58,8 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }
ref,
obj: obj[key],
key: refKey,
depth: depth + 1
depth: depth + 1,
resolve
}),
path: ref.path
}
Expand All @@ -67,13 +70,13 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0 }
})
}

function subscribeToDocument ({ ref, obj, key, depth }) {
function subscribeToDocument ({ ref, obj, key, depth, resolve }) {
// TODO max depth param, default to 1?
if (depth > 3) throw new Error('more than 5 nested refs')
const subs = Object.create(null)
return ref.onSnapshot(doc => {
if (doc.exists) {
updateDataFromDocumentSnapshot({ snapshot: createSnapshot(doc), obj, key, subs, depth })
updateDataFromDocumentSnapshot({ snapshot: createSnapshot(doc), obj, key, subs, depth, resolve })
} else {
obj[key] = null
}
Expand All @@ -88,33 +91,25 @@ function bindDocument ({
reject
}) {
// TODO warning check if key exists?
// TODO create boundRefs object
// const boundRefs = Object.create(null)

let ready
const subs = Object.create(null)
// bind here the function so it can be resolve anywhere
// this is specially useful for refs
resolve = callOnceWithArg(resolve, () => vm[key])
return document.onSnapshot(doc => {
if (doc.exists) {
updateDataFromDocumentSnapshot({
snapshot: createSnapshot(doc),
obj: vm,
key,
subs
subs,
resolve
})
} else {
resolve()
}
// TODO should resolve be called when all refs are bound?
if (!ready) {
ready = true
resolve(vm[key])
}
// TODO bind refs
// const d = doc.data()
// if (!boundRefs[d.path]) {
// console.log('bound ref', d.path)
// boundRefs[d.path] = d.onSnapshot((doc) => {
// console.log('ref snap', doc)
// }, err => console.log('onSnapshot ref ERR', err))
// }
// TODO resolve when does not exist ?
}, reject)

// TODO return a custom unbind function that unbind all refs
Expand Down
10 changes: 10 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,13 @@ export function extractRefs (doc) {
return tot
}, [{}, {}])
}

export function callOnceWithArg (fn, argFn) {
let called
return () => {
if (!called) {
called = true
return fn(argFn())
}
}
}
15 changes: 15 additions & 0 deletions test/bind.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,18 @@ test('unbinds previously bound refs', async () => {
expect(vm.$firestoreRefs.item).toBe(doc2)
expect(vm.item).toEqual({ bar: 'bar' })
})

test('resolves the promise when refs are resolved in a document', async () => {
const a = db.collection().doc()
await a.update({ a: true })
await document.update({ ref: a })

await vm.$bind('item', document)
expect(vm.item).toEqual({ ref: { a: true }})
})

test('resolves the promise when the document does not exist', async () => {
expect(vm.item).toEqual(null)
await vm.$bind('item', document)
expect(vm.item).toBe(null)
})

0 comments on commit 5d37389

Please sign in to comment.