Skip to content

Commit

Permalink
feat: support timestamps (Firestore 4.13.0)
Browse files Browse the repository at this point in the history
Closes #181
  • Loading branch information
posva committed Apr 29, 2018
1 parent 8ed95ab commit 6e1f56f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 30 deletions.
5 changes: 3 additions & 2 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<head>
<meta charset="utf-8">
<title>VueFire Todo App Demo</title>
<script src="https://www.gstatic.com/firebasejs/4.6.0/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.6.0/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.13.0/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.13.0/firebase-firestore.js"></script>
<script src="https://unpkg.com/vue"></script>
<script src="../dist/vuefire.js"></script>
</head>
Expand Down Expand Up @@ -64,6 +64,7 @@ <h5>Original data</h5>
databaseURL: 'https://vue-fire-store.firebaseio.com'
})
const db = firebase.firestore()
db.settings({ timestampsInSnapshots: true })
const todos = db.collection('todos')
const unFinishedTodos = todos.where('finished', '==', false)
const finishedTodos = todos.where('finished', '==', true)
Expand Down
14 changes: 12 additions & 2 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ function isObject (o) {
return o && typeof o === 'object'
}

function isTimestamp (o) {
return o.toDate
}

function isRef (o) {
return o && o.onSnapshot
}

export function extractRefs (doc, oldDoc, path = '', result = [{}, {}]) {
// must be set here because walkGet can return null or undefined
oldDoc = oldDoc || {}
Expand All @@ -19,7 +27,7 @@ export function extractRefs (doc, oldDoc, path = '', result = [{}, {}]) {
return Object.keys(doc).reduce((tot, key) => {
const ref = doc[key]
// if it's a ref
if (ref && typeof ref.isEqual === 'function') {
if (isRef(ref)) {
tot[0][key] = oldDoc[key] || ref.path
// TODO handle subpathes?
tot[1][path + key] = ref
Expand All @@ -28,8 +36,10 @@ export function extractRefs (doc, oldDoc, path = '', result = [{}, {}]) {
tot[0][key] = Array(ref.length).fill(null)
extractRefs(ref, oldDoc[key], path + key + '.', [tot[0][key], tot[1]])
} else if (
ref instanceof Date ||
ref == null ||
// Firestore < 4.13
ref instanceof Date ||
isTimestamp(ref) ||
(ref.longitude && ref.latitude) // GeoPoint
) {
tot[0][key] = ref
Expand Down
73 changes: 48 additions & 25 deletions test/helpers/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ export class GeoPoint {
return this._long
}
}

export class Timestamp {
constructor (seconds, nanoseconds) {
this.seconds = seconds
this.nanoseconds = nanoseconds
}

toDate () {
return new Date(this.toMillis())
}

toMillis () {
return this.seconds * 1000 + this.nanoseconds / 1e6
}
}

export class DocumentSnapshot {
constructor (firestore, key, document, exists) {
this._firestore = firestore
Expand Down Expand Up @@ -63,9 +79,7 @@ class callbacksAndErrors {
}

_callCallbacks (data) {
Object.values(this.cbs).forEach(
cb => cb(data)
)
Object.values(this.cbs).forEach(cb => cb(data))
}
}

Expand Down Expand Up @@ -148,12 +162,14 @@ class CollectionReference extends callbacksAndErrors {
index: Object.keys(this.data).length
})
this._callCallbacks({
docChanges: [{
type: 'added',
doc: new DocumentSnapshot(null, id, data),
newIndex: Object.keys(this.data).length - 1,
oldIndex: -1
}]
docChanges: [
{
type: 'added',
doc: new DocumentSnapshot(null, id, data),
newIndex: Object.keys(this.data).length - 1,
oldIndex: -1
}
]
})
return this.data[id.v]
}
Expand All @@ -163,22 +179,27 @@ class CollectionReference extends callbacksAndErrors {

doc (id) {
id = new Key(id)
return this.data[id.v] || new DocumentReference({
collection: this,
id,
data: {},
index: Object.keys(this.data).length
})
return (
this.data[id.v] ||
new DocumentReference({
collection: this,
id,
data: {},
index: Object.keys(this.data).length
})
)
}

async _remove (id) {
const ref = this.data[id.v]
delete this.data[id.v]
this._callCallbacks({
docChanges: [{
doc: new DocumentSnapshot(null, id, ref.data),
type: 'removed'
}]
docChanges: [
{
doc: new DocumentSnapshot(null, id, ref.data),
type: 'removed'
}
]
})
ref.collection = null
ref.data = null
Expand All @@ -192,12 +213,14 @@ class CollectionReference extends callbacksAndErrors {
type = 'added'
}
this._callCallbacks({
docChanges: [{
type,
doc: new DocumentSnapshot(null, id, data),
oldIndex: this.data[id.v].index,
newIndex: this.data[id.v].index
}]
docChanges: [
{
type,
doc: new DocumentSnapshot(null, id, data),
oldIndex: this.data[id.v].index,
newIndex: this.data[id.v].index
}
]
})
}
}
Expand Down
13 changes: 12 additions & 1 deletion test/utils.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createSnapshot, extractRefs } from '../src/utils'
import { Key, db, _id, DocumentReference, GeoPoint, DocumentSnapshot } from './helpers'
import { Key, db, _id, DocumentReference, GeoPoint, DocumentSnapshot, Timestamp } from './helpers'

let id, doc, snapshot, collection, docRef
beforeEach(() => {
Expand Down Expand Up @@ -56,6 +56,17 @@ test('leave Date objects alone when extracting refs', () => {
expect(refs).toEqual({})
})

test('leave Timestamps objects alone when extracting refs', () => {
const d = new Timestamp(10, 10)
const [doc, refs] = extractRefs({
foo: 1,
bar: d
})
expect(doc.foo).toBe(1)
expect(doc.bar).toBe(d)
expect(refs).toEqual({})
})

test('leave GeoPoint objects alone when extracting refs', () => {
const d = new GeoPoint(2, 48)
const [doc, refs] = extractRefs({
Expand Down

0 comments on commit 6e1f56f

Please sign in to comment.