Decorator is a neat design pattern which lets you extend the functionality without modifying it. It's usually also a higher order function = function that takes another function as an argument.

I need a way connect to Mongodb

In my NextJS project I use mongodb as a persistence layer, and to be able to do queries I need to :

await connect(config.mongoose.uri, config.mongoose.options)

This turns out to be a repetitive task for any api route or a page.

I could use a middleware

NextJS has a middleware to do that, but I'm not sure that I like using middleware for that purpose.

Middleware gets called for everything, even the _next routes. And If you don't want to call it for everything, you'd use a matcher, something like:

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|favicon.ico).*)',
  ],
}

I prefer decorators instead

Now, a middleware may be perfectly fine for logging, but it looked off to me to use it to connect to the mongo database.

Instead, I created a decorator that connects to the database under the hood. It still is a repetitive task, but I prefer to explicitly call it whenever I need mongodb in the scope.

export function withMongooseSessionApiRoute<T>(
  handler: NextApiHandler<T>,
  uri: string,
  options: ConnectOptions
): NextApiHandler<T> {
  return async function nextApiHandler(req: NextApiRequest, res: NextApiResponse) {
    await connect(uri, options);
    return handler(req, res);
  };
}

withMongooseSessionApiRoute is a function that takes another function (nextjs handler) and mongodb connect options. Inside the withMongooseSessionApiRoute, a connection to mongo gets done first and nextjs handler call is second.

And for an api route, you'd call like:

export default withMongooseSessionApiRoute(
  async function handler(req, res) {

  }
);

Small caveat on the current implementation is that cache is not supported for multiple different uris. If you need that implementation, please open a new issue request at https://github.com/eisberg-labs/next-mongoose-session/issues.

You can check out the code and instructions at https://github.com/eisberg-labs/next-mongoose-session.

If you're not sure how to configure mongoose schemas, take a look at my other post!