no-unpublished-import
UnreleasedConfiguration
Disallow imports of unpublished files and development dependencies from published files.
Rule details
The rule checks static imports, re-exports, and dynamic import() calls with
literal arguments. It uses the nearest package.json, its files list, and
applicable .npmignore or .gitignore files to determine what is published.
Imports from unpublished files are ignored.
In a published file, an import is reported when its target is outside the
package or excluded from publication, or its package is listed only in
devDependencies. A dependency also listed in dependencies, peerDependencies,
or optionalDependencies is accepted. A development dependency need not be
installed to be reported. Workspace ancestors do not supply production
dependencies for this check.
Given a package with files: ['lib'] and devDependencies: { dev: '*' }, these
imports in lib/index.js are incorrect:
These imports are correct when lib/helper.js exists:
Use node/no-missing-import to check whether targets exist and
node/no-extraneous-import to check undeclared packages. This rule provides
no fixes or suggestions.
Options
allowModulesaccepts package roots, including scoped andvirtual:names. Allowingdevalso allowsdev/subpath. It does not exempt local files.ignoreTypeImportdefaults tofalse. Setting it totrueskips wholeimport typedeclarations. Type re-exports and individualtypespecifiers in value imports are still checked.ignorePrivatedefaults totrue, skipping packages withprivate: true. Set it tofalseto check those packages, for example before deployment.convertPathmaps both the importing file and local targets from source paths to published paths, relative to the package directory. It accepts an object such as{ 'src/**': ['^src/(.*)\\.ts$', 'lib/$1.js'] }, or an ordered array of{ include, exclude?, replace }entries. The first matching entry wins. Omit the option instead of usingnull, which the upstream schema also rejects.resolvePathssupplies extra resolution base directories before the importing file's directory. Relative values use the working directory orsettings.cwdwhen configured.tryExtensionsdefaults to['.js', '.json', '.node', '.mjs', '.cjs']. An empty array disables extension guessing.resolverConfigsupportsmodules,alias,fallback,fullySpecified,extensions,extensionAlias,conditionNames,mainFields,mainFiles, andaliasFields, as described for no-missing-import.
Except for ignoreTypeImport and ignorePrivate, these options can also be
supplied through settings.node. Rule options take precedence over shared
settings; legacy settings.n takes precedence over settings.node. Explicit
empty lists override shared lists. TypeScript extension mappings and path
aliases affect which local file is checked. A package alias does not exempt
a development dependency from this rule.
Differences from upstream
Compared with eslint-plugin-n v18.3.0:
- Subdirectory ignore files affect which files are considered published; upstream only uses the package root's ignore file.
README.jsis treated as published even withfiles: []. Included files such aslib/..hidden.jsare also treated as published.- On case-insensitive filesystems,
mainmatches filenames regardless of case; upstream can skip checking those files' imports. - In
files,[!b]excludesb,\*matches a literal*, and whitespace is significant. Upstream may select different files for these patterns. - Overlapping object-form
convertPath,resolverConfig.alias, andresolverConfig.fallbackentries use alphabetical priority instead of declaration order. Use arrays to set priority. - Absolute
convertPathreplacements stay absolute; targets outside the package are reported. - An invalid
convertPathregex in shared settings skips the check instead of failing lint. resolverConfigoptions not listed above, includingsymlinks, are not supported.
See no-missing-import for shared module-resolution differences.