Firebase-functions: ES2017 - import fails: Cannot read property "config" of undefined

Created on 14 Mar 2018  Â·  3Comments  Â·  Source: firebase/firebase-functions

Version info

firebase-functions: 0.8.2

firebase-tools: 3.17.6

firebase-admin: 5.8.2

node -v: 6.9.5

npm -v: 5.0.3

Test case

I've tried to use simple import-statements, compile the file using babel-cli and deploy the compiled code to firebase.

For readability, I'll provide you with the uncompiled and compiled source code. I am very certain that this is not an issue with babel-cli, as e.g. the import statement from firebase-admin works and I also did not encounter any issues with other projects and a similar setup of babel.

Nevertheless, I am new to firebase and it could be an issue on my side. If there are any more information you need/would like to have, please let me know.


index.src.js

import admin from 'firebase-admin';
import functions from 'firebase-functions';
admin.initializeApp(functions.config().firebase);

.babelrc

{
    "presets": ["env"]
}

index.js

'use strict';

var _firebaseAdmin = require('firebase-admin');

var _firebaseAdmin2 = _interopRequireDefault(_firebaseAdmin);

var _firebaseFunctions = require('firebase-functions');

var _firebaseFunctions2 = _interopRequireDefault(_firebaseFunctions);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

_firebaseAdmin2.default.initializeApp(_firebaseFunctions2.default.config().firebase);

Result:

"TypeError: Cannot read property 'config' of undefined"

Steps to reproduce

Either:

a) Use the above index.js for your functions and deploy it, or
b) Use the above .babelrc and the index.src.js to generate index.js and deploy it.

Were you able to successfully deploy your functions?


I received the error message:

TypeError: Cannot read property 'config' of undefined
    at Object.<anonymous> (index.js:13:66)

Expected behavior


I would expect that the deployment succeeds without any error message. The deployed service would have 0 functions, but the deploy itself should succeed.

Actual behavior


Instead of suceeding, the deployment fails because functions is undefined instead of
containing the exports from the firebase-functions module. On the other hand, the same import-statement works fine with the firebase-admin module - and i did not encounter similar issues so far with other modules.

The firebase-debug.log:

