Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Firestore] Can not connect to both production and local emulator database #1839

Closed
danielo515 opened this issue Jul 27, 2022 · 8 comments
Closed

Comments

@danielo515
Copy link

danielo515 commented Jul 27, 2022

[REQUIRED] Step 1

Yes, I think this is the right place

[REQUIRED] Step 2: Describe your environment

  • Operating System version: MacOS
  • Firebase SDK version: 11.0.0
  • Firebase Product: Firestore
  • Node.js version: 16
  • NPM version: yarn

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

Please take a look at the attached code in the next section.
When you try to run that code you will get an error saying that TypeError: this.ensureApp(...).firestore is not a function. Seems that the initializeApp method is not returning an actual app instance that includes everything.

I want to be able to connect both to my production app and to my local emulator suite so I can do some dumps from one to the other.

admin.firestore.setLogFunction(console.log);

This will print Firestore logs to the console.

Relevant Code:

import { cert, initializeApp, applicationDefault } from 'firebase-admin/app';
import * as admin from 'firebase-admin';
import authData from '../admin-sdk.json';
import { Firestore } from 'firebase-admin/firestore';
import { emulators } from '../firebase.json';

initializeApp({
  // the cert accepts either an string or an object, but it si wrongly typed
  credential: cert(authData as unknown as string),
});

const localApp = initializeApp(
  { credential: applicationDefault(), databaseURL: `localhost:${emulators.firestore.port}` },
  'local',
);

export const db = admin.firestore();
export const localDb = admin.firestore(localApp);
@google-oss-bot
Copy link

I found a few problems with this issue:

  • I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
  • This issue does not seem to follow the issue template. Make sure you provide all the required information.

@danielo515
Copy link
Author

So it seems that THE ONLY WAY to connect to a local firestore database is by setting the environment variable. I tried this and, indeed it connected to the local database, what I can not be sure about is I am able to connect to both at the same time. It will be nice if docs were more clear about this, and it will be awesome if you allow to just pass that as a configuration option in the initialize app config object

@lahirumaramba
Copy link
Member

lahirumaramba commented Jan 17, 2023

You can probably set the emulator environment variable in the code and remove once you initialize the production app.
Something like below:

process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080';

const localApp = initializeApp(
  { projectId: 'test-project', databaseURL: `localhost:${emulators.firestore.port}` },
  'local',
);

delete process.env.FIRESTORE_EMULATOR_HOST;

In the future, please use StackOverflow for usage questions.

@CodingDoug
Copy link

I'm trying to do this as well, and I think it's a perfectly reasonable feature request to not have to depend on env vars to accomplish this. It's just not very clean to have to add and remove env vars on a temporary basis when an API would be better. There should be some options to pass to initializeApp() to ask it to use the emulator, or alternatively, an API similar to those provided by the client SDKs to tell the app to connect to an emulator.

@cherylEnkidu
Copy link

cherylEnkidu commented Oct 5, 2023

Hi @CodingDoug ,

Thank you for suggesting this. There are different products in Firebase and you get the choices to use some of it against emulator and others against production. So it is not easy to add simple options on this top level function initializeApp.

However, you can do something like the following to bypass environment variables:

const admin = require('firebase-admin');
admin.initializeApp();

const firestore = admin.firestore();

firestore.settings({ 
  ...firestore.settings,
  host: 'localhost:8080',
  ssl: false
}); 

@CodingDoug
Copy link

@cherylEnkidu Wouldn't it be possible to introduce a new function to initialize the app against the emulator alone? I don't really need to single out one product for use with the emulator. What I want is two initialized apps, one against the project and another against the emulator, so that I can have an easier time copying data between them using more than one product.

Right now I'm doing this:

import { initializeApp } from "firebase-admin/app"
import { getAuth } from "firebase-admin/auth"
import { getFirestore } from "firebase-admin/firestore"

export const remote = initializeApp()
export const remoteAuth = getAuth(remote)
export const remoteFirestore = getFirestore(remote)

process.env.FIRESTORE_EMULATOR_HOST = 'localhost:8080'
export const local = initializeApp(undefined, "local")
export const localAuth = getFirestore(local)
export const localFirestore = getFirestore(local)
delete process.env.FIRESTORE_EMULATOR_HOST

It seems unnecessarily complex when I could instead just use a different initializer function for the emulator-only instance.

@cherylEnkidu
Copy link

Hi @CodingDoug ,

Can you open a new issue, label api:core, and also provide a expected code sample? Developers from the core team will collaborate with you. Thank you.

@CodingDoug
Copy link

@cherylEnkidu Added here: #2327
I'm unable to manipulate labels here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants