Vue + Firebase: Functions useEmulator() ignored - javascript

I found this line of code in the Firebase docs firebase.functions().useEmulator('localhost', 5001) that supposedly points your Vue app to the locally running emulator, but for some reason my project is ignoring said line of code and continues to call the remotely deployed function instead.
Here's what the relevant part of my #/plugins/firebase.js looks like:
import firebase from 'firebase/app';
import 'firebase/functions';
firebase.initializeApp({
apiKey: process.env.VUE_APP_FIREBASE_API_KEY,
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL,
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID,
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.VUE_APP_FIREBASE_MESSAGE_SENDER_ID,
appId: process.env.VUE_APP_FIREBASE_APP_ID,
measurementId: process.env.VUE_APP_FIREBASE_MEASUREMENT_ID
});
firebase.functions().useEmulator('localhost', 5001);
const func = {
botcheck: firebase.app().functions('europe-west2').httpsCallable('validateRecaptcha'),
};
export { func };
And then to call the botcheck function, I'll run the following in a Vuex action:
const fb = require('#/plugins/firebase');
...
await fb.func.botcheck();
What am I doing wrong? How do I get it to correctly point to my locally running emulator?
Vue project versions:
vue: 2.6.11
firebase: 8.3.2
Functions project versions:
firebase-admin: 9.2.0
firebase-functions: 3.11.0
Let me know if I need to include additional information.

This line:
firebase.functions()
is functionally equivalent to:
firebase.app().functions('us-central1')
In your current code, you connect functions that don't specify a region to the emulator. Because you specify the region as europe-west2 when using it, you need to connect the europe-west2 functions to the emulator. You can do this by changing this line:
firebase.functions().useEmulator('localhost', 5001);
to use the correct region:
firebase.app().functions('europe-west2').useEmulator('localhost', 5001)
Additional Note: While firebase.functions() and firebase.app().functions() return the same instance of a Functions object (connected to the us-central1 region), firebase.app().functions('us-central1') (where you pass in the region) returns a different instance of Functions. You would need to connect each instance that you use to the emulator.

Here's your code as I make sure that useEmulator() is configured properly with Cloud Functions for Firebase Emulator. Feel free to try it:
import firebase from 'firebase/app';
import 'firebase/functions';
const firebaseConfig = {
// Your config
};
const app = firebase.initializeApp(firebaseConfig);
const functions = app.functions('europe-west2');
functions.useEmulator('localhost', 5001);
const func = {
botcheck: functions.httpsCallable('validateRecaptcha'),
};
export { func };

Related

Having error attempting to use RTDB in Expo managed

I'm attempting to use firebase realtime database on my app. I first authenticate and then I need to use the RTDB. Here is my attempt.
import { initializeApp } from 'firebase/app';
import 'firebase/auth';
import 'firebase/storage';
import { getDatabase } from "firebase/database";
import getEnvVars from '../environment';
const ENV = getEnvVars();
const firebaseConfig = {
apiKey: ENV.firebase.API_KEY,
authDomain: ENV.firebase.AUTH_DOMAIN,
databaseURL: ENV.firebase.DATABASE_URL,
projectId: ENV.firebase.PROJECT_ID,
storageBucket: ENV.firebase.STORAGE_BUCKET,
messagingSenderId: ENV.firebase.MESSAGING_SENDER_ID,
appId: ENV.firebase.APP_ID
};
initializeApp(firebaseConfig);
export const db = getDatabase();
The error I get is:
TypeError: (0, _database.getDatabase) is not a function. (In '(0, _database.getDatabase)()', '(0, _database.getDatabase)' is undefined)
You're mixing up the old, namespaced syntax of SDK versions 8 and lower, with the new, modular syntax of SDK versions 9 and above.
To get the database in v9, you call getDatabase() as a top-level function:
export const db = getDatabase();
I recommend keeping the Firebase documentation ready when going through this, as it has code samples for both the old and new syntax so you can easily compare. For this specific call, see the documentation on getting a database reference.

How to use firestore emulator with Nextjs

