0

In my TypeScript file, I have the following:

import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions'
const serviceAccountKey = "serviceAccountKey.json"
const databaseURL = "https://blahblah.firebaseio.com"

admin.initializeApp({
    credential: admin.credential.cert(serviceAccountKey),
    databaseURL: databaseURL
});

My functions run fine in the emulator (which can only happen if the json key is successfully passed) but when I try to deploy them, I get the following error:

Error: Error occurred while parsing your function triggers.
Error: Failed to parse certificate key file: Error: ENOENT: no such file or directory, open 'serviceAccountKey.json'

I've tried moving the json file to the root folder, the lib folder (where the index.js file resides), the functions folder, without any luck. How do I pass the key when deploying?

enter image description here

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
lurning too koad
  • 2,698
  • 1
  • 17
  • 47
  • What does your package directory structure look like? Might this help https://stackoverflow.com/questions/43117124/how-to-read-local-files-in-the-google-cloud-functions-emulator – Kolban Dec 04 '19 at 01:03
  • @Kolban check edit for folder structure – lurning too koad Dec 04 '19 at 01:06
  • 1
    You pose a good question ... got me wondering what the running environment of a Cloud Function looks like from a file system perspective. I made some tests and got some results. What I'd suggest is look at the following ... https://stackoverflow.com/questions/59167743/how-can-i-see-the-file-system-nature-of-my-node-js-cloud-function-environment/59167744#59167744 and incorporate this as a test. – Kolban Dec 04 '19 at 01:36
  • 1
    @Kolban you've been a lot of help! Thanks! – lurning too koad Dec 04 '19 at 01:51
  • did you find an answer? What was it? Maybe post an answer to your own question? – Kolban Dec 04 '19 at 03:11
  • On a bigger meta note ... I'd be tempted to run your cloud function with its own service account that implicitly has the authority it needs (via IAM) to access firebase. This will mean that you don't need to pass around credentials files with all the negative impacts that may have. – Kolban Dec 04 '19 at 04:51

1 Answers1

3

When you deploy content to Cloud Functions using the Firebase CLI, it will upload the entire contents of your functions folder (except node_modules, which it will rebuild using the contents of your package.json). That folder will become the root of your deployment. When your function executes, it will have all of those files ready for use, but you will have to refer to them correctly using relative paths.

Using that as perspective, I can see that your serviceAccount.json and compiled index.js are all in a folder called "lib". If you want code in index.js to be able to load JSON out of other files in the same folder, what you'll have to do is refer to it using a relative path, like this:

const serviceAccountKey = "./serviceAccountKey.json"

Note the "./" at the start of the path. That's telling node that you want to refer to a file that's in the same folder as the current source file.

I'll make one recommendation: For TypeScript projects, lib is typically reserved for compiled code. I would avoid putting your service account file in there, since that folder could be removed during clean build. It might be better to put it at the root of the deployment and refer to it as "../serviceAccount.json", which is my usual practice.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Howdy Doug ... is there a semantic difference between const serviceAccountKey = "serviceAccountKey.json" and const serviceAccountKey = "./serviceAccountKey.json" – Kolban Dec 04 '19 at 16:03
  • @Kolban It's a matter of being specific about telling the Admin SDK where the file lives. – Doug Stevenson Dec 04 '19 at 17:41
  • @DougStevenson one note I would add is that if you are writing your cloud function using typescript, and you use a relative path, you must place your .json folder in the lib folder where the index.js file is located, not in the src file where index.ts is located. – Hudson Kim Aug 08 '20 at 05:56
  • @HudsonKim Or, you can place it in the functions folder as I suggested here, in neither src nor lib, and refer to it as "../file.json". In this way, it doesn't matter where the including file lived, and you don't have to put files in lib that are not compiled files. – Doug Stevenson Aug 08 '20 at 06:46