How to attach multiple js modules onto single firebase instance - javascript

I am refactoring some code so that different javascript modules in different js files can use the same Firebase instance. I also want to eliminate the possibility of race conditions as different modules are loaded.
I believe that these are the steps that I would need to follow in order to avoid a race condition:
Load firebase.js
Initialize firebase prototype with authentication
Execute external JS files module1.js and module2.js
In code this will roughly translate to the following:
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="crossorigin="anonymous"></script>
<script src="https://www.gstatic.com/firebasejs/3.6.1/firebase.js"></script>
<script type="text/javascript">
if (firebase.apps.length === 0) {
firebase.initializeApp({
apiKey: "<REMOVED>",
authDomain: "<REMOVED>",
databaseURL: "<REMOVED>",
storageBucket: "<REMOVED>",
messagingSenderId: "<REMOVED>"
});
}
firebase.auth().signOut().then(function () {
var customTokenUrl = "<REMOVED>";
$.ajax({
url: customTokenUrl,
data: {},
xhrFields: {withCredentials: true},
crossDomain: true,
success: function (token) {
firebase.auth().signInWithCustomToken(token);
},
type: 'POST'
});
});
</script>
<script src="someurl/module1.js"></script>
<script src="someurl/module2.js"></script>
This is roughly the code for both module1.js and module2.js:
var module1 = (function (MODULE) {
...
...
firebase.auth().onAuthStateChanged(MODULE.onAuthStateChanged.bind(MODULE));
function onAuthStateChanged(user) {
if (user) {
// User is signed in.
MODULE.uid = user.uid;
setWatchers(); // This is where I set the firebase refs
}
}
return MODULE;
}
Here are the questions I have:
In module1.js, is there a possibility that onAuthStateChanged won't fire? I think that, theoretically, module1.js can execute after the auth state changed in firebase. Wouldn't that make the onAuthStateChanged method not fire?
Can the var firebase ever be undefined in module1.js?

Related

Uncaught TypeError while importing from firebase/database

error that i'm getting:
Uncaught TypeError: Failed to resolve module specifier
"firebase/database". Relative references must start with either "/",
"./", or "../".
i am trying to setup firebase configuration for the latest version of firebase 9.1
<script type="module">
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-app.js";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "....",
appId: "..."
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
//below import statement is causing the error
import { getDatabase, ref, set } from "firebase/database";
const db = getDatabase();
</script>
<script type="text/javascript" >
function InsertData() {
set(ref(db, 'TheStudent/'+rollV), {
NameOfStudent: "abc",
RollNo: 13,
Section: "B",
Gender: "Male"
});
}
document.getElementById('insertBtn').onclick = InsertData;
</script>
PS. i have hidden the config on purpose, so thats not the problem.
It seems you are using Firebase SDK over CDN so try importing database in same way:
import { getDatabase, ref, set } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-database.js";
// CDN URL instead of "firebase/database"

How to use firebase in front end as a module?

I am making a project in which I am using typescript and also using the module system(type="module"). I put the following inside my main.html file.
<script src="https://www.gstatic.com/firebasejs/7.6.1/firebase-app.js"></script>
I have another file firebase.ts which contains
// #ts-nocheck;
var firebaseConfig = {
apiKey: "AIzaSyAePVmVNzKbvbLnAGP1VVQwyEaE7pJ3a_M",
authDomain: "chess-3ea12.firebaseapp.com",
databaseURL: "https://chess-3ea12.firebaseio.com",
projectId: "chess-3ea12",
storageBucket: "chess-3ea12.appspot.com",
messagingSenderId: "454944098464",
appId: "1:454944098464:web:9d10fe0a1808233f5ca1c5"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default {
fs: firebase.database(),
db: firebase.database().ref(),
auth: firebase.auth()
}
Typescript will obviously show error
Cannot find name 'firebase'
How I can fix this means that I could get firebase a module so I could import it inside any file.
You can install Firebase as a dependency so that it appears in node_modules. You won't actually be using anything in it except for its definition file, though. With typeof import(...) syntax, you can import the type of a module, so import it and declare the Firebase type onto the window:
declare global {
interface Window {
firebase: typeof import('firebase');
}
}
Then, you'll be able to reference window.firebase and use its types:
const { firebase } = window;
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export default {
fs: firebase.database(),
db: firebase.database().ref(),
auth: firebase.auth()
}

How to store Firebase credentials in Vue.js projects after building (env_var)

I have been trying to deploy my firebase&vue app.
However I couldn't add firebase credentials to the env variable.
Basically this is the structure on vue.js
config
---- key.js
---- keys_dev.js
---- keys_prod.js
key.js
if(process.env.NODE_ENV == 'production'){
module.exports = require('./keys_prod');
} else {
module.exports = require('./keys_dev');
}
keys_dev.js
module.exports = {
firebase: {
apiKey: "*********************************",
authDomain: "*****************************",
databaseURL: "****************************",
projectId: "******************************",
storageBucket: "**************************",
messagingSenderId: "**********************",
}
}
keys_prod.js
module.exports = {
firebase: {
apiKey: process.env['FIREBASE_apiKey'],
authDomain: process.env['FIREBASE_authDomain'],
databaseURL: process.env['FIREBASE_databaseURL'],
projectId: process.env['FIREBASE_projectId'],
storageBucket: process.env['FIREBASE_storageBucket'],
messagingSenderId: process.env['FIREBASE_messagingSenderId'],
}
}
Also I tried like this in keys_prod.js but I guess we can not use object in the env_var, so I changed it to the code above.
module.exports = {
firebase: process.env.FIREBASE_CONFIG
}
After npm run build, I created express app, define process.env's however when I run server, I am getting error because of env_vars are missing.
I tried to see logs on both front and backend console. I can see envs on node console but not in browser.
I also tried to deploy this app to heroku and firebase hosting. In both cases I added envs externally, but nothing change. (I guess there is no difference to use env_vars in localhost or remote server right ?)
Finally I tried to change keys.js (keys_prod > keys_dev)
if(process.env.NODE_ENV == 'production'){
module.exports = require('./keys_dev');
} else {
module.exports = require('./keys_dev');
}
then it works, but I can find the credentials in the source code this time.
There's a better way that the other answer. You don't need to import - that would bring the settings into the deployed JS, which isn't a good idea.
Create a file like .env.local in the root of the Vue app, like this:
$ cat .env.local
# REMEMBER:
# ----------------------------------------------------------
# In development, *restart* "yarn serve" to pick up changes.
# ----------------------------------------------------------
VUE_APP_FIREBASE_API_KEY='1234-F1xH53UCnk'
VUE_APP_FIREBASE_AUTH_DOMAIN='your-web-1234.firebaseapp.com'
VUE_APP_FIREBASE_DATABASE_URL='https://your-web-1234.firebaseio.com'
VUE_APP_FIREBASE_PROJECT_ID='your-web-1234'
VUE_APP_FIREBASE_STORAGE_BUCKET='your-web-1234.appspot.com'
VUE_APP_FIREBASE_MESSAGING_SENDER_ID='12345678'
VUE_APP_FIREBASE_APP_ID='1:1234:web:0398509235'
Wherever you want firebase, do something like:
function getFirebaseConfig() {
const firebaseConfig = {
// see .env file for instructions
apiKey: process.env.VUE_APP_FIREBASE_API_KEY || 'api-key-not-set',
authDomain: process.env.VUE_APP_FIREBASE_AUTH_DOMAIN || 'env-not-set',
databaseURL: process.env.VUE_APP_FIREBASE_DATABASE_URL || 'env-not-set',
projectId: process.env.VUE_APP_FIREBASE_PROJECT_ID || 'env-not-set',
storageBucket: process.env.VUE_APP_FIREBASE_STORAGE_BUCKET || 'env-not-set',
messagingSenderId: process.env.VUE_APP_FIREBASE_MESSAGING_SENDER_ID || 'env-not-set',
appId: process.env.VUE_APP_FIREBASE_APP_ID || 'env-not-set',
}
return firebaseConfig
}
// Initialize Firebase
firebase.initializeApp(getFirebaseConfig())
I'm using TypeScript, so I put that in a file called cloud-functions.ts` and after the above, I have:
export const postContactFunc = firebase.functions().httpsCallable('postContact')
Then, where I want to consume that function, I have:
// somewhere-else.ts
import {postContactFunc} from '#/services/cloud-functions'
Note that .env*.local is never checked in.
To remind myself what the file should be, I have this content in .env which is checked in:
$ cat .env
# REMEMBER:
# ----------------------------------------------------------
# DO NOT EDIT THIS FILE
#
# Edit .env.local or similar.
# ----------------------------------------------------------
# Get these from console - look on the _app_ area not the _project_ area.
VUE_APP_FIREBASE_API_KEY='not-set-yet'
VUE_APP_FIREBASE_AUTH_DOMAIN='not-set-yet'
VUE_APP_FIREBASE_DATABASE_URL='not-set-yet'
VUE_APP_FIREBASE_PROJECT_ID='not-set-yet'
VUE_APP_FIREBASE_STORAGE_BUCKET='not-set-yet'
VUE_APP_FIREBASE_MESSAGING_SENDER_ID='not-set-yet'
VUE_APP_FIREBASE_APP_ID='not-set-yet'
Here how you can do it.
Firstly, add dev.env to your project and add firebase variables.
FIREBASE_CONFIG: {
apiKey: "*********************************",
authDomain: "*****************************",
databaseURL: "****************************",
projectId: "******************************",
storageBucket: "**************************",
messagingSenderId: "**********************",
}
Import the file in dev.env.js
import merge from 'webpack-merge';
import env from './dev.env';
module.exports = merge(env, {
NODE_ENV: 'development'
}
Now, Initialize your firebase app with
import * as firebase from 'firebase';
firebase.initializeApp({VUE_APP_FIREBASE_CONFIG})
There you go! Firebase is set up for you
Hope this helps!

firebase.auth.RecaptchaVerifier is not a constructor error

Trying to add the Firebase script in my html, after initializing Firebase app with firebase.initializeApp(config);.
So then I have this :
<script>
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button',
{
'size': 'invisible',
'callback': function(response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
onSignInSubmit();
}
});
</script>
Which provides the error :
firebase.auth.RecaptchaVerifier is not a constructor error
How to solve this error (found similar questions without a direct answer)
How to proceed from here with the full flow ?
EDIT:
I have this in the beginning of the html :
<script src="https://www.gstatic.com/firebasejs/5.7.0/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.7.0/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-database.js"></script>
I am initializing the app with :
<script>
var config = {
apiKey: "AIzaSxxxxxxxxxxxxxxxZQ14",
authDomain: "xxxxxx.firebaseapp.com",
databaseURL: "https://xxxxxxx.firebaseio.com",
projectId: "xxxxxx",
storageBucket: "xxxxxxx.appspot.com",
messagingSenderId: "xxxxxxxxx"
};
firebase.initializeApp(config);
const db = firebase.firestore();
db.settings({timestampsInSnapshots:true});
</script>
and those are the only things relate to Firebase I have in this file.
Solved by changing version of the imported files with : (thanks a lot Frank)
<script src="https://www.gstatic.com/firebasejs/5.7.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.7.0/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-messaging.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-functions.js"></script>

Cannot authenticate with emberfire

I am currently following this tutorial to authenticate my EmberApp with Firebase: Ember authentication with Firebase. I am working on the part which uses the Torii addon for authentication.
Here is what I have done so far:
app/torii-adapters/application.js
import Ember from 'ember';
import ToriiFirebaseAdapter from 'emberfire/torii-adapters/firebase';
export default ToriiFirebaseAdapter.extend({
firebase: Ember.inject.service()
});
app/adapters/application.js
import config from '../../config/environment';
import FirebaseAdapter from 'emberfire/adapters/firebase';
import Firebase from 'firebase';
export default FirebaseAdapter.extend({
firebase: new Firebase(config.firebase)
});
config/environment.js
module.exports = function(environment) {
var ENV = {
modulePrefix: 'my-auth-test',
environment: environment,
baseURL: '/',
locationType: 'auto',
firebase: 'MY_FIREBASE_URL',
torii: {
sessionServiceName: 'session'
},
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
...
routes/application.js -> Login function
login: function() {
var controller = this.get('controller');
var email = controller.get('userEmail');
var password = controller.get('userPassword');
this.get('session').open('firebase', {
provider: 'password',
email: email,
password: password
}).then(function() {
this.transitionTo('protected');
}.bind(this));
}
The problem that I have is the following error:
Please set the firebase property in your environment config.
But as far as I can see I have the property set. Can someone help me fix this issue?
That's the old method. Recently I ran into a similar issue after copy/pasting my old implementation, but after a quick look at https://github.com/firebase/emberfire I updated my config/environment.js to the following and was able to get it to work.
Try:
// config/environment.js
var ENV = {
firebase: {
apiKey: 'xyz',
authDomain: 'YOUR-FIREBASE-APP.firebaseapp.com',
databaseURL: 'https://YOUR-FIREBASE-APP.firebaseio.com',
storageBucket: 'YOUR-FIREBASE-APP.appspot.com',
}

Categories