From 3467215935145a91225fedfe4dadf88d1b842328 Mon Sep 17 00:00:00 2001 From: Scott Geary Date: Thu, 15 Aug 2019 13:03:43 +1000 Subject: [PATCH 1/2] Add wait option for RTDB and Firestore --- .../vuefire-core/src/firestore/index.ts | 33 ++++++++++++++----- .../@posva/vuefire-core/src/rtdb/index.ts | 26 ++++++++++----- packages/vuexfire/src/firestore.ts | 15 +++++++-- packages/vuexfire/src/rtdb.ts | 15 +++++++-- 4 files changed, 65 insertions(+), 24 deletions(-) diff --git a/packages/@posva/vuefire-core/src/firestore/index.ts b/packages/@posva/vuefire-core/src/firestore/index.ts index 3446a972..1c40f8b4 100644 --- a/packages/@posva/vuefire-core/src/firestore/index.ts +++ b/packages/@posva/vuefire-core/src/firestore/index.ts @@ -5,6 +5,7 @@ import { firestore } from 'firebase' export interface FirestoreOptions { maxRefDepth?: number reset?: boolean | (() => any) + wait?: boolean serialize?: FirestoreSerializer } @@ -13,6 +14,7 @@ const DEFAULT_OPTIONS: Required = { maxRefDepth: 2, reset: true, serialize: createSnapshot, + wait: false, } export { DEFAULT_OPTIONS as firestoreOptions } @@ -187,7 +189,8 @@ export function bindCollection( const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) // fill default values // TODO support pathes? nested.obj.list (walkSet) // NOTE use ops object - const array = ops.set(vm, key, []) + let array: any[] = options.wait ? [] : ops.set(vm, key, []) + // const array = (vm[key] = []) const originalResolve = resolve let isResolved: boolean @@ -204,6 +207,7 @@ export function bindCollection( const [data, refs] = extractRefs(snapshot) // NOTE use ops ops.add(array, newIndex, data) + // array.splice(newIndex, 0, data) subscribeToRefs( { @@ -228,7 +232,7 @@ export function bindCollection( const [data, refs] = extractRefs(snapshot, oldData) // NOTE use ops ops.add(array, newIndex, data) - // array.splice(newIndex, 0, data) + subscribeToRefs( { refs, @@ -277,6 +281,9 @@ export function bindCollection( resolve = ({ id }) => { if (id in validDocs) { if (++count >= expectedItems) { + if (options.wait) { + array = ops.set(vm, key, array) + } originalResolve(vm[key]) // reset resolve to noop resolve = () => {} @@ -284,19 +291,26 @@ export function bindCollection( } } } + docChanges.forEach(c => { change[c.type](c) }) // resolves when array is empty - if (!docChanges.length) resolve() + if (!docChanges.length) { + if (options.wait) { + array = ops.set(vm, key, array) + } + resolve() + } }, reject) // TODO: we could allow an argument to unbind to override reset - return () => { + return (reset?: FirestoreOptions['reset']) => { unbind() - if (options.reset !== false) { - const value = typeof options.reset === 'function' ? options.reset() : [] + const resetOption = reset === undefined ? options.reset : reset + if (resetOption !== false) { + const value = typeof resetOption === 'function' ? resetOption() : [] ops.set(vm, key, value) } arraySubs.forEach(unsubscribeAll) @@ -344,10 +358,11 @@ export function bindDocument( } }, reject) - return () => { + return (reset?: FirestoreOptions['reset']) => { unbind() - if (options.reset !== false) { - const value = typeof options.reset === 'function' ? options.reset() : null + const resetOption = reset === undefined ? options.reset : reset + if (resetOption !== false) { + const value = typeof resetOption === 'function' ? resetOption() : [] ops.set(vm, key, value) } unsubscribeAll(subs) diff --git a/packages/@posva/vuefire-core/src/rtdb/index.ts b/packages/@posva/vuefire-core/src/rtdb/index.ts index a6505f5e..c786460e 100644 --- a/packages/@posva/vuefire-core/src/rtdb/index.ts +++ b/packages/@posva/vuefire-core/src/rtdb/index.ts @@ -4,11 +4,13 @@ import { OperationsType } from '../shared' export interface RTDBOptions { reset?: boolean | (() => any) serialize?: RTDBSerializer + wait?: boolean } const DEFAULT_OPTIONS: Required = { reset: true, serialize: createRecordFromRTDBSnapshot, + wait: false, } export { DEFAULT_OPTIONS as rtdbOptions } @@ -45,10 +47,11 @@ export function rtdbBindAsObject( ) document.once('value', resolve) - return () => { + return (reset?: RTDBOptions['reset']) => { document.off('value', listener) - if (options.reset !== false) { - const value = typeof options.reset === 'function' ? options.reset() : null + const resetOption = reset === undefined ? options.reset : reset + if (resetOption !== false) { + const value = typeof resetOption === 'function' ? resetOption() : null ops.set(vm, key, value) } } @@ -69,8 +72,7 @@ export function rtdbBindAsArray( extraOptions: RTDBOptions = DEFAULT_OPTIONS ) { const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) - const array: any[] = [] - ops.set(vm, key, array) + const array: any[] = options.wait ? [] : ops.set(vm, key, []) const childAdded = collection.on( 'child_added', @@ -108,15 +110,21 @@ export function rtdbBindAsArray( reject ) - collection.once('value', resolve) + collection.once('value', data => { + if (options.wait) { + ops.set(vm, key, array) + } + resolve(data) + }) - return () => { + return (reset?: RTDBOptions['reset']) => { + const resetOption = reset === undefined ? options.reset : reset collection.off('child_added', childAdded) collection.off('child_changed', childChanged) collection.off('child_removed', childRemoved) collection.off('child_moved', childMoved) - if (options.reset !== false) { - const value = typeof options.reset === 'function' ? options.reset() : [] + if (resetOption !== false) { + const value = typeof resetOption === 'function' ? resetOption() : [] ops.set(vm, key, value) } } diff --git a/packages/vuexfire/src/firestore.ts b/packages/vuexfire/src/firestore.ts index fa228d5d..73d01c46 100644 --- a/packages/vuexfire/src/firestore.ts +++ b/packages/vuexfire/src/firestore.ts @@ -123,11 +123,20 @@ export function firestoreAction( ) return data }, - add: (target, newIndex, data) => - commit(VUEXFIRE_ARRAY_ADD, { target, newIndex, data }, commitOptions), + add: (target, newIndex, data) => { + if ('__ob__' in target) { + commit(VUEXFIRE_ARRAY_ADD, { target, newIndex, data }, commitOptions) + } else { + target[newIndex] = data + } + }, remove: (target, oldIndex) => { const data = target[oldIndex] - commit(VUEXFIRE_ARRAY_REMOVE, { target, oldIndex }, commitOptions) + if ('__ob__' in target) { + commit(VUEXFIRE_ARRAY_REMOVE, { target, oldIndex }, commitOptions) + } else { + target.splice(oldIndex, 1) + } return [data] }, } diff --git a/packages/vuexfire/src/rtdb.ts b/packages/vuexfire/src/rtdb.ts index 40ca5b1b..8d58a04b 100644 --- a/packages/vuexfire/src/rtdb.ts +++ b/packages/vuexfire/src/rtdb.ts @@ -101,11 +101,20 @@ export function firebaseAction( ) return data }, - add: (target, newIndex, data) => - commit(VUEXFIRE_ARRAY_ADD, { target, newIndex, data }, commitOptions), + add: (target, newIndex, data) => { + if ('__ob__' in target) { + commit(VUEXFIRE_ARRAY_ADD, { target, newIndex, data }, commitOptions) + } else { + target[newIndex] = data + } + }, remove: (target, oldIndex) => { const data = target[oldIndex] - commit(VUEXFIRE_ARRAY_REMOVE, { target, oldIndex }, commitOptions) + if ('__ob__' in target) { + commit(VUEXFIRE_ARRAY_REMOVE, { target, oldIndex }, commitOptions) + } else { + target.splice(oldIndex, 1) + } return [data] }, } From fabfb81347a0dc2654419c533de368a778529c16 Mon Sep 17 00:00:00 2001 From: Scott Geary Date: Thu, 15 Aug 2019 16:46:23 +1000 Subject: [PATCH 2/2] fix tests --- packages/@posva/vuefire-core/src/firestore/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@posva/vuefire-core/src/firestore/index.ts b/packages/@posva/vuefire-core/src/firestore/index.ts index 1c40f8b4..356da581 100644 --- a/packages/@posva/vuefire-core/src/firestore/index.ts +++ b/packages/@posva/vuefire-core/src/firestore/index.ts @@ -362,7 +362,7 @@ export function bindDocument( unbind() const resetOption = reset === undefined ? options.reset : reset if (resetOption !== false) { - const value = typeof resetOption === 'function' ? resetOption() : [] + const value = typeof resetOption === 'function' ? resetOption() : null ops.set(vm, key, value) } unsubscribeAll(subs)