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

Namespaced firebase-admin access not working in emulator, works in production #5460

Closed
tannerstern opened this issue Jan 24, 2023 · 4 comments

Comments

@tannerstern
Copy link

tannerstern commented Jan 24, 2023

After making several changes to our codebase recently, we discovered that we are unable to access firebase-admin sub-classes in various namespaces with the emulator. This may be an issue with firebase-admin itself, but the errors we are getting (see below) only appear when emulating our functions, and not on live code.

Others experiencing similar issues with firebase-admin posted about it on an issue (transferred to discussion) on that project's repo. See this comment by pascalbe-dev. Granted, most comments in that thread seem to be related to esm imports, and here we're using commonjs. I'm not sure what to make of it.

Environment info

firebase-tools: 11.21.0

Platform: Ubuntu (GitHub Codespace)

Test case

functions/index.js

const https = require('firebase-functions/v1/https');
const admin = require('firebase-admin');

admin.initializeApp();

module.exports.callableTest = https.onCall((data, context) => {
  const timestamp = admin.firestore.Timestamp.now();
  console.log(`timestamp:`, timestamp);
});

index.js

// You will need to initialize Firebase JS SDK on local

firebase.functions().useEmulator('localhost', 8080); // Or your environment default
firebase.functions().httpsCallable('callableTest')();

// "Unhandled error TypeError: Cannot read properties of undefined (reading 'now')"

functions/package.json

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "dependencies": {
    "firebase-admin": "^11.5.0",
    "firebase-functions": "^4.1.1"
  },
  "private": true,
  "type": "commonjs",
  "engines": {
    "node": "16"
  }
}

Steps to reproduce

Provided you have correctly initialized Firebase on the client, you can simply run firebase emulators:start --only functions and run /index.js to call the test function. (Truthfully, I opened a page in our app and simply ran those two lines in the Chrome console. I don't believe the way in which the http function is called is relevant to the issue.)

Expected behavior

Firebase Emulator UI would have logged the current timestamp (timestamp object { seconds: number, nanoseconds: number }).

Actual behavior

We get an error that looks like:

Unhandled error TypeError: Cannot read properties of undefined (reading 'now')
    at /workspaces/test_repo/functions/index.js:7:47
    at newHandler (/home/codespace/.nvm/versions/node/v16.19.0/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:317:16)
    at fixedLen (/workspaces/test_repo/functions/node_modules/firebase-functions/lib/v1/providers/https.js:74:41)
    at /workspaces/test_repo/functions/node_modules/firebase-functions/lib/common/providers/https.js:411:32
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async runFunction (/home/codespace/.nvm/versions/node/v16.19.0/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:504:9)
    at async runHTTPS (/home/codespace/.nvm/versions/node/v16.19.0/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:529:5)
    at async /home/codespace/.nvm/versions/node/v16.19.0/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:694:21

We first noticed this with admin.firestore.Timestamp, but then also with admin.database.ServerValue. In both cases, admin.firestore and admin.database are both empty objects, rendering Timestamp and ServerValue undefined.

If, however, you boot up a local node session, you can get the following:

@tannerstern $ node
Welcome to Node.js v16.19.0.
Type ".help" for more information.
> const admin = require('./functions/node_modules/firebase-admin')
undefined
> admin.firestore.Timestamp.now()
Timestamp { _seconds: 1674591147, _nanoseconds: 187000000 }
>
@taeold
Copy link
Contributor

taeold commented Jan 27, 2023

Hey @tannerstern. I recently had to fix a similar issue, and I wonder if you might be having similar issue:

- JSON.stringify(require("firebase-admin").firestore.FieldValue.increment(4))
  JSON.stringify(require("firebase-admin/firestore").FieldValue.increment(4))

The latest firebase admin sdk (v11) is now "modular" and require changes like above. I'm not sure why the code is only erroring in the Emulator case, but I'd suggest you try to change the import path anyway and see if it helps.

@taeold taeold added the Needs: Author Feedback Issues awaiting author feedback label Jan 31, 2023
@tannerstern
Copy link
Author

tannerstern commented Feb 6, 2023

Hi @taeold thanks for the response, apologies for not responding sooner.

I will try switching things out and using the new recommended entry points. I fully expect that to solve the errors. The issue for us is the inconsistency between the emulator and production. In past development, we (regrettably) relied heavily on passing the firebase or admin global namespaces around between modules.

For shared code between our client- and server-side, most of the time we passed firebase in as a parameter. Not good practice, but something that we weren't budgeting time towards fixing just yet. Maybe we'll have to; not that big of a deal, but I figured it was worth the ask.

We rely on the emulator to test changes before going live, hence the problem with the two environments handling things differently.

Edit: I suppose it is also worth noting that the documentation that outlines the switch to "modular" exports uses language like "We recommend developers to use these new entry points", which I read to mean "we recommend but do not require" this usage.

@google-oss-bot google-oss-bot added Needs: Attention and removed Needs: Author Feedback Issues awaiting author feedback labels Feb 6, 2023
@christhompsongoogle christhompsongoogle added Needs: Author Feedback Issues awaiting author feedback and removed Needs: Author Feedback Issues awaiting author feedback labels Feb 7, 2023
@taeold
Copy link
Contributor

taeold commented Mar 15, 2023

Thanks for sharing your issue with detail @tannerstern.

My guess is that the difference in execution environment between the emulated and the prod environment may be due to some of the old hacks we have in the codebase that tries to monkey-patch the firebase admin sdk. It's an ancient code, one that was useful when Firebase Emulator was still a useful thing, and it's a code it's difficult to remove without some heroic effort.

I'm not surprised and a bit sad to see that it could've caused an issue like you are seeing. While I can't promise we'll cleanup that tech debt soon, I'll keep this your issue in mind.

Going to close this issue for now - let us know if we can help with anything else (I'll ping the SDK team and see if we can update the wording as you suggested).

@taeold taeold closed this as completed Mar 15, 2023
@tannerstern
Copy link
Author

Thanks for the follow-up @taeold, that seems fair.

A question though: you don't believe Firebase Emulator to be useful anymore? Is that because of bugs such as these, or are there replacements / alternative methods for such things?

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