Error: The class constructor MongoStore must be called with the keyword 'new' in order to be invoked

Currently, I am in the process of developing a web application using Next.js....

Within my app.js file located in the server directory, the following code is present:

const express = require("express");
const next = require("next");

const expressValidator = require("express-validator");
const mongoose = require("mongoose");
const passport = require("passport");
const mongoSessionStore = require("connect-mongo");
const session = require("express-session");

/* Loads all variables from .env file to "process.env" */
// npm install dotenv
// require("dotenv").config();

require("./models/Listing");
require("./models/User");

const routes = require("./routes");

const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const ROOT_URL = dev ? `http://localhost:${port}` : process.env.PRODUCTION_URL;
const app = next({ dev });
const handle = app.getRequestHandler();

const mongooseOptions = {
    useNewUrlParser: true,
    useCreateIndex: true,
    useFindAndModify: false,
    useUnifiedTopology: true
};

mongoose
    .connect(
        process.env.MONGODB_URI,
        mongooseOptions
    )
    .then(() => console.log("DB connected"));

mongoose.connection.on("error", err => {
    console.log(`DB connection error: ${err.message}`);
});

app.prepare().then(() => {
    const server = express();

    if(!dev) {
        /* Helmet helps secure our app by setting various HTTP headers */
        server.use(helmet());
        /* Compression gives us gzip compression */
        server.use(compression());
    }

    /* Body Parser built-in to Express as of version 4.16 */
    server.use(express.json());

    /* Express Validator will validate form data sent to the backend */
    // server.use(expressValidator());

    /* apply routes from the "routes" folder */
    server.use("/", routes);

    /* give all Next.js's requests to Next.js server */
    server.get("/_next/*", (req, res) => {
        handle(req, res);
    });

    server.get("/static/*", (req, res) => {
        handle(req, res);
    });

    const MongoStore = new mongoSessionStore(session);
    const sessionConfig = {
        name: "next-connect.sid",
        // secret used for using signed cookies w/ the session
        secret: process.env.SESSION_SECRET,
        store: new MongoStore({
          mongooseConnection: mongoose.connection,
          ttl: 14 * 24 * 60 * 60 // save session for 14 days
        }),
        // forces the session to be saved back to the store
        resave: false,
        // don't save unmodified sessions
        saveUninitialized: false,
        cookie: {
          httpOnly: true,
          maxAge: 1000 * 60 * 60 * 24 * 14 // expires in 14 days
        }
      };

    if (!dev) {
    sessionConfig.cookie.secure = true; // serve secure cookies in production environment
    server.set("trust proxy", 1); // trust first proxy
    }

    /* Apply our session configuration to express-session */
    server.use(session(sessionConfig));

    /* Add passport middleware to set passport up */
    server.use(passport.initialize());
    server.use(passport.session());

    server.use((req, res, next) => {
        /* custom middleware to put our user data (from passport) on the req.user so we can access it as such anywhere in our app */
        res.locals.user = req.user || null;
        next();
    });


    server.get("*", (req, res) => {
        handle(req, res);
    });
        
    server.listen(port, err => {
        if (err) throw err;
        console.log(`Server listening on ${ROOT_URL}`);
    });
    
})

Upon running the code above, I am encountering the following error:

UnhandledPromiseRejectionWarning: TypeError: Class constructor MongoStore cannot be invoked without 'new'

It appears that the line causing this error is:

const MongoStore = new mongoSessionStore(session);

How can this issue be resolved?

Answer №1

After some investigation, I discovered that the code I was using was based on connect-mongo ^2.0.1, while the version in my package.json file was ^4.4.0

Therefore, I had to make adjustments to the code to match the new version, and here is the final result:

const sessionConfig = {
        name: "next-connect.sid",
        // secret used for using signed cookies w/ the session
        secret: process.env.SESSION_SECRET,
        resave: false,
        saveUninitialized: false,
        store: MongoStore.create({
            mongoUrl: process.env.MONGODB_URI,
            mongooseConnection: mongoose.connection,
            ttl: 14 * 24 * 60 * 60 // save session for 14 days
        }),

        cookie: {
            httpOnly: true,
            maxAge: 1000 * 60 * 60 * 24 * 14 // expires in 14 days
        }
    }

    if (!dev) {
        sessionConfig.cookie.secure = true; // serve secure cookies in production environment
        server.set("trust proxy", 1); // trust first proxy
    }


    /* Apply our session configuration to express-session */
    server.use(session(sessionConfig));

So far, it seems to be functioning correctly...

Answer №2

Facing a similar issue within my application due to an update of connect-mongo to the latest version (4.1). Resolved the problem by removing the current connect-mongo package and reinstalling version 3.1.2.

To install version 3.1.2, you can use the following command:

npm install <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="debdb1b0b0bbbdaaf3b3b1b0b9b19eedf0eff0ec">[email protected]</a>

Alternatively, you can add the following line to your .json file and then run npm install to switch to the desired version:

"connect-mongo": "^3.1.2",

Answer №3

It appears that 'mongoSessionStore' is a Class Constructor.
Within a Class lies the blueprint for creating a fresh Object for the session, a task typically carried out in a Constructor.

Perhaps the solution is as simple as adding the keyword 'new' before mongoSessionStore. By doing so, Mongo will generate a new Object for the Session to commence.

Answer №4

You might be experiencing this issue because of your usage of connect-mongo@v4. A possible solution could be to install

