Skip to content

Commit 350a08f

Browse files
committed
feat(refs): support deeply nested refs in objects within docs
1 parent 1b84695 commit 350a08f

File tree

4 files changed

+81
-13
lines changed

4 files changed

+81
-13
lines changed

src/index.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createSnapshot, extractRefs, callOnceWithArg } from './utils'
1+
import { createSnapshot, extractRefs, callOnceWithArg, deepGetSplit } from './utils'
22

33
function bindCollection ({
44
vm,
@@ -43,8 +43,10 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
4343
const [data, refs] = extractRefs(snapshot)
4444
obj[key] = data
4545
const refKeys = Object.keys(refs)
46-
if (!refKeys.length) resolve()
46+
if (!refKeys.length) return resolve()
4747
// TODO check if no ref is missing
48+
// TODO max depth param, default to 1?
49+
if (++depth > 3) throw new Error('more than 5 nested refs')
4850
refKeys.forEach(refKey => {
4951
// check if already bound to the same ref -> skip
5052
const sub = subs[refKey]
@@ -53,12 +55,13 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
5355
sub.unbind()
5456
}
5557
// maybe wrap the unbind function to call unbind on every child
58+
const [innerObj, innerKey] = deepGetSplit(obj[key], refKey)
5659
subs[refKey] = {
5760
unbind: subscribeToDocument({
5861
ref,
59-
obj: obj[key],
60-
key: refKey,
61-
depth: depth + 1,
62+
obj: innerObj,
63+
key: innerKey,
64+
depth,
6265
// TODO parentSubs
6366
resolve
6467
}),
@@ -72,8 +75,6 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
7275
}
7376

7477
function subscribeToDocument ({ ref, obj, key, depth, resolve }) {
75-
// TODO max depth param, default to 1?
76-
if (depth > 3) throw new Error('more than 5 nested refs')
7778
const subs = Object.create(null)
7879
const unbind = ref.onSnapshot(doc => {
7980
if (doc.exists) {

src/utils.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@ export function extractRefs (doc, path = '', result = [{}, {}]) {
1818
// TODO handle subpathes?
1919
tot[1][path + key] = ref
2020
} else if (Array.isArray(ref)) {
21-
// TODO hndle array
21+
// TODO handle array
2222
tot[0][key] = ref
2323
} else if (isObject(ref)) {
24-
console.log('isobject omg', key, ref)
2524
tot[0][key] = {}
26-
extractRefs(ref, key + '.', [tot[0][key], tot[1]])
25+
extractRefs(ref, path + key + '.', [tot[0][key], tot[1]])
2726
} else {
2827
tot[0][key] = ref
2928
}
@@ -40,3 +39,16 @@ export function callOnceWithArg (fn, argFn) {
4039
}
4140
}
4241
}
42+
43+
export function deepGetSplit (obj, path) {
44+
const keys = path.split('.')
45+
// We want the containing obj and the last key
46+
// key is the one we're going to bind to
47+
const key = keys.pop()
48+
return [
49+
keys.reduce((res, key) => {
50+
return res[key]
51+
}, obj),
52+
key
53+
]
54+
}

test/refs.spec.js

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ beforeEach(async () => {
1919
await d.update({ ref: c })
2020

2121
vm = new Vue({
22-
render: h => h(),
2322
data: () => ({
2423
a: null,
2524
b: null,
@@ -56,6 +55,50 @@ test('binds refs on documents', async () => {
5655
})
5756
})
5857

58+
test('binds refs nested in documents (objects)', async () => {
59+
const item = collection.doc()
60+
await item.update({
61+
obj: {
62+
ref: c
63+
}
64+
})
65+
await vm.$bind('item', item)
66+
67+
// NOTE same as above
68+
await delay(5)
69+
70+
expect(vm.item).toEqual({
71+
obj: {
72+
ref: { c: true }
73+
}
74+
})
75+
})
76+
77+
test('binds refs deeply nested in documents (objects)', async () => {
78+
const item = collection.doc()
79+
await item.update({
80+
obj: {
81+
nested: {
82+
ref: c
83+
}
84+
}
85+
})
86+
await vm.$bind('item', item)
87+
88+
// NOTE same as above
89+
await delay(5)
90+
91+
expect(vm.item).toEqual({
92+
obj: {
93+
nested: {
94+
ref: {
95+
c: true
96+
}
97+
}
98+
}
99+
})
100+
})
101+
59102
test('update inner ref', async () => {
60103
expect(vm.d).toEqual({
61104
ref: {

test/utils.spec.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,22 @@ test('extract object nested refs from document', () => {
6060
ref: docRef
6161
}
6262
})
63-
console.log(noRefsDoc)
6463
expect(noRefsDoc.obj.ref).toEqual(docRef.path)
65-
console.log(refs)
6664
expect(refs).toEqual({
6765
'obj.ref': docRef
6866
})
6967
})
68+
69+
test('extract deep object nested refs from document', () => {
70+
const [noRefsDoc, refs] = extractRefs({
71+
obj: {
72+
nested: {
73+
ref: docRef
74+
}
75+
}
76+
})
77+
expect(noRefsDoc.obj.nested.ref).toEqual(docRef.path)
78+
expect(refs).toEqual({
79+
'obj.nested.ref': docRef
80+
})
81+
})

0 commit comments

Comments
 (0)