Why does using the "camelcase-keys" package cause a Firebase "initializeApp()" error?

Viewed 113

I am trying to build some Firebase Cloud Functions, and also use the npm package camelcase-keys to transform the keys of an API response.

But whenever use that imported package I get this error:

Error: Failed to load function definition from source: Failed to generate manifest from function source: 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.

This error is strange to me because I am following the advice here and only calling admin.initializeApp() once at my function entry point (index.ts).

Here is what the file structure looks like, and a copy of the code I am using.

Instead of including all the code, I have only included the salient parts (imports, exports, and admin.initializeApp). Let me know if more code pasted here would be helpful:

functions/
├─ src/
│  ├─ index.ts
│  ├─ dataForSeo.ts

index.ts

import 'source-map-support/register';
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp();

export const sydneyFunctions = functions.region('australia-southeast1');
export const db = admin.firestore();

export {
  dataForSeoSerpGoogleOrganicDailyEnqueue,
  dataForSeoSerpGoogleOrganicTask,
  dataForSeoSerpGoogleOrganicPostbackUrl,
  dataForSeoOnPageStartCrawl,
  dataForSeoOnPageEnqueuePingbackUrl,
  dataForSeoOnPageGetResultTask,
} from './dataForSeo';

dataForSeo.ts

import camelcaseKeys from 'camelcase-keys';
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import axios from 'axios';
import { getFunctions } from 'firebase-admin/functions';
import { DataForSeoGoogleOrganicPostTask, Serp, SerpItem } from './types';
import { getSecretVersion } from './googleSecretManager';
import { db, sydneyFunctions } from './index';

// Example usage
const test = camelcaseKeys(
  { 'foo-bar': true, nested: { unicorn_rainbow: true } },
  { deep: true }
);
functions.logger.info(test);

...
// Other functions below here

UPDATE:

Instead of using the camelcase-keys package I tried creating a recursive function using lodash that does the same thing.

This works without error:

import { camelCase, isPlainObject } from 'lodash';

const camelizeKeys = <
  T extends Record<string, unknown> | Record<string, unknown>[]
>(
  obj: T
): T => {
  if (Array.isArray(obj)) {
    return <T>obj.map((v) => camelizeKeys(v));
  } else if (isPlainObject(obj)) {
    return <T>Object.keys(obj).reduce(
      (result, key) => ({
        ...result,
        [camelCase(key)]: camelizeKeys(<T>obj[key]),
      }),
      {}
    );
  }
  return obj;
};

While this custom function is a work-around, I would still like to get the camelcase-keys package working.

1 Answers

That is a truly a strange case. I cannot say why it is occurring but to prevent re-initializing the app try this:

if (!admin.apps.length) {
  admin.initializeApp();
}
Related