Skip to content

Commit

Permalink
feat(refs): support deeply nested refs in objects within docs
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Dec 24, 2017
1 parent 1b84695 commit 350a08f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 13 deletions.
15 changes: 8 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createSnapshot, extractRefs, callOnceWithArg } from './utils'
import { createSnapshot, extractRefs, callOnceWithArg, deepGetSplit } from './utils'

function bindCollection ({
vm,
Expand Down Expand Up @@ -43,8 +43,10 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
const [data, refs] = extractRefs(snapshot)
obj[key] = data
const refKeys = Object.keys(refs)
if (!refKeys.length) resolve()
if (!refKeys.length) return resolve()
// TODO check if no ref is missing
// TODO max depth param, default to 1?
if (++depth > 3) throw new Error('more than 5 nested refs')
refKeys.forEach(refKey => {
// check if already bound to the same ref -> skip
const sub = subs[refKey]
Expand All @@ -53,12 +55,13 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
sub.unbind()
}
// maybe wrap the unbind function to call unbind on every child
const [innerObj, innerKey] = deepGetSplit(obj[key], refKey)
subs[refKey] = {
unbind: subscribeToDocument({
ref,
obj: obj[key],
key: refKey,
depth: depth + 1,
obj: innerObj,
key: innerKey,
depth,
// TODO parentSubs
resolve
}),
Expand All @@ -72,8 +75,6 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
}

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)
const unbind = ref.onSnapshot(doc => {
if (doc.exists) {
Expand Down
18 changes: 15 additions & 3 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ export function extractRefs (doc, path = '', result = [{}, {}]) {
// TODO handle subpathes?
tot[1][path + key] = ref
} else if (Array.isArray(ref)) {
// TODO hndle array
// TODO handle array
tot[0][key] = ref
} else if (isObject(ref)) {
console.log('isobject omg', key, ref)
tot[0][key] = {}
extractRefs(ref, key + '.', [tot[0][key], tot[1]])
extractRefs(ref, path + key + '.', [tot[0][key], tot[1]])
} else {
tot[0][key] = ref
}
Expand All @@ -40,3 +39,16 @@ export function callOnceWithArg (fn, argFn) {
}
}
}

export function deepGetSplit (obj, path) {
const keys = path.split('.')
// We want the containing obj and the last key
// key is the one we're going to bind to
const key = keys.pop()
return [
keys.reduce((res, key) => {
return res[key]
}, obj),
key
]
}
45 changes: 44 additions & 1 deletion test/refs.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ beforeEach(async () => {
await d.update({ ref: c })

vm = new Vue({
render: h => h(),
data: () => ({
a: null,
b: null,
Expand Down Expand Up @@ -56,6 +55,50 @@ test('binds refs on documents', async () => {
})
})

test('binds refs nested in documents (objects)', async () => {
const item = collection.doc()
await item.update({
obj: {
ref: c
}
})
await vm.$bind('item', item)

// NOTE same as above
await delay(5)

expect(vm.item).toEqual({
obj: {
ref: { c: true }
}
})
})

test('binds refs deeply nested in documents (objects)', async () => {
const item = collection.doc()
await item.update({
obj: {
nested: {
ref: c
}
}
})
await vm.$bind('item', item)

// NOTE same as above
await delay(5)

expect(vm.item).toEqual({
obj: {
nested: {
ref: {
c: true
}
}
}
})
})

test('update inner ref', async () => {
expect(vm.d).toEqual({
ref: {
Expand Down
16 changes: 14 additions & 2 deletions test/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,22 @@ test('extract object nested refs from document', () => {
ref: docRef
}
})
console.log(noRefsDoc)
expect(noRefsDoc.obj.ref).toEqual(docRef.path)
console.log(refs)
expect(refs).toEqual({
'obj.ref': docRef
})
})

test('extract deep object nested refs from document', () => {
const [noRefsDoc, refs] = extractRefs({
obj: {
nested: {
ref: docRef
}
}
})
expect(noRefsDoc.obj.nested.ref).toEqual(docRef.path)
expect(refs).toEqual({
'obj.nested.ref': docRef
})
})

0 comments on commit 350a08f

Please sign in to comment.