IjzerenHein / firestorter

Use Google Firestore in React with zero effort, using MobX 🤘
http://firestorter.com
MIT License
378 stars 50 forks source link

Set custom SnapshotOptions, especially serverTimestamps option #30

Closed Strate closed 5 years ago

Strate commented 6 years ago

Hi!

By default, firestore's DocumentSnapshot.data() converts ServerTimestamp tp null. It is possible to override this default behaviour by passing extra option to DocumentSnapshot.data(), for example:

snapshot.data({serverTimestamp: "estimate"})

But I didn't find a way how to do this in the firestorter. Could you help me with that?

Strate commented 6 years ago

Temporary fixed by pathing data function:

firebase.firestore.DocumentSnapshot.prototype.data = (function(baseDataFn) {
  return function patchedData(options) {
    if (options == null) {
      options = {
        serverTimestamps: "estimate"
      };
    }
    return baseDataFn.call(this, options);
  };
})(firebase.firestore.DocumentSnapshot.prototype.data);
IjzerenHein commented 5 years ago

Hi, what do you mean by that it converts the timestamp to null? It should return a timestamp right? Are you using firestore.settings({ timestampsInSnapshots: true });?

cheers

Strate commented 5 years ago

@IjzerenHein hi, firestore by default converts pending servertimestamp to null untill it is not loaded from backend, or provided special SnapshotOptions: https://firebase.google.com/docs/reference/js/firebase.firestore.SnapshotOptions

IjzerenHein commented 5 years ago

Hey Artur, I think I understand now and am working on supporting it. The problem I'm having now is to reproduce the situation where Firestore returns null. For instance, in my test I do:

const doc = new Document('artists/TimeStampTest');
await doc.set({
  date: getFirebase().firestore.FieldValue.serverTimestamp()
});
await doc.fetch();
expect(doc.data.date).toHaveProperty('seconds');
expect(doc.data.date).toHaveProperty('nanoseconds');

But this always succeeds. I assume caching plays a role here. Could you provide me with an example on how to get Firestore to return null?

cheers, Hein

IjzerenHein commented 5 years ago

Okay I've just added the option to specify snapshotOptions to Document (on master, not released yet). You can specify the snapshot options like this:

new Document('todos', {
  snapshotOptions: {
    serverTimestamps: 'estimate'
  }
});

Would this solve your use case? cheers

IjzerenHein commented 5 years ago

Okay I've just added the option to specify snapshotOptions to Document (on master, not released yet). You can specify the snapshot options like this:

new Document('todos', {
  snapshotOptions: {
    serverTimestamps: 'estimate'
  }
});

Would this solve your use case? cheers

Just released this in official version v1.1.0

Strate commented 5 years ago

@IjzerenHein thank you for that, I think collection need support same thing. Or possibility to set something like Document.defaultSnapshotOptions = {}

IjzerenHein commented 5 years ago

You can already do it by creating a custom document and collection:

class CustomDocument extends Document {
  constructor(source, options = {}) {
    super(source, {
       snapshotOptions: {
         serverTimestamps: 'estimate'
       },
       ...options
    });  
  }
}

class CustomCollection extends Collection {
  constructor(source, options = {}) {
    super(source, {
      createDocument: (source, options) => new CustomDocument(source, options),
      ...options
    });
  }
}
Strate commented 5 years ago

Great, thank you for that!