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

[import/no-extraneous-dependencies]: better support for monorepos #1650

Closed
armano2 opened this issue Feb 8, 2020 · 16 comments
Closed

[import/no-extraneous-dependencies]: better support for monorepos #1650

armano2 opened this issue Feb 8, 2020 · 16 comments

Comments

@armano2
Copy link

armano2 commented Feb 8, 2020

This is a feature request

Its possible that this is just an issue in documentation as i didn't dig to source code yet

packageDir option should take into account yarn workspaces or lerna projects if present to ease usage of for large monorepo projects

this can be also achieved by allowing us to use regexp / glob to find roots

Context

i recently noticed that in some of projects that I'm using, has this rule configured incorrectly,
user has to provide paths to all package.json configs even if he is working on monorepos

example of projects that can benefit from this change (big one that i worked on):

Note that all of those projects currently have invalid configuration for this rule,
unless i misread documentation and package.json files are resolved relatively to parsed file


related comments/issues:

@armano2
Copy link
Author

armano2 commented Feb 8, 2020

it seems that this rule is not working even with directories to package configs are provided

const path = require('path');
const fs = require('fs');

const isDirectory = source => fs.lstatSync(source).isDirectory();
const getDirectories = source =>
	fs
		.readdirSync(source)
		.map(name => path.join(source, name))
		.filter(isDirectory);

module.exports = {
	root: true,
	plugins: ['@typescript-eslint', 'jest', 'import'],
	env: {
		es6: true,
		node: true
	},
	parser: '@typescript-eslint/parser',
	parserOptions: {
		sourceType: 'module',
		ecmaVersion: 11,
		ecmaFeatures: {
			jsx: false
		}
	},
	extends: [
		'eslint:recommended',
		'prettier',
		'plugin:import/typescript'
	],
	rules: {
		// disallow non-import statements appearing before import statements
		'import/first': 'error',
		// Forbid import of modules using absolute paths
		'import/no-absolute-path': 'error',
		// disallow AMD require/define
		'import/no-amd': 'error',
		// Forbid the use of extraneous packages
		'import/no-extraneous-dependencies': [
			'error',
			{
				packageDir: [
					__dirname,
					...getDirectories(path.join(__dirname, '@packages')),
					...getDirectories(path.join(__dirname, '@commitlint')),
					...getDirectories(path.join(__dirname, '@alias'))
				]
			}
		],
		// Forbid mutable exports
		'import/no-mutable-exports': 'error',
		// Prevent importing the default as if it were named
		'import/no-named-default': 'error',
		// Prohibit named exports
		'import/no-named-export': 'off', // we want everything to be a named export
		// Forbid a module from importing itself
		'import/no-self-import': 'error',
		// Require modules with a single export to use a default export
		'import/prefer-default-export': 'off' // we want everything to be named
	},
	overrides: [
		{
			files: ['*.ts'],
			parser: '@typescript-eslint/parser',
			extends: [
				'plugin:@typescript-eslint/eslint-recommended',
				'plugin:@typescript-eslint/recommended',
				'prettier/@typescript-eslint'
			],
			rules: {
				'@typescript-eslint/no-unused-vars': 'off',
				'@typescript-eslint/no-use-before-define': 'off',
				'@typescript-eslint/no-explicit-any': 'off',
				'@typescript-eslint/explicit-function-return-type': 'off',
				'@typescript-eslint/no-var-requires': 'off',
				'@typescript-eslint/no-inferrable-types': 'off',
				'@typescript-eslint/no-non-null-assertion': 'off',

				// TODO: enable those rules?
				'no-empty': 'off',
				'no-var': 'off'
			}
		},
		{
			files: ['*.test.ts', '*.test.js'],
			env: {
				jest: true
			},
			extends: ['plugin:jest/recommended'],
			rules: {
				'@typescript-eslint/no-explicit-any': 'off',
				'@typescript-eslint/no-var-requires': 'off',
				'import/first': 'off'
			}
		}
	]
};

@armano2
Copy link
Author

armano2 commented Feb 8, 2020

from my tests it seems that this rule does not work at all for monorepos even if packageDir is set

@ljharb
Copy link
Member

ljharb commented Feb 8, 2020

A PR with failing test cases would be appreciated.

@armano2
Copy link
Author

armano2 commented Feb 9, 2020

