GithubHelp home page GithubHelp logo

mesqueeb / vuex-easy-firestore Goto Github PK

View Code? Open in Web Editor NEW
233.0 9.0 31.0 8.08 MB

Easy coupling of firestore and a vuex module. 2-way sync with 0 boilerplate!

Home Page: https://mesqueeb.github.io/vuex-easy-firestore

License: MIT License

JavaScript 70.52% TypeScript 29.48%
firestore vuex vuex-store sync firebase store vuejs vue google-firebase firebase-firestore firebase-cloud-firestore

vuex-easy-firestore's Introduction

Vuex Easy Firestore ๐Ÿ”ฅ

In just 4 lines of code, get your vuex module in complete 2-way sync with firestore:

const userModule = {
  firestorePath: 'users/{userId}/data',
  firestoreRefType: 'collection', // or 'doc'
  moduleName: 'user',
  statePropName: 'docs',
  // the rest of your module here
}
// add userModule as vuex plugin wrapped in vuex-easy-firestore

and Alakazam! Now you have a vuex module called user with state: {docs: {}}. All firestore documents in your collection will be added with the doc's id as key inside docs in your state.

Now you just update and add docs with dispatch('user/set', newItem) and forget about the rest!

Other features include hooks, fillables (limit props to sync), default values (add props on sync), a fetch function and much more...

Installation and setupใ€€โ†’

Motivation

I didn't like writing an entire an API wrapper from scratch for firestore every single project. If only a vuex module could be in perfect sync with firestore without having to code all the boilerplate yourself...

And that's how Vuex Easy Firestore was born.

Documentation

See the all new documentation made with VuePress!

Full documentation

Support

If you like what I built, you can say thanks by buying me a coffee! :)

Buy Me A Coffee

Thank you so much!! Every little bit helps.

vuex-easy-firestore's People

Contributors

ajgagnon avatar dependabot[bot] avatar dsl101 avatar fergusmeiklejohn avatar gnopps avatar louisameline avatar mesqueeb avatar wifisher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vuex-easy-firestore's Issues

[Request] closeDBChannel function

Hi,

In the example Variables for firestorePath or filters there's an example that uses the user id to load data, one problem i have run into is that I want to load a specific collection's docs based on the store state, but i haven't found something like a closeDBChannel action which means that I end up syncing multiple DB locations to the same module's state. Is there any way i can .off() or is there something like closeDBChannel that I've missed?

Keep up the good work

[documentation] clarify the "doc order" of a collection

Below is my config. I have a collection that is synced by desc. but after server hook run, latest document get appended to the bottom.

const billsDataModule = {
  firestorePath: 'companies/{companyId}/bills',
  firestoreRefType: 'collection',
  moduleName: 'billsData',
  statePropName: 'bills',
  sync: {
    orderBy: ['timestamp', 'desc'],
    where: [['type', '==', process.env.NODE_ENV]]
  },
  serverChange: {
    addedHook: function (updateStore, doc, id, store, source, change) {
      updateStore(doc)
    },
    modifiedHook: function (updateStore, doc, id, store, source, change) {
      updateStore(doc)
    },
    removedHook: function (updateStore, doc, id, store, source, change) { updateStore(doc) }
  },
  getters: {
    getBillById: (state) => (id) => {
      return state.bills[id]
    }
  }
}

Insert batch: created_at error

An firebase error is thrown when not using the firestorePath: 'users/{userId}/data as the path but instead for example:

const userModule = {
  firestorePath: 'users',
  firestoreRefType: 'collection',
  moduleName: 'userData',
  statePropName: 'docs',
  // the rest of your module here
}

When using any of the following two options:

dispatch('userData/set', doc)
dispatch('userData/insert', doc)

The insert fails due to the created_at field not having {userId} passed in. It was never included as it was not set in as part of the firestorePath config. Its when inserting into a batch in file index.es.js on line 397.

The reason it was never set is related to line 988 that looks for the {userId} in the path. If not found the userid is not set.

  inserts.forEach(function (item) {
    item.created_at = Firebase.firestore.FieldValue.serverTimestamp();
    item.created_by = userId;
    var newRef = dbRef.doc(item.id);
    batch.set(newRef, item);
  });

The temp edited snippet of the code that works when fetching the uid directly off the Firebase instance.

  inserts.forEach(function (item) {
    item.created_at = Firebase.firestore.FieldValue.serverTimestamp();
    item.created_by = Firebase.auth().currentUser.uid;
    var newRef = dbRef.doc(item.id);
    batch.set(newRef, item);
  });