I'm trying to use Firebase Emulator on a local project based on Nextjs. Following the guidance from Firebase here I'm trying to use db.useEmulator('localhost', 8080); after I initialised Firebase but I have this error:
Error was not caught TypeError: db.useEmulator is not a function
at Module.eval (VM79706 firebase.js:30)
at eval (VM79706 firebase.js:91)
at Module../utils/firebase.js (_app.js?ts=1603918354205:23994)
...
I've been using the emulator to test cloud functions and it's working pretty well. I just don't understand how to connect it with Firestore.
Here is how I set up Firebase:
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
import 'firebase/analytics';
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
};
// Check that `window` is in scope for the analytics module!
if (typeof window !== 'undefined' && !firebase.apps.length) {
firebase.initializeApp(clientCredentials);
if ('measurementId' in clientCredentials) firebase.analytics();
const db = firebase.firestore();
if (process.env.NEXT_PUBLIC_DB_HOST === 'localhost') {
db.useEmulator('localhost', 8080);
}
}
export default firebase;
Any idea why I'm getting this error and how I connect Firebase emulator with Nextjs?
To answer my own question, the problem was that this method was introduced in the new version of firebase 8.0.0. I just had the update and voila!
Using firebase ver. 9.4.1.
You may using database UI for work with database locally. Url to database UI show, when start emulators.
Regular url: localhost:PORT/database

How do I fix this error TypeError: _components_firebase_Firebase__WEBPACK_IMPORTED_MODULE_2__.default.auth is not a function

I am using Firebase with next.js and I have the files set up like below. I am trying to use the firebase client side sdk but it does not seem to be working on the sign up.
Firebase.js where the firebase app is initialized
import firebase from 'firebase/app'
import 'firebase/auth'
const config = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
measurementId: process.env.FIREBASE_MEASUREMENT_ID
};
export default function initFirebase() {
if (!firebase.apps.length) {
firebase.initializeApp(config)
}
}
The function which is erroring on the sign up paenter code herege.
import Firebase from "../../components/firebase/Firebase";
Firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
});
You didn't export anything from Firebase.js called auth. That's what the error message is trying to tell you. If you don't export it, you can't access it after an import.
If you want to access the auth() function from the global firebase namespace, consider exporting it:
export function auth() {
return firebase.auth();
}
Then you can import it in another source file:
import { auth } from "../../components/firebase/Firebase";
auth().createUserWithEmailAndPassword(...);
In general, you should avoid using default exports as you're using now. It's far better to name each export individually. You can also consider exporting the entire firebase namespace if you want to expose the entire SDK.
I think the issue with your Firebase.js module is that you're exporting your initFirebase function rather than firebase itself.
Try changing that bottom section to:
if (!firebase.apps.length) {
firebase.initializeApp(config)
}
export default firebase;
P.S. When I first saw your post, I was hung up on a seemingly similar problem of my own causing me to overlook this export issue when I made my comments. I should have caught this export issue earlier. This is my lesson to myself about not jumping to conclusions.

React Native - Firebase credentials in separate file

My goal is to have my firebase setup in a firebase_setup.js file in my root directory of my React Native project. I want to do this because it will allow me to perform import firebaseApp from 'AppName/firebase_setup' in my login.js and signup.js files.
I don't want to keep copying and pasting my Firebase credentials in every component I want to use the firebaseApp variable in.
firebase_setup.js
import * as firebase from 'firebase';
// Initialize Firebase
const firebaseConfig = {
apiKey: "FIREBASE_API_KEY",
authDomain: "FIREBASE_AUTH_DOMAIN",
databaseURL: "FIREBASE_DB_URL",
storageBucket: "",
};
export default const firebaseApp = firebase.initializeApp(firebaseConfig);
However, when I refresh the iPhone simulator I get this error:
SyntaxError: AppName/firebase_setup.js: Unexpected token (11:15)
It seems to have some issue with me using export default on firebaseApp. Any insight on this issue would be greatly appreciated! Thanks!
Try changing the last line to:
const firebaseApp = firebase.initializeApp(firebaseConfig);
export default firebaseApp;
Why the syntax is invalid
Exporting a variable declaration list as "default" wouldn't make sense: for one, the list can have more than one element:
export default var a, b, c; // Non-sensical

Initialize Firebase references in two separate files in the new API

