entry-point
Enforce entry point restrictions for elements in your project.
boundaries/entry-point is kept for backward compatibility but is deprecated and will be removed in a future major version. Use boundaries/dependencies instead.
It keeps working without changes; you will see a deprecation warning in your console:
Rule "boundaries/entry-point" is deprecated and will be removed in future versions. Please migrate to the "boundaries/dependencies" rule with appropriate selectors.
Read the migration guide below for conversion examples, and the v6 to v7 migration guide for the full picture.
This rule builds on the same base configuration documented in Policies (a default plus a rules array). The differences are: its rule entries use a required target entity selector (an alias of to) instead of from/to, and the policy allow/disallow values match the imported fileInternalPath entry points. Read Policies first, then the options below for the differences.
Rule Details
This rule validates dependencies to ensure that each element is imported only through its defined entry point. Files that are not declared as entry points cannot be imported from other elements.
Options
"boundaries/entry-point":
[<severity>, { "default": <string>, "message": <string>, "rules": <object> }]
The first item in the array is the ESLint severity (0 = off, 1 = warning, 2 = error). The second item is the options object:
default:"allow"or"disallow". Determines the default behavior for imports that don't match any policy rule. If"allow", imports are allowed unless explicitly disallowed by a rule. If"disallow", imports are disallowed unless explicitly allowed by a policy.message: Custom error message for rule violations. Note that the default message provides detailed information about why the error occurred, so only define a custom message if necessary. See error messages for more informationrules: An array of policy objects processed in order to determine whether an import should be allowed. Each policy object can have the following properties:target(required):<entity selectors>- The policy is only evaluated when the imported element matches this selector. Accepts both legacy element selectors (for example{ type: "module" }) and entity selectors (for example{ element: { type: "module" } }).disallow:<string>- A micromatch pattern. If the imported file path matches this pattern, the import is disallowed (can be overridden by a subsequent rule returning"allow"). The pattern is matched against thefileInternalPath— the imported file's path relative to its element root (for exampleindex.jsorsubfolder/main.js)allow:<string>- A micromatch pattern. If the imported file path matches this pattern, the import is allowed (can be overridden by a subsequent rule returning"disallow"). Likedisallow, the pattern is matched against thefileInternalPathimportKind:<string>- Optional. Makes sense when using TypeScript only. If defined, the policy is only evaluated for dependencies of the specified kind. Possible values:"value","type", or"typeof"message:<string>- Custom error message for this specific policy. See error messages for more information
Each policy requires target and at least one of allow or disallow.
The policy-level importKind option is deprecated. When you migrate to boundaries/dependencies, replace it with the dependency.kind selector property. See the v6 to v7 migration guide for details.
Enable debug mode in the plugin configuration to inspect the descriptions assigned to each file and dependency. This can help you understand how selectors are matching and how to configure your rules effectively.
Configuration Example
{
rules: {
"boundaries/entry-point": [2, {
// disallow all entry points by default
default: "disallow",
policies: [
{
// when importing helpers
target: { type: "helper" },
// allow importing any file from a helper element
allow: "*"
},
{
// when importing components or modules
target: {
type: [
"component",
"module"
]
},
// only allow index.js
allow: "index.js",
// allow only importing values, not types (TypeScript only)
// note: importKind is deprecated, use dependency.kind after migrating
importKind: "value"
}
]
}]
}
}
Settings
The following examples use this project structure and settings configuration.
Project structure:
src/
├── components/
│ ├── atoms/
│ │ ├── atom-a/
│ │ │ ├── index.js
│ │ │ └── AtomA.js
│ │ └── atom-b/
│ │ ├── index.js
│ │ └── AtomB.js
│ └── molecules/
│ ├── molecule-a/
│ │ ├── index.js
│ │ └── MoleculeA.js
│ └── molecule-b/
│ ├── index.js
│ └── MoleculeB.js
├── helpers/
│ ├── data/
│ │ ├── sort.js
│ │ └── parse.js
│ └── permissions/
│ └── roles.js
└── modules/
├── module-a/
│ ├── index.js
│ └── ModuleA.js
└── module-b/
├── index.js
└── ModuleB.js
Settings configuration:
{
settings: {
"boundaries/elements": [
{
type: "helper",
pattern: "helpers/*",
capture: ["family"]
},
{
type: "component",
pattern: "components/*/*",
capture: ["family", "elementName"]
},
{
type: "module",
pattern: "modules/*",
capture: ["elementName"]
}
],
"import/resolver": {
"babel-module": {}
}
}
}
These examples use aliases for the src/helpers, src/components, and src/modules folders. You can also use relative paths. You can configure the plugin to recognize aliases by using resolvers.
Examples
Incorrect
Importing files other than index.js from components:
// src/modules/module-a/ModuleA.js
import AtomA from 'components/atoms/atom-a/AtomA'
Importing files other than index.js from modules:
// src/modules/module-a/ModuleA.js
import ModuleB from 'modules/module-b/ModuleB'
Importing types from module entry points:
// src/modules/module-a/ModuleA.js
import type ModuleB from 'modules/module-b'
Correct
Importing helper files:
// src/components/atoms/atom-a/AtomA.js
import { someParser } from 'helpers/data/parse'
Importing index.js from components:
// src/components/atoms/atom-a/AtomA.js
import ComponentB from 'components/atoms/atom-b'
Explicitly importing index.js from components:
// src/components/atoms/atom-a/AtomA.js
import ComponentB from 'components/atoms/atom-b/index.js'
Importing index.js from modules:
// src/modules/module-a/ModuleA.js
import ModuleB from 'modules/module-b'
Error Messages
This rule provides detailed error messages to help you understand and resolve violations.
It uses the same default message format as boundaries/dependencies. The message includes information about the violated rule and the elements involved in the violation, as well as the internal path of the imported file.
For example:
Dependencies to elements of type "module", captured values: elementName="module-a" and fileInternalPath "ModuleA.js" are not allowed. Denied by rule at index 1
Custom Messages with Templates
You can customize error messages globally or for specific rules. See Rules Configuration -> Message Templating for more details.
Migration to boundaries/dependencies
The entry point restrictions enforced by this rule can also be achieved with the boundaries/dependencies rule. There, you select the target element with to, and constrain the importable files with the fileInternalPath property of the element sub-selector.
The following example shows how to migrate a configuration from boundaries/entry-point to boundaries/dependencies. The legacy target becomes to, and allow: "index.js" becomes a policy that allows only files whose fileInternalPath matches index.js. The deprecated importKind option becomes dependency.kind:
{rules: {"boundaries/entry-point": [2, {"boundaries/dependencies": [2, {default: "disallow",policies: [{target: ["component", "module"],allow: "index.js",importKind: "value"}{to: { element: { type: ["component", "module"] } },allow: {to: { element: { fileInternalPath: "index.js" } }},dependency: { kind: "value" }}]}]}}
Read more about entity selectors and the fileInternalPath property in the Selectors documentation, and see the v6 to v7 migration guide for the complete migration.
With boundaries/dependencies you can also define rules to allow different entry points depending on the importer element, which was not possible with the entry-point rule. For example, you could allow importing index.js from components but only allow importing main.js from modules.
Further Reading
Learn more about related topics:
- Defining Elements - Learn how to define architectural elements in your project
- Selectors - Learn how to use element, file, and module selectors (the
targetoption accepts entity selectors) - Policies - Learn how to configure common rule options
- Global Settings - Learn about global settings that affect all rules
- Migrating from v6 to v7 - Migrate deprecated rules to
boundaries/dependencies