Skip to content

Commit c4ab275

Browse files
committed
fix: nested refs
1 parent 6e6557f commit c4ab275

File tree

4 files changed

+22
-12
lines changed

4 files changed

+22
-12
lines changed

playground/src/firebase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function createFirebaseApp() {
2222
const firestore = getFirestore(firebaseApp)
2323
const analytics = getAnalytics(firebaseApp)
2424

25-
connectFirestoreEmulator(firestore, 'localhost', 8080)
25+
// connectFirestoreEmulator(firestore, 'localhost', 8080)
2626

2727
return { firebaseApp, firestore, analytics }
2828
}

playground/src/pages/config.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { useFirestore } from '@/firebase'
66
77
const db = useFirestore()
88
const configRef = doc(db, 'configs', 'jORwjIykFo2NmkdzTkhU')
9-
const itemRef = doc(db, 'tests', 'item')
9+
// const itemRef = doc(db, 'tests', 'item')
1010
1111
const config = ref()
12-
firestoreBind(config, itemRef)
13-
// firestoreBind(config, configRef)
12+
// firestoreBind(config, itemRef)
13+
firestoreBind(config, configRef)
1414
</script>
1515

1616
<template>

src/firestore/utils.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import type {
44
CollectionReference,
55
DocumentSnapshot,
66
DocumentData,
7+
GeoPoint,
78
} from 'firebase/firestore'
89
import { isTimestamp, isObject, isDocumentRef, TODO } from '../shared'
910

1011
export type FirestoreReference = Query | DocumentReference | CollectionReference
1112

1213
// TODO: fix type not to be any
13-
export function createSnapshot(doc: DocumentSnapshot): TODO {
14+
export function createSnapshot<T = DocumentData>(
15+
doc: DocumentSnapshot<T>
16+
): { id: string } & T {
1417
// TODO: it should create a deep copy instead because otherwise we will modify internal data
1518
// defaults everything to false, so no need to set
19+
// FIXME: can this be called when the document doesn't exist?
20+
// @ts-expect-error
1621
return Object.defineProperty(doc.data() || {}, 'id', { value: doc.id })
1722
}
1823

@@ -54,18 +59,18 @@ export function extractRefs(
5459

5560
// recursively traverse doc to copy values and extract references
5661
for (const key in doc) {
57-
const ref: TODO = doc[key]
62+
const ref: unknown = doc[key]
5863
if (
5964
// primitives
6065
ref == null ||
6166
// Firestore < 4.13
6267
ref instanceof Date ||
6368
isTimestamp(ref) ||
64-
(ref.longitude && ref.latitude) // GeoPoint
69+
isGeoPoint(ref)
6570
) {
6671
data[key] = ref
6772
} else if (isDocumentRef(ref)) {
68-
// allow values to be null (like non-existant refs)
73+
// allow values to be null (like non-existent refs)
6974
// TODO: better typing since this isObject shouldn't be necessary but it doesn't work
7075
data[key] =
7176
typeof oldDoc === 'object' &&
@@ -104,3 +109,7 @@ export function extractRefs(
104109

105110
return dataAndRefs
106111
}
112+
113+
function isGeoPoint(value: unknown): value is GeoPoint {
114+
return isObject(value) && 'latitude' in value && 'longitude' in value
115+
}

src/shared.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export function walkSet<T>(
5252
* Checks if a variable is an object
5353
* @param o
5454
*/
55-
export function isObject(o: any): o is object {
55+
export function isObject(o: any): o is Record<any, unknown> {
5656
return o && typeof o === 'object'
5757
}
5858

@@ -69,9 +69,11 @@ export function isTimestamp(o: any): o is Date {
6969
* @param o
7070
*/
7171
export function isDocumentRef(o: any): o is DocumentReference {
72-
return o && o.onSnapshot
72+
return isObject(o) && o.type === 'document'
7373
}
7474

75+
type ReferenceType = 'collection' | 'document' | 'query'
76+
7577
/**
7678
* Wraps a function so it gets called only once
7779
* @param fn Function to be called once
@@ -81,8 +83,7 @@ export function callOnceWithArg<T, K>(
8183
fn: (arg: T) => K,
8284
argFn: () => T
8385
): () => K | undefined {
84-
/** @type {boolean | undefined} */
85-
let called = false
86+
let called: boolean | undefined
8687

8788
return (): K | undefined => {
8889
if (!called) {

0 commit comments

Comments
 (0)