Cannot access 'getSession' before initialization: How to resolve circular dependencies in SWR/Passport.js?

Viewed 124

I'm trying to implement MongoDB, Next.JS and Passport.js, However upon starting my app and while trying to login, I get this 500 status error:

Cannot access 'getSession' before initialization

The preamble for all this is I am using a hook which calls/api/user to see if the req.user has been set by passport thus creating the 'user' below. And if one exists you get access to the other links/routes in the app.

This is the function declaration regarding the getSession function in the session.js file. So I suspect this is what is causing the circular dependencies issue, naturally.

import MongoStore from "connect-mongo";

import nextSession from 'next-session';

import { getMongoClient } from "./mongodb";

const mongoStore = MongoStore.create({
  clientPromise: getMongoClient(),
  stringify: false,
});

const getSession = nextSession({
  store: mongoStore,
  cookie: {
    httpOnly: true,
    secure: process.env.NODE_ENV === "production",
    maxAge: 2 * 7 * 24 * 60 * 60, // 2 weeks,
    path: "/",
    sameSite: "strict",
  },
  touchAfter: 1 * 7 * 24 * 60 * 60, // 1 week
});

export default function session(req, res, next) {
  getSession(req, res);
  next();
}

And this is the auth file with the passport file, passport initialization and session.

import passport from '../lib/passport'
import session from '../lib/session'

const auths = [session, passport.initialize(), passport.session()];

export default auths;

/component/Layout

export default function Layout({ children, showFooter = false }) {

  const [user, { mutate }] = useCurrentUser();

  async function handleLogout() {
    axios
      .get('/api/logout').then(() => {
        mutate({ user: null })
        Router.push('/',)
      }).catch(err => console.log('err', err))
  }

  return <>
    <div className="shadow bg-base-200 drawer h-screen">
          <div className="flex-none hidden lg:block">
            <ul className="menu horizontal">

              {user
                ?
                <>
                  <li>
                    <Link href="/profile">
                      <a>Profile</a>
                    </Link>
                  </li>
                  <li>
                    <Link href="/dashboard">
                      <a>Dashboard</a>
                    </Link>
                  </li>
                  <li>
                    <a role="button" onClick={handleLogout}>
                      Logout
                    </a>
                  </li>
                  <li className="avatar">
                    <div className="rounded-full w-10 h-10 m-1">
                      <img src="https://i.pravatar.cc/500?img=32" />
                    </div>
                  </li></>
                :
                <>
                  <li>
                    <Link href="/login">
                      <a>Login</a>
                    </Link>
                  </li>
                  <li>
                    <Link href="/registration">
                      <a>Register</a>
                    </Link>
                  </li>
                </>
              }
            </ul>
          </div>
        </div>
  </>;
}

This is the hook itself:

import useSWR from 'swr';

export const fetcher = (url) => {
  try {
    return fetch(url).then((res) => {
      console.log('res', res)
      return res.json()
    })
  } catch (error) {
    console.log('error', error)
  }
}
export function useCurrentUser() {
  const { data, mutate } = useSWR('/api/user', fetcher);
  const user = data?.user;
  return [user, { mutate }];
}

export function useUser(id) {
  const { data } = useSWR(`/api/users/${id}`, fetcher, {
    revalidateOnFocus: false,
  });
  return data?.user;
}

And this is the api: /api/user:

import nextConnect from 'next-connect'
import auth from '/middleware/auth'

const handler = nextConnect()

handler
  .use(auth)
  .get((req, res) => {
    console.log("req.user ", req.user);
    if (req.user) {
      res.json({ user: req.user })
    } else {
      res.json({ user: null })
    }
  })


export default handler

Also this is my repo And this is a link to the app on vercel.

0 Answers
Related