initializeApp when adding firebase to app and to server
Asked Answered
E

6

19

I'm using firebase for auth and db, and AWS lambda for cloud functions.

To add firebase to my JS project, I initializeApp with the firebase config as parameter, as documented here : https://firebase.google.com/docs/web/setup.

As documented here : https://firebase.google.com/docs/admin/setup, I also need to initializeApp in my lambda function.

Something as follows here :

const admin = require('firebase-admin');
const serviceAccount = require('../path/to/service-account.json');

const firebaseAdmin = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "dB_URL"
});

The credentials come from the firebase-admin library, so I cannot add this to my web firebase config. So, I need to initialize twice.

However, if I proceed like this, the server will throw an error :

The default Firebase app already exists. This means you called initializeApp() more than once without providing an app name as the second argument. In most cases you only need to call initializeApp() once.But if you do want to initialize multiple apps, pass a second argument to initializeApp() to give each app a unique name.

Am I missing something here ? What's the best practice ? I'm confused.

Someone faced the same issue before it seems : Use Firebase SDK with Netlify Lambda Functions

What worked for this user was to use the REST API as documented here : https://firebase.google.com/docs/projects/api/workflow_set-up-and-manage-project

The documentation says it's in beta though.

Thanks for your kind help

Extemporize answered 3/9, 2019 at 1:21 Comment(0)
I
56

It seems that lambda may load the script file that calls admin.initializeApp({...}) multiple times. To prevent the Admin SDK from initializing multiple times, you can for example detect if that already happened:

if (!admin.apps.length) {
    const firebaseAdmin = admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "dB_URL"
    });
}

As cnexans commented, if you're on the modular API the equivalent would be:

if (!getApps().length) {
  ...
Injurious answered 3/9, 2019 at 1:26 Comment(5)
Awesome. That worked. Thanks for the tip. Now I have another related issue : I can declare a document reference. However a get() request to get the data containted in that document returns the following error message : "Error getting document: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number". It's the error logged from the catch, as in documented here : firebase.google.com/docs/firestore/query-data/get-data. Can't tell whether it is Firebase related. Sorry if it's not.Extemporize
It looks like you're passing in a number, while keys/ids are always strings. If they're numeric values, convert it to a string first with something like 42.toString() or ''+42. Please note that in general it's best to open a new question for... uhm... new questions like this. ;-)Injurious
I'm sorry, I don't get it. Where am I passing a number ? I'm doing a basic get request, as in the official documentation. Which keys/ids are you referring to ? (Noted. I wasn't sure as it's somewhat related)Extemporize
If my comment doesn't explain it well enough, open a new question with the minimal standalone code that anyone can run to reproduce the problem.Injurious
This will do the work export const app = getApps().length === 0 ? initializeApp(firebaseAdminConfig, "server") : getApp("server");Consanguineous
P
9

Have similar problem. Based on answer from @Frank van Puffelen ( Thanks to him ), Now a days, Using ES6 ( Firebase admin V >= 9 )

import { initializeApp, applicationDefault, getApps } from "firebase-admin/app";

...

        if ( !getApps().length ) {
            initializeApp({
                credential: applicationDefault(),
                databaseURL: 'https://XXXXXXX.firebaseio.com'
            });
        }
...
Pessimist answered 7/2, 2022 at 1:26 Comment(0)
C
5

An alternative in the simplest case might be something like this:

import { initializeApp, getApp } from "firebase-admin/app";

function appSingleton () {
  try {
    return getApp()
  } catch (err) {
    return initializeApp()
  }
}
Crossbreed answered 19/1, 2023 at 20:3 Comment(0)
D
0

so my mistake is i write initializeApp in seperate function every time it calls that function produce this avoid are you initialize app ones it ok dont initialize again and again

Djerba answered 22/11, 2023 at 9:21 Comment(1)
If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From ReviewServile
Y
0

if you used initializeApp() more than once, you could add the app name after you add the option object parameter. This will be more useful for you.

const firebaseAdmin = admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "dB_URL"
},"give-your-app-name");
Youlandayoulton answered 14/1, 2024 at 7:37 Comment(0)
K
0

I tried this and it works. declare all those needed such as initialize, at the top.

 const serviceAccount = require("./serviceAccountKey.json");  
 const readyToUser = admin.initializeApp({
 credential: admin.credential.cert(serviceAccount),   
 databaseURL: "https://hello.firebaseio.com",   
  });

then in the function part just

exports.deleteuser = onDocumentDeleted("user/{uid}", (event) => {
 const snap = event.data;
 const data = snap.data();
 return readyToUser.auth().deleteUser(event.params.uid);  
 });
Krasnoyarsk answered 1/7, 2024 at 4:11 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.