A PR with failing test cases would be appreciated.

not possible ATM, as there is no way to run this project on windows


from my tests it seems to be related to yarn, from what i understund this rule require that package is installed within node_modules, in case of yarn that may be not a case as it can be hoisted to root node_modules

@armano2
Copy link
Author

armano2 commented Feb 9, 2020

@ljharb https://github.com/armano2/test-eslint-monorpo


it seems that this issue is present only on windows machines

you can find output at:

@armano2

This comment has been minimized.

@armano2 armano2 changed the title [import/no-extraneous-dependencies]: better support for monorepos [import/no-extraneous-dependencies]: better support for monorepos on windows Feb 9, 2020
@armano2 armano2 changed the title [import/no-extraneous-dependencies]: better support for monorepos on windows [import/no-extraneous-dependencies]: better support for monorepos Feb 9, 2020
@paztis
Copy link

paztis commented Apr 9, 2020

Hi all
I've create a PR (#1696) to correctly Work with monorepo.
It does the internal / external detection on the resolved moduelpath instead of the of the hypothetic name.
This means it also correctly work with animy resolver, because it only consider the resolved path. It resolves a lot of problematic cases.

But I've no news about the merge of it...

You can try it from my branch if you want.

@mikestopcontinues
Copy link

I got it working while looking at this thread. Given...

<root>
- packages
- - app
- - jest-config // and deps!
- - eslint-config

<root>/packages/eslint-config/index.js

// import

const path = require('path');

// export

module.exports = {
  root: true,

  extends: [
    './preset/eslint.js',
    './preset/babel.js',
    './preset/import.js',
    // etc...
  ],

  overrides: [
    {
      files: ['**/*.test.{js,ts,jsx,tsx,mjs}'],

      extends: [
        './preset/jest.js',
        './preset/jest-formatting.js',
      ],

      rules: {
        'import/no-extraneous-dependencies': [
          'error',
          {packageDir: [process.cwd(), path.resolve(__dirname, '../jest-config')]},
          // resolves to [<root>/packages/app, <root>/packages/jest-config]
        ],
      },
    },
  ],
};

<root>/packages/app/lib.test.js

import {advanceTo, clear} from 'jest-date-mock';

Despite the fact that jest-config depends on jest-date-mock, plugin-import no longer throws an error.

@armano2
Copy link
Author

armano2 commented Jan 8, 2021

I got it working while looking at this thread. Given...

yes, that correct, some of issues got solved, since i created this ticket,
we do have consistent results between windows and linux machines

https://github.com/armano2/test-eslint-monorpo/actions/runs/471003942

@ljharb
Copy link
Member

ljharb commented Jan 26, 2021

@armano2 does that mean this can be closed? which are the outstanding items?

@armano2
Copy link
Author

armano2 commented Jan 26, 2021

yes it's look like issue with monorepos has been solved.

from my tests this is working fine now on win/linux/mac machines,

https://github.com/conventional-changelog/commitlint/blob/75b67b8fb7fc4df21267b98f0c9daeeb1130b824/.eslintrc.js#L31-L36

	// Forbid the use of extraneous packages
	'import/no-extraneous-dependencies': [
		'error',
		{
			devDependencies: ['**/*.test.js', '**/*.test.ts'],
		},
	],

@armano2 armano2 closed this as completed Jan 26, 2021
@paztis
Copy link

paztis commented Jan 27, 2021

Change is published in npm ?

@armano2
Copy link
Author

armano2 commented Jan 27, 2021

@paztis i tested it on version from npm

@paztis
Copy link

paztis commented Jan 27, 2021

packageJson version is still to 2.22.1 (4 months ago publlished)
Npm page still point to version 2.22.1
Npm semver also (https://semver.npmjs.com/)

Where do you sere it on npm ?

@ljharb
Copy link
Member

ljharb commented Jan 27, 2021

@paztis they're saying that published version works for them.

@armano2
Copy link
Author

armano2 commented Jan 27, 2021

@paztis they're saying that published version works for them.

exactly, in current version of package, issues reported by this tikcet has been solved, most likely there are other issues related to monorepos, but they are not related to this ticket

in current implementation you can but not have to specify packageDir to make it work with monorepos, and issue related to incositency between linux and windows machines has been resolved

https://github.com/armano2/test-eslint-monorpo/actions/runs/471003942

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants