src/content/docs/linter/rules/no-private-imports.mdx
import { Tabs, TabItem } from '@astrojs/starlight/components';
<Tabs> <TabItem label="JavaScript (and super languages)" icon="seti:javascript"> :::note This rule belongs to the project domain. This means that its activation will activate the Biome Scanner to scan the files of your project. Read more about it in the [documentation page](/linter/domains#project) ::: ## Summary - Rule available since: `v2.0.0` - Diagnostic Category: [`lint/correctness/noPrivateImports`](/reference/diagnostics#diagnostic-category) - This rule is **recommended**, meaning it is enabled by default. - This rule doesn't have a fix. - The default severity of this rule is [**warning**](/reference/diagnostics#warning). - This rule belongs to the following domains: - [`project`](/linter/domains#project) - Sources: - Same as [`import-access/eslint-plugin-import-access`](https://github.com/uhyo/eslint-plugin-import-access){
"linter": {
"rules": {
"correctness": {
"noPrivateImports": "error"
}
}
}
}
Restrict imports of private exports.
In JavaScript and TypeScript, as soon as you export a symbol, such as
a type, function, or anything else that can be exported, it is
considered public and can be imported from anywhere else. Unfortunately,
this makes it hard to enforce module boundaries, or to prevent importing
things that were only exported for test purposes, for instance.
This rule recognizes the JSDoc tags @public, @package, and
@private so that you are free to set the visibility of exports.
Exports without tag have a default visibility of public, but this
can be configured.
The @access tag is also supported if it's used with one of the values
public, package, or private.
Public visibility is the default and means there are no restrictions for importing a given symbol. In other words, without this rule, all exported symbols are implicitly public.
Within the context of this rule, package visibility means that a symbol is visible within the same "package", which means that any module that resides in the same folder, or one of its subfolders, is allowed to import the symbol. Modules that only share a common folder higher up in the hierarchy are not allowed to import the symbol.
For a visual explanation, see this illustration.
Private visibility means that a symbol may not be imported from other modules.
The key thing to understanding the usefulness of @private is that this
rule doesn't treat modules and files as one and the same thing. While
files are indeed modules, folders are considered modules too, with their
files and subfolders being submodules. Therefore, symbols exported as
@private from an index file, such as index.js, can still be
imported from other submodules in that same module.
:::note
For the sake of compatibility with conventions used with Deno, modules
named mod.js/mod.ts are considered index files too.
:::
Another reason why private visibility may still be useful is that it
allows you to choose specific exceptions. For example, using
overrides, you
may want to disable this rule in all files with a .test.js extension.
This way, symbols marked private cannot be imported from outside
modules, with the exception of test files.
import()
expressions or CommonJS require() calls.node_modules are considered out of
scope./**
* @package
*/
export const fooPackageVariable = 1;
// Attempt to import package private variable from `sub/foo.js` from
// outside its `sub` module:
import { fooPackageVariable } from "./sub/foo.js";
/**
* @private For test purposes only!
*/
export function getTestStuff() {}
// Attempt to import a private export. To allow this, you probably want
// to configure an `override` to disable this rule in test files.
// See: https://biomejs.dev/reference/configuration/#overrides
import { getTestStuff } from "./bar.js";
// Package-private exports can be imported from inside the same module.
import { fooPackageVariable } from "./foo.js";
// Resources (anything other than JS/TS files) are always exempt.
import { barResource } from "../resources/bar.png";
/** @private */
export const subPrivateVariable = 2;
// Private exports are accessible within the same module only, but
// modules can be nested. So the following works because you can always
// import from the index file of a parent module:
import { subPrivateVariable } from "../index.js";