1

I am running NEXT JS with firebase and have created firebase-admin services as shown below:

import { initializeApp } from 'firebase-admin/app';
import { credential } from 'firebase-admin';
import { getAuth } from 'firebase-admin/auth';
import { getFirestore } from 'firebase-admin/firestore';

const pvtKey = process.env.FB_ADMIN_PRIVATE_KEY
  ? process.env.FB_ADMIN_PRIVATE_KEY.replace(/\n/gm, '\n')
  : '';
const app = initializeApp({
  credential: credential.cert({
    clientEmail: process.env.FB_ADMIN_CLIENT_EMAIL,
    privateKey: pvtKey,
    projectId: process.env.FB_ADMIN_PROJECT_ID,
  }),
});
const auth = getAuth(app);
const db = getFirestore(app);

export const verifyUser = async (idToken: string) => {
  try {
    const decodedToken = await auth.verifyIdToken(idToken);
    return {
      authenticated: true,
      user: decodedToken,
    };
  } catch (e) {
    return { authenticated: false, user: {} };
  }
};

I import verifyUser in another API Route as shown below:

import type { NextApiHandler } from 'next';
import { NextApiRequest, NextApiResponse } from 'next';

import { verifyUser } from '../../firebase/firebase_server';

interface ExpectedRequest {
  idToken: string;
}

const countHandler: NextApiHandler = async (
  request: NextApiRequest,
  response: NextApiResponse
) => {
  const { idToken } = request.body as ExpectedRequest;
  if (!idToken) {
    response.status(401).json({ msg: 'Unauthenticated Input' });
    return;
  }
  const { user, authenticated } = await verifyUser(idToken);
  if (!authenticated) {
    response.status(400).json({ msg: 'Invalid Input' });
    return;
  }
  // const email = user ?? 'Chal Ja bhai';
  // console.log('Pinging with ', email);
  // const resp = await registerNewUserData(email);
  // console.log('Response = ', await resp);
  response.status(200).json({ data: 'success' });
};

export default countHandler;

but for some reason this is failing by saying: ReferenceError: Cannot access 'verifyUser' before initialization

I checked a lot of places and they said it happens due to circular import, but in my case I am not importing anything in that manner.

It's just importing from the firebase_server.ts.

In case you're interested in checking my tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": false,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "strictNullChecks": true
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

Can anyone help me here, please?

Shivam Sahil
  • 4,055
  • 3
  • 31
  • 62

1 Answers1

0

After digging a lot, I realized that I was trying to use firebase-admin in the wrong way. And internally those cyclic imports were happening. Here's the useful info for anyone who may want to initialize firebase-admin setup in NEXT js:

import admin from 'firebase-admin';

admin.initializeApp({
  credential: admin.credential.cert({
    clientEmail: process.env.FB_ADMIN_CLIENT_EMAIL,
    privateKey: process.env.FB_ADMIN_PRIVATE_KEY,
    projectId: process.env.FB_ADMIN_PROJECT_ID,
  }),
});

const db = admin.firestore();
const auth = admin.auth();

export { auth, db };

//To Add other Details:
//https://stackoverflow.com/questions/38389341/firebase-create-user-with-email-password-display-name-and-photo-url
//User specific Rules: https://stackoverflow.com/questions/57680416/firestore-rules-how-to-make-user-can-only-read-write-to-document-with-their-name


Shivam Sahil
  • 4,055
  • 3
  • 31
  • 62