Checks import from
declarations, import
and require
calls then updates or removes package.json dependencies (if update
option described below is set to true
, otherwise you only get informed) from package.json files. Works great with single-package modules as well as with big projects with multiple package.json files (for example if you have a monorepo powered by lerna).
Install: npm i -D check-imports
and use: npx check-imports
.
- The library gets all .js, .jsx, .ts files by a given path;
- Builds their AST trees via @babel/parser;
- Retrieves import paths from
import from
,require()
,import()
; - Runs some filters and mappings:
- Ignore relative paths;
- Ignore built-in NodeJS modules such as
path
,fs
,child_process
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 "parent" (a closest) package.json file;
- 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"
or"peerDependencies"
then"dependencies"
aren't going to be updated and a dependency version remains the same; - If neither of things above is happened then a dependency of a latest version retrieved from NPM registry is going to be added to
"dependencies"
.
- If
Note that after an update you still need to run npm install
manually.
A 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"
.
const { checkImports } = require('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. It also allows to set a list of babel plugin passed to babelParser
in case if you need to make the tool work with flow syntax for example.
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.babelPlugins = require('./defaultBabelPlugins')
- a list of parser plugins described there.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,
});