Reputation: 107
I have created a NextJS application and I want to use mongoDB as my database, but I have a problem, when ever I'm calling the function that uses the database from one of the pages it works just fine, but when I am calling it from the middleware.js
that clerk is using I am getting this error:
mongoose__WEBPACK_IMPORTED_MODULE_0___default(...).connect is not a function
The nextjs version I am using is 14.0.4 and the mongoose is 8.0.3. And the package I installed is mongoose using the npm install mongoose
command.
I am using the connect statment in the user model.
/lib/models/user.model.js
contains this code:
"use server";
import mongoose, { Schema } from "mongoose";
mongoose.connect(process.env.MONGODB_URI);
mongoose.Promise = global.Promise;
const userSchema = new Schema(
{
// some fields here
},
{ timestamps: true }
);
const User = mongoose.models.User || mongoose.model("User", userSchema);
export default User;
these are the functions that I am calling from different parts of the code that contains the functions /lib/actions/actions.js
:
"use server";
import User from "../models/user.model";
export async function updateUser(params) {
try {
await User.findOneAndUpdate(
{
// putting the params here.
}
{ upsert: true }
);
} catch (error) {
throw new Error(`Faild to create/update user ${error.message}`);
}
}
export async function fetchUser(ClerkUserId) {
try {
const user = await User.findOne({ ClerkUserId });
return user;
} catch (error) {
console.error("Error fetching user:", error);
return null;
}
}
when I call the updateUser
from /components/forms/OnBoardingForm.jsx
the process works greate and the data is being inserted/updated to the database. (The form is called from a page.jsx that is int eh app route).
but when I am calling is from the middleware that is in /middleware.js
that is running before the pages of the app I am getting the error mentioned above.
Does someone knows why it is happening and how can I fix it?
For thos who who wants to get a look on the OnBoardingForm.jsx, middleware.js and layout.js:
OnBoardingForm.jsx:
"use client";
import { useState } from "react";
import { updateUser } from "@/lib/actions/actions";
const OnBoardingForm = ({ userData }) => {
const [username, setUsername] = useState(userData.username);
const [phoneNumber, setPhoneNumber] = useState("");
const [location, setLocation] = useState("");
const submitForm = async () => {
await updateUser(
userData.id,
userData.username,
userData.firstName,
userData.lastName,
userData.location,
userData.phoneNumber
);
};
return (
<>
<div className="flex flex-col px-20 gap-6 mt-20">
<div className="flex flex-col">
<label>username</label>
<input
className="px-5 py-2 rounded text-black"
value={username}
placeholder="Enter your busines name"
onChange={(e) => {
userData.username = e.target.value;
setUsername(e.target.value);
}}
/>
</div>
<div className="flex flex-col">
<label>location</label>
<input
className="px-5 py-2 rounded text-black"
value={location}
placeholder="Enter your location"
onChange={(e) => {
userData.location = e.target.value;
setLocation(e.target.value);
}}
/>
</div>
<div className="flex flex-col">
<label>phone number</label>
<input
className="px-5 py-2 rounded text-black"
value={phoneNumber}
placeholder="Enter your phone number"
onChange={(e) => {
userData.phoneNumber = e.target.value;
setPhoneNumber(e.target.value);
}}
/>
</div>
<button
className="mt-5 bg-white rounded py-3 font-bold"
style={{
fontSize: "1.2rem",
backgroundColor: "#6a48f2",
}}
onClick={() => {
submitForm();
}}
>
Continue
</button>
</div>
</>
);
};
export default OnBoardingForm;
middleware.js
"use server";
import { authMiddleware, redirectToSignIn } from "@clerk/nextjs";
import { fetchUser } from "./lib/actions/actions";
export default authMiddleware({
publicRoutes: ["/"],
afterAuth: async (auth, req, evt) => {
if (!auth.userId && !auth.isPublicRoute) {
return redirectToSignIn({ returnBackUrl: req.url });
} else if (auth.userId) {
await fetchUser(auth.userId);
}
},
});
export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
layout.js
import { Inter } from "next/font/google";
import "./globals.css";
import { ClerkProvider } from "@clerk/nextjs";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<ClerkProvider>
<html lang="en">
<body className={inter.className}>
<main className="flex flex-col w-full min-h-screen">{children}</main>
</body>
</html>
</ClerkProvider>
);
}
Upvotes: 1
Views: 204
Reputation: 103
Currently mongodb calls are not supported in Next.js middleware because middleware edge runtime nature is not compatible with mongodb adapter for connection.
There are alternatives to approach this here: https://medium.com/@chxiuy/mongodb-in-nextjs-overcoming-the-edge-runtime-middleware-hurdle-4beee31eaa30 and an official discussion about it here: https://github.com/vercel/next.js/discussions/46722
Upvotes: 0