Skip to content

Commit 76d36f5

Browse files
committed
feat(firestore): allow passing snapshot options
Close #955
1 parent dd16b79 commit 76d36f5

File tree

2 files changed

+50
-24
lines changed

2 files changed

+50
-24
lines changed

Diff for: src/firestore/index.ts

+40-20
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,42 @@ import type {
1414
DocumentSnapshot,
1515
FirestoreDataConverter,
1616
Query,
17+
SnapshotListenOptions,
18+
SnapshotOptions,
1719
} from 'firebase/firestore'
1820
import { onSnapshot } from 'firebase/firestore'
1921

2022
export interface FirestoreOptions {
2123
maxRefDepth?: number
2224
reset?: boolean | (() => any)
2325

26+
// FIXME: should only be possible in global options
2427
converter?: FirestoreDataConverter<unknown>
2528

29+
initialValue?: unknown
30+
31+
snapshotOptions?: SnapshotOptions
32+
33+
/**
34+
* @inheritdoc {SnapshotListenOptions}
35+
*/
36+
snapshotListenOptions?: SnapshotListenOptions
37+
2638
wait?: boolean
2739
}
2840

29-
const DEFAULT_OPTIONS: Required<FirestoreOptions> = {
41+
export interface _GlobalFirestoreOptions extends FirestoreOptions {
42+
maxRefDepth: number
43+
reset: boolean | (() => any)
44+
converter: FirestoreDataConverter<unknown>
45+
wait: boolean
46+
}
47+
48+
export interface VueFireFirestoreOptions extends FirestoreOptions {
49+
converter?: FirestoreDataConverter<unknown>
50+
}
51+
52+
const DEFAULT_OPTIONS: _GlobalFirestoreOptions = {
3053
maxRefDepth: 2,
3154
reset: true,
3255
converter: firestoreDefaultConverter,
@@ -50,7 +73,7 @@ function unsubscribeAll(subs: Record<string, FirestoreSubscription>) {
5073
}
5174

5275
function updateDataFromDocumentSnapshot<T>(
53-
options: Required<FirestoreOptions>,
76+
options: _GlobalFirestoreOptions,
5477
target: Ref<T>,
5578
path: string,
5679
snapshot: DocumentSnapshot<T>,
@@ -81,7 +104,7 @@ interface SubscribeToDocumentParamater {
81104

82105
function subscribeToDocument(
83106
{ ref, target, path, depth, resolve, ops }: SubscribeToDocumentParamater,
84-
options: Required<FirestoreOptions>
107+
options: _GlobalFirestoreOptions
85108
) {
86109
const subs = Object.create(null)
87110
const unbind = onSnapshot(ref, (snapshot) => {
@@ -122,7 +145,7 @@ function subscribeToDocument(
122145
// first one is calling the other on every ref and subscribeToDocument may call
123146
// updateDataFromDocumentSnapshot which may call subscribeToRefs as well
124147
function subscribeToRefs(
125-
options: Required<FirestoreOptions>,
148+
options: _GlobalFirestoreOptions,
126149
target: CommonBindOptionsParameter['target'],
127150
path: string | number,
128151
subs: Record<string, FirestoreSubscription>,
@@ -183,6 +206,7 @@ function subscribeToRefs(
183206
})
184207
}
185208

209+
// TODO: get rid of the any
186210
interface CommonBindOptionsParameter {
187211
// vm: Record<string, any>
188212
target: Ref<any>
@@ -193,20 +217,18 @@ interface CommonBindOptionsParameter {
193217
ops: OperationsType
194218
}
195219

196-
interface BindCollectionParameter extends CommonBindOptionsParameter {
197-
collection: CollectionReference | Query
198-
}
199-
200220
export function bindCollection<T = unknown>(
201-
target: BindCollectionParameter['target'],
221+
target: CommonBindOptionsParameter['target'],
202222
collection: CollectionReference<T> | Query<T>,
203-
ops: BindCollectionParameter['ops'],
204-
resolve: BindCollectionParameter['resolve'],
205-
reject: BindCollectionParameter['reject'],
223+
ops: CommonBindOptionsParameter['ops'],
224+
resolve: CommonBindOptionsParameter['resolve'],
225+
reject: CommonBindOptionsParameter['reject'],
206226
extraOptions: FirestoreOptions = DEFAULT_OPTIONS
207227
) {
208228
const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) // fill default values
209229

230+
const { snapshotListenOptions, snapshotOptions, wait } = options
231+
210232
if (!collection.converter) {
211233
// @ts-expect-error: seems like a ts error
212234
collection = collection.withConverter(
@@ -216,8 +238,8 @@ export function bindCollection<T = unknown>(
216238
}
217239

218240
const key = 'value'
219-
if (!options.wait) ops.set(target, key, [])
220-
let arrayRef = ref(options.wait ? [] : target[key])
241+
if (!wait) ops.set(target, key, [])
242+
let arrayRef = ref(wait ? [] : target[key])
221243
const originalResolve = resolve
222244
let isResolved: boolean
223245

@@ -229,10 +251,9 @@ export function bindCollection<T = unknown>(
229251
added: ({ newIndex, doc }: DocumentChange<T>) => {
230252
arraySubs.splice(newIndex, 0, Object.create(null))
231253
const subs = arraySubs[newIndex]
232-
// FIXME: wrong cast, needs better types
233-
// TODO: pass SnapshotOptions
234254
const [data, refs] = extractRefs(
235-
doc.data() as DocumentData,
255+
// @ts-expect-error: FIXME: wrong cast, needs better types
256+
doc.data(snapshotOptions),
236257
undefined,
237258
subs
238259
)
@@ -253,8 +274,7 @@ export function bindCollection<T = unknown>(
253274
const subs = arraySubs[oldIndex]
254275
const oldData = array[oldIndex]
255276
// @ts-expect-error: FIXME: Better types
256-
// TODO: pass SnapshotOptions
257-
const [data, refs] = extractRefs(doc.data(), oldData, subs)
277+
const [data, refs] = extractRefs(doc.data(snapshotOptions), oldData, subs)
258278
// only move things around after extracting refs
259279
// only move things around after extracting refs
260280
arraySubs.splice(newIndex, 0, subs)
@@ -287,7 +307,7 @@ export function bindCollection<T = unknown>(
287307
// from the query appearing as added
288308
// (https://firebase.google.com/docs/firestore/query-data/listen#view_changes_between_snapshots)
289309

290-
const docChanges = snapshot.docChanges()
310+
const docChanges = snapshot.docChanges(snapshotListenOptions)
291311

292312
if (!isResolved && docChanges.length) {
293313
// isResolved is only meant to make sure we do the check only once

Diff for: src/vuefire/firestore.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import type {
1111
Query,
1212
FirestoreError,
1313
DocumentData,
14+
SnapshotOptions,
15+
SnapshotListenOptions,
1416
} from 'firebase/firestore'
1517
import {
1618
getCurrentInstance,
@@ -33,8 +35,6 @@ type UnbindType = ReturnType<typeof bindCollection | typeof bindDocument>
3335

3436
export interface _UseFirestoreRefOptions extends FirestoreOptions {
3537
target?: Ref<unknown>
36-
37-
initialValue?: unknown
3838
}
3939

4040
/**
@@ -119,6 +119,8 @@ export function _useFirestoreRef(
119119
return data as _RefFirestore<unknown>
120120
}
121121

122+
// TODO: remove in stable release or before
123+
122124
/**
123125
* Binds a Firestore reference onto a Vue Ref and keep it updated.
124126
*
@@ -146,7 +148,7 @@ export function usePendingPromises() {
146148
return Promise.all(pendingPromises)
147149
}
148150

149-
export interface UseCollectionOptions {}
151+
export interface UseCollectionOptions extends _UseFirestoreRefOptions {}
150152

151153
/**
152154
* Creates a reactive collection (usually an array) of documents from a collection ref or a query from Firestore. Extracts the the type of the
@@ -185,7 +187,9 @@ export function useCollection<T>(
185187
>
186188
}
187189

188-
export interface UseDocumentOptions {}
190+
// TODO: split document and collection into two different parts
191+
192+
export interface UseDocumentOptions extends _UseFirestoreRefOptions {}
189193

190194
/**
191195
* Creates a reactive document from a document ref from Firestore. Extracts the the type of the converter
@@ -222,6 +226,8 @@ export function useDocument<T>(
222226
return _useFirestoreRef(documentRef, options) as _RefFirestore<T>
223227
}
224228

229+
// TODO: move to an unsubscribe file
230+
225231
export function internalUnbind(
226232
key: string,
227233
unbinds:

0 commit comments

Comments
 (0)