npm i <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="05666a6b6b60667128686a6b6c6c642b353236">[email protected]</a> --save
to resolve the problem.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on customizing the MSAL login commands for successful integration with numerous users

Successfully implemented the code to login using a username and password combination with Cypress for a webapp integrated with MSAL. In the end-to-end Testfile: describe('Login with MSAL as xxUsername', () => { beforeEach(() => { cy.Lo ...

Creating a link button using JavaScript

I have integrated a Setmore code on my website to facilitate appointment booking, which triggers a popup similar to what you would see on a hotel reservation site. <script id="setmore_script" type="text/javascript" src="https://my.setmore.com/js/iframe ...

Is it possible to leverage specific client-side Javascript APIs on the server-side?

Exploring APIs designed for web browsers that require their .js code to return audio streams. In a broader sense, these APIs provide byte streams (such as audio) for playback in the browser. Is it possible to use these APIs in server-side Javascript frame ...

Tips for obtaining a cropped image as form data in React after the cropping process

import React, { PureComponent } from 'react'; import ReactCrop from 'react-image-crop'; import 'react-image-crop/dist/ReactCrop.css'; class CoachDashboard extends PureComponent { state = { src: null, crop: { u ...

How can I transfer the data from a file to upload it in Angular 9 without manually typing it out?

In my Angular application, I have a functionality where users can upload two files for processing on the server. However, I am looking to add a feature that allows users to simply copy and paste the contents of the files into two textboxes instead of going ...

Guide to accessing a newly opened window from a different domain originating from the current window

Currently working on an Angular project, I am facing a scenario where I have a link on page A that directs users to a different origin page B. The HTML code for the link is shown below: ... <a href="https://another.origin"> PAGE B </a> ... On ...

Dealing with Nginx and Next.js when encountering a 404 error on static files

I currently have a WordPress site hosted in the /var/www/html/ path with an nginx server. However, I am looking to integrate a specific page using nextjs (also in the /var/www/html/ path) through proxy on port 3000. When I try to access example.com/specifi ...

How can I convert Typescript absolute paths to relative paths in Node.js?

Currently, I am converting TypeScript to ES5/CommonJS format. To specify a fixed root for import statements, I am utilizing TypeScript's tsconfig.json paths property. For instance, my path configuration might look like this: @example: './src/&ap ...

What is the best way to remove a property from an object that is generated by mongoose?

I am looking to query the users collection without returning the password. I want to verify if it's possible to execute javascript operations on mongodb objects. Take a look at my code snippet below: router.get("/:userId", async (req, res) => { ...

Step-by-step guide on uploading a template in unlayer-react-email-editor

<EmailEditor ref={emailEditorRef} onReady={onTemplateReady} /> const onTemplateReady = () => { try { const templateJson = htmlToJSON(savedData?.email?.content); console.log({ templateJson }); emailEditorRef?.current?.editor?. ...

Obtaining dynamic text from an animated gif image using Java for Selenium automation

https://i.sstatic.net/hLXva.gif I am looking to extract all the text from this gif image and then confirm the accuracy of certain text. ...

Unleashing the Power of Google Apps Script Filters

Having some data in a Google Sheet, I am looking to filter it based on specific criteria and return corresponding values from another column. Additionally, I need to count the number of elements in the resulting column. Below is an example of the data: Sa ...

Implementing Google Tag Manager in NextJS to Address Discrepancies in Session and Click Tracking

After following the Google Tag Manager implementation recommended by NextJS developers at https://github.com/vercel/next.js/tree/canary/examples/with-google-tag-manager, we noticed discrepancies with some services connected through GTM (such as Google Anal ...

Issue with IE preventing Selenium from triggering Onchange event and causing page to fail to Postback

I am currently working on a web application where selecting an item from one drop-down list triggers the loading of another. However, when using Selenium to automate this process, I have encountered an issue where the page post back is prevented and the se ...

Issues with Skrollr JS on mobile device causing scrolling problem

Currently facing an issue with Skrollr js. It is functioning perfectly in web browsers and mobile devices. However, there seems to be a problem when tapping on a menu or scrolling down arrow as it does not initiate scrolling. Assistance would be greatly ...

I am facing an issue where the state in Next.js React does not get updated when passing a

"use client"; import { EntityType, World } from "@/types/World"; import React, { useState } from "react"; import dynamic from "next/dynamic"; ; let RayTracingPage = dynamic(()=>import("./RayTracingCanvas&qu ...

Adjusting the rotation transform by deleting and reapplying canvas is causing the chart to not display data after redrawing

I am facing a challenge with my previous issue and I am exploring different solutions. One approach I am considering is to remove the canvas element completely and then re-add it, effectively resetting all rotations on the canvas. Although this method alm ...

Combining two Unix timestamps into a single value

Looking for a way to condense a date range into GET parameters for my application, I pondered the possibility of encoding two Unix timestamps into a single parameter to minimize URL length. While a basic CSV of two timestamps would suffice, my aim is to f ...

"Rails Ajax spinner functions properly in the development environment, but encounters issues in the

I am currently implementing this JavaScript code: verify_link.js ... a=$(this).parent(); a.html('<img src="assets/ajax-loader.gif">'); ... The image file is located in app/assets/images/ajax-loader.gif Everything works fine in de ...

Adding a unique element to other elements in jQuery/Javascript can be achieved even when the existing elements only have classes assigned to them

One interesting feature of a Wordpress theme is the ability for site administrators to create forms with descriptions for each field. These descriptions share a common class, 'description,' and look like this: <div class="field-head"><l ...