Skip to content

Commit

Permalink
feat(firestore): allow passing snapshot options
Browse files Browse the repository at this point in the history
Close #955
  • Loading branch information
posva committed Oct 19, 2022
1 parent dd16b79 commit 76d36f5
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 24 deletions.
60 changes: 40 additions & 20 deletions src/firestore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,42 @@ import type {
DocumentSnapshot,
FirestoreDataConverter,
Query,
SnapshotListenOptions,
SnapshotOptions,
} from 'firebase/firestore'
import { onSnapshot } from 'firebase/firestore'

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

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

initialValue?: unknown

snapshotOptions?: SnapshotOptions

/**
* @inheritdoc {SnapshotListenOptions}
*/
snapshotListenOptions?: SnapshotListenOptions

wait?: boolean
}

const DEFAULT_OPTIONS: Required<FirestoreOptions> = {
export interface _GlobalFirestoreOptions extends FirestoreOptions {
maxRefDepth: number
reset: boolean | (() => any)
converter: FirestoreDataConverter<unknown>
wait: boolean
}

export interface VueFireFirestoreOptions extends FirestoreOptions {
converter?: FirestoreDataConverter<unknown>
}

const DEFAULT_OPTIONS: _GlobalFirestoreOptions = {
maxRefDepth: 2,
reset: true,
converter: firestoreDefaultConverter,
Expand All @@ -50,7 +73,7 @@ function unsubscribeAll(subs: Record<string, FirestoreSubscription>) {
}

function updateDataFromDocumentSnapshot<T>(
options: Required<FirestoreOptions>,
options: _GlobalFirestoreOptions,
target: Ref<T>,
path: string,
snapshot: DocumentSnapshot<T>,
Expand Down Expand Up @@ -81,7 +104,7 @@ interface SubscribeToDocumentParamater {

function subscribeToDocument(
{ ref, target, path, depth, resolve, ops }: SubscribeToDocumentParamater,
options: Required<FirestoreOptions>
options: _GlobalFirestoreOptions
) {
const subs = Object.create(null)
const unbind = onSnapshot(ref, (snapshot) => {
Expand Down Expand Up @@ -122,7 +145,7 @@ function subscribeToDocument(
// first one is calling the other on every ref and subscribeToDocument may call
// updateDataFromDocumentSnapshot which may call subscribeToRefs as well
function subscribeToRefs(
options: Required<FirestoreOptions>,
options: _GlobalFirestoreOptions,
target: CommonBindOptionsParameter['target'],
path: string | number,
subs: Record<string, FirestoreSubscription>,
Expand Down Expand Up @@ -183,6 +206,7 @@ function subscribeToRefs(
})
}

// TODO: get rid of the any
interface CommonBindOptionsParameter {
// vm: Record<string, any>
target: Ref<any>
Expand All @@ -193,20 +217,18 @@ interface CommonBindOptionsParameter {
ops: OperationsType
}

interface BindCollectionParameter extends CommonBindOptionsParameter {
collection: CollectionReference | Query
}

export function bindCollection<T = unknown>(
target: BindCollectionParameter['target'],
target: CommonBindOptionsParameter['target'],
collection: CollectionReference<T> | Query<T>,
ops: BindCollectionParameter['ops'],
resolve: BindCollectionParameter['resolve'],
reject: BindCollectionParameter['reject'],
ops: CommonBindOptionsParameter['ops'],
resolve: CommonBindOptionsParameter['resolve'],
reject: CommonBindOptionsParameter['reject'],
extraOptions: FirestoreOptions = DEFAULT_OPTIONS
) {
const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions) // fill default values

const { snapshotListenOptions, snapshotOptions, wait } = options

if (!collection.converter) {
// @ts-expect-error: seems like a ts error
collection = collection.withConverter(
Expand All @@ -216,8 +238,8 @@ export function bindCollection<T = unknown>(
}

const key = 'value'
if (!options.wait) ops.set(target, key, [])
let arrayRef = ref(options.wait ? [] : target[key])
if (!wait) ops.set(target, key, [])
let arrayRef = ref(wait ? [] : target[key])
const originalResolve = resolve
let isResolved: boolean

Expand All @@ -229,10 +251,9 @@ export function bindCollection<T = unknown>(
added: ({ newIndex, doc }: DocumentChange<T>) => {
arraySubs.splice(newIndex, 0, Object.create(null))
const subs = arraySubs[newIndex]
// FIXME: wrong cast, needs better types
// TODO: pass SnapshotOptions
const [data, refs] = extractRefs(
doc.data() as DocumentData,
// @ts-expect-error: FIXME: wrong cast, needs better types
doc.data(snapshotOptions),
undefined,
subs
)
Expand All @@ -253,8 +274,7 @@ export function bindCollection<T = unknown>(
const subs = arraySubs[oldIndex]
const oldData = array[oldIndex]
// @ts-expect-error: FIXME: Better types
// TODO: pass SnapshotOptions
const [data, refs] = extractRefs(doc.data(), oldData, subs)
const [data, refs] = extractRefs(doc.data(snapshotOptions), oldData, subs)
// only move things around after extracting refs
// only move things around after extracting refs
arraySubs.splice(newIndex, 0, subs)
Expand Down Expand Up @@ -287,7 +307,7 @@ export function bindCollection<T = unknown>(
// from the query appearing as added
// (https://firebase.google.com/docs/firestore/query-data/listen#view_changes_between_snapshots)

const docChanges = snapshot.docChanges()
const docChanges = snapshot.docChanges(snapshotListenOptions)

if (!isResolved && docChanges.length) {
// isResolved is only meant to make sure we do the check only once
Expand Down
14 changes: 10 additions & 4 deletions src/vuefire/firestore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import type {
Query,
FirestoreError,
DocumentData,
SnapshotOptions,
SnapshotListenOptions,
} from 'firebase/firestore'
import {
getCurrentInstance,
Expand All @@ -33,8 +35,6 @@ type UnbindType = ReturnType<typeof bindCollection | typeof bindDocument>

export interface _UseFirestoreRefOptions extends FirestoreOptions {
target?: Ref<unknown>

initialValue?: unknown
}

/**
Expand Down Expand Up @@ -119,6 +119,8 @@ export function _useFirestoreRef(
return data as _RefFirestore<unknown>
}

// TODO: remove in stable release or before

/**
* Binds a Firestore reference onto a Vue Ref and keep it updated.
*
Expand Down Expand Up @@ -146,7 +148,7 @@ export function usePendingPromises() {
return Promise.all(pendingPromises)
}

export interface UseCollectionOptions {}
export interface UseCollectionOptions extends _UseFirestoreRefOptions {}

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

export interface UseDocumentOptions {}
// TODO: split document and collection into two different parts

export interface UseDocumentOptions extends _UseFirestoreRefOptions {}

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

// TODO: move to an unsubscribe file

export function internalUnbind(
key: string,
unbinds:
Expand Down

0 comments on commit 76d36f5

Please sign in to comment.