Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exports are not respected #132

Open
mangs opened this issue Oct 14, 2022 · 10 comments
Open

exports are not respected #132

mangs opened this issue Oct 14, 2022 · 10 comments
Labels
bug Something isn't working

Comments

@mangs
Copy link

mangs commented Oct 14, 2022

Hi,
Thank you for creating this great tool! I found it while looking through the eslint-plugin-unicorn repo and stumbling upon this PR: sindresorhus/eslint-plugin-unicorn#1930

I would love to use your tool for my own ESLint library, but unfortunately it does not respect the exports defined in my library's package.json. Here is the output I see and the associated package.json exports config:

Terminal output

eric@Erics-MacBook-Pro eslint-config-usa-tech.js $ npm run update:readme-eslint-rules-list

> @lessonnine/eslint-config-usa-tech.js@1.1.2 update:readme-eslint-rules-list
> eslint-doc-generator

node:internal/errors:477
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/eric/code/babbel/eslint-config-usa-tech.js/index.js' imported from /Users/eric/code/babbel/eslint-config-usa-tech.js/node_modules/eslint-doc-generator/dist/lib/import.js
    at new NodeError (node:internal/errors:387:5)
    at finalizeResolution (node:internal/modules/esm/resolve:429:11)
    at moduleResolve (node:internal/modules/esm/resolve:1006:10)
    at defaultResolve (node:internal/modules/esm/resolve:1214:11)
    at nextResolve (node:internal/modules/esm/loader:165:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:844:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:431:18)
    at ESMLoader.import (node:internal/modules/esm/loader:528:22)
    at importModuleDynamically (node:internal/modules/esm/translators:110:35)
    at importModuleDynamicallyCallback (node:internal/process/esm_loader:35:14) {
  code: 'ERR_MODULE_NOT_FOUND'
}

exports config from package.json

"exports": {
  ".": "./lib/eslintBaseConfig.json",
  "./browser": "./lib/eslintBrowserConfig.json",
  "./jest": "./lib/eslintJestConfig.json",
  "./node": "./lib/eslintNodeConfig.json",
  "./preact": "./lib/eslintPreactConfig.json",
  "./preact-typescript": "./lib/eslintPreactTypescriptConfig.json",
  "./react": "./lib/eslintReactConfig.json",
  "./react-typescript": "./lib/eslintReactTypescriptConfig.json",
  "./typescript": "./lib/eslintTypescriptConfig.json"
},

My repo does not have an index.js file, and as you can see above, my root export is defined in exports and comes from a JSON file (./lib/eslintBaseConfig.json). ESLint has no problem consuming this library, and I plan to open source it using your tool to improve my documentation. Any help you could provide would be greatly appreciated.

@bmish bmish added the bug Something isn't working label Oct 14, 2022
@bmish
Copy link
Owner

bmish commented Oct 14, 2022

Thanks for the report! I'll definitely plan to support exports ASAP.

@mangs
Copy link
Author

mangs commented Oct 14, 2022

No worries. I'm happy to work with you to get it working if that would help.

@bmish
Copy link
Owner

bmish commented Oct 14, 2022

I currently have some manual logic for importing the eslint plugin package entry point which only handles main. We could fix it by adding logic to handle exports too:

const pluginEntryPoint = join(

However, this issue has made me realize that there must be a simpler technique for importing a local package without having to implement all the entry point logic...

@bmish bmish added this to the v1.0.0 milestone Oct 15, 2022
@mangs
Copy link
Author

mangs commented Oct 16, 2022

Hmm, interesting. I know ESLint supports my setup just fine, so unless I'm doing something wrong and ESLint is just super-accepting of incorrect setups, let's look at what ESLint is doing for handling imports. I've found the exact same problem with Stylelint (I haven't filed an issue there yet; I have a Stylelint library too), so I'm sure you're not the only one asking this question.

@mangs
Copy link
Author

mangs commented Oct 16, 2022

From reading through the documentation on handling packages in Node.js, it should be handling this "automatically" when you import a package path. Perhaps I'm missing something?

@bmish
Copy link
Owner

bmish commented Oct 16, 2022

To be clear, you're not doing anything wrong, we definitely want to handle both CJS/ESM ESLint plugins (using either main or exports).

Node will automatically find/load a package's entry point when importing it with require('package-name') or import('package-name').

But in this tool, we are not importing an ESLint plugin via its package name. Instead, we're dealing with a local package on the filesystem that might not even be published, and we just have the path to this package. So the code I linked above manually looks at package.json at that file path to find the entry point to load.

So if we could find a way to automatically load a local package (which could be CJS or ESM) via its file path, that would solve the problem. Passing a path to import(path) won't work because that tries to load a specific file path instead of resolve the package entry point.

@bmish
Copy link
Owner

bmish commented Oct 16, 2022

A few more questions:

  1. Does your package have main defined in package.json?
  2. Does your package have type defined in package.json?
  3. Anything else about ESLint defined in your package.json?
  4. Is your package written in CJS or ESM?
  5. Is there any compilation step in your plugin?

@bmish
Copy link
Owner

bmish commented Oct 16, 2022

Can you also show me how your ESLint plugin/config is used?

@mangs
Copy link
Author

mangs commented Oct 17, 2022

A few more questions:

1. Does your package have `main` defined in package.json?

2. Does your package have `type` defined in package.json?

3. Anything else about ESLint defined in your package.json?

4. Is your package written in CJS or ESM?

5. Is there any compilation step in your plugin?

Replies by number:

  1. No
  2. No
  3. No
  4. Neither, it's only JSON files
  5. No

As you can see in the exports list, there are quite a few different ESLint configs; they are meant to be layerable. For example, if you're running a browser environment with Preact, you can use the browser and preact configs simultaneously:

"extends": ["@lessonnine/usa-tech.js/preact", "@lessonnine/usa-tech.js/browser"]

or for Node.js, TypeScript, and Jest:

"extends": ["@lessonnine/usa-tech.js/typescript", "@lessonnine/usa-tech.js/jest", "@lessonnine/usa-tech.js/node"]

Hope that makes sense. It's meant to be a library of configs that are easy to pickup and use regardless of your use case.

@bmish
Copy link
Owner

bmish commented Oct 19, 2022

Thanks for the details. I may have more questions later as I work on a fix.

@bmish bmish removed this from the v1.0.0 milestone Nov 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants