eslint-plugin-import icon indicating copy to clipboard operation
eslint-plugin-import copied to clipboard

`no-extraneous-dependencies` doesn't support nested package.json

Open fregante opened this issue 5 years ago • 7 comments

With Node’s ES Module support explicitly suggesting to use multiple package.json files in subfolders, I think no-extraneous-dependencies should automatically support nested package.json without further config

The nearest parent package.json is defined as the first package.json found when searching in the current folder, that folder’s parent, and so on up until the root of the volume is reached.

I know that no-extraneous-dependencies has options to manually specify each folder, but I think that this could be done automatically.

fregante avatar Sep 29 '20 01:09 fregante

I think that when finding a package.json, we should skip it unless it has one of the deps fields - since node’s suggestion is solely to have “type: module” in a nested package.json file (if and only if you want .js to mean something nonstandard, ie, ESM instead of CJS).

Simpler would be to skip if it it only has the type field.

ljharb avatar Sep 29 '20 01:09 ljharb

A temporary solution for Yarn workspaces:

// root .eslintrc.js
const fs   = require('fs');
const path = require('path');
const fg   = require('fast-glob');

const { workspaces } = require('./package.json');

const projectDirs = workspaces
    .flatMap(pattern => fg.sync(pattern, { onlyDirectories: true }))
    .filter(projectPath => fs.existsSync(path.join(__dirname, projectPath, 'package.json')));

module.exports = {
  // ...
  rules: {
    // ...
    'import/no-extraneous-dependencies': [
      'error',
      { devDependencies: ['**/*spec.ts', '**/*mocks.ts', 'src/typings/*.d.ts'] },
    ],
    // ...
  },
  overrides: {
  
    ...projectDirs.map(projectDir => ({
      files: [`${ projectDir }/**/*.{t,j}s`],
      rules: {
        'import/no-extraneous-dependencies': [
          'error',
          {
            devDependencies: ['**/*spec.ts', '**/*mocks.ts'],
            packageDir: [__dirname, path.join(__dirname, projectDir)],
            //           ^^^ root package.json is here
          },
        ],
      },
    })),
    
  },
};

korniychuk avatar Feb 09 '22 17:02 korniychuk

Regarding the OP, a nested package.json file wrt node's ESM is for the "type" field, not for dependencies.

ljharb avatar Feb 09 '22 18:02 ljharb

Since npm now has workspaces support, that's certainly something this plugin should work well with, but it has nothing to do with node's ESM implementation.

ljharb avatar Feb 09 '22 18:02 ljharb

Since npm now has workspaces support, that's certainly something this plugin should work well with.

Yes, this plugin detects package.json files in workspaces. (I use workspaces provided by Yarn 3.1.1) And the plugin considers only the package.json files that are located in the workspaces (without any parent).

Example:

/package.json        <-- root package.json
    dependencies: { "lodash": "..." }
/foo.ts              <-- here lodash is available, @nestjs/core - isn't. Fine.

/libs/utils/package.json
    dependencies: { "@nestjs/core": "..." }
/libs/utils/bar.ts   // I would like to import both lodash & @nestjs/core in this file
                     // but lodash isn't available (plugin shouws an error)
                     // without duplicating lodash in the local package.json 

We can reach such behavior if add packageDir: [__dirname, 'libs/utils']. But it is necessary to duplicate the rule to make it work for all workspaces. So, it would be great to have the ability to make it work without such an additional code to list all workspace paths.

If it is possible to add an option like considerParents: boolean = false that enables automatically merging package.json files from workspaces and root, it would be great.

korniychuk avatar Feb 09 '22 19:02 korniychuk

Duplicate of #1103?

glasser avatar May 22 '25 21:05 glasser

Related, but not a duplicate.

ljharb avatar May 22 '25 21:05 ljharb