I have upgraded to the new API and don't know how to initialize Firebase references in two separate files:
/* CASE 1 */
// 1st file
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
// 2nd file - initialize again
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
RESULT: bundle.js:535 Uncaught Error: Firebase App named '[DEFAULT]' already exists.
/* CASE 2 */
// 1st file
var config = {/* ... */};
firebase.initializeApp(config);
var rootRef = firebase.database().ref();
// 2nd file - don't initialize
var rootRef = firebase.database().ref();
RESULT: bundle.js:529 Uncaught Error: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp().
Before the new API I just called
var myFirebaseRef = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
in each file, and it worked okay.
This is an issue I ran into as well upgrading to the new version of Firebase. You might want two separate firebase apps initialized, like explained in other answers, but I just wanted to use the refs in two different locations in my app and I was getting the same error.
What you need to do for this situation is to create a firebase module for your app that only initializes firebase once, then you import or require it elsewhere in your app.
This is pretty simple, here is mine: modules/firebase.js
import firebase from 'firebase';
var firebaseConfig = {
apiKey: "some-api-key",
authDomain: "some-app.firebaseapp.com",
databaseURL: "https://some-app.firebaseio.com",
storageBucket: "some-app.appspot.com",
};
var FbApp = firebase.initializeApp(firebaseConfig);
module.exports.FBApp = FbApp.database(); //this doesnt have to be database only
And then elsewhere in your application you simply:
import FBApp from '/your/module/location'
var messagesRef = FBApp.ref("messages/");
You need to name your different instances (Apps as Firebase calls them); by default you're working with the [DEFAULT] App, because that's the most common use case, but when you need to work with multiple Apps then you have to add a name when initialising:
// Intialize the "[DEFAULT]" App
var mainApp = firebase.intializeApp({ ... });
// Intialize a "Secondary" App
var secondaryApp = firebase.initializeApp({ ... }, "Secondary");
...
mainApp.database().ref("path/to/data").set(value);
secondaryApp.database().ref("path/to/data").set(anotherValue);
You can find a more example scenarios in the updated Initialize multiple apps section of the Add Firebase to your JavaScript Project guide.
If you don't have the control over where Firebase will be instantiated, you can do something like this:
try {
let firApp = firebase.app(applicationName);
return firApp;
} catch (error) {
return firebase.initializeApp({
credential: firebase.credential.cert(firebaseCredentials),
databaseURL: firebaseUrl
}, applicationName);
}
Firebase will try to get the application, if it doesn't exist, then you can initialize it freely.
I made the mistake by importing like this.
import firebase from 'firebase'
const firebaseConfig = {
apiKey: 'key',
authDomain: 'domain',
databaseURL: 'url',
storageBucket: ''
};
firebase.initializeApp(firebaseConfig);
This worked fine for a few days but when I tried to sign in with custom tokens my auth object was not changed. I had to refresh the page for it to update so I could make certain calls to the database which were protected by my own auth credentials rules.
".read": "$uid === auth.uid || auth.isAdmin === true || auth.isTeacher === true",
When I changed my imports to this it worked again.
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
const firebaseConfig = {
apiKey: 'key',
authDomain: 'domain',
databaseURL: 'url',
storageBucket: ''
};
firebase.initializeApp(firebaseConfig);
Then whenever I need to use Firebase in a certain module I import this(notice the import from firebase/app instead of firebase):
import firebase from 'firebase/app';
And talk to certain services like so:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// Authenticated.
} else {
// Logged out.
}
});
firebase.database().ref('myref').once('value').then((snapshot) => {
// do stuff with the snapshot
});
To make multiple instances using new firebase.initializeApp(), you need a second parameter for the firebase constructor:
firebase.initializeApp( {}, "second parameter" );
Compare it to the old way to generate multiple instances where
new Firebase.Context()
is the second parameter:
new Firebase('', new Firebase.Context() );
For a small fraction of the people here, this issue might be cause by trying to initialize fb admin on the same script that you used to initialize fb on the front end. If anybody is initializing firebase twice on the same script (once for admin and once for frontend), then you need initialize firebase admin in a different script than in front end, and do not import anything that is exported on the backend script on the frontend (and vise versa).

Categories

Resources