GitSquared / node-geolite2-redist

Redistribution of MaxMind GeoLite2 GeoIP databases as an npm library
https://gitsquared.github.io/node-geolite2-redist/
Other
86 stars 18 forks source link

ERR_REQUIRE_ESM error when importing module in Nestjs project #22

Closed rvalle closed 2 years ago

rvalle commented 2 years ago

I am getting into trouble just trying to use geolite2-redist from nestjs

I am not completely sure who is at fault if the module metadata or nestjs compilation process.

Since nestjs is a very widespread nodejs appolication framework I deceded to notify it here.

Looks like nestjs is assuming this library is CJS but it looks ESM to me. I would assume that something in project.json is triggering this situation.

Any idea why this is happening?

It can be reproduced by creating an empty NestJS project and using geolite2-redist from the controller or service.

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: .../node_modules/geolite2-redist/dist/index.js
require() of ES modules is not supported.
require() of .../node_modules/geolite2-redist/dist/index.js from .../dist/geolite.service.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from .../node_modules/geolite2-redist/package.json.
GitSquared commented 2 years ago

You'll find helpful information here on how to use modern ESM packages

rvalle commented 2 years ago

As a module user, I think I am using it correctly:

import geolite2, {GeoIpDbName} from 'geolite2-redist';
import maxmind from 'maxmind';

from my typescript service.

rvalle commented 2 years ago

I am also using other ESM modules (all nestjs distribution), but those look similar to geolite2-redist....

so, I am not sure what exactly is causing the trouble.

rvalle commented 2 years ago

the issue can easily be reproduced by creating a new nestjs project, and replacing the controller with this code, which would inject the databases as a dependency into the controller after they have been downloaded:

import { Controller, Get } from '@nestjs/common';
import { Inject, Injectable, Logger } from '@nestjs/common';

import { AppService } from './app.service';

import geolite2, { GeoIpDbName } from 'geolite2-redist';
import maxmind from 'maxmind';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject('GEOLITE_DB') private readonly geolite,
  ) {
    // nothing
  }

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

export const GeoliteDBService = {
  provide: 'GEOLITE_DB',
  useFactory: async () => {
    const logger = new Logger('GEOLITE_DB');
    await geolite2.downloadDbs();
    logger.log('Geolite2 Databases Downloaded');
    return {
      asn: await geolite2.open(GeoIpDbName.ASN, (path) => maxmind.open(path)),
      country: await geolite2.open(GeoIpDbName.Country, (path) =>
        maxmind.open(path),
      ),
    };
  },
};
rvalle commented 2 years ago

this seems to be related https://github.com/nestjs/nest/issues/7021

rvalle commented 2 years ago

this is very strange.... anyway, the only workaround I can find is to downgrade to version 2.x

GitSquared commented 2 years ago

Hmm, indeed, your usage is correct.

I'm not familiar with Nest.js, but this comment in the issue you linked seems to indicate that you could work around the issue by adding a bundler like Rollup to your build step?

Also, are you using node 12 or later?

rvalle commented 2 years ago

I am testing against node 14 and 16, both display the issue.

I think, generally speaking, this issue is related to the "transition" to ESM, everybody seems to be taking steps towards it, but steps may be conflicting.

I am not familiar with Rollup, but I will certainly review it.

notimobi commented 2 years ago

I have the same issue with 3.0. I tried the sample code from the README, using both nodejs 14 and16. All result in the same error. The only solution to me is to downgrade to 2.0. I have not found a workaround yet.

GitSquared commented 2 years ago

@notimobi have you looked here? Are you using nestjs as well?

notimobi commented 2 years ago

I think I found the cause of the issue. When using nvm, this issue arises. After bypassing the nvm command, the code works fine. Thanks @GitSquared

rvalle commented 2 years ago

This seems to be an issue on NestJS, for not having direct support of ESM modules. I found it easier just to use the 2.0 for now. I guess the other alternative is to use bundling. It not intuitive to be writing ESM modules and not been able to use them, at the same time.

GitSquared commented 2 years ago

Closing as there's nothing I can do here, but feel free to link an issue on Nest's side if they start working on this...