Chevrotain / chevrotain

Parser Building Toolkit for JavaScript
https://chevrotain.io
Apache License 2.0
2.44k stars 199 forks source link

Error: No "exports" main defined #1992

Closed dhowe closed 5 months ago

dhowe commented 8 months ago

Greetings, I have a project to which I am trying to add chevrotain. I have been running mocha tests as follows:

$ NODE_ENV=dev npx mocha -r @babel/register ./test/*.js

After installing chevrotain with npm (I see "^11.0.3" in my package.json ), I get the error below when I run the test command. The only code I have added is the a new file with this one line:

import { CstParser } from "chevrotain"

Line 19 of before.js, from which the error appears to originate, is as follows:

let module = await import(file);
   Error: No "exports" main defined in /PATH_TO_PROJECT/node_modules/chevrotain/package.json
   at new NodeError (node:internal/errors:393:5)
      at throwExportsNotFound (node:internal/modules/esm/resolve:340:9)
      at packageExportsResolve (node:internal/modules/esm/resolve:564:7)
      at resolveExports (node:internal/modules/cjs/loader:492:36)
      at Function.Module._findPath (node:internal/modules/cjs/loader:532:31)
      at Function.Module._resolveFilename (node:internal/modules/cjs/loader:941:27)
      at Function.Module._load (node:internal/modules/cjs/loader:803:27)
      at Module.require (node:internal/modules/cjs/loader:1021:19)
      at require (node:internal/modules/cjs/helpers:103:18)
      at Object.<anonymous> (src/riscript.js:1:1)
      at Module._compile (node:internal/modules/cjs/loader:1119:14)
      at Module._compile (node_modules/pirates/lib/index.js:117:24)
      at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
      at Object.newLoader [as .js] (node_modules/pirates/lib/index.js:121:7)
      at Module.load (node:internal/modules/cjs/loader:997:32)
      at Function.Module._load (node:internal/modules/cjs/loader:838:12)
      at Module.require (node:internal/modules/cjs/loader:1021:19)
      at require (node:internal/modules/cjs/helpers:103:18)
      at Object.<anonymous> (src/rita.js:16:1)
      at Module._compile (node:internal/modules/cjs/loader:1119:14)
      at Module._compile (node_modules/pirates/lib/index.js:117:24)
      at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
      at Object.newLoader [as .js] (node_modules/pirates/lib/index.js:121:7)
      at Module.load (node:internal/modules/cjs/loader:997:32)
      at Function.Module._load (node:internal/modules/cjs/loader:838:12)
      at Module.require (node:internal/modules/cjs/loader:1021:19)
      at require (node:internal/modules/cjs/helpers:103:18)
      at /PATH_TO_PROJECT//test/before.js:19:25
      at processTicksAndRejections (node:internal/process/task_queues:95:5)
msujew commented 8 months ago

Given the stack trace, Mocha runs your code as CommonJS, but Chevrotain is now an ESM only library. It cannot be imported via require.

dhowe commented 8 months ago

I use import throughout the code base, and this problem only occurs when I add that one line, importing CstParser:

import Inflector from './inflector';
import RandGen from './randgen';
import Util from './util';
import { Query } from "mingo"

 // adding this line triggers the issue
import { CstParser } from "chevrotain"
msujew commented 8 months ago

Copying from your supplied stack trace:

      at Module.require (node:internal/modules/cjs/loader:1021:19)
      at require (node:internal/modules/cjs/helpers:103:18)
      at /Users/dhowe/git/ritajs.v3/test/before.js:19:25

It looks like it still uses require/cjs internally. Might be more related to mocha than nodejs directly.

dhowe commented 8 months ago

Right -- I guess what I'm trying to figure out is what is different about chevrotain that triggers this issue, while none of the many other libraries I'm using do

msujew commented 8 months ago

Chevrotain is probably different in the sense that it only has an import export. Others such as mingo also export a require, which is used in this context. I would recommend vitest for testing an ESM app by the way. I assume that babel + mocha is messing with the import and transforms it into a require.

dhowe commented 8 months ago

Hmmm, ok vitest looks like it would be a good option if I didn't already have many hundreds of mocha tests

msujew commented 8 months ago

Afaik, vitest should be a drop-in replacement for mocha. You just need to adjust your imports/globals.

dhowe commented 8 months ago

This is a related question: I want to bundle my library (which uses Chevrotain) as cjs for node. Is this possible given that chevrotain is now ESM only?

Or, would, you recommend, at the end of 2023, that newly-created libraries also be ESM only?

A reddit thread on the question

msujew commented 8 months ago

@dhowe You could call Chevrotain (in it's current state) CJS compatible ESM code. Bundlers such as esbuild can compile it back into cjs without any issues. I use it like that as well when bundling for vscode extensions.

I feel like the ecosystem is still in a transitional period. My company has recently migrated to releasing newer major versions of libraries as ESM-only. However, adoption for those new versions isn't high enough yet to get a good grip on whether people can deal well with it. Generally, I've seen most libraries currently exporting both CJS and ESM, which seems to work well. I imagine them eventually dropping CJS though, such as Chevrotain did.

dhowe commented 8 months ago

thanks for this @msujew - do you mind sharing your esbuild config options for bundling Chevrotain as commonjs (I'm using tsup which is built on esbuild ) ??

msujew commented 8 months ago

@dhowe We're using esbuild to build language servers (using Chevrotain as the parser engine) for vscode, which only accepts cjs right now. See here for our esbuild config.

dhowe commented 8 months ago

thank you @msujew