flamelink / flamelink-js-sdk

🦊 Official Flamelink JavaScript SDK for both the Firebase Realtime database and Cloud Firestore
https://flamelink.github.io/flamelink-js-sdk
MIT License
43 stars 5 forks source link

Issue with obtaining schema from promise #126

Closed singamnv closed 4 years ago

singamnv commented 4 years ago

Hi,

When I was using just firestore, the firebase.js config file looked like this:

firebase.initializeApp(config); const db = firebase.firestore() export const firebaseAuth = firebase.auth() export const dbMenuRef = db.collection('general')

However, when I use Flamelink, I get a TypeError: undefined is not a promise with the following code in the firebase.js:

const firebaseApp = firebase.initializeApp(config);

const app = flamelink({ firebaseApp, // required dbType: "cf", // can be either 'rtdb' or 'cf' for Realtime DB or Cloud Firestore env: "production", // optional, default shown locale: "en-US", // optional, default shown precache: true, // optional, default shown. Currently it only precaches "schemas" for better performance });

export async function dbGeneral() { return await app.content.get({ schemaKey: 'general' })

My Store Actions looks like this: import { dbMenuRef } from "../../firebase";

const actions = { setGeneralRef: firestoreAction(context => { return context.bindFirestoreRef('menuItems', dbGeneralRef) }), }

I am unable to import the dbGeneral into my store actions. Any ideas? Is there a simpler way to obtain the content of this schema?

gitdubz commented 4 years ago

Hi @singamnv, Where is firestoreAction defined? I can see that you are using it but it is not defined anywhere.

gitdubz commented 4 years ago

To better help you, it seems like you are using VuexFire? (I am following the example here - https://vuefire.vuejs.org/api/vuexfire.html#firestoreaction)

Additionally export const dbMenuRef = db.collection('general') - I am assuming the dbMenuRef you are creating here is to a custom collection you already have in Firestore.

/* firebase.js */
const firebaseApp = firebase.initializeApp(config);
const db = firebase.firestore()
export const firebaseAuth = firebase.auth()
export const dbMenuRef = db.collection('general')

const app = flamelink({
firebaseApp, // required
dbType: "cf", // can be either 'rtdb' or 'cf' for Realtime DB or Cloud Firestore
env: "production", // optional, default shown
locale: "en-US", // optional, default shown
precache: true, // optional, default shown. Currently it only precaches "schemas" for better performance
});
/* actions/store.js */
import { firestoreAction } from 'vuexfire'
import { dbMenuRef } from "../../firebase";

// Creating a ref to the fl_settings.general document
const actions = {
 setGeneralRef: firestoreAction(context => {
    context.bindFirestoreRef('general', app.content.get({ schemaKey: 'general' }));
    context.unbindFirestoreRef('general');
 }),

// Creating a ref to the db.collection('general') collection
 setMenuRef: firestoreAction(context => {
   context.bindFirestoreRef('menuItems', dbMenuRef);
    context.unbindFirestoreRef('menuItems');
 }),
}
singamnv commented 4 years ago

Thank you for your reply. I feel like I am still missing something. I am trying to bind using app.vue created() method. Still getting a TypeError. Below are the firebase.js, general.js (store), and app.vue files. Thank you for your assistance. I am just learning my way around web development.

Firebase.js file

import firebase from "firebase/app"
import 'firebase/firestore'
import flamelink from "flamelink/app";
import "flamelink/content";

const config = {
  apiKey: "xxxxxxxxxxxxxx,
  authDomain: "xxxxxxxxxxx",
  databaseURL: "xxxxxxxxxxxxx,
  projectId: "xxxxxxxxx",
  storageBucket: "xxxxxxxxx",
  messagingSenderId: "xxxxxx",
  appId: "1:xxxxxxx:xxxxxx",
  measurementId: "G-xxxxxxxxxxx",
};

const firebaseApp = firebase.initializeApp(config);

export const app = flamelink({
  firebaseApp, // required
  dbType: "cf", // can be either 'rtdb' or 'cf' for Realtime DB or Cloud Firestore
  env: "production", // optional, default shown
  locale: "en-US", // optional, default shown
  precache: true, // optional, default shown. Currently it only precaches "schemas" for better performance
});

general.js (part of firebases tore)

mport { firestoreAction } from "vuexfire";
import { app } from "../../firebase";

const state = {
  generalContent: []
};

const getters = {
  getGeneralContent:(state) => state.generalContent,
};
const mutations = {};
const actions = {
  setGeneralRef: firestoreAction(context => {
    context.bindFirestoreRef('general', app.content.get({ schemaKey: 'general' }));
    context.unbindFirestoreRef('general');
  })
};
export default {
  state,
  mutations,
  getters,
  actions,
};

App.vue


<template>
  <b-container fluid>
        <app-header />
         <b-container class="home-wrapper" fluid>
            <Sidebar class="nav-bar"/>
            <router-view class="home"></router-view>
        </b-container>
  </b-container>
</template>

<script>
  import Header from './components/Header'
  import Sidebar from './components/Sidebar'
  import { app } from './firebase'
  export default {
  name: 'App',
  components: {
    appHeader: Header,
    Sidebar,
  },
  async created(){
      this.$store.dispatch('setGeneralRef', app.content.get({ schemaKey: 'general' }))
  }
}
</script>
singamnv commented 4 years ago

Also when I try console.log this is what i get:

console.log(app.content.get({ schemaKey: "general" }));

above

 context.bindFirestoreRef('general', app.content.get({ schemaKey: 'general' }));

I get this:

Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Object

And the error I am getting is:

Uncaught (in promise) TypeError: document.onSnapshot is not a function
    at bindDocument (vuexfire.esm.js?3317:444)
    at eval (vuexfire.esm.js?3317:602)
    at new Promise (<anonymous>)
    at bind$1 (vuexfire.esm.js?3317:591)
    at Object.bindFirestoreRef (vuexfire.esm.js?3317:643)
    at Store.eval (general.js?d886:55)
    at Store.firestoreEnhancedActionFn (vuexfire.esm.js?3317:642)
    at Array.wrappedActionHandler (vuex.esm.js?2f62:772)
    at Store.dispatch (vuex.esm.js?2f62:453)
    at Store.boundDispatch [as dispatch] (vuex.esm.js?2f62:343)
gitdubz commented 4 years ago

Hi @singamnv I think the issue is that VuexFire requires a ref for binding and the app.content.get actually makes the get call.

You can change app.content.get to app.content.ref see below.

/ actions/store.js /

import { firestoreAction } from 'vuexfire'

// Creating a ref to the fl_settings.general document
const actions = {
 setGeneralRef: firestoreAction(context => {
    context.bindFirestoreRef('general', app.content.ref('general'));
    context.unbindFirestoreRef('general');
 }),
}

The content.ref API is not documented but you can use it in two ways. For the whole collection - app.content.ref('general') For a specific entry - app.content.ref(['general', 'someFirestoreDocumentId']) ☝️ you will need to replace someFirestoreDocumentId with an actual Id from your DB.

singamnv commented 4 years ago

I appreciate your response. I transitioned out of Flamelink for this particular project. I like the CMS though and I will try again for a future project. Thanks

gitdubz commented 4 years ago

All the best! Hope to see you soon 👍