vuejs / vuefire

🔥 Firebase bindings for Vue.js
https://vuefire.vuejs.org
MIT License
3.82k stars 323 forks source link

`toFirestore` inside `globalFirestoreOptions.converter` is never called #1497

Closed mrleblanc101 closed 4 months ago

mrleblanc101 commented 4 months ago

Reproduction

.

Steps to reproduce the bug

I created this global converter, the fromFirestore gets called, but not the toFirestore. I see test 2 in the console, but never test 1, and the data in my firestore does not have the field created_at.

globalFirestoreOptions.converter = {
    toFirestore(docData: any) {
        console.log('test 1');
        return {
            created_at: serverTimestamp(),
            ...docData,
        }
    },
    fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): DocumentData {
        console.log('test 2');
        const data = firestoreDefaultConverter.fromFirestore(snapshot)!;
        return data;
    },
};

Expected behavior

Both toFirestore and fromFirestore should be called.

Actual behavior

Only the fromFirestore is called.

Additional information

I want to automatically add a created_at field so that I can sort by date when fetching.

Important: Unlike "push IDs" in the Firebase Realtime Database, Cloud Firestore auto-generated IDs do not provide any automatic ordering. If you want to be able to order your documents by creation date, you should store a timestamp as a field in the documents. Ref: https://firebase.google.com/docs/firestore/manage-data/add-data?hl=fr

mrleblanc101 commented 4 months ago

It works if I use .withConverter instead. Exemple:

const addDefaultFields = {
    toFirestore(docData: DocumentData): DocumentData {
        console.log('test 1');
        return {
            created_at: serverTimestamp(),
            ...docData,
        }
    },
    fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): DocumentData {
        console.log('test 2');
        const data = firestoreDefaultConverter.fromFirestore(snapshot)!;
        return data;
    },
};

...

async function addProject(option: Project) {
    const project = await addDoc(collection(db, 'projects').withConverter(addDefaultFields), {
        name: option.name,
        user: user.value!.uid,
    })
    return { id: project.id, name: option.name };
}