Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firestore Roadmap #145

Closed
24 of 36 tasks
posva opened this issue Nov 17, 2017 · 37 comments
Closed
24 of 36 tasks

Firestore Roadmap #145

posva opened this issue Nov 17, 2017 · 37 comments
Labels
docs firestore new Cloud Store RTDB Old Firebase realtime database

Comments

@posva
Copy link
Member

posva commented Nov 17, 2017

It's time for vuefire to update to Cloud Firestore 🎉

In order to give you some visibility about the new version, here's a checklist with features. Feel free to ask about new things, I'll probably forget to add every single feature to the list.

Until the version becomes stable there may be breaking changes, but if you're using the current version of vuefire, don't worry, it won't affect you. The new version will be published under the next tag on npm, meaning that you can already play with it if you want

Firestore is now supported by the latest tag

Keep in mind, there're still no docs but you can check the exapmles/ folder and tests for inspiration

Features

  • Document binding
  • Collection binding
  • unbind on destroy
  • Manual bind
  • Manual unbind
  • Support firestore as a function
  • bind -> returns a promise
  • option to remove data right away when binding on top of an already bound ref
  • Automatic unbind when already bound
  • Development warnings
  • Recursive ref binding + unbinding
    • Bind refs in documents
      • bind refs inside of objects
      • bind refs inside of arrays
      • bind plain refs
    • Stop at 1st depth by default
    • allow passing max depth
  • customizing id key used
  • Move tests to Jest
  • Split code to have both, vuefire and vuexfire code here
  • Allow users to use both RTDB and Firestore at the same time
  • Documentation
    • Vuepress site
    • Live Examples
    • Figure out a way to document common things between vuefire /vuexfire
    • Vuexfire
    • Cookbook
      • Pagination
      • How to write tests
      • Using without a bundler (prototyping)
        • Add full template to use
      • Using with Typescript
      • Dynamically bound properties (Vue.set)
    • Note in getting started about docs being for people using webpack (or project with cli
    • Link to cookbook

If you find bugs, please, open a new issue (but make sure to check if it hasn't been fixed already 😛 )
if you want to check the ongoing work, it's on the firestore branch

This was referenced Nov 17, 2017
@posva
Copy link
Member Author

posva commented Dec 28, 2017

Small update: Things are working really well, I just released an alpha version. The reason is taking so much time is because there's a lot of edge cases for refs (embed documents into other documents) to handle 😆
Most things are working but if you find bugs, please open an issue with a repro, it would really help!
For instance, I yet have to fix a bug when updating a document referenced in an array on a bound document that makes the update delay fixed in latest release

@taylorhoward92
Copy link

Thanks for your hard work in supporting Firestore. When binding to a collection, is there a way to get the ID or ref of each document within the collection?

@posva
Copy link
Member Author

posva commented Feb 24, 2018

it's the key id attribute. It's non-enumerable, so it doesn't appear when copying the object

@taylorhoward92
Copy link

Thanks. I was using a collection with v-for on a component and binding to the object instead of binding on each property. This meant that the id prop in the component could not be found.

Specifying a property for the id did the trick:
<ListingItem v-for="listing in listings" :key="listing.id" v-bind="listing" :id="listing.id"/>

@posva

This comment has been minimized.

@WillieCubed

This comment has been minimized.

@posva

This comment has been minimized.

@eeerrrttty

This comment has been minimized.

@classikd
Copy link

It works like a charm ! Thanks for your job

@posva posva mentioned this issue Mar 27, 2018
@posva posva added the firestore new Cloud Store label Apr 15, 2018
@joshualyon
Copy link

joshualyon commented May 7, 2018

@BernardMarieOnzo as noted in the first post:

Keep in mind, there're still no docs but you can check the exapmles/ folder and tests for inspiration

Here's a direct link to the firestore branch's examples folder:
Vuefire: https://github.com/vuejs/vuefire/blob/master/packages/vuefire/examples/index.html
Vuexfire: https://github.com/vuejs/vuefire/blob/master/packages/vuexfire/examples/index.html

You might also find this medium article helpful as they walk through the end-to-end process of setting up and using Vue + VueFire + Firestore:
https://medium.com/vue-mastery/full-stack-vue-js-with-firestore-62e2fe2ec1f3

Edit: Also note that while the syntax and usage is similar to the RTDB approach you linked to, the syntax and usage is different - eg. it matches the firestore library methods rather than the firebase methods.

@nick-jonas

This comment has been minimized.

@FlorianWerndl

This comment has been minimized.

@nick-jonas

This comment has been minimized.

@vuejs vuejs deleted a comment from gboor Jun 26, 2018
@vuejs vuejs deleted a comment from gboor Jun 26, 2018
@tukutela

This comment has been minimized.

@posva

This comment has been minimized.

@tukutela

This comment has been minimized.

@humanismusic

This comment has been minimized.

@posva

This comment has been minimized.

@humanismusic

This comment has been minimized.

@posva
Copy link
Member Author

posva commented Dec 6, 2018

I haven't been able to do more for a long time. The packages have been stable for some time, I need to write documentation add support for RTDB and then I will publish a stable release. I will get some time to work on this during xmas. Hopefully I should be able to publish it before 2019

@coffeeneed

This comment has been minimized.

@posva

This comment has been minimized.

@posva
Copy link
Member Author

posva commented Mar 17, 2019

an update on this: Been really busy with work + personal life since January. I want to have at least the guide ready for both vuefire and vuexfire before releasing the version as stable. Especially because being able to support both RTDB and Firestore includes some breaking changes in exports to make the library tree shakable so people do not include code they don't need

@posva
Copy link
Member Author

posva commented Mar 22, 2019

I just published a new version with support for RTDB. There are a few breaking changes to accomodate that it's a matter of renaming imports https://twitter.com/posva/status/1109175186694328322

There are also wip docs at https://vuefire.netlify.com/ (not final link). Feedback welcome

@posva posva added docs RTDB Old Firebase realtime database and removed enhancement labels Jun 7, 2019
@joelxr
Copy link

joelxr commented Sep 20, 2019

Hi, I started to use vuexfire I know there is an entry in the roadmap called How to write tests but these days I'm facing some difficulties to write unit tests to some modules with vuexfire. If someone knows a place to read something about or see any examples would be great!

If I'll be able to write some tests I can definitely contribute with docs and examples.

@posva
Copy link
Member Author

posva commented Sep 20, 2019

@joelxr I think you could check how tests are written in this repository. We have our own mock for Firestore and we https://github.com/soumak77/firebase-mock for the RTDB but it should be able to mock both

@joemanfoo
Copy link

joemanfoo commented Jan 7, 2020

Hey @posva - Passing in the last doc and the .startAt(lastDocFromQuery) isn't returning results.
The issue is that the last document isn't a firesore snapshop which is what is required for the SDK to work. If I get a few minutes I can take the Todo's sample and slap together a repo demonstrating the issue. Currently the only fix that I understand is to query the DB for a record and store it. Then passing it in on the bind.

const lastDocId = this.items[this.items.length - 1].id
lastItem = await db.collection('marketplace').doc(lastDocId).get()
// notice this isn't lastItem.data()
...
//then when we want to go to next page:
this.$store.dispatch('searchDatabase', originalQueryRef.startAt(lastItem).limit(n))

// where action:
searchDatabase: firestoreAction(async ({ bindFirestoreRef, commit }, ref) => {
    // set state loading = true
    commit('setToggleSearching', true)
    await bindFirestoreRef('items', ref)
    // set state loading = false
    commit('setToggleSearching', false)
  })

It would be great if vuexfire would hold on to these first and last document refs (hell they might be but I'm not seeing it). If these were to persist and be accessible somehow then folks wouldn't have to hit the database 3 times per page (after the first initial page, which would only have 2 DB calls). I'm 99.999% sure you have access to these first and last document refs within the @posva/vuefire-core package.

By the way - thanks a million for the work on these packages, incredible work! My brain turns into a puddle of junk when I try to understand the code that goes into these wonderful tools.

[edit]
I was able to get pagination working with the bound items via:
in vuexfire.esm.js

function createSnapshot(doc) {
    // defaults everything to false, so no need to set
    // change from this
    return Object.defineProperty(doc.data(), { 'id': { value: doc.id });
    // to this
    return Object.defineProperties(doc.data(), { 'id': { value: doc.id }, ['.ref']: { value: doc } }); 
}

Which the above probably could be done in a custom serialize option ... but ...
in the function:
function extractRefs(doc, oldDoc, path, result) {
there this:

// TODO: this won't work if the user defines their own defined properties
    // should we do it for every non enumerable property?
    var idDescriptor = Object.getOwnPropertyDescriptor(doc, 'id');
    if (idDescriptor && !idDescriptor.enumerable) {
        // console.log('hi there extractRefs id: ', idDescriptor)
        Object.defineProperty(data, 'id', idDescriptor);
    }

Which I had to add another if check on:

idDescriptor = Object.getOwnPropertyDescriptor(doc, '.ref');
    if (idDescriptor && !idDescriptor.enumerable) {
        // console.log('hi there extractRefs id: ', idDescriptor)
        Object.defineProperty(data, '.ref', idDescriptor);
    }

So now when setting up vuex module:

searchDatabase: firestoreAction(async ({ bindFirestoreRef, commit }, queryRef) => {
    // set state loading = true
    commit('setToggleSearching', true)
    await bindFirestoreRef('items', ref)
    // set state loading = true
    commit('setToggleSearching', false)
  })

This now gives item['.ref']'s that is passable to firebase firestore SDK so this will now work:
this.searchDatabase(queryRef.startAfter(lastItem['.ref']).limit(pageSize))

@posva
Copy link
Member Author

posva commented Jan 7, 2020

@joemanfoo Thanks, I'm glad you like the library! If you manage to reproduce it, please open an issue with the repro. You can use one of the examples as a starting point: https://github.com/vuejs/vuefire/tree/master/packages/vuefire/examples

@sebastiaan-de-vries
Copy link

Dear @posva,

Thank you for creating and sharing this awesome project. I would like to use both the RTDB and Firestore in the same project. Is it just that the documentation around this is not yet available or is it currently hard to implement? Is there any chance you could provide a gist or point me in the right direction for implementing this?

Thanks!
Sebastiaan

@posva
Copy link
Member Author

posva commented Jan 23, 2020

@sebastiaan-de-vries you can use both, you need to follow both examples and use both plugins to support firebase and firestore options. For Vuex, you can also do firebaseAction(firestoreAction(...))

@zv3
Copy link

zv3 commented Feb 5, 2020

@joemanfoo Vuexfire 3.2.1 seems to have fixed the issue with non-enumerable properties being removed from the modified DocumentData (through the serialize option).

By the way, I was also looking into a way to get the last document's reference to get pagination done with a cursor by using the .startAt() , and the exposed workaround works perfectly, thanks! I wish there was an easier way to get the first and last document references though.

@eagerestwolf
Copy link

eagerestwolf commented Mar 9, 2020

If I could make a suggestion for the cookbook...since I have struggled with this issue for a hot minute now; but I think I've got a workaround that kinda works. An example for Firebase Hosting that uses the reserved URL configuration would be nice. I've come up with the following code for my Firebase initialization (it's kind of simple because I don't use the GeoPoints or Timestamps):

EDIT: Nevermind my code, it doesn't work...apparently Webpack (any by extension the Vue CLI service) doesn't allow mixing module types; so, I can't have an ES module with AMD or CJS exports.

EDIT 2: I finally came up with a working solution. It's not the most elegant, but I think it would really help people come up with a working solution for a production application.

src/plugins/firebase/firebase.js

import axios from 'axios';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

// Initialize the Firebase SDK
// NOTE: Since we are using Firebase Hosting, we use the "reserved" URL
// configuration. Therefore, instead of returning the firebase instance,
// we return a Promise that returns the firebase instance.
export default async function initializeFirebase() {
  return new Promise((resolve, reject) => {
    axios.get('/__/firebase/init.json').then(async (res) => {
      try {
        firebase.app();
        resolve(firebase);
      } catch (err) {
        firebase.initializeApp(await res.data);
        resolve(firebase);
      }
    }).catch((err) => {
      reject(err);
    });
  });
}

src/plugins/firebase/init.js

import initializeFirebase from './firebase';

(async () => {
  await initializeFirebase();
})();

src/plugins/firebase/db.js (could also apply to auth, functions, etc)

This one seems unneccessay, but I did it this way, so that I can go back and expand it later; in case, I need to export Timestamps, GeoPoints, etc.

/* eslint-disable import/prefer-default-export */

import firebase from 'firebase/app';
import 'firebase/firestore';

export const db = firebase.firestore();

src/plugins/firebase/index.js

import { auth } from './auth';
import { db } from './db';

import './init';

export { auth, db };

src/main.js

import Vue from 'vue';
import { firestorePlugin } from 'vuefire';
// Other imports

import App from './App.vue';
import router from './router';
import store from './store';

import './plugins/firebase/init';

Vue.config.productionTip = false;

Vue.use(firestorePlugin);

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

I did do the init in two places, which isn't an issue since I'm just initializing the Firebase SDK and my code already looks to see if there is a default app, but I really wanted to make sure it's initialized before it's needed.

@bhaskar-nair2
Copy link

Really looking forward to the Pagination Cookbook...

@tohagan
Copy link

tohagan commented Jun 25, 2020

Any chance you could just add a non-enumerable doc property (same as id) to the data values that get bound or otherwise return the doc or docs via bindFirestoreRef() in some way? I'm hitting the same issue needed to use Firestore cursors using startAfter(doc) but don't see a solution other than reloading the document.

UPDATE: OK ... I think I found the answer which I've just documented on StackOverflow. I see its in this RoadMap. I saw that serializer was referenced above but was "clear as mud" what it all meant so I've documented it here:

https://stackoverflow.com/a/62575953/365261

@silasrm
Copy link

silasrm commented Jun 29, 2020

Any solution to pagination?

@bhaskar-nair2
Copy link

Really looking forward to the Pagination Cookbook...

Well, hello there

@posva
Copy link
Member Author

posva commented Oct 13, 2022

Thanks everybody for the feedback 🙏.

I'm currently migrating the library and I hope to start releasing alphas soon. You can follow the advancement at #1241
I will add things from this issue as I advance

@posva posva closed this as completed Oct 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs firestore new Cloud Store RTDB Old Firebase realtime database
Projects
None yet
Development

No branches or pull requests