Global Type Setup

This file extends the global namespace so TypeScript knows that global.mongoose exists. We store the active connection and the connection promise here. It prevents TS errors and lets us reuse the same connection during development.
//type.ts
  import { Connection } from "mongoose";

declare global {
  var mongoose: {
    conn: Connection | null;
    promise: Promise<Connection> | null;
  };
}

export {};

MongoDB Connection Logic

This function connects our app to MongoDB. In dev mode, Next.js hot reload can run database code multiple times. To avoid opening new connections every refresh, we keep a cached connection on global.mongoose. If a connection already exists, we reuse it. If not, we create one and store it.
import mongoose from "mongoose";
  
  const MONGO_URL = process.env.MONGO_URL;
  
  if (!MONGO_URL) {
    throw new Error("MongoDB URL not found");
  }
  
  // global cache to avoid multiple connections in dev
  let cached = global.mongoose;
  
  if (!cached) {
    cached = global.mongoose = { conn: null, promise: null };
  }
  
  const dbConnect = async () => {
    if (cached.conn) {
      // console.log("Cashed db connected")
      return cached.conn;
    }
    if (!cached.promise) {
      cached.promise = mongoose.connect(MONGO_URL).then((m) => m.connection);
    }
  
    try {
      cached.conn = await cached.promise;
      return cached.conn;
      // console.log("DB connected")
    } catch (error) {
      cached.promise = null;
      throw error;
    }
  };
  
  export default dbConnect;