[debug] [2018-03-14T17:44:17.451Z] ----------------------------------------------------------------------
[debug] [2018-03-14T17:44:17.467Z] Command:       C:\Program Files\nodejs\node.exe C:\Users\Username\AppData\Roaming\npm\node_modules\firebase-tools\bin\firebase deploy --only functions
[debug] [2018-03-14T17:44:17.467Z] CLI Version:   3.17.6
[debug] [2018-03-14T17:44:17.467Z] Platform:      win32
[debug] [2018-03-14T17:44:17.467Z] Node Version:  v6.9.5
[debug] [2018-03-14T17:44:17.467Z] Time:          Wed Mar 14 2018
[debug] [2018-03-14T17:44:17.467Z] ----------------------------------------------------------------------
[debug] 
[debug] [2018-03-14T17:44:17.513Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
[debug] [2018-03-14T17:44:17.529Z] > authorizing via signed-in user
[debug] [2018-03-14T17:44:17.529Z] >>> HTTP REQUEST GET https://admin.firebase.com/v1/projects/my-project  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:18.092Z] <<< HTTP RESPONSE 200
[debug] [2018-03-14T17:44:18.092Z] >>> HTTP REQUEST GET https://admin.firebase.com/v1/database/my-project/tokens  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:18.467Z] <<< HTTP RESPONSE 200
[info] 
[info] === Deploying to 'my-project'...
[info] 
[info] i  deploying functions
[info] Running command: npm --prefix "$RESOURCE_DIR" run lint
[info] +  functions: Finished running predeploy script.
[debug] [2018-03-14T17:44:27.123Z] > [functions] package.json contents: {
  "name": "functions",
  "description": "Cloud Functions for my-project",
  "scripts": {
    "lint": "eslint .",
    "serve": "firebase serve --only functions",
    "shell": "firebase experimental:functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log",
    "build": "node node_modules/babel-cli/bin/babel.js src/ --out-dir ./"
  },
  "dependencies": {
    "firebase-admin": "^5.8.2",
    "firebase-functions": "^0.8.1"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "eslint": "^4.12.0",
    "eslint-plugin-promise": "^3.6.0"
  },
  "private": true
}
[info] i  functions: ensuring necessary APIs are enabled...
[debug] [2018-03-14T17:44:27.123Z] >>> HTTP REQUEST GET https://servicemanagement.googleapis.com/v1/services/cloudfunctions.googleapis.com/projectSettings/my-project?view=CONSUMER_VIEW  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:27.123Z] >>> HTTP REQUEST GET https://servicemanagement.googleapis.com/v1/services/runtimeconfig.googleapis.com/projectSettings/my-project?view=CONSUMER_VIEW  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:27.920Z] <<< HTTP RESPONSE 200
[debug] [2018-03-14T17:44:27.936Z] <<< HTTP RESPONSE 200
[info] +  functions: all necessary APIs are enabled
[debug] [2018-03-14T17:44:27.936Z] >>> HTTP REQUEST GET https://cloudresourcemanager.googleapis.com/v1/projects/my-project  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:28.422Z] <<< HTTP RESPONSE 200
[debug] [2018-03-14T17:44:28.422Z] >>> HTTP REQUEST GET https://mobilesdk-pa.googleapis.com/v1/projects/some-numeric-id:getServerAppConfig  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:28.912Z] <<< HTTP RESPONSE 200
[info] i  functions: preparing functions directory for uploading...
[debug] [2018-03-14T17:44:28.927Z] >>> HTTP REQUEST GET https://runtimeconfig.googleapis.com/v1beta1/projects/my-project/configs  

 Wed Mar 14 2018
[debug] [2018-03-14T17:44:29.406Z] <<< HTTP RESPONSE 200

Most helpful comment

@SargTeX
Hey, I ran into this problem while converting require to import/export.

In es6, there are different ways of importing. There are also different methods of exporting. When you export like this export { name1, name2, …, nameN };, it exports an object of key/value pairs. When you export like this export default expression;, I think it sets the key 'default' to the expression.

When you import like this import defaultExport from "module-name";, it reads the value at the default key. When you import like this import * as name from "module-name"; it'll read in all the key/value pairs.

config must not be the default export, that's why it didn't work. require must be catching both scenarios, that's why using require works.
My solution is:

import * as functions from 'firebase-functions'; // <-- solution

/* eslint-disable-next-line import/no-mutable-exports */
let config;
if (!functions || process.env.NODE_ENV === ('silent' || 'test')) {
  // handle local unit testing
  config = {};
} else {
  config = functions.config();
}

export default config;

update:
If you checkout the source code, you'll see that there is no default export.

All 3 comments

Okay, I've debugged a little bit further. The following source code also compiles and deploys successfully:

import admin from 'firebase-admin';
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);

I was capable to pinpoint the problem down to the ".default"-usage: If, in the compiled source code, the erroneous line (13) gets changed to the following:

_firebaseAdmin2.default.initializeApp(_firebaseFunctions2.config().firebase);

it seems to work. Therefore, the problem is that _firebaseFunctions2.default is undefined. Unfortunately, I have to stop at this point as I do not understand enough about how ES6-modules work internally, and what exactly the function _interopRequireDefault() is required for - and why it checks for obj.__esModule. Maybe someone with more knowledge to that could help me out?

At this point, I am unsure if this is a bug or a feature request - as most other modules seem to work with that kind of import structure, but firebase-functions doesnt. I never noticed that I had to do anything special on my own modules so that they work, so I am a little bit confused right now :D

@SargTeX
Hey, I ran into this problem while converting require to import/export.

In es6, there are different ways of importing. There are also different methods of exporting. When you export like this export { name1, name2, …, nameN };, it exports an object of key/value pairs. When you export like this export default expression;, I think it sets the key 'default' to the expression.

When you import like this import defaultExport from "module-name";, it reads the value at the default key. When you import like this import * as name from "module-name"; it'll read in all the key/value pairs.

config must not be the default export, that's why it didn't work. require must be catching both scenarios, that's why using require works.
My solution is:

import * as functions from 'firebase-functions'; // <-- solution

/* eslint-disable-next-line import/no-mutable-exports */
let config;
if (!functions || process.env.NODE_ENV === ('silent' || 'test')) {
  // handle local unit testing
  config = {};
} else {
  config = functions.config();
}

export default config;

update:
If you checkout the source code, you'll see that there is no default export.

Thanks for stepping in @jhu7235 !

You can also do import { config } from 'firebase-functions'
You can add other imports to that list, for example:
import {config, database, firestore} from 'firebase-functions'

Was this page helpful?
0 / 5 - 0 ratings