arashsheyda / nuxt-mongoose

A Nuxt module for simplifying the use of Mongoose in your project.
https://docs.arashsheyda.me/nuxt-mongoose
75 stars 13 forks source link

fix: Do not interrupt the module setup process when missing MONGODB_URI #54

Closed Coiggahou2002 closed 5 months ago

Coiggahou2002 commented 5 months ago

TL;DR

An early return statement in the setup function of nuxt-mongoose module interrupts type-generation process due to missing env MONGODB_URI at build process and cause error at runtime.

Related Issue

52

Background Information

I integrated mongoose into my Nuxt3 project using the nuxt-mongoose module. During the development and deployment process, I discovered the following problems:

Note: The npm run dev, npm run build and npm run preview mentioned above refer to nuxt dev, nuxt build and nuxt preview respectively.

What the bug looks like

Weird things happened during both the build process and runtime

build process

During the build process running on the builder-machine of Github Actions, more specifically AFTER building the client bundle and BEFORE building the server bundle.

[warn] Missing MongoDB URI. You can set it in your `nuxt.config` or in your `.env` as `MONGODB_URI

...

(node-resolve plugin) Could not resolve import "#nuxt/mongoose" 
in /path/to/myProject/server/models/record.schema.ts
 using imports defined in /path/to/myProject/sensor-attention/package.json.

(node-resolve plugin) Could not resolve import "#nuxt/mongoose"
 in /path/to/myProject/server/models/record.schema.ts 
using imports defined in /path/to/myProject/sensor-attention/package.json.

"#nuxt/mongoose" is imported by "server/models/record.schema.ts", but could not be 
resolved – treating it as an external dependency.

runtime

One of my API routes use the schema to fetch data from the remote database, the following error occurs.

 [nuxt] [request error] [unhandled] [500] Package import specifier
 "#nuxt/mongoose" is not defined in package /path/to/myProject/.output/server/package.json 
imported from /path/to/myProject/.output/server/chunks/routes/api/records/list.get.mjs

Reproduction

I've made a minimal reproduction here. The reproduction steps are written in README.md inside the following StackBlitz project 👇

nuxt-mongoose PR issue#52 reproduction - StackBlitz

How the bug happens

  1. The setup function of nuxt-mongoose will first merge the user's config and the default config, and then generate the typing file.nuxt/types/nuxt-mongoose.d.ts which contains declare module '#nuxt/mongoose' {... ..}, this setup function will be executed at BUILD time.
  2. If I did not inject the MONGODB_URI env during the BUILD PROCESS(e.g. enject envs via PM2 config), the setup process will be interrupted by an early return, and the subsequent statements which generates type files located in .nuxt/ would not be executed, causing the @rollup/plugin-node-resolve of Rollup not recognizing '#nuxt/mongose' during compilation thus treat it as an external dependency, causing this line of statement to be retained in the compiled product, triggering an error at runtime.
// src/module.ts
const module = defineNuxtModule({
  meta: {
    name: "nuxt-mongoose",
    configKey: "mongoose"
  },
  defaults: {
    // eslint-disable-next-line n/prefer-global/process
    uri: process.env.MONGODB_URI,
    devtools: true,
    options: {},
    modelsDir: "models"
  },
  hoosk: {...}, 
  async setup(options, nuxt) {
    //...
    if (!options.uri) {
      logger.warn("Missing MongoDB URI. You can set it in your `nuxt.config` or in your `.env` as `MONGODB_URI`");
      return;
    }
    //...
    addTemplate({
      filename: "types/nuxt-mongoose.d.ts",
      getContents: () => [
        "declare module '#nuxt/mongoose' {",
        `  const defineMongooseConnection: typeof import('${resolve("./runtime/server/services")}').defineMongooseConnection`,
        `  const defineMongooseModel: typeof import('${resolve("./runtime/server/services")}').defineMongooseModel`,
        "}"
      ].join("\n")
    });
    nuxt.hook("prepare:types", (options2) => {
      options2.references.push({ path: resolve(nuxt.options.buildDir, "types/nuxt-mongoose.d.ts") });
    });
    //...
});

Conclusion

I think we should not interrupt the type-generation process when MONGODB_URI is missing during the build process, because we need that env actually runtime-only. 😊

arashsheyda commented 5 months ago

@Coiggahou2002 this is great and very well explained, thank you so much!