import-js / eslint-plugin-import

ESLint plugin with rules that help validate proper imports.
MIT License
5.51k stars 1.56k forks source link

import/no-unresolved does not report none-existing function in Yarn workspace #1832

Open chrisdoc opened 4 years ago

chrisdoc commented 4 years ago

I noticed that import/no-unresolved is not warning me when I forgot to export a function from a Yarn workspace which will be imported from another Yarn workspace.

I created a minimal repo https://github.com/chrisdoc/eslint-plugin-import-bug-minimal-repo which consists of two workspaces foo and bar.

.
├── .eslintrc.js
├── .gitignore
├── bar
│   ├── index.js
│   └── package.json
├── foo
│   ├── index.js
│   └── package.json
├── LICENSE
├── package.json
├── README.md
└── yarn.lock

Inside foo/index.js there is a single function helloFoo which is exported so that it can be consumed by bar

function helloFoo() {
  // eslint-disable-next-line no-console
  console.log('hello foo');
}

module.exports = { helloFoo };

Now in bar/index.js I import both helloFoo and a none existing helloFooV2 via:

const { helloFoo, helloFooV2 } = require('@my/foo');

Now when I run yarn lint no errors are reported:

yarn lint
yarn run v1.22.4
$ eslint .
✨  Done in 1.23s.

When I then try to execute yarn bar which calls bar/index.js NodeJS fails due to calling helloFooV2 which does not exist.

yarn run v1.22.4
$ yarn workspace @my/bar start
$ node index.js
hello foo
/Users/chrisdoc/dev/eslint-plugin-import-bug-minimal-repo/bar/index.js:4
helloFooV2();
^

TypeError: helloFooV2 is not a function
    at Object.<anonymous> (/Users/chrisdoc/dev/eslint-plugin-import-bug-minimal-repo/bar/index.js:4:1)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed.
Exit code: 1
Command: /Users/chrisdoc/.nvm/versions/node/v12.13.0/bin/node
Arguments: /Users/chrisdoc/.yarn/lib/cli.js start
Directory: /Users/chrisdoc/dev/eslint-plugin-import-bug-minimal-repo/bar
Output:

info Visit https://yarnpkg.com/en/docs/cli/workspace for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Here you can see an example being run on Github Workflows that shows that yarn lint succeeds and that yarn bar fails

https://github.com/chrisdoc/eslint-plugin-import-bug-minimal-repo/runs/787914292

ljharb commented 4 years ago

I assume this is because the ExportMap doesn't traverse symlinks - does it fail as expected when things are installed, not symlinked in?

SanjiKir commented 4 years ago

I have the same issue in monorepo. import/named doesn't check private yarn workspaces.

ljharb commented 4 years ago

@SanjiKir you'd have to provide a custom resolver if you have a custom layout, including any "workspaces" things.

jd2rogers2 commented 3 years ago

@ljharb can expand further on what my custom resolver would need to do please?! i'm having the same issue, @SanjiKir did you get yours working?

ljharb commented 3 years ago

@jd2rogers2 anything that doesn’t match standard node resolution has to tell this plugin how to resolve files.

In this specific case, no-unresolved isn’t the issue, since the file resolves; it’d be a different rule that should be warning on a missing export from a present file.

jd2rogers2 commented 3 years ago

@jd2rogers2 anything that doesn’t match standard node resolution has to tell this plugin how to resolve files.

In this specific case, no-unresolved isn’t the issue, since the file resolves; it’d be a different rule that should be warning on a missing export from a present file.

@ljharb right, i'm getting input/named false negatives (lack of error when i'd expect there to be one) i have import { DoesntExist } from 'react-dom'; but not getting an error and

module.exports = {
  env: {
    browser: true,
    'cypress/globals': true,
    es6: true,
    'jest/globals': true,
  },
  extends: [
    'eslint:recommended',
    'plugin:import/errors',
    'plugin:import/warnings',
    'plugin:import/typescript',
    'airbnb',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  globals: {
    Atomics: 'readonly',
    SharedArrayBuffer: 'readonly',
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  plugins: [
    'cypress',
    'jest',
    'react',
    '@typescript-eslint',
    'import',
  ],
  rules: {
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/member-delimiter-style': 'off',
    '@typescript-eslint/no-empty-function': 'off',
    '@typescript-eslint/no-empty-interface': 'off',
    '@typescript-eslint/no-unused-vars': 'error',
    'arrow-parens': ['error', 'as-needed'],
    'import/extensions': ['error', 'never'],
    'import/prefer-default-export': ['off'],
    'import/no-cycle': ['off'],
    'import/no-unresolved': 2,
    'import/named': 2,
    'max-len': ['error', { 'code': 100 }],
    'no-multiple-empty-lines': ['error', { max: 2 }],
    'no-unused-vars': 'off',
    'react/jsx-filename-extension': ['error', { extensions: ['.tsx'] }],
    'react/jsx-one-expression-per-line': ['off'],
    'react/jsx-props-no-spreading': ['off'],
    'react/prop-types': 0,
    'react/require-default-props': ['error', { ignoreFunctionalComponents: true }],
  },
  settings: {
    // 'import/extensions': ['.js', '.jsx', '.ts', '.tsx'],
    'import/resolver': {
      node: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
      // 'typescript': { extensions: ['.ts', '.tsx'] },
    },
    'import/internal-regex': [
      '^node_modules/@premisedata',
      '^node_modules/portal',
      '^packages/apps/portal/', 
      '^packages/apps/stories/', 
      '^packages/apps/tools/', 
      '^packages/apps/web-api/',
      '^packages/libs/base-ui/', 
    ],
  }
};

(not exactly in the best shape as i've been trying a bunch of stuff but i would still expect those named errors) am i wrong in assuming that it should fail for node_modules too?

ljharb commented 3 years ago

You aren't wrong. Could you file a new issue for that, since I think it's not related to this issue?