The reason for not including the {userId} in the firestorePath is to avoid having to use sub-collections and that we use signIn anonymously users that wont have their data nested under their own userId. Instead would use the created_by field to fetch a single users records from a specific collection.

Hope this helps explain, kindly :)

patch operations revert

this is probably going to be hard to explain, sorry. Please let me know what else I should send?

I've uploaded a short video for your reference
http://www.youtube.com/watch?v=-KZ5UvPyGVM

patchHook(updateStore, doc, store) {
                const temp = {}
                // lodash.set(temp, doc.key, doc.val)
                temp[doc.key] = doc.val
                temp.id = doc.id
                console.log('updating item before patch!', temp)
                return updateStore(temp)
            }

that console prints

"id":"wXtIWV2ACo7HtAkDkYNn",
  "allergy": {
    "dairy": false,
    "dairy_o": true,
    "egg": true,
    "egg_o": false,
    "fish": false,
    "fish_o": true,
    "gluten": true,
    "gluten_o": false,
    "peanuts": true,
    "peanuts_o": true,
    "shellfish": false,
    "shellfish_o": false,
    "soy": true,
    "soy_o": true,
    "tree_nut": false,
    "tree_nut_o": false,
    "wheat": true,
    "wheat_o": true
  }
}"

my dispatch is inside a components method:

        vendorUpdateItem({ key }) {
            console.log('updating item!', this.item.id, key, lodash.get(this.item, key))
            this.$store.dispatch(`item/patch`, { id: this.item.id, key, val: lodash.get(this.item, key) })
        },

[Question] Auto creating a doc / connecting to a doc/collection that doesn't exist

If you try and openDBChannel to a doc that does not exist (such as a users/{user_id}) as they have just logged in for the first time you get a 'trying to merge a non-object' error.

Makes sense as no object in Firestore exisits. Usually with Firestore you can create a new doc by passing int o the collection and receiving the ID, but you should also be able to specify the ID and save a new doc.

Given you have to openDBChannel which they try's to access the doc - is there a good way to auto create a blank doc / populate it with default data?
It maybe that I cannot find in the docs a ref to 'setDefaultValues' which may be exactly what I want!!!

Quasar Support

Iโ€™ve installed and configured but cannot seem to call dispatch from my modules in quasar. Any ideas

Resolve insert/patch promises after actual execution at Firestore

Improve the way that inserting/patching gives feedback to the Dev to allow the Dev to easily implement things like loading spinners / animated svgs etc.


After about two years of open source, I finally got accepted for Github Sponsors!

๐Ÿ’œ github.com/sponsors/mesqueeb ๐Ÿ’œ

A little about me:

  • I love open-source
  • 6 months ago I got a son, and am trying to be an awesome father ๐Ÿ˜…
  • I'm doing freelance work here and there as my main job

If anyone was helped with vuex-easy-firestore, I'd greatly appreciate any support!

BTW, donations get's paid DOUBLE by GitHub! (they're alchemists... ๐Ÿฆพ)

Going forward ๐Ÿ‘จ๐Ÿผโ€๐Ÿ’ป

  • I got great plans for the future of vuex-easy-firestore going above and beyond!! Look forward to it!!
  • On to many more years of open-sourcing! ๐ŸŽ‰

Error: Data type: Reference in doc causes `Maximum call stack size exceeded`

When using a reference data type in a document, Maximum call stack size exceeded error is thrown during retrieval. If I use a different data type for that field author it works fine. Am i doing something wrong here?

Snapshot of document structure:

image

Module configuration code

const newsFeedModule = {
  firestorePath: "newsFeed",
  firestoreRefType: "collection",
  statePropName: "items"
};

Error in console

image

Firebase warning

This might need considering:

AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the
following code to your app before calling any other Cloud Firestore methods:

  const firestore = firebase.firestore();
  const settings = {/* your settings... */ timestampsInSnapshots: true};
  firestore.settings(settings);

With this change, timestamps stored in Cloud Firestore will be read back as
Firebase Timestamp objects instead of as system Date objects. So you will also
need to update code expecting a Date to instead expect a Timestamp. For example:

  // Old:
  const date = snapshot.get('created_at');
  // New:
  const timestamp = snapshot.get('created_at');
  const date = timestamp.toDate();

Please audit all existing usages of Date when you enable the new behavior. In a
future release, the behavior will change to the new behavior, so if you do not
follow these steps, YOUR APP MAY BREAK.```

[Bug] modules with overlapping names batch improperly

      const groupId = 'fooBarBaz';
      await this.$store.dispatch("groups/insert", {
        id: groupId,
      });
      await this.$store.dispatch("usergroups/insert", {
        id: 'tootyFruity',
        groupId,
        userId: this.$store.state.profile.uid,
      });

Running both of those insert statements back to back causes two objects to be inserted into the groups collection rather than one in both:

[vuex-easy-firestore] api call batch:
index.esm.js?34ed:414 Firestore PATH: groups
index.esm.js?34ed:416 updates:  []
index.esm.js?34ed:416 prop deletions:  []
index.esm.js?34ed:416 deletions:  []
index.esm.js?34ed:416 inserts:  (2)ย [{โ€ฆ}, {โ€ฆ}]

Am I doing something wrong or is this a bug?

make sure openDBChannel cannot be opened twice with the same path & conditions

First and foremost, great package. I have a question about the openDBChannel action: When I use openDBChannel multiple times for the same path, e.g. users/{userId} does it really register a new onSnapshot listener every time? So, let's say 5 components are interested in real-time updates (but not rendered at the same time) and in there created method they call the openDBChannel method, do I have 5 listeners now? And if so, what's the performance impact, if any?

Document References and document ids

I very much like the spirit of this module! I've been working with vue.js and firebase for a bit now and have had to roll-my-own for this functionality. Good on your for generalizing it!

However, before I can fully endorse it, there are a few things I'd like to know how to do:

Handling document references

I have firestore docs that look like this:

let userDoc = {
   userName: 'bob',
   defaultRegionRef: '/regions/northern-maine'
}

Is there a way where vuex-easy-firestore can populate the reference? Is my only option to do

userDoc.defaultRegionRef.get()...

and manually add it to the store?

Access the ID for a single doc

With the following doc firestoreRefType, I am unable to access the document id after retrieval.

const currentUserModule = {
    firestorePath: "users/{userId}",
    firestoreRefType: "doc", // or 'doc'
    moduleName: "currentUser",
};

after currentUser/openDBChannel

console.log(
   "user id:",
   this.$store.state.currentUser.id
);
// logs out "user id: {userId}"

Thanks so much!

Collections inception

Hey there!

I was wondering how to handle collections where documents have a subcollection and where those documents also have subcollections. For example: countries/{countryId}/cities/{cityId]/streets.
Is there a way to load all the data in one object, and still be able to add to these documents?
Another example, say I'd like to add the cities Amsterdam and The Hague into 'The Netherlands' document, and add 'Kalverstraat' to the city 'Amsterdam'. Is this possible, or is my DB flawed by design? I'd have views where I'd like to show all countries, all cities in a specific country, and all streets in a specific city in a specific country.

sub collections

Excellent project.
How do you work with subcollections when the key is a variable.

const userModule = {
firestorePath: 'boats/{myBoatID}/data',
firestoreRefType: 'collection', // or 'doc'
moduleName: 'boats',
statePropName: 'docs',
// the rest of your module here
}

[docs] manually assigning IDs

Add this to readme:

Manually assigning IDs

When assigning ID's manually the recommended way to do so is:
store.getters['yourModule/dbRef'].doc().id

There is a getter called dbRef created on each vuex-easy-firestore module with the reference of your firestorePath. So with adding .doc().id to that you will "create" a new ID you can pass.

You could wrap it like so:

function newId () {
  return store.getters['yourModule/dbRef'].doc().id
}

and just do newId() to get a new ID each time! (I'll have to clarify this in the docs)

[NUXT] Set Firestore in nuxtServerInit

I'm currently using in the created() method of the home page but I was wondering if this would be possible to use with the nuxtServerInit action.
I'm specifically using 'fetch' but would love to know how to use any of the functions within nuxtServerInit.

    this.$store.dispatch('locationData/fetch', { orderBy: ['rating', 'desc'] })
      .then(querySnapshot => {
        if (querySnapshot.done === true) {
          // `{done: true}` is returned when everything is already fetched and there are 0 docs:
          return '0 docs left to retrieve'
        }
        // here you can the Firestore `querySnapshot` which is returned
        querySnapshot.forEach(doc => {
          // you have to manually add the doc with `fetch`
          const location = doc.data()
          location.id = doc.id
          location.rating = doc.data().rating
          location.lodging = doc.data().budget.lodging
          location.food = doc.data().budget.food
          location.transportation = doc.data().budget.transportation
          db.collection('locations').doc(location.id).collection('historic').doc(currentMonth).get()
          .then(doc => {
              location.airTemp = doc.data().airTemp != null ? doc.data().airTemp : 0
              location.waterTemp = doc.data().waterTemp
              location.currentMonthRating = doc.data().rating != null ? doc.data().rating : 0
              this.$store.commit('locationData/INSERT_DOC', location)
              // also don't forget that in this case `defaultValues` will not be applied         
          })
        })
      })
      .catch(console.error) 

Has anyone worked with VuexFire ?

I have seen VuexFire before, but I don't have much experience with it.

If anyone has worked with VuexFire before, please let me know down below what you thought of it compared to vuex-easy-firestore!

I'd love to know any differences you have noticed or if there are any features on VuexFire we could implement in here as well!

I believe vuex-easy-firestore's strong points are:

  • great documentation
  • simple setup
  • easy to use
  • very powerful customisation possible

I believe vuex-easy-firestore's weak points are:

  • slight size overhead: I want to make it as lightweight as possible going forward!
  • documentation is only in English
    • please let me know (open an issue) if you want to contribute in another language!
    • I would love Chinese, Spanish & French asap!

Vuex Easy Firestore was made with โ™ฅ by Luca Ban.
If this library helped you in any way you can support me by buying me a cup of coffee.

Get Doc but id always equals null

When I call collections, the id comes back correctly for each item, but when calling a single document the id always is null...

store.js

const locksData = {
  firestorePath: 'locks/',
  firestoreRefType: 'collection', // collection or 'doc'
  moduleName: 'locksData',
  statePropName: 'data',
  sync:{
    where:[['cId', '==', '{customerId}']]
  }
}

const lockData = {
  firestorePath: 'locks/{lockId}/',
  firestoreRefType: 'doc', // collection or 'doc'
  moduleName: 'lockData',
  statePropName: 'data',
}

component.js

this.$store.dispatch('lockData/openDBChannel', {lockId: this.$route.params.lockId})
      .then(console.log)
      .catch(console.error)

collection results

image

single doc result

image

Setting empty object doesn't sync properly

Hi! First of all, thanks for this great library @mesqueeb

I'm trying to build a kind of restaurant management system with Vuex and Firestore. But when I update the shipping basket/checkout, although correctly updated in Vuex, it's not updated rightly in Firestore and it returns the old items.

Sample of Checkouts Firestore collection

checkouts = {
    "vlVVfyVtXFRmpIqVqNPV": {
        id: "vlVVfyVtXFRmpIqVqNPV",
        table: 2,
        totalPrice: 23,
        items: {
            "87jHxITagtdioYowShp2": {
                id: "87jHxITagtdioYowShp2",
                name: "Cake",
                units: 2,
                price: 2.5,
                totalPrice: 5
            },
            "A7k23pIRr4VqWJLbFHcb": {
                id: "A7k23pIRr4VqWJLbFHcb",
                name: "Orange Juice",
                units: 1,
                price: 3,
                totalPrice: 3
            }
        }
    }
}

Expected behaviour

When I remove an item (because I added by mistake), I do:

// Remove the product because it has only 1 unit
// Either do `delete updatedCheckout.items["A7k23pIRr4VqWJLbFHcb"]`
// or Vue.delete(updatedCheckout.items,"A7k23pIRr4VqWJLbFHcb" )
// so I end up with:
checkout = {
    id: "vlVVfyVtXFRmpIqVqNPV",
    table: 2,
    totalPrice: 23,
    items: {
        "87jHxITagtdioYowShp2": {
            id: "87jHxITagtdioYowShp2",
            name: "Cake",
            units: 2,
            price: 2.5,
            totalPrice: 5
        }
    }
}

this.$store.dispatch('chargeData/patch', checkout)

checkoutsData/PATCH_DOC is executed twice, one with the document with one item, but the second (that comes from the server) has the two items, so I end with not being able to remove an item!

I think that it's because Firestore doesn't get along with empty objects (it happens the same if I want to delete all items by dispatching items: {}). I've read something about a mergeparam mentioned here that maybe could help.

I would appreciate any help on how could I set empty objects and being properly sync'ed with Firestore.

Thank you very much @mesqueeb

Error: The behavior for Date objects stored in Firestore is going to change

The most recent version of Firestore (5.5.0) introduces a warning that requires you to pass in a new configuration object in order to suppress it. Currently there seems to be no way to accomplish this in the vuex-easy-firestore initialization.

Here is the logged warning by Firestore:

@firebase/firestore: Firestore (5.5.0): 
The behavior for Date objects stored in Firestore is going to change
AND YOUR APP MAY BREAK.
To hide this warning and ensure your app does not break, you need to add the
following code to your app before calling any other Cloud Firestore methods:

  const firestore = firebase.firestore();
  const settings = {/* your settings... */ timestampsInSnapshots: true};
  firestore.settings(settings);

With this change, timestamps stored in Cloud Firestore will be read back as
Firebase Timestamp objects instead of as system Date objects. So you will also
need to update code expecting a Date to instead expect a Timestamp. For example:

  // Old:
  const date = snapshot.get('created_at');
  // New:
  const timestamp = snapshot.get('created_at');
  const date = timestamp.toDate();

Please audit all existing usages of Date when you enable the new behavior. In a
future release, the behavior will change to the new behavior, so if you do not
follow these steps, YOUR APP MAY BREAK.

[Question] I can't get the data

I am unable to get my data in vuex. It's state always empty.

  • I initialized firebase config in my main.js file
  • My store contains the plugin
  • I am not using user authentication, may be I need to use openDBChannel, but where?

code

Please, what are my doing wrong ?

use with typescript

Hello,
congratulations for this very interesting module.

Is it possible to use it with Vuex and Typescript?

I already have a code base using Vuex+Typescript, but decided to test vuex-easy-firestore for a new store module.

I'm getting 2 errors:

  1. When importing module.js into index.ts i get:

Could not find a declaration file for module './events/index.js'. '/home/andreav/Workspace/sosfilomena/src/store/events/index.js' implicitly has an 'any' type

I changed the import from:
import EventModule from './events/index.js'
to
let EventModule = require('./events/index')

  1. Now when I start the site, I get this error:
Uncaught TypeError: plugin is not a function
 at eval (vuex.esm.js?2f62:351)
    at Array.forEach (<anonymous>)
    at new Store (vuex.esm.js?2f62:351)
    at eval (index.ts?0613:23)
    at Module../src/store/index.ts (main.js:8875)
    at __webpack_require__ (main.js:768)
    at fn (main.js:131)
    at eval (auth-guard.js?cfc9:1)
    at Module../src/router/auth-guard.js (main.js:8839)
    at __webpack_require__ (main.js:768)

My versions:

    "vue": "^2.5.17",
    "vuex": "^3.0.1",
    "vuex-easy-firestore": "^1.17.0"

My index.ts

import Vue from 'vue';
import Vuex, { StoreOptions } from 'vuex';
import { RootState } from './types';
import { user } from './user/index';
let EventModule = require('./events/index')

Vue.use(Vuex);

const store: StoreOptions<RootState> = {
    state: {
        version: '1.0.0' // a simple property
    },
    modules: {
        user,
    },
    plugins: [EventModule]
};

export default new Vuex.Store<RootState>(store);

Thank you!

[Bug] FIRESTORE (5.5.9) INTERNAL ASSERTION FAILED: AsyncQueue is already failed

This lib has saved me so much time, thank you!
I'm trying to find out if this error is because of something I'm doing, but I am successfully using this in most of my app without problems.

I'll keep looking into it.

code calling the store patch

const temp = { id: modObj.id, [`choices.${idx}`]: modObj.choices[idx] }
console.log('updating choices at index', temp)
this.$store.dispatch('mod/patch', temp)

here is my module:

patchHook(updateStore, doc, store) {
     console.log('updating mod store', doc)
     // PRINTS:  updating mod store {choices: "Description", id: "ijDrBfbGZooA9J0sXKh4"}
     return updateStore(doc)
},

Which then prints from the debugger:

[vuex-easy-firestore] api call batch:
VM108118 index.esm.js:522 Firestore PATH: mod/ [mod/]
VM108118 index.esm.js:524 updates:  [{โ€ฆ}]
VM108118 index.esm.js:524 prop deletions:  []
VM108118 index.esm.js:524 deletions:  []
VM108118 index.esm.js:524 inserts:  []

The error itself

VM108112 index.esm.js:81 [2018-11-24T22:12:54.348Z]  @firebase/firestore: Firestore (5.5.9): FIRESTORE (5.5.9) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: Error: FIRESTORE (5.5.9) INTERNAL ASSERTION FAILED: Transform results missing for TransformMutation.
    at fail (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:151:11)
    at assert (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:159:9)
    at TransformMutation.applyToRemoteDocument (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:3808:9)
    at MutationBatch.applyToRemoteDocument (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:7972:37)
    at eval (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:12773:33)
    at eval (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:8235:63)
    at PersistencePromise.wrapUserFunction (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:8221:26)
    at PersistencePromise.wrapSuccess (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:8235:25)
    at PersistencePromise.next (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:8196:29)
    at eval (webpack-internal:///./node_modules/@firebase/firestore/dist/index.cjs.js:12768:18)
defaultLogHandler @ VM108112 index.esm.js:81
Logger.error @ VM108112 index.esm.js:171
error @ VM108114 index.cjs.js:99
fail @ VM108114 index.cjs.js:147
AsyncQueue.verifyNotFailed @ VM108114 index.cjs.js:7743
AsyncQueue.enqueue @ VM108114 index.cjs.js:7695
AsyncQueue.enqueueAndForget @ VM108114 index.cjs.js:7687
FirestoreClient.write @ VM108114 index.cjs.js:18326
(anonymous) @ VM108114 index.cjs.js:19811
step @ VM108106 tslib.es6.js:111
(anonymous) @ VM108106 tslib.es6.js:92
(anonymous) @ VM108106 tslib.es6.js:85
__awaiter @ VM108106 tslib.es6.js:81
WriteBatch.commit @ VM108114 index.cjs.js:19806
(anonymous) @ VM108118 index.esm.js:736
batchSync @ VM108118 index.esm.js:735
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
(anonymous) @ VM108118 index.esm.js:725
Promise.then (async)
handleSyncStackDebounce @ VM108118 index.esm.js:725
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
patchDoc @ VM108118 index.esm.js:666
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
storeUpdateFn @ VM108118 index.esm.js:1060
patchHook @ VM108125 index.js:39
patch @ VM108118 index.esm.js:1064
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
updateConfigObj @ VM108655 modManager.vue:273
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM118663 modListItem.vue:59
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM108677 modDetail.vue:50
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM108693 multipleChoice.vue:114
blur @ VM108691 multipleChoice.vue:59
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
__onBlur @ VM108005 input.js:56
(anonymous) @ VM108005 input.js:50
setTimeout (async)
__onInputBlur @ VM108005 input.js:49
invoker @ VM107773 vue.esm.js:2026
fn._withTask.fn._withTask @ VM107773 vue.esm.js:1825
VM108118 index.esm.js:749 Error during synchronisation โ†“
(anonymous) @ VM108118 index.esm.js:749
Promise.catch (async)
(anonymous) @ VM108118 index.esm.js:746
batchSync @ VM108118 index.esm.js:735
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
(anonymous) @ VM108118 index.esm.js:725
Promise.then (async)
handleSyncStackDebounce @ VM108118 index.esm.js:725
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
patchDoc @ VM108118 index.esm.js:666
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
local.dispatch @ VM108097 vuex.esm.js:642
storeUpdateFn @ VM108118 index.esm.js:1060
patchHook @ VM108125 index.js:39
patch @ VM108118 index.esm.js:1064
wrappedActionHandler @ VM108097 vuex.esm.js:712
dispatch @ VM108097 vuex.esm.js:434
boundDispatch @ VM108097 vuex.esm.js:340
updateConfigObj @ VM108655 modManager.vue:273
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM118663 modListItem.vue:59
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM108677 modDetail.vue:50
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
updateModObj @ VM108693 multipleChoice.vue:114
blur @ VM108691 multipleChoice.vue:59
invoker @ VM107773 vue.esm.js:2026
Vue.$emit @ VM107773 vue.esm.js:2537
e.(anonymous function) @ VM107663 backend.js:1
__onBlur @ VM108005 input.js:56
(anonymous) @ VM108005 input.js:50
setTimeout (async)
__onInputBlur @ VM108005 input.js:49
invoker @ VM107773 vue.esm.js:2026
fn._withTask.fn._withTask @ VM107773 vue.esm.js:1825
VM108114 index.cjs.js:151 Uncaught (in promise) Error: FIRESTORE (5.5.9) INTERNAL ASSERTION FAILED: AsyncQueue is already failed: Error: FIRESTORE (5.5.9) INTERNAL ASSERTION FAILED: Transform results missing for TransformMutation.
    at fail (VM108114 index.cjs.js:151)
    at assert (VM108114 index.cjs.js:159)
    at TransformMutation.applyToRemoteDocument (VM108114 index.cjs.js:3808)
    at MutationBatch.applyToRemoteDocument (VM108114 index.cjs.js:7972)
    at eval (VM108114 index.cjs.js:12773)
    at eval (VM108114 index.cjs.js:8235)
    at PersistencePromise.wrapUserFunction (VM108114 index.cjs.js:8221)
    at PersistencePromise.wrapSuccess (VM108114 index.cjs.js:8235)
    at PersistencePromise.next (VM108114 index.cjs.js:8196)
    at eval (VM108114 index.cjs.js:12768)
    at fail (VM108114 index.cjs.js:151)
    at assert (VM108114 index.cjs.js:159)
    at TransformMutation.applyToRemoteDocument (VM108114 index.cjs.js:3808)
    at MutationBatch.applyToRemoteDocument (VM108114 index.cjs.js:7972)
    at eval (VM108114 index.cjs.js:12773)
    at eval (VM108114 index.cjs.js:8235)
    at PersistencePromise.wrapUserFunction (VM108114 index.cjs.js:8221)
    at PersistencePromise.wrapSuccess (VM108114 index.cjs.js:8235)
    at PersistencePromise.next (VM108114 index.cjs.js:8196)
    at eval (VM108114 index.cjs.js:12768)
    at fail (VM108114 index.cjs.js:151)
    at AsyncQueue.verifyNotFailed (VM108114 index.cjs.js:7743)
    at AsyncQueue.enqueue (VM108114 index.cjs.js:7695)
    at AsyncQueue.enqueueAndForget (VM108114 index.cjs.js:7687)
    at FirestoreClient.write (VM108114 index.cjs.js:18326)
    at WriteBatch.eval (VM108114 index.cjs.js:19811)
    at step (VM108106 tslib.es6.js:111)
    at Object.eval [as next] (VM108106 tslib.es6.js:92)
    at eval (VM108106 tslib.es6.js:85)
    at new Promise (<anonymous>)****

Vue CLI basic example, demo app needed

First let me thank you for this interesting library.
This is what I would need to start my simple project.
But it would be great help if you could add simple demo app based on Vue CLI template.
Especially for someone that starts with Vue and Firestore for first time, would be much easier to see what's going where in the code.

Best way to reload documents with a different path variable?

Say I have the following vuex-easy-firestore module, where a set of projects are located under a single organization:

const projectsModule = {
    firestorePath: 'organizations/{orgId}/projects',
    firestoreRefType: 'collection',
    moduleName: 'projects',
    statePropName: 'docs',
}

The module state can be populated from within a component with

this.$store.dispatch('projects/openDBChannel', { orgId: this.orgId })

So far so good. But when the user selects a different organization, I need the local projects state to be cleared and re-populated according to the new value of orgId. What's the most efficient vuex-easy-firestore way to do that? Thanks in advance!

[Request] Action to handle transactions

I have a situation, I need transaction for example find this scenario. Here I have to increment a number before insert. How can I handle this with vuex-easy-firestore. What is the best way

[db.runTransaction(t => {
        let companyRef = db.collection('companies').doc(user.company)
        return t.get(companyRef)
          .then(doc => {
            let currentBillNumber = doc.data().currentBillNumber + 1
            t.update(companyRef, {currentBillNumber: currentBillNumber})
            billDocRef = db.collection('companies/' + user.company + '/bills').doc()
            newBillState = {
              firstname: this.firstname,
              lastname: this.lastname,
              emailaddress: this.emailaddress,
              phonenumber: this.phonenumber,
              amount: this.amount,
              items: this.items,
              slug: slug,
              timestamp: new Date().getTime(),
              type: process.env.NODE_ENV,
              vehiclenumber: this.vehiclenumber,
              sequenceNumber: currentBillNumber
            }
            t.set(billDocRef, newBillState)
          })
      }).then(result => {
        console.log('incrementAndUpdateBill Transaction success!')
      }).catch(err => {
        console.log('incrementAndUpdateBill Transaction failure:', err)
      })
    }]([url](url))

[Question] How to Auth with firestore

Hi!
You have an example of how to connect to Firestore using the AuthStateChanged but is it possible to pass in a firebase object or config with a API key etc?
Basically can you connect to firebase the normal way?

Thanks for this package!
D

Multiple Collections Help

I've spent a few days trying to get this working, but I'm not understanding where I'm going wrong.

I added this to main.js

let app;
firebase.auth().onAuthStateChanged(function(user) {
  if(!app){
    if (user) {
      console.log('user', user);
      // user is logged in
      store.dispatch('userData/openDBChannel')
        .then( () => {
          
        })
        .catch(console.error)

      }
    /* eslint-disable no-new */
    app = new Vue ({
      el:'#app',
      router,
      store,
      render: h => h(App)
    })

  }
});

The User loads just fine, at first I was loading another collection inside the ".then" after dispatch and it was calling the collection immediately when the site loaded. I needed to delay this for when the component loads, so I moved it inside the component at the "created()" function, but it never got my second collection. What am I doing wrong?

Neat library by the way, it will save a lot of redundant code :)

dbRef.onSnapshot is not a function

Hey,

would love to get this working.

When trying this setup:

const userDataModule = {
  firestorePath: 'users/{userId}/displayName',
  firestoreRefType: 'collection', // or 'doc'
  moduleName: 'userData',
  statePropName: 'userDocs',
}

I keep getting: dbRef.onSnapshot is not a function

Also, how to use this module with mapGetters?

Injection of userId on sync.where

Hi

It would be really usable if one have userId injected onto a sync.where configuration like:

sync: {
    where: [['users', 'array-contains', '{userId}']]
  } 

Best regards,
Jon

Adding orderBy to sync returns no results

I've run into some strange behavior I think may be a bug?

This code:

export default {
  firestorePath: 'groups',
  firestoreRefType: 'collection',
  moduleName: 'groups',
  statePropName: 'collection',
  sync: {
    orderBy: ['created_date']
  }
}

Only returns results when the orderBy field has been commented out. With the orderBy line as it is above, I get no results. If I remove that line, the results of my query appear. I've verified the automatic created_date is present so I'm not sure why its not returning data.

How to do forEach/multiple channels?

I'm not sure about I'm missing something or not.

How to multiple channels? like..

// forEach
dispatch('users/openDBChannel', { uid: 'ABC' })
dispatch('users/openDBChannel', { uid: 'XYZ' })

And right now I'm doing something like... (and it's work)

createEasyFirestore({
  firestorePath: 'users/{uid}',
  firestoreRefType: 'doc',
  moduleName: 'users',
  serverChange: {
    modifiedHook: (updateStore, doc, id, store, source, change) => {
      store.state.users[doc.uid] = doc
    },
    addedHook: (updateStore, doc, id, store, source, change) => {
      store.state.users[doc.uid] = doc
    }
  }
})

But does it not easier if we could do something like...?

createEasyFirestore({
  firestorePath: 'users/{uid}',
  firestoreRefType: 'doc',
  // moduleName: 'users/{uid}', ???
  // statePropName: '{uid}' ???
})

Expected result:

state : {
   users: {
      'ABC' : 'data',
      'XYZ' : 'data',
      // _conf: (...)
      // _sync: (...)
   }
}

I'm missing something?

Cheers! vuex-easy-firestore ๐Ÿบ

Fetch single document

Hey again,

how to best fetch a single document, for example in a route?
Do I need to do a fetchAndAdd with a filter for the doc id?
or could i use a the 'doc' mode?

Thanks

Serverchange hooks

When making changes to data in firestore (updating a data attribute via the database view in firebase), i dont see the serverChange.modifiedHook firing. Here's the module code. Is this misconfigured?

const module = {
    firestorePath: 'items',
    firestoreRefType: 'collection', 
    moduleName: 'items',
    statePropName: 'docs',
    serverChange: {
        modifiedHook: function (updateStore, doc, id, store, source, change) { console.log("modified");  }
    }
}

Trouble referencing docs

Not had a problem with collections.
But not sure why I can't reference a document correctly.
In my store...
const gameData = { firestorePath: "games/{gameId}", firestoreRefType: "doc", moduleName: "gameData", statePropName: "game" };
In my view
this.$store .dispatch("gameData/openDBChannel", { gameId: "game1" }) //this.$route.params

This creates a document with the id {gameId} in my firestore DB
I want "games/game1" not "games/{gameId}"

TypeError: Cannot create property 'id' on number '0'

I'm inserting a new document and get the error

TypeError: Cannot create property 'id' on number '0'
    at Store.insert (index.esm.js?34ed:993)
        addMod() {
            const order = this.itemMods.length
            this.$store.dispatch('mod/insert', { order })
             // order = { order: 0 }
        },

if I change that by simply adding another key it works.

        addMod() {
            const order = this.itemMods.length
            this.$store.dispatch('mod/insert', { order, required:true })
        },

store module (even though it doesn't even make it this far)

export default {
    mod: {
        firestorePath: 'mod/',
        firestoreRefType: 'collection',
        moduleName: 'mod',
        statePropName: 'modList',
        sync: {
            insertHook(updateStore, doc, store) {
                console.log('inserted', doc)
                const defaultItem = {
                    id: doc.id,
                    required: true,
                    label: 'Option Name',
                    min: 1,
                    max: 1,
                    order: doc.order,
                    basePriceOverride: false,
                    type: 'multiple-choice',
                    choices: [
                        {
                            key: '0',
                            label: '',
                            order: 0,
                            p: '0',
                        },
                    ],
                }
                console.log('updating store', defaultItem)
                return updateStore(defaultItem)
            }
        },
    },
}

error in dispatch call

@mesqueeb I tried calling
dispatch('user/openDBChannel')
where user is the name of a module From another Module's action I used for initialisation and get the below error

unknown local action type: user/openDBChannel, global type: util/user/openDBChannel

do i still need to pass in

{ root: true }

to dispatch action in other modules?
P.S I tried with the {root:true} option and got same error still

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.