Checks import from
declarations, import
and require
calls in your code and reports if:
- Dependency is listed at package.json but never used at the folder relative to the package.json file.
- A module is imported but dependency isn't listed at the closest package.json.
With --update
option updates dependencies automatically (adds missing, removes unused).
Originally created for monorepos but can be used with any nested project structure with one or multiple package.json files.
npx check-imports
- The library gets all .js, .jsx, .ts, .mjs, .mts, .cjs files from CWD or directory relative to CWD that's defined with
-d
flag; - Builds AST via ts-morph and retrieves import paths from
import from
,require()
,import()
; - Runs the following filtering and mapping:
- Ignore relative paths;
- Ignore built-in NodeJS modules such as
node:path
,path
,node:fs
,fs
, etc; - Retrieve module names (
lodash/pick
becomeslodash
); - Retrieve module names from scoped packages (
@scope/module/foo/bar
becomes@scope/module
); - Get rid of Webpack syntax (
foo!bar!baz?quux=bat&xyzzy=plugh
becomesbaz
);
- Finds a closest package.json file relative to the file with import;
- Compares its contents with the retrieved list of imports and if
update
option is set totrue
the script updates it.- If
ignore
option is provided then"dependencies"
aren't going to be updated with a given dependency or multiple dependencies; - If a dependency already exists either at
"dependencies"
,"optionalDependencies"
,"devDependencies"
or"peerDependencies"
then"dependencies"
aren't going to be updated and a dependency version remains the same; - If none of these two, a dependency of a latest version is retrieved from NPM registry and going to be added to
"dependencies"
.
- If
After an update you still need to run npm install
manually.
Bonus: imports can be ignored directly in code via check-imports-ignore-line
comment.
require('lodash'); // check-imports-ignore-line
The tool can be run via npx check-imports
.
-u
,--update
- update parent package.json files.-e
,--throw-error
- exit process with code 1 in case if there are redundant or missing dependencies (good for CI).-d
,--directory-path <value>
- a directory where JavaScript/TypeScript/JSX files are located.--ignore-path <items>
- a glob pattern (or coma-delimited patterns) to ignore processed files (--ignore-path "**/foo/*.js"
).-n
,--ignore-imports <items>
- a comma-delimited list of dependencies that don't need to appear at"dependencies"
.
import checkImports from 'check-imports';
The API includes a bit wider set of options. It allows to map dependencies to check if a dependency needs to be ignored or get a wanted version.
const results = await checkImports(options);
update = false
- either update package.json files or not.throwError = false
- throw an error in case if there are redundant or missing dependencieslog = false
- print CLI outputdirectoryPath = process.cwd()
- a directory where JavaScript/TypeScript/JSX files are located.ignorePath = []
- a glob pattern or an array of patterns to ignore processed files.processManually = null
- a function which is run agains every found import. You may want to define it in case if you want to ignore some dependencies or set a wanted version. It should return either of the following values:true
- process a dependency a regular way.false
- ignore a dependency.- An object with optional keys
version
andtype
.version
field makes possible to forcibly define a dependency version.type
field defines a key at package.json where a dependency needs to be stored ("optionalDependencies"
,"peerDependencies"
or any custom). By default its value is"dependencies"
.
const results = await checkImports({
directoryPath: path.resolve(__dirname, 'foo'),
ignorePath: ['**/ignored.*'],
processManually: (dependency) => {
if (dependency === 'react') {
// forcibly set version to 1.1.1 and add it to peerDependencies
return {
version: '1.1.1',
type: 'peerDependencies',
};
}
if (dependency === 'react-redux') {
// add it to customDependencies
return {
type: 'customDependencies',
};
}
if (dependency === 'moment') {
// forcibly set version to ^999.999.999
return {
version: '^999.999.999',
};
}
if (dependency === 'redux') {
// ignore the dependency
return false;
}
// else process regularly
return true;
},
update: true,
});