Closed Tattomoosa closed 6 years ago
it should be an easy fix, indeed. thanks for letting me know 🙂
I am seeing the following error when subscribing to a document w/ Timestamp fields:
Uncaught TypeError: ref.onSnapshot is not a function
at subscribeToDocument (vuexfire.es.js?b50a:340)
at eval (vuexfire.es.js?b50a:164)
at Array.forEach (<anonymous>)
at subscribeToRefs (vuexfire.es.js?b50a:148)
at Object.added (vuexfire.es.js?b50a:210)
at eval (vuexfire.es.js?b50a:288)
at Array.forEach (<anonymous>)
at Object.eval [as next] (vuexfire.es.js?b50a:287)
at next (index.cjs.js?5a4f:16152)
at eval (index.cjs.js?5a4f:14282)
The ref
that is being passed in is normally a DocumentReference class...
...but when a document contains a Timestamp field the ref
is actually a Timestamp class!
I think something in extractRefs
is getting confused when it sees an object of type Timestamp.
I think my theory was correct. I changed utils.js to have the following:
const isObject = o => o && typeof o === 'object'
// Quick and dirty; please improve per https://stackoverflow.com/a/332429/252308
const isTimestamp = o => o && o.constructor.name === 'Timestamp'
export function extractRefs (doc, oldDoc, path = '', result = [{}, {}]) {
// must be set here because walkGet can return null or undefined
oldDoc = oldDoc || {}
const idDescriptor = Object.getOwnPropertyDescriptor(doc, 'id')
if (idDescriptor && !idDescriptor.enumerable) {
Object.defineProperty(result[0], 'id', idDescriptor)
}
return Object.keys(doc).reduce((tot, key) => {
const ref = doc[key]
// if it's a ref
if (
ref instanceof Date || isTimestamp(ref) ||
ref == null ||
(ref.longitude && ref.latitude) // GeoPoint
) {
tot[0][key] = ref
} else if (ref && typeof ref.isEqual === 'function') {
tot[0][key] = oldDoc[key] || ref.path
tot[1][path + key] = ref
} else if (Array.isArray(ref)) {
tot[0][key] = Array(ref.length).fill(null)
extractRefs(ref, oldDoc[key], path + key + '.', [tot[0][key], tot[1]])
} else if (isObject(ref)) {
tot[0][key] = {}
extractRefs(ref, oldDoc[key], path + key + '.', [tot[0][key], tot[1]])
} else {
tot[0][key] = ref
}
return tot
}, result)
}
Cool! Thanks!
A few days ago, Firestore started sending a warning about an upcoming change to
snapshots
where they will be sent as timestamps instead of Dates. If you implement their recommended change to stop this warning then VuexFire breaks.The Firestore warning:
The error:
I'm assuming this happens any time an object with a field that's a timestamp is received. Timestamps have a
toDate()
method so it should be an easy fix. I might look at when I get a chance but I figured I'd make